summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius <mariausol@gmail.com>2010-10-29 13:00:23 +0300
committerMarius <mariausol@gmail.com>2010-10-29 13:00:23 +0300
commit42c4d16ce1daa37425d12be6c87d6f64a72b5094 (patch)
tree494b8c10ccef29abe26db9acf08261ce78c16cf6
parentf56f0054360a9bdfb57de9abcf0d81a2766c22b9 (diff)
downloadcontext-42c4d16ce1daa37425d12be6c87d6f64a72b5094.tar.gz
beta 2010.10.29 11:35
-rw-r--r--scripts/context/lua/mtx-chars.lua3
-rw-r--r--scripts/context/lua/mtx-check.lua150
-rw-r--r--scripts/context/lua/mtx-context.lua64
-rw-r--r--scripts/context/lua/mtx-unzip.lua21
-rw-r--r--scripts/context/lua/mtxrun.lua1556
-rw-r--r--scripts/context/stubs/mswin/mtxrun.lua1556
-rw-r--r--scripts/context/stubs/unix/mtxrun1556
-rw-r--r--tex/context/base/back-exp.lua36
-rw-r--r--tex/context/base/back-ini.lua2
-rw-r--r--tex/context/base/back-pdf.lua9
-rw-r--r--tex/context/base/back-pdf.mkiv2
-rw-r--r--tex/context/base/bibl-bib.lua10
-rw-r--r--tex/context/base/bibl-tra.lua31
-rw-r--r--tex/context/base/blob-ini.lua9
-rw-r--r--tex/context/base/buff-ini.lua20
-rw-r--r--tex/context/base/catc-ctx.tex1
-rw-r--r--tex/context/base/char-def.lua16
-rw-r--r--tex/context/base/char-ini.lua108
-rw-r--r--tex/context/base/char-utf.lua49
-rw-r--r--tex/context/base/chem-str.lua49
-rw-r--r--tex/context/base/colo-ini.lua25
-rw-r--r--tex/context/base/cont-new.tex2
-rw-r--r--tex/context/base/context.tex2
-rw-r--r--tex/context/base/core-con.lua52
-rw-r--r--tex/context/base/core-ctx.lua2
-rw-r--r--tex/context/base/core-sys.lua1
-rw-r--r--tex/context/base/data-env.lua1
-rw-r--r--tex/context/base/data-exp.lua106
-rw-r--r--tex/context/base/data-ini.lua20
-rw-r--r--tex/context/base/data-met.lua2
-rw-r--r--tex/context/base/data-res.lua56
-rw-r--r--tex/context/base/data-sch.lua14
-rw-r--r--tex/context/base/data-tmf.lua2
-rw-r--r--tex/context/base/data-tmp.lua2
-rw-r--r--tex/context/base/font-ctx.lua65
-rw-r--r--tex/context/base/font-def.lua17
-rw-r--r--tex/context/base/font-enh.lua91
-rw-r--r--tex/context/base/font-ext.lua15
-rw-r--r--tex/context/base/font-log.lua7
-rw-r--r--tex/context/base/font-map.lua12
-rw-r--r--tex/context/base/font-mis.lua2
-rw-r--r--tex/context/base/font-otf.lua74
-rw-r--r--tex/context/base/font-otn.lua50
-rw-r--r--tex/context/base/font-ott.lua21
-rw-r--r--tex/context/base/font-syn.lua48
-rw-r--r--tex/context/base/font-tfm.lua8
-rw-r--r--tex/context/base/font-xtx.lua2
-rw-r--r--tex/context/base/grph-inc.lua213
-rw-r--r--tex/context/base/grph-inc.mkiv2
-rw-r--r--tex/context/base/l-boolean.lua16
-rw-r--r--tex/context/base/l-dimen.lua138
-rw-r--r--tex/context/base/l-dir.lua19
-rw-r--r--tex/context/base/l-file.lua10
-rw-r--r--tex/context/base/l-lpeg.lua260
-rw-r--r--tex/context/base/l-number.lua2
-rw-r--r--tex/context/base/l-os.lua2
-rw-r--r--tex/context/base/l-set.lua5
-rw-r--r--tex/context/base/l-string.lua222
-rw-r--r--tex/context/base/l-table.lua249
-rw-r--r--tex/context/base/l-unicode.lua68
-rw-r--r--tex/context/base/lang-ini.lua7
-rw-r--r--tex/context/base/lang-wrd.lua124
-rw-r--r--tex/context/base/lang-wrd.mkiv6
-rw-r--r--tex/context/base/lpdf-col.lua8
-rw-r--r--tex/context/base/lpdf-epa.lua43
-rw-r--r--tex/context/base/lpdf-epd.lua5
-rw-r--r--tex/context/base/lpdf-ini.lua43
-rw-r--r--tex/context/base/lpdf-tag.lua6
-rw-r--r--tex/context/base/luat-cbk.lua2
-rw-r--r--tex/context/base/luat-cnf.lua3
-rw-r--r--tex/context/base/luat-env.lua29
-rw-r--r--tex/context/base/luat-fio.lua2
-rw-r--r--tex/context/base/luat-fmt.lua11
-rw-r--r--tex/context/base/luat-ini.lua2
-rw-r--r--tex/context/base/luat-lib.mkiv2
-rw-r--r--tex/context/base/luat-run.lua2
-rw-r--r--tex/context/base/lxml-aux.lua28
-rw-r--r--tex/context/base/lxml-lpt.lua116
-rw-r--r--tex/context/base/lxml-tex.lua11
-rw-r--r--tex/context/base/lxml-xml.lua33
-rw-r--r--tex/context/base/m-database.lua18
-rw-r--r--tex/context/base/meta-pdf.lua13
-rw-r--r--tex/context/base/mlib-pdf.lua57
-rw-r--r--tex/context/base/mlib-pps.lua15
-rw-r--r--tex/context/base/mlib-run.lua2
-rw-r--r--tex/context/base/mult-cld.lua15
-rw-r--r--tex/context/base/mult-clm.lua4
-rw-r--r--tex/context/base/node-fin.lua35
-rw-r--r--tex/context/base/node-fnt.lua27
-rw-r--r--tex/context/base/node-ini.lua9
-rw-r--r--tex/context/base/node-inj.lua14
-rw-r--r--tex/context/base/node-pro.lua12
-rw-r--r--tex/context/base/node-res.lua10
-rw-r--r--tex/context/base/node-rul.lua2
-rw-r--r--tex/context/base/node-ser.lua10
-rw-r--r--tex/context/base/node-spl.lua26
-rw-r--r--tex/context/base/node-tra.lua4
-rw-r--r--tex/context/base/page-lin.lua5
-rw-r--r--tex/context/base/s-fnt-10.tex4
-rw-r--r--tex/context/base/scrn-int.mkiv2
-rw-r--r--tex/context/base/sort-ini.lua49
-rw-r--r--tex/context/base/spac-ver.lua10
-rw-r--r--tex/context/base/strc-bkm.lua6
-rw-r--r--tex/context/base/strc-des.mkiv39
-rw-r--r--tex/context/base/strc-doc.lua50
-rw-r--r--tex/context/base/strc-lst.lua35
-rw-r--r--tex/context/base/strc-lst.mkiv3
-rw-r--r--tex/context/base/strc-not.mkiv2
-rw-r--r--tex/context/base/strc-ref.lua15
-rw-r--r--tex/context/base/strc-reg.lua119
-rw-r--r--tex/context/base/supp-fil.lua14
-rw-r--r--tex/context/base/supp-fil.mkiv9
-rw-r--r--tex/context/base/toks-ini.lua53
-rw-r--r--tex/context/base/trac-inf.lua13
-rw-r--r--tex/context/base/trac-set.lua4
-rw-r--r--tex/context/base/typo-krn.lua2
-rw-r--r--tex/context/base/typo-spa.lua4
-rw-r--r--tex/context/base/util-fmt.lua4
-rw-r--r--tex/context/base/util-lua.lua24
-rw-r--r--tex/context/base/util-pck.lua12
-rw-r--r--tex/context/base/util-prs.lua31
-rw-r--r--tex/context/base/util-seq.lua42
-rw-r--r--tex/context/base/util-sto.lua11
-rw-r--r--tex/context/base/util-tab.lua11
-rw-r--r--tex/context/base/x-mathml.lua11
-rw-r--r--tex/generic/context/luatex-fonts-merged.lua957
126 files changed, 5532 insertions, 3918 deletions
diff --git a/scripts/context/lua/mtx-chars.lua b/scripts/context/lua/mtx-chars.lua
index 67243dcf3..d356bb5bb 100644
--- a/scripts/context/lua/mtx-chars.lua
+++ b/scripts/context/lua/mtx-chars.lua
@@ -239,13 +239,14 @@ function scripts.chars.makeencoutf()
end
end
end
+ local template = "\\def\\%-".. length .. "s{\\char\"%05X } %% %s: %s\n"
for i=1,#list do
local code = list[i]
if code > 0x5B and code <= 0xFFFF then
local chr = data[code]
if chr and chr.contextname then
local ch = utfchar(code)
- f:write(format("\\def\\%s{\\char\"%05X } %% %s: %s\n", chr.contextname:rpadd(length," "), code, chr.description, ch))
+ f:write(format(template, chr.contextname, code, chr.description, ch))
end
end
end
diff --git a/scripts/context/lua/mtx-check.lua b/scripts/context/lua/mtx-check.lua
index 0c9a1708d..7704d86ae 100644
--- a/scripts/context/lua/mtx-check.lua
+++ b/scripts/context/lua/mtx-check.lua
@@ -11,86 +11,82 @@ scripts.checker = scripts.checker or { }
local validator = { }
-do
-
- validator.n = 1
- validator.errors = { }
- validator.trace = false
- validator.direct = false
-
- validator.printer = print
- validator.tracer = print
-
- local message = function(position, kind)
- local ve = validator.errors
- ve[#ve+1] = { kind, position, validator.n }
- if validator.direct then
- validator.printer(string.format("%s error at position %s (line %s)", kind, position, validator.n))
- end
+validator.n = 1
+validator.errors = { }
+validator.trace = false
+validator.direct = false
+
+validator.printer = print
+validator.tracer = print
+
+local message = function(position, kind)
+ local ve = validator.errors
+ ve[#ve+1] = { kind, position, validator.n }
+ if validator.direct then
+ validator.printer(string.format("%s error at position %s (line %s)", kind, position, validator.n))
end
- local progress = function(position, data, kind)
- if validator.trace then
- validator.tracer(string.format("%s at position %s: %s", kind, position, data or ""))
- end
+end
+local progress = function(position, data, kind)
+ if validator.trace then
+ validator.tracer(string.format("%s at position %s: %s", kind, position, data or ""))
end
+end
- local P, R, S, V, C, CP, CC = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.C, lpeg.Cp, lpeg.Cc
-
- local i_m, d_m = P("$"), P("$$")
- local l_s, r_s = P("["), P("]")
- local l_g, r_g = P("{"), P("}")
-
- local okay = lpeg.P("{[}") + lpeg.P("{]}")
-
- local esc = P("\\")
- local cr = P("\r")
- local lf = P("\n")
- local crlf = P("\r\n")
- local space = S(" \t\f\v")
- local newline = crlf + cr + lf
-
- local line = newline / function() validator.n = validator.n + 1 end
-
- -- local grammar = P { "tokens",
- -- ["tokens"] = (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + V("errors") + 1)^0,
- -- ["whatever"] = line + esc * 1 + C(P("%") * (1-line)^0),
- -- ["grouped"] = CP() * C(l_g * (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_g - r_g))^0 * r_g) * CC("group") / progress,
- -- ["setup"] = CP() * C(l_s * (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_s - r_s))^0 * r_s) * CC("setup") / progress,
- -- ["display"] = CP() * C(d_m * (V("whatever") + V("grouped") + (1 - d_m))^0 * d_m) * CC("display") / progress,
- -- ["inline"] = CP() * C(i_m * (V("whatever") + V("grouped") + (1 - i_m))^0 * i_m) * CC("inline") / progress,
- -- ["errors"] = (V("gerror") + V("serror") + V("derror") + V("ierror")) * true,
- -- ["gerror"] = CP() * (l_g + r_g) * CC("grouping") / message,
- -- ["serror"] = CP() * (l_s + r_g) * CC("setup error") / message,
- -- ["derror"] = CP() * d_m * CC("display math error") / message,
- -- ["ierror"] = CP() * i_m * CC("inline math error") / message,
- -- }
-
- local startluacode = P("\\startluacode")
- local stopluacode = P("\\stopluacode")
-
- local somecode = startluacode * (1-stopluacode)^1 * stopluacode
-
- local grammar = P { "tokens",
- ["tokens"] = (V("ignore") + V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + V("errors") + 1)^0,
- ["whatever"] = line + esc * 1 + C(P("%") * (1-line)^0),
- ["grouped"] = l_g * (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_g - r_g))^0 * r_g,
- ["setup"] = l_s * (okay + V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_s - r_s))^0 * r_s,
- ["display"] = d_m * (V("whatever") + V("grouped") + (1 - d_m))^0 * d_m,
- ["inline"] = i_m * (V("whatever") + V("grouped") + (1 - i_m))^0 * i_m,
- ["errors"] = (V("gerror")+ V("serror") + V("derror") + V("ierror")),
- ["gerror"] = CP() * (l_g + r_g) * CC("grouping") / message,
- ["serror"] = CP() * (l_s + r_g) * CC("setup error") / message,
- ["derror"] = CP() * d_m * CC("display math error") / message,
- ["ierror"] = CP() * i_m * CC("inline math error") / message,
- ["ignore"] = somecode,
- }
-
- function validator.check(str)
- validator.n = 1
- validator.errors = { }
- grammar:match(str)
- end
+local P, R, S, V, C, CP, CC = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.C, lpeg.Cp, lpeg.Cc
+
+local i_m, d_m = P("$"), P("$$")
+local l_s, r_s = P("["), P("]")
+local l_g, r_g = P("{"), P("}")
+
+local okay = lpeg.P("{[}") + lpeg.P("{]}")
+
+local esc = P("\\")
+local cr = P("\r")
+local lf = P("\n")
+local crlf = P("\r\n")
+local space = S(" \t\f\v")
+local newline = crlf + cr + lf
+
+local line = newline / function() validator.n = validator.n + 1 end
+
+-- local grammar = P { "tokens",
+-- ["tokens"] = (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + V("errors") + 1)^0,
+-- ["whatever"] = line + esc * 1 + C(P("%") * (1-line)^0),
+-- ["grouped"] = CP() * C(l_g * (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_g - r_g))^0 * r_g) * CC("group") / progress,
+-- ["setup"] = CP() * C(l_s * (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_s - r_s))^0 * r_s) * CC("setup") / progress,
+-- ["display"] = CP() * C(d_m * (V("whatever") + V("grouped") + (1 - d_m))^0 * d_m) * CC("display") / progress,
+-- ["inline"] = CP() * C(i_m * (V("whatever") + V("grouped") + (1 - i_m))^0 * i_m) * CC("inline") / progress,
+-- ["errors"] = (V("gerror") + V("serror") + V("derror") + V("ierror")) * true,
+-- ["gerror"] = CP() * (l_g + r_g) * CC("grouping") / message,
+-- ["serror"] = CP() * (l_s + r_g) * CC("setup error") / message,
+-- ["derror"] = CP() * d_m * CC("display math error") / message,
+-- ["ierror"] = CP() * i_m * CC("inline math error") / message,
+-- }
+
+local startluacode = P("\\startluacode")
+local stopluacode = P("\\stopluacode")
+
+local somecode = startluacode * (1-stopluacode)^1 * stopluacode
+
+local grammar = P { "tokens",
+ ["tokens"] = (V("ignore") + V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + V("errors") + 1)^0,
+ ["whatever"] = line + esc * 1 + C(P("%") * (1-line)^0),
+ ["grouped"] = l_g * (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_g - r_g))^0 * r_g,
+ ["setup"] = l_s * (okay + V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_s - r_s))^0 * r_s,
+ ["display"] = d_m * (V("whatever") + V("grouped") + (1 - d_m))^0 * d_m,
+ ["inline"] = i_m * (V("whatever") + V("grouped") + (1 - i_m))^0 * i_m,
+ ["errors"] = (V("gerror")+ V("serror") + V("derror") + V("ierror")),
+ ["gerror"] = CP() * (l_g + r_g) * CC("grouping") / message,
+ ["serror"] = CP() * (l_s + r_g) * CC("setup error") / message,
+ ["derror"] = CP() * d_m * CC("display math error") / message,
+ ["ierror"] = CP() * i_m * CC("inline math error") / message,
+ ["ignore"] = somecode,
+}
+function validator.check(str)
+ validator.n = 1
+ validator.errors = { }
+ grammar:match(str)
end
--~ str = [[
@@ -117,7 +113,7 @@ function scripts.checker.check(filename)
["\t"] = " <tab> ",
})
data = data:gsub("^ *","")
- print(string.format("% 5i %s %s", line,string.rpadd(kind,10," "),data))
+ print(string.format("% 5i %-10s %s", line, kind, data))
end
else
print("no error")
diff --git a/scripts/context/lua/mtx-context.lua b/scripts/context/lua/mtx-context.lua
index 38cffe63e..6e4eea39f 100644
--- a/scripts/context/lua/mtx-context.lua
+++ b/scripts/context/lua/mtx-context.lua
@@ -695,8 +695,19 @@ function scripts.context.run(ctxdata,filename)
local texexec = resolvers.findfile("texexec.rb") or ""
if texexec ~= "" then
os.setenv("RUBYOPT","")
- local command = string.format("ruby %s %s",texexec,environment.reconstructcommandline(environment.arguments_after))
- os.exec(command)
+ local options = environment.reconstructcommandline(environment.arguments_after)
+ options = string.gsub(options,"--purge","")
+ options = string.gsub(options,"--purgeall","")
+ local command = string.format("ruby %s %s",texexec,options)
+ if environment.argument("purge") then
+ os.execute(command)
+ scripts.context.purge_job(filename,false,true)
+ elseif environment.argument("purgeall") then
+ os.execute(command)
+ scripts.context.purge_job(filename,true,true)
+ else
+ os.exec(command)
+ end
end
end
else
@@ -1110,6 +1121,10 @@ local persistent_runfiles = {
"tuo", "tub", "top", "tuc"
}
+local special_runfiles = {
+ "-mpgraph*", "-mprun*"
+}
+
local function purge_file(dfile,cfile)
if cfile and lfs.isfile(cfile) then
if os.remove(dfile) then
@@ -1122,31 +1137,38 @@ local function purge_file(dfile,cfile)
end
end
-function scripts.context.purge_job(jobname,all)
+local function remove_special_files(pattern)
+end
+
+function scripts.context.purge_job(jobname,all,mkiitoo)
if jobname and jobname ~= "" then
jobname = file.basename(jobname)
local filebase = file.removesuffix(jobname)
- local deleted = { }
- for i=1,#obsolete_results do
- deleted[#deleted+1] = purge_file(filebase.."."..obsolete_results[i],filebase..".pdf")
- end
- for i=1,#temporary_runfiles do
- deleted[#deleted+1] = purge_file(filebase.."."..temporary_runfiles[i])
- end
- if all then
- for i=1,#persistent_runfiles do
- deleted[#deleted+1] = purge_file(filebase.."."..persistent_runfiles[i])
+ if mkiitoo then
+ scripts.context.purge(all,filebase,true) -- leading "./"
+ else
+ local deleted = { }
+ for i=1,#obsolete_results do
+ deleted[#deleted+1] = purge_file(filebase.."."..obsolete_results[i],filebase..".pdf")
+ end
+ for i=1,#temporary_runfiles do
+ deleted[#deleted+1] = purge_file(filebase.."."..temporary_runfiles[i])
+ end
+ if all then
+ for i=1,#persistent_runfiles do
+ deleted[#deleted+1] = purge_file(filebase.."."..persistent_runfiles[i])
+ end
+ end
+ if #deleted > 0 then
+ logs.simple("purged files: %s", table.concat(deleted,", "))
end
- end
- if #deleted > 0 then
- logs.simple("purged files: %s", table.concat(deleted,", "))
end
end
end
-function scripts.context.purge(all)
+function scripts.context.purge(all,pattern,mkiitoo)
local all = all or environment.argument("all")
- local pattern = environment.argument("pattern") or "*.*"
+ local pattern = environment.argument("pattern") or (pattern and (pattern.."*")) or "*.*"
local files = dir.glob(pattern)
local obsolete = table.tohash(obsolete_results)
local temporary = table.tohash(temporary_runfiles)
@@ -1159,6 +1181,12 @@ function scripts.context.purge(all)
local basename = file.basename(name)
if obsolete[suffix] or temporary[suffix] or persistent[suffix] or generic[basename] then
deleted[#deleted+1] = purge_file(name)
+ elseif mkiitoo then
+ for i=1,#special_runfiles do
+ if string.find(name,special_runfiles[i]) then
+ deleted[#deleted+1] = purge_file(name)
+ end
+ end
end
end
if #deleted > 0 then
diff --git a/scripts/context/lua/mtx-unzip.lua b/scripts/context/lua/mtx-unzip.lua
index f990f4210..85a4b9e7b 100644
--- a/scripts/context/lua/mtx-unzip.lua
+++ b/scripts/context/lua/mtx-unzip.lua
@@ -1,5 +1,15 @@
+if not modules then modules = { } end modules ['mtx-unzip'] = {
+ version = 1.001,
+ comment = "companion to mtxrun.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
-- maybe --pattern
+local format = string.format
+
logs.extendbanner("Simple Unzipper 0.10")
messages.help = [[
@@ -36,10 +46,13 @@ function scripts.unzipper.list()
if #k.filename > n then n = #k.filename end
end
local files, paths, compressed, uncompressed = 0, 0, 0, 0
+ local template_a = "%-"..n.."s"
+ local template_b = "%-"..n.."s % 9i % 9i"
+ local template_c = "\n%-"..n.."s % 9i % 9i"
for k in zipfile:files() do
if k.filename:find("/$") then
paths = paths + 1
- print(string.format("%s", k.filename:rpadd(n," ")))
+ print(format(template_a, k.filename))
else
files = files + 1
local cs, us = k.compressed_size, k.uncompressed_size
@@ -49,10 +62,10 @@ function scripts.unzipper.list()
if us > uncompressed then
uncompressed = us
end
- print(string.format("%s % 9i % 9i", k.filename:rpadd(n," "),cs,us))
+ print(format(template_b,k.filename,cs,us))
end
- end
- print(string.format("\n%s % 9i % 9i", (files .. " files, " .. paths .. " directories"):rpadd(n," "),compressed,uncompressed))
+ end -- check following pattern, n is not enough
+ print(format(template_c,files .. " files, " .. paths .. " directories",compressed,uncompressed))
end
end
diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua
index d091fa405..7af51ba30 100644
--- a/scripts/context/lua/mtxrun.lua
+++ b/scripts/context/lua/mtxrun.lua
@@ -54,7 +54,7 @@ if not modules then modules = { } end modules ['l-string'] = {
local string = string
local sub, gsub, find, match, gmatch, format, char, byte, rep, lower = string.sub, string.gsub, string.find, string.match, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
-local lpegmatch = lpeg.match
+local lpegmatch, S, C, Ct = lpeg.match, lpeg.S, lpeg.C, lpeg.Ct
-- some functions may disappear as they are not used anywhere
@@ -62,145 +62,68 @@ if not string.split then
-- this will be overloaded by a faster lpeg variant
- function string:split(pattern)
- if #self > 0 then
- local t = { }
- for s in gmatch(self..pattern,"(.-)"..pattern) do
- t[#t+1] = s
+ function string.split(str,pattern)
+ local t = { }
+ if #str > 0 then
+ local n = 1
+ for s in gmatch(str..pattern,"(.-)"..pattern) do
+ t[n] = s
+ n = n + 1
end
- return t
- else
- return { }
end
+ return t
end
end
-string.patterns = { }
-
-local escapes = {
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["^"] = "%^", ["$"] = "%$",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%(", [")"] = "%)",
- ["{"] = "%{", ["}"] = "%}"
-}
-
-string.patterns.escapes = escapes
-
-function string:esc() -- variant 2
- return (gsub(self,"(.)",escapes))
-end
-
-function string:unquote()
- return (gsub(self,"^([\"\'])(.*)%1$","%2"))
+function string.unquoted(str)
+ return (gsub(str,"^([\"\'])(.*)%1$","%2"))
end
-function string:quote() -- we could use format("%q")
- return format("%q",self)
+function string.quoted(str)
+ return format("%q",str) -- always "
end
-function string:count(pattern) -- variant 3
+function string.count(str,pattern) -- variant 3
local n = 0
- for _ in gmatch(self,pattern) do
+ for _ in gmatch(str,pattern) do -- not for utf
n = n + 1
end
return n
end
-function string:limit(n,sentinel)
- if #self > n then
+function string.limit(str,n,sentinel)
+ if #str > n then
sentinel = sentinel or " ..."
- return sub(self,1,(n-#sentinel)) .. sentinel
+ return sub(str,1,(n-#sentinel)) .. sentinel
else
- return self
- end
-end
-
-
-do -- roberto's variant:
- local space = lpeg.S(" \t\v\n")
- local nospace = 1 - space
- local stripper = space^0 * lpeg.C((space^0 * nospace^1)^0)
- function string.strip(str)
- return lpegmatch(stripper,str) or ""
- end
-end
-
-function string:is_empty()
- return not find(self,"%S")
-end
-
-function string:enhance(pattern,action)
- local ok, n = true, 0
- while ok do
- ok = false
- self = gsub(self,pattern, function(...)
- ok, n = true, n + 1
- return action(...)
- end)
+ return str
end
- return self, n
end
-if not string.characters then
-
- local function nextchar(str, index)
- index = index + 1
- return (index <= #str) and index or nil, sub(str,index,index)
- end
- function string:characters()
- return nextchar, self, 0
- end
- local function nextbyte(str, index)
- index = index + 1
- return (index <= #str) and index or nil, byte(sub(str,index,index))
- end
- function string:bytes()
- return nextbyte, self, 0
- end
+local space = S(" \t\v\n")
+local nospace = 1 - space
+local stripper = space^0 * C((space^0 * nospace^1)^0) -- roberto's code
+function string.strip(str)
+ return lpegmatch(stripper,str) or ""
end
-function string:rpadd(n,chr)
- local m = n-#self
- if m > 0 then
- return self .. rep(chr or " ",m)
- else
- return self
- end
-end
-
-function string:lpadd(n,chr)
- local m = n-#self
- if m > 0 then
- return rep(chr or " ",m) .. self
- else
- return self
- end
+function string.is_empty(str)
+ return not find(str,"%S")
end
-string.padd = string.rpadd
-
local patterns_escapes = {
- ["-"] = "%-",
- ["."] = "%.",
- ["+"] = "%+",
- ["*"] = "%*",
["%"] = "%%",
- ["("] = "%)",
- [")"] = "%)",
- ["["] = "%[",
- ["]"] = "%]",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
}
-function string:escapedpattern()
- return (gsub(self,".",patterns_escapes))
-end
-
local simple_escapes = {
["-"] = "%-",
["."] = "%.",
@@ -208,24 +131,32 @@ local simple_escapes = {
["*"] = ".*",
}
-function string:partialescapedpattern()
- return (gsub(self,".",simple_escapes))
+function string.escapedpattern(str,simple)
+ if simple then
+ return (gsub(str,".",simple_escapes))
+ else
+ return (gsub(str,".",patterns_escapes))
+ end
end
-function string:tohash()
- local t = { }
- for s in gmatch(self,"([^, ]+)") do -- lpeg
- t[s] = true
+function string.topattern(str,lowercase,strict)
+ if str == "" then
+ return ".*"
+ else
+ str = gsub(str,".",simple_escapes)
+ if lowercase then
+ str = lower(str)
+ end
+ if strict then
+ return "^" .. str .. "$"
+ else
+ return str
+ end
end
- return t
end
-local pattern = lpeg.Ct(lpeg.C(1)^0)
-
-function string:totable()
- return lpegmatch(pattern,self)
-end
+-- The following functions might end up in another namespace.
function string.tabtospace(str,tab)
-- we don't handle embedded newlines
@@ -246,30 +177,17 @@ function string.tabtospace(str,tab)
return str
end
-function string:compactlong() -- strips newlines and leading spaces
- self = gsub(self,"[\n\r]+ *","")
- self = gsub(self,"^ *","")
- return self
-end
-function string:striplong() -- strips newlines and leading spaces
- self = gsub(self,"^%s*","")
- self = gsub(self,"[\n\r]+ *","\n")
- return self
+function string.striplong(str) -- strips all leading spaces
+ str = gsub(str,"^%s*","")
+ str = gsub(str,"[\n\r]+ *","\n")
+ return str
end
-function string:topattern(lowercase,strict)
- if lowercase then
- self = lower(self)
- end
- self = gsub(self,".",simple_escapes)
- if self == "" then
- self = ".*"
- elseif strict then
- self = "^" .. self .. "$"
- end
- return self
-end
+-- obsolete names:
+
+string.quote = string.quoted
+string.unquote = string.unquoted
end -- of closure
@@ -292,15 +210,29 @@ local patterns = lpeg.patterns
local P, R, S, Ct, C, Cs, Cc, V = lpeg.P, lpeg.R, lpeg.S, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.V
local match = lpeg.match
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
local digit, sign = R('09'), S('+-')
local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local utf8byte = R("\128\191")
+local utf8next = R("\128\191")
+local escaped = P("\\") * P(1)
+local squote = P("'")
+local dquote = P('"')
-patterns.utf8byte = utf8byte
patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8byte
-patterns.utf8three = R("\224\239") * utf8byte * utf8byte
-patterns.utf8four = R("\240\244") * utf8byte * utf8byte * utf8byte
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = P('\000\000\254\255') + P('\255\254\000\000') + P('\255\254') + P('\254\255') + P('\239\187\191')
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * P(-1) * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
patterns.digit = digit
patterns.sign = sign
@@ -327,17 +259,24 @@ patterns.nonspace = 1 - patterns.space
patterns.nonspacer = 1 - patterns.spacer
patterns.whitespace = patterns.eol + patterns.spacer
patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.utf8 = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-patterns.utfbom = P('\000\000\254\255') + P('\255\254\000\000') + P('\255\254') + P('\254\255') + P('\239\187\191')
-patterns.validutf8 = patterns.utf8^0 * P(-1) * Cc(true) + Cc(false)
patterns.comma = P(",")
patterns.commaspacer = P(",") * patterns.spacer^0
patterns.period = P(".")
-
-patterns.undouble = P('"')/"" * (1-P('"'))^0 * P('"')/""
-patterns.unsingle = P("'")/"" * (1-P("'"))^0 * P("'")/""
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.undouble = (dquote/"") * ((escaped + (1-dquote))^0) * (dquote/"")
+patterns.unsingle = (squote/"") * ((escaped + (1-squote))^0) * (squote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
patterns.unspacer = ((patterns.spacer^1)/"")^0
+local unquoted = Cs(patterns.unquoted * P(-1)) -- not C
+
+function string.unquoted(str)
+ return match(unquoted,str) or str
+end
+
+
function lpeg.anywhere(pattern) --slightly adapted from website
return P { P(pattern) + 1 * V(1) } -- why so complex?
end
@@ -353,8 +292,8 @@ local content = (empty + nonempty)^1
local capture = Ct(content^0)
-function string:splitlines()
- return match(capture,self)
+function string.splitlines(str)
+ return match(capture,str)
end
patterns.textline = content
@@ -366,12 +305,12 @@ 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 other, any = C((1 - separator)^0), P(1)
+ local any = P(1)
splitter = other * (separator * C(any^0) + "") -- ?
splitters_s[separator] = splitter
else
- local other = C((1 - separator)^0)
splitter = other * (separator * other)^0
splitters_m[separator] = splitter
end
@@ -392,16 +331,15 @@ function lpeg.split(separator,str)
return match(c,str)
end
-function string:split(separator)
+function string.split(str,separator)
local c = cache[separator]
if not c then
c = Ct(splitat(separator))
cache[separator] = c
end
- return match(c,self)
+ return match(c,str)
end
-lpeg.splitters = cache
local cache = { }
@@ -409,22 +347,22 @@ function lpeg.checkedsplit(separator,str)
local c = cache[separator]
if not c then
separator = P(separator)
- local other = C((1 - separator)^0)
+ local other = C((1 - separator)^1)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
return match(c,str)
end
-function string:checkedsplit(separator)
+function string.checkedsplit(str,separator)
local c = cache[separator]
if not c then
separator = P(separator)
- local other = C((1 - separator)^0)
+ local other = C((1 - separator)^1)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
- return match(c,self)
+ return match(c,str)
end
@@ -435,7 +373,9 @@ local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2
local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-patterns.utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
@@ -469,19 +409,25 @@ function lpeg.keeper(str)
end
end
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
function lpeg.replacer(t)
if #t > 0 then
local p
for i=1,#t do
local ti= t[i]
local pp = P(ti[1]) / ti[2]
- p = (p and p + pp ) or pp
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
end
return Cs((p + 1)^0)
end
end
-
local splitters_f, splitters_s = { }, { }
function lpeg.firstofsplit(separator) -- always return value
@@ -505,11 +451,170 @@ function lpeg.secondofsplit(separator) -- nil if not split
end
function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
return P { left * ((1 - left - right) + V(1))^0 * right }
end
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + P(1))^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + P(1))^0)
+
+function string.escapedpattern(str,simple)
+ if simple then
+ return match(s,str)
+ else
+ return match(p,str)
+ end
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -577,24 +682,26 @@ end
-- extra functions, some might go (when not used)
function table.strip(tab)
- local lst = { }
+ local lst, l = { }, 0
for i=1,#tab do
local s = gsub(tab[i],"^%s*(.-)%s*$","%1")
if s == "" then
-- skip this one
else
- lst[#lst+1] = s
+ l = l + 1
+ lst[l] = s
end
end
return lst
end
function table.keys(t)
- local k = { }
+ local keys, k = { }, 0
for key, _ in next, t do
- k[#k+1] = key
+ k = k + 1
+ keys[k] = key
end
- return k
+ return keys
end
local function compare(a,b)
@@ -607,9 +714,10 @@ local function compare(a,b)
end
local function sortedkeys(tab)
- local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed
+ local srt, kind, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
for key,_ in next, tab do
- srt[#srt+1] = key
+ s = s + 1
+ srt[s] = key
if kind == 3 then
-- no further check
else
@@ -632,10 +740,11 @@ local function sortedkeys(tab)
end
local function sortedhashkeys(tab) -- fast one
- local srt = { }
+ local srt, s = { }, 0
for key,_ in next, tab do
if key then
- srt[#srt+1] = key
+ s= s + 1
+ srt[s] = key
end
end
sort(srt)
@@ -649,8 +758,7 @@ local function nothing() end
local function sortedhash(t)
if t then
- local s = sortedhashkeys(t) -- maybe just sortedkeys
- local n = 0
+ local n, s = 0, sortedkeys(t) -- the robust one
local function kv(s)
n = n + 1
local k = s[n]
@@ -666,20 +774,30 @@ table.sortedhash = sortedhash
table.sortedpairs = sortedhash
function table.append(t, list)
- for _,v in next, list do
- insert(t,v)
+ local n = #t
+ for i=1,#list do
+ n = n + 1
+ t[n] = list[i]
end
+ return t
end
function table.prepend(t, list)
- for k,v in next, list do
- insert(t,k,v)
+ 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, ...) -- first one is target
t = t or { }
- local lst = {...}
+ local lst = { ... }
for i=1,#lst do
for k, v in next, lst[i] do
t[k] = v
@@ -689,7 +807,7 @@ function table.merge(t, ...) -- first one is target
end
function table.merged(...)
- local tmp, lst = { }, {...}
+ local tmp, lst = { }, { ... }
for i=1,#lst do
for k, v in next, lst[i] do
tmp[k] = v
@@ -699,22 +817,24 @@ function table.merged(...)
end
function table.imerge(t, ...)
- local lst = {...}
+ local lst, nt = { ... }, #t
for i=1,#lst do
local nst = lst[i]
for j=1,#nst do
- t[#t+1] = nst[j]
+ nt = nt + 1
+ t[nt] = nst[j]
end
end
return t
end
function table.imerged(...)
- local tmp, lst = { }, {...}
+ local tmp, ntmp, lst = { }, 0, {...}
for i=1,#lst do
local nst = lst[i]
for j=1,#nst do
- tmp[#tmp+1] = nst[j]
+ ntmp = ntmp + 1
+ tmp[ntmp] = nst[j]
end
end
return tmp
@@ -790,11 +910,14 @@ function table.tohash(t,value)
end
function table.fromhash(t)
- local h = { }
+ local hsh, h = { }, 0
for k, v in next, t do -- no ipairs here
- if v then h[#h+1] = k end
+ if v then
+ h = h + 1
+ hsh[h] = k
+ end
end
- return h
+ return hsh
end
table.serialize_functions = true
@@ -815,20 +938,23 @@ local function simple_table(t)
n = n + 1
end
if n == #t then
- local tt = { }
+ local tt, nt = { }, 0
for i=1,#t do
local v = t[i]
local tv = type(v)
if tv == "number" then
+ nt = nt + 1
if hexify then
- tt[#tt+1] = format("0x%04X",v)
+ tt[nt] = format("0x%04X",v)
else
- tt[#tt+1] = tostring(v) -- tostring not needed
+ tt[nt] = tostring(v) -- tostring not needed
end
elseif tv == "boolean" then
- tt[#tt+1] = tostring(v)
+ nt = nt + 1
+ tt[nt] = tostring(v)
elseif tv == "string" then
- tt[#tt+1] = format("%q",v)
+ nt = nt + 1
+ tt[nt] = format("%q",v)
else
tt = nil
break
@@ -1123,10 +1249,11 @@ local function serialize(root,name,_handle,_reduce,_noquotes,_hexify)
end
-function table.serialize(root,name,reduce,noquotes,hexify)
- local t = { }
+function table.serialize(root,name,reduce,noquotes,hexify) -- can be faster if flush == false and t as argument
+ local t, n = { }, 0
local function flush(s)
- t[#t+1] = s
+ n = n + 1
+ t[n] = s
end
serialize(root,name,flush,reduce,noquotes,hexify)
return concat(t,"\n")
@@ -1152,12 +1279,13 @@ function table.tofile(filename,root,name,reduce,noquotes,hexify)
if f then
local maxtab = table.tofile_maxtab
if maxtab > 1 then
- local t = { }
+ local t, n = { }, 0
local function flush(s)
- t[#t+1] = s
- if #t > maxtab then
+ n = n + 1
+ t[n] = s
+ if n > maxtab then
f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
- t = { }
+ t, n = { }, 0 -- we could recycle t if needed
end
end
serialize(root,name,flush,reduce,noquotes,hexify)
@@ -1173,52 +1301,66 @@ function table.tofile(filename,root,name,reduce,noquotes,hexify)
end
end
-local function flatten(t,f,complete) -- is this used? meybe a variant with next, ...
- for i=1,#t do
- local v = t[i]
- if type(v) == "table" then
- if complete or type(v[1]) == "table" then
- flatten(v,f,complete)
+local function flattened(t,f,depth)
+ if f == nil then
+ f = { }
+ depth = 0xFFFF
+ elseif tonumber(f) then
+ -- assume then only two arguments are given
+ 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
+ f[k] = v
end
+ end
+ end
+ local n = #f
+ for k=1,#t do
+ local v = t[k]
+ if depth > 0 and type(v) == "table" then
+ flattened(v,f,depth-1)
+ n = #f
else
- f[#f+1] = v
+ n = n + 1
+ f[n] = v
end
end
-end
-
-function table.flatten(t)
- local f = { }
- flatten(t,f,true)
return f
end
-function table.unnest(t) -- bad name
- local f = { }
- flatten(t,f,false)
- return f
-end
-
-table.flattenonelevel = table.unnest
-
--- a better one:
+table.flattened = flattened
-local function flattened(t,f)
- if not f then
+local function unnest(t,f) -- only used in mk, for old times sake
+ if not f then -- and only relevant for token lists
f = { }
end
- for k, v in next, t do
+ for i=1,#t do
+ local v = t[i]
if type(v) == "table" then
- flattened(v,f)
+ if type(v[1]) == "table" then
+ unnest(v,f)
+ else
+ f[#f+1] = v
+ end
else
- f[k] = v
+ f[#f+1] = v
end
end
return f
end
-table.flattened = flattened
+function table.unnest(t) -- bad name
+ return unnest(t)
+end
+
+
local function are_equal(a,b,n,m) -- indexed
if a and b and #a == #b then
@@ -1244,7 +1386,7 @@ end
local function identical(a,b) -- assumes same structure
for ka, va in next, a do
- local vb = b[k]
+ local vb = b[ka]
if va == vb then
-- same
elseif type(va) == "table" and type(vb) == "table" then
@@ -1258,8 +1400,8 @@ local function identical(a,b) -- assumes same structure
return true
end
-table.are_equal = are_equal
table.identical = identical
+table.are_equal = are_equal
-- maybe also make a combined one
@@ -1285,14 +1427,14 @@ function table.contains(t, v)
end
function table.count(t)
- local n, e = 0, next(t)
- while e do
- n, e = n + 1, next(t,e)
+ local n = 0
+ for k, v in next, t do
+ n = n + 1
end
return n
end
-function table.swapped(t,s)
+function table.swapped(t,s) -- hash
local n = { }
if s then
for k, v in next, s do
@@ -1305,52 +1447,34 @@ function table.swapped(t,s)
return n
end
-
-function table.clone(t,p) -- t is optional or nil or table
- if not p then
- t, p = { }, t or { }
- elseif not t then
- t = { }
- end
- setmetatable(t, { __index = function(_,key) return p[key] end }) -- why not __index = p ?
- return t
-end
-
-function table.hexed(t,seperator)
- local tt = { }
- for i=1,#t do tt[i] = format("0x%04X",t[i]) end
- return concat(tt,seperator or " ")
-end
-
-function table.swaphash(h) -- needs another name
- local r = { }
- for k,v in next, h do
- r[v] = lower(gsub(k," ",""))
- end
- return r
-end
-
-function table.reverse(t)
- local tt = { }
- if #t > 0 then
- for i=#t,1,-1 do
- tt[#tt+1] = t[i]
+function table.reversed(t)
+ if t then
+ local tt, tn = { }, #t
+ if tn > 0 then
+ local ttn = 0
+ for i=tn,1,-1 do
+ ttn = ttn + 1
+ tt[ttn] = t[i]
+ end
end
+ return tt
end
- return tt
end
function table.sequenced(t,sep,simple) -- hash only
- local s = { }
+ local s, n = { }, 0
for k, v in sortedhash(t) do
if simple then
if v == true then
- s[#s+1] = k
+ n = n + 1
+ s[n] = k
elseif v and v~= "" then
- s[#s+1] = k .. "=" .. tostring(v)
+ n = n + 1
+ s[n] = k .. "=" .. tostring(v)
end
else
- s[#s+1] = k .. "=" .. tostring(v)
+ n = n + 1
+ s[n] = k .. "=" .. tostring(v)
end
end
return concat(s, sep or " | ")
@@ -1360,7 +1484,7 @@ function table.print(...)
table.tohandle(print,...)
end
--- -- -- obsolete but we keep them for a while and will comment them later -- -- --
+-- -- -- obsolete but we keep them for a while and might comment them later -- -- --
-- roughly: copy-loop : unpack : sub == 0.9 : 0.4 : 0.45 (so in critical apps, use unpack)
@@ -1375,14 +1499,7 @@ function table.is_empty(t)
end
function table.has_one_entry(t)
- local n = next(t)
- return n and not next(t,n)
-end
-
-function table.replace(a,b)
- for k,v in next, b do
- a[k] = v
- end
+ return t and not next(t,next(t))
end
@@ -1627,6 +1744,8 @@ if not modules then modules = { } end modules ['l-number'] = {
license = "see context related readme files"
}
+-- this module will be replaced when we have the bit library
+
local tostring = tostring
local format, floor, insert, match = string.format, math.floor, string.match
local concat, insert = table.concat, table.insert
@@ -1768,10 +1887,11 @@ function set.tolist(n)
if n == 0 or not tabs[n] then
return ""
else
- local t = { }
+ local t, n = { }, 0
for k, v in next, tabs[n] do
if v then
- t[#t+1] = k
+ n = n + 1
+ t[n] = k
end
end
return concat(t," ")
@@ -1950,7 +2070,7 @@ end
-- no need for function anymore as we have more clever code and helpers now
-- this metatable trickery might as well disappear
-os.resolvers = os.resolvers or { }
+os.resolvers = os.resolvers or { } -- will become private
local resolvers = os.resolvers
@@ -2279,7 +2399,7 @@ end
file.isreadable = file.is_readable -- depricated
file.iswritable = file.is_writable -- depricated
--- todo: lpeg
+-- todo: lpeg \\ / .. does not save much
local checkedsplit = string.checkedsplit
@@ -2295,7 +2415,7 @@ end
-- we can hash them weakly
-function file.collapse_path(str,anchor)
+function file.collapsepath(str,anchor)
if anchor and not find(str,"^/") and not find(str,"^%a:") then
str = getcurrentdir() .. "/" .. str
end
@@ -2350,6 +2470,8 @@ function file.collapse_path(str,anchor)
end
end
+file.collapse_path = file.collapsepath
+
function file.robustname(str)
return (gsub(str,"[^%a%d%/%-%.\\]+","-"))
@@ -2782,9 +2904,12 @@ local function glob(str,t)
end
return t
elseif isfile(str) then
- local t = t or { }
- t[#t+1] = str
- return t
+ if t then
+ t[#t+1] = str
+ return t
+ else
+ return { str }
+ end
else
local split = lpegmatch(pattern,str)
if split then
@@ -2812,6 +2937,7 @@ local function globfiles(path,recurse,func,files) -- func == pattern or function
func = function(name) return find(name,s) end
end
files = files or { }
+ local noffiles = #files
for name in walkdir(path) do
if find(name,"^%.") then
--- skip
@@ -2822,12 +2948,9 @@ local function globfiles(path,recurse,func,files) -- func == pattern or function
globfiles(path .. "/" .. name,recurse,func,files)
end
elseif mode == "file" then
- if func then
- if func(name) then
- files[#files+1] = path .. "/" .. name
- end
- else
- files[#files+1] = path .. "/" .. name
+ if not func or func(name) then
+ noffiles = noffiles + 1
+ files[noffiles] = path .. "/" .. name
end
end
end
@@ -3012,8 +3135,12 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
+-- function boolean.tonumber(b)
+-- return b and 1 or 0 -- test and test and return or return
+-- end
+
function boolean.tonumber(b)
- if b then return 1 else return 0 end
+ if b then return 1 else return 0 end -- test and return or return
end
function toboolean(str,tolerant)
@@ -3037,6 +3164,8 @@ function toboolean(str,tolerant)
end
end
+string.toboolean = toboolean
+
function string.is_boolean(str,default)
if type(str) == "string" then
if str == "true" or str == "yes" or str == "on" or str == "t" then
@@ -3048,14 +3177,6 @@ function string.is_boolean(str,default)
return default
end
-function boolean.alwaystrue()
- return true
-end
-
-function boolean.falsetrue()
- return false
-end
-
end -- of closure
@@ -3144,30 +3265,37 @@ function unicode.utftype(f)
end
function unicode.utf16_to_utf8(str, endian) -- maybe a gsub is faster or an lpeg
- local result, tmp, n, m, p = { }, { }, 0, 0, 0
+ local result, tmp, n, m, p, r, t = { }, { }, 0, 0, 0, 0, 0 -- we reuse tmp
-- lf | cr | crlf / (cr:13, lf:10)
local function doit()
if n == 10 then
if p ~= 13 then
- result[#result+1] = concat(tmp)
- tmp = { }
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
+ t = 0
+ end
p = 0
end
elseif n == 13 then
- result[#result+1] = concat(tmp)
- tmp = { }
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
+ t = 0
+ end
p = n
else
- tmp[#tmp+1] = utfchar(n)
+ t = t + 1
+ tmp[t] = utfchar(n)
p = 0
end
end
for l,r in bytepairs(str) do
if r then
if endian then
- n = l*256 + r
+ n = 256*l + r
else
- n = r*256 + l
+ n = 256*r + l
end
if m > 0 then
n = (m-0xD800)*0x400 + (n-0xDC00) + 0x10000
@@ -3180,29 +3308,36 @@ function unicode.utf16_to_utf8(str, endian) -- maybe a gsub is faster or an lpeg
end
end
end
- if #tmp > 0 then
- result[#result+1] = concat(tmp)
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
end
return result
end
function unicode.utf32_to_utf8(str, endian)
- local result = { }
- local tmp, n, m, p = { }, 0, -1, 0
+ local result, tmp, n, m, p, r, t = { }, { }, 0, -1, 0, 0, 0
-- lf | cr | crlf / (cr:13, lf:10)
local function doit()
if n == 10 then
if p ~= 13 then
- result[#result+1] = concat(tmp)
- tmp = { }
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
+ t = 0
+ end
p = 0
end
elseif n == 13 then
- result[#result+1] = concat(tmp)
- tmp = { }
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
+ t = 0
+ end
p = n
else
- tmp[#tmp+1] = utfchar(n)
+ t = t + 1
+ tmp[t] = utfchar(n)
p = 0
end
end
@@ -3210,15 +3345,15 @@ function unicode.utf32_to_utf8(str, endian)
if a and b then
if m < 0 then
if endian then
- m = a*256*256*256 + b*256*256
+ m = 256*256*256*a + 256*256*b
else
- m = b*256 + a
+ m = 256*b + a
end
else
if endian then
- n = m + a*256 + b
+ n = m + 256*a + b
else
- n = m + b*256*256*256 + a*256*256
+ n = m + 256*256*256*b + 256*256*a
end
m = -1
doit()
@@ -3228,13 +3363,14 @@ function unicode.utf32_to_utf8(str, endian)
end
end
if #tmp > 0 then
- result[#result+1] = concat(tmp)
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
end
return result
end
local function little(c)
- local b = byte(c) -- b = c:byte()
+ local b = byte(c)
if b < 0x10000 then
return char(b%256,b/256)
else
@@ -3264,9 +3400,10 @@ function unicode.utf8_to_utf16(str,littleendian)
end
function unicode.utfcodes(str)
- local t = { }
- for k,v in utfvalues(str) do
- t[#t+1] = format("0x%04X",k)
+ local t, n = { }, 0
+ for u in utfvalues(str) do
+ n = n + 1
+ t[n] = format("0x%04X",u)
end
return concat(t,separator or " ")
end
@@ -3324,6 +3461,189 @@ end -- of closure
do -- create closure to overcome 200 locals limit
+if not modules then modules = { } end modules ['util-tab'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+utilities = utilities or {}
+utilities.tables = utilities.tables or { }
+local tables = utilities.tables
+
+local format, gmatch = string.format, string.gmatch
+local concat, insert, remove = table.concat, table.insert, table.remove
+local setmetatable = setmetatable
+
+function tables.definetable(target) -- defines undefined tables
+ local composed, t, n = nil, { }, 0
+ for name in gmatch(target,"([^%.]+)") do
+ n = n + 1
+ if composed then
+ composed = composed .. "." .. name
+ else
+ composed = name
+ end
+ t[n] = format("%s = %s or { }",composed,composed)
+ end
+ return concat(t,"\n")
+end
+
+function tables.accesstable(target)
+ local t = _G
+ for name in gmatch(target,"([^%.]+)") do
+ t = t[name]
+ end
+ return t
+end
+
+function tables.removevalue(t,value) -- todo: n
+ if value then
+ for i=1,#t do
+ if t[i] == value then
+ remove(t,i)
+ -- remove all, so no: return
+ end
+ end
+ end
+end
+
+function tables.insertbeforevalue(t,value,extra)
+ for i=1,#t do
+ if t[i] == extra then
+ remove(t,i)
+ end
+ end
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i,extra)
+ return
+ end
+ end
+ insert(t,1,extra)
+end
+
+function tables.insertaftervalue(t,value,extra)
+ for i=1,#t do
+ if t[i] == extra then
+ remove(t,i)
+ end
+ end
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i+1,extra)
+ return
+ end
+ end
+ insert(t,#t+1,extra)
+end
+
+local _empty_table_ = { __index = function(t,k) return "" end }
+
+function table.setemptymetatable(t)
+ setmetatable(t,_empty_table_)
+end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['util-sto'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local setmetatable, getmetatable = setmetatable, getmetatable
+
+utilities = utilities or { }
+utilities.storage = utilities.storage or { }
+local storage = utilities.storage
+
+function storage.mark(t)
+ if not t then
+ texio.write_nl("fatal error: storage '%s' cannot be marked",t)
+ os.exit()
+ end
+ local m = getmetatable(t)
+ if not m then
+ m = { }
+ setmetatable(t,m)
+ end
+ m.__storage__ = true
+ return t
+end
+
+function storage.allocate(t)
+ t = t or { }
+ local m = getmetatable(t)
+ if not m then
+ m = { }
+ setmetatable(t,m)
+ end
+ m.__storage__ = true
+ return t
+end
+
+function storage.marked(t)
+ local m = getmetatable(t)
+ return m and m.__storage__
+end
+
+function storage.checked(t)
+ if not t then
+ texio.write_nl("fatal error: storage '%s' has not been allocated",t)
+ os.exit()
+ end
+ return t
+end
+
+function setmetatablekey(t,key,value)
+ local m = getmetatable(t)
+ if not m then
+ m = { }
+ setmetatable(t,m)
+ end
+ m[key] = value
+end
+
+function getmetatablekey(t,key,value)
+ local m = getmetatable(t)
+ return m and m[key]
+end
+
+
+function storage.setinitializer(data,initialize)
+ local m = getmetatable(data) or { }
+ m.__index = function(data,k)
+ m.__index = nil -- so that we can access the entries during initializing
+ initialize()
+ return data[k]
+ end
+ setmetatable(data, m)
+end
+
+local keyisvalue = { __index = function(t,k)
+ t[k] = k
+ return k
+end }
+
+function storage.sparse(t)
+ t = t or { }
+ setmetatable(t,keyisvalue)
+ return t
+end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
if not modules then modules = { } end modules ['util-mrg'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -3483,7 +3803,7 @@ utilities.report = utilities.report or print
function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
- local command = "-o " .. string.quote(lucfile) .. " " .. string.quote(luafile)
+ local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
@@ -3496,6 +3816,12 @@ function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: clean
end
+
+
+
+
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3516,7 +3842,7 @@ parsers.patterns = parsers.patterns or { }
local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
local lpegmatch = lpeg.match
local concat, format, gmatch = table.concat, string.format, string.gmatch
-local tostring, type, next = tostring, type, next
+local tostring, type, next, setmetatable = tostring, type, next, setmetatable
local sortedhash = table.sortedhash
local escape, left, right = P("\\"), P('{'), P('}')
@@ -3635,7 +3961,7 @@ end
function parsers.hash_to_string(h,separator,yes,no,strict,omit)
if h then
- local t, s = { }, table.sortedkeys(h)
+ local t, tn, s = { }, 0, table.sortedkeys(h)
omit = omit and table.tohash(omit)
for i=1,#s do
local key = s[i]
@@ -3644,15 +3970,19 @@ function parsers.hash_to_string(h,separator,yes,no,strict,omit)
if type(value) == "boolean" then
if yes and no then
if value then
- t[#t+1] = key .. '=' .. yes
+ tn = tn + 1
+ t[tn] = key .. '=' .. yes
elseif not strict then
- t[#t+1] = key .. '=' .. no
+ tn = tn + 1
+ t[tn] = key .. '=' .. no
end
elseif value or not strict then
- t[#t+1] = key .. '=' .. tostring(value)
+ tn = tn + 1
+ t[tn] = key .. '=' .. tostring(value)
end
else
- t[#t+1] = key .. '=' .. value
+ tn = tn + 1
+ t[tn] = key .. '=' .. value
end
end
end
@@ -3679,10 +4009,11 @@ function parsers.settings_to_set(str,t) -- tohash? -- todo: lpeg -- duplicate an
end
function parsers.simple_hash_to_string(h, separator)
- local t = { }
+ local t, tn = { }, 0
for k, v in sortedhash(h) do
if v then
- t[#t+1] = k
+ tn = tn + 1
+ t[tn] = k
end
end
return concat(t,separator or ",")
@@ -3700,99 +4031,18 @@ end
function parsers.getparameters(self,class,parentclass,settings)
local sc = self[class]
if not sc then
- sc = table.clone(self[parent])
+ sc = { }
self[class] = sc
- end
- parsers.settings_to_hash(settings,sc)
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util-tab'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-utilities = utilities or {}
-utilities.tables = utilities.tables or { }
-local tables = utilities.tables
-
-local format, gmatch = string.format, string.gmatch
-local concat, insert, remove = table.concat, table.insert, table.remove
-local setmetatable = setmetatable
-
-function tables.definetable(target) -- defines undefined tables
- local composed, t = nil, { }
- for name in gmatch(target,"([^%.]+)") do
- if composed then
- composed = composed .. "." .. name
- else
- composed = name
- end
- t[#t+1] = format("%s = %s or { }",composed,composed)
- end
- return concat(t,"\n")
-end
-
-function tables.accesstable(target)
- local t = _G
- for name in gmatch(target,"([^%.]+)") do
- t = t[name]
- end
- return t
-end
-
-function table.removevalue(t,value) -- todo: n
- if value then
- for i=1,#t do
- if t[i] == value then
- remove(t,i)
- -- remove all, so no: return
+ if parentclass then
+ local sp = self[parentclass]
+ if not sp then
+ sp = { }
+ self[parentclass] = sp
end
+ setmetatable(sc, { __index = sp })
end
end
-end
-
-function table.insertbeforevalue(t,value,extra)
- for i=1,#t do
- if t[i] == extra then
- remove(t,i)
- end
- end
- for i=1,#t do
- if t[i] == value then
- insert(t,i,extra)
- return
- end
- end
- insert(t,1,extra)
-end
-
-function table.insertaftervalue(t,value,extra)
- for i=1,#t do
- if t[i] == extra then
- remove(t,i)
- end
- end
- for i=1,#t do
- if t[i] == value then
- insert(t,i+1,extra)
- return
- end
- end
- insert(t,#t+1,extra)
-end
-
-local _empty_table_ = { __index = function(t,k) return "" end }
-
-function table.setemptymetatable(t)
- setmetatable(t,_empty_table_)
+ parsers.settings_to_hash(settings,sc)
end
@@ -3831,9 +4081,9 @@ local number = digit^1 * (case_1 + case_2)
local stripper = Cs((number + 1)^0)
-lpeg.patterns.strip_zeros = stripper
+lpeg.patterns.stripzeros = stripper
-function formatters.strip_zeros(str)
+function formatters.stripzeros(str)
return lpegmatch(stripper,str)
end
@@ -4005,88 +4255,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['util-sto'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local setmetatable, getmetatable = setmetatable, getmetatable
-
-utilities = utilities or { }
-utilities.storage = utilities.storage or { }
-local storage = utilities.storage
-
-function storage.mark(t)
- if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
- end
- local m = getmetatable(t)
- if not m then
- m = { }
- setmetatable(t,m)
- end
- m.__storage__ = true
- return t
-end
-
-function storage.allocate(t)
- t = t or { }
- local m = getmetatable(t)
- if not m then
- m = { }
- setmetatable(t,m)
- end
- m.__storage__ = true
- return t
-end
-
-function storage.marked(t)
- local m = getmetatable(t)
- return m and m.__storage__
-end
-
-function storage.checked(t)
- if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
- end
- return t
-end
-
-function setmetatablekey(t,key,value)
- local m = getmetatable(t)
- if not m then
- m = { }
- setmetatable(t,m)
- end
- m[key] = value
-end
-
-function getmetatablekey(t,key,value)
- local m = getmetatable(t)
- return m and m[key]
-end
-
-
-function storage.setinitializer(data,initialize)
- local m = getmetatable(data) or { }
- m.__index = function(data,k)
- m.__index = nil -- so that we can access the entries during initializing
- initialize()
- return data[k]
- end
- setmetatable(data, m)
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['trac-inf'] = {
version = 1.001,
comment = "companion to trac-inf.mkiv",
@@ -4102,6 +4270,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
local format = string.format
local clock = os.gettimeofday or os.clock -- should go in environment
+local write_nl = texio.write_nl
statistics = statistics or { }
local statistics = statistics
@@ -4197,7 +4366,7 @@ end
function statistics.show(reporter)
if statistics.enable then
- if not reporter then reporter = function(tag,data,n) texio.write_nl(tag .. " " .. data) end end
+ if not reporter then reporter = function(tag,data,n) write_nl(tag .. " " .. data) end end
-- this code will move
local register = statistics.register
register("luatex banner", function()
@@ -4220,18 +4389,24 @@ function statistics.show(reporter)
reporter(s[1],r,n)
end
end
- texio.write_nl("") -- final newline
+ write_nl("") -- final newline
statistics.enable = false
end
end
+
+local template, nn = nil, 0 -- we only calcute it once
+
function statistics.showjobstat(tag,data,n)
if type(data) == "table" then
for i=1,#data do
statistics.showjobstat(tag,data[i],n)
end
else
- texio.write_nl(format("%-15s: %s - %s","mkiv lua stats",tag:rpadd(n," "),data))
+ if not template or n > nn then
+ template, n = format("%%-%ss: %%-%ss - %%s",15,n), nn
+ end
+ write_nl(format(template,"mkiv lua stats",tag,data))
end
end
@@ -4288,7 +4463,7 @@ if not modules then modules = { } end modules ['trac-set'] = { -- might become u
local type, next, tostring = type, next, tostring
local concat = table.concat
-local format, find, lower, gsub, partialescapedpattern = string.format, string.find, string.lower, string.gsub, string.partialescapedpattern
+local format, find, lower, gsub, escapedpattern = string.format, string.find, string.lower, string.gsub, string.escapedpattern
local is_boolean = string.is_boolean
local settings_to_hash = utilities.parsers.settings_to_hash
local allocate = utilities.storage.allocate
@@ -4368,7 +4543,7 @@ local function set(t,what,newvalue)
for name, functions in next, data do
if done[name] then
-- prevent recursion due to wildcards
- elseif find(name,partialescapedpattern(w)) then
+ elseif find(name,escapedpattern(w,true)) then
done[name] = true
for i=1,#functions do
functions[i](value)
@@ -5151,7 +5326,7 @@ local report_resolvers = logs.new("resolvers")
local allocate, mark = utilities.storage.allocate, utilities.storage.mark
local format, sub, match, gsub, find = string.format, string.sub, string.match, string.gsub, string.find
-local unquote, quote = string.unquote, string.quote
+local unquoted, quoted = string.unquoted, string.quoted
local concat = table.concat
-- precautions
@@ -5219,7 +5394,7 @@ function environment.initializearguments(arg)
if index > 0 then
local flag, value = match(argument,"^%-+(.-)=(.-)$")
if flag then
- arguments[flag] = unquote(value or "")
+ arguments[flag] = unquoted(value or "")
else
flag = match(argument,"^%-+(.+)")
if flag then
@@ -5284,19 +5459,21 @@ end
function environment.reconstructcommandline(arg,noquote)
arg = arg or environment.originalarguments
if noquote and #arg == 1 then
+ -- we could just do: return unquoted(resolvers.resolve(arg[i]))
local a = arg[1]
a = resolvers.resolve(a)
- a = unquote(a)
+ a = unquoted(a)
return a
elseif #arg > 0 then
local result = { }
for i=1,#arg do
+ -- we could just do: result[#result+1] = format("%q",unquoted(resolvers.resolve(arg[i])))
local a = arg[i]
a = resolvers.resolve(a)
- a = unquote(a)
+ a = unquoted(a)
a = gsub(a,'"','\\"') -- tricky
if find(a," ") then
- result[#result+1] = quote(a)
+ result[#result+1] = quoted(a)
else
result[#result+1] = a
end
@@ -5307,6 +5484,7 @@ function environment.reconstructcommandline(arg,noquote)
end
end
+
if arg then
-- new, reconstruct quoted snippets (maybe better just remove the " then and add them later)
@@ -6767,7 +6945,7 @@ apply_axis['root'] = function(list)
rt = ll
end
end
- collected[#collected+1] = rt
+ collected[l] = rt
end
return collected
end
@@ -6777,7 +6955,7 @@ apply_axis['self'] = function(list)
end
apply_axis['child'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
local dt = ll.dt
@@ -6786,7 +6964,8 @@ apply_axis['child'] = function(list)
for k=1,#dt do
local dk = dt[k]
if dk.tg then
- collected[#collected+1] = dk
+ c = c + 1
+ collected[c] = dk
dk.ni = k -- refresh
en = en + 1
dk.ei = en
@@ -6798,68 +6977,74 @@ apply_axis['child'] = function(list)
return collected
end
-local function collect(list,collected)
+local function collect(list,collected,c)
local dt = list.dt
if dt then
local en = 0
for k=1,#dt do
local dk = dt[k]
if dk.tg then
- collected[#collected+1] = dk
+ c = c + 1
+ collected[c] = dk
dk.ni = k -- refresh
en = en + 1
dk.ei = en
- collect(dk,collected)
+ c = collect(dk,collected,c)
end
end
list.en = en
end
+ return c
end
apply_axis['descendant'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
- collect(list[l],collected)
+ c = collect(list[l],collected,c)
end
return collected
end
-local function collect(list,collected)
+local function collect(list,collected,c)
local dt = list.dt
if dt then
local en = 0
for k=1,#dt do
local dk = dt[k]
if dk.tg then
- collected[#collected+1] = dk
+ c = c + 1
+ collected[c] = dk
dk.ni = k -- refresh
en = en + 1
dk.ei = en
- collect(dk,collected)
+ c = collect(dk,collected,c)
end
end
list.en = en
end
+ return c
end
apply_axis['descendant-or-self'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
if ll.special ~= true then -- catch double root
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
end
- collect(ll,collected)
+ c = collect(ll,collected,c)
end
return collected
end
apply_axis['ancestor'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
while ll do
ll = ll.__p__
if ll then
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
end
end
end
@@ -6867,14 +7052,16 @@ apply_axis['ancestor'] = function(list)
end
apply_axis['ancestor-or-self'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
while ll do
ll = ll.__p__
if ll then
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
end
end
end
@@ -6882,11 +7069,12 @@ apply_axis['ancestor-or-self'] = function(list)
end
apply_axis['parent'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local pl = list[l].__p__
if pl then
- collected[#collected+1] = pl
+ c = c + 1
+ collected[c] = pl
end
end
return collected
@@ -6909,7 +7097,7 @@ apply_axis['preceding'] = function(list) -- incomplete
end
apply_axis['following-sibling'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
local p = ll.__p__
@@ -6917,7 +7105,8 @@ apply_axis['following-sibling'] = function(list)
for i=ll.ni+1,#d do
local di = d[i]
if type(di) == "table" then
- collected[#collected+1] = di
+ c = c + 1
+ collected[c] = di
end
end
end
@@ -6925,7 +7114,7 @@ apply_axis['following-sibling'] = function(list)
end
apply_axis['preceding-sibling'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
local p = ll.__p__
@@ -6933,7 +7122,8 @@ apply_axis['preceding-sibling'] = function(list)
for i=1,ll.ni-1 do
local di = d[i]
if type(di) == "table" then
- collected[#collected+1] = di
+ c = c + 1
+ collected[c] = di
end
end
end
@@ -6941,7 +7131,7 @@ apply_axis['preceding-sibling'] = function(list)
end
apply_axis['reverse-sibling'] = function(list) -- reverse preceding
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
local p = ll.__p__
@@ -6949,7 +7139,8 @@ apply_axis['reverse-sibling'] = function(list) -- reverse preceding
for i=ll.ni-1,1,-1 do
local di = d[i]
if type(di) == "table" then
- collected[#collected+1] = di
+ c = c + 1
+ collected[c] = di
end
end
end
@@ -6975,7 +7166,7 @@ local function apply_nodes(list,directive,nodes)
return { }
end
else
- local collected, m, p = { }, 0, nil
+ local collected, c, m, p = { }, 0, 0, nil
if not nns then -- only check tag
for l=1,#list do
local ll = list[l]
@@ -6984,11 +7175,13 @@ local function apply_nodes(list,directive,nodes)
if directive then
if ntg == ltg then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
elseif ntg ~= ltg then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
end
end
@@ -7000,11 +7193,13 @@ local function apply_nodes(list,directive,nodes)
if directive then
if lns == nns then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
elseif lns ~= nns then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
end
end
@@ -7018,11 +7213,13 @@ local function apply_nodes(list,directive,nodes)
if directive then
if ok then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
elseif not ok then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
end
end
@@ -7030,7 +7227,7 @@ local function apply_nodes(list,directive,nodes)
return collected
end
else
- local collected, m, p = { }, 0, nil
+ local collected, c, m, p = { }, 0, 0, nil
for l=1,#list do
local ll = list[l]
local ltg = ll.tg
@@ -7047,11 +7244,13 @@ local function apply_nodes(list,directive,nodes)
if directive then
if ok then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
elseif not ok then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
end
end
@@ -7062,12 +7261,13 @@ end
local quit_expression = false
local function apply_expression(list,expression,order)
- local collected = { }
+ local collected, c = { }, 0
quit_expression = false
for l=1,#list do
local ll = list[l]
if expression(list,ll,l,order) then -- nasty, order alleen valid als n=1
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
end
if quit_expression then
break
@@ -7363,7 +7563,7 @@ local function nodesettostring(set,nodetest)
if not ns or ns == "" then ns = "*" end
if not tg or tg == "" then tg = "*" end
tg = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
- t[#t+1] = (directive and tg) or format("not(%s)",tg)
+ t[i] = (directive and tg) or format("not(%s)",tg)
end
if nodetest == false then
return format("not(%s)",concat(t,"|"))
@@ -7382,7 +7582,7 @@ local function tagstostring(list)
local ns, tg = li.ns, li.tg
if not ns or ns == "" then ns = "*" end
if not tg or tg == "" then tg = "*" end
- t[#t+1] = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
+ t[i] = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
end
return concat(t," ")
end
@@ -8102,16 +8302,17 @@ end
function xml.collect_tags(root, pattern, nonamespace)
local collected = xmlapplylpath(root,pattern)
if collected then
- local t = { }
+ local t, n = { }, 0
for c=1,#collected do
local e = collected[c]
local ns, tg = e.ns, e.tg
+ n = n + 1
if nonamespace then
- t[#t+1] = tg
+ t[n] = tg
elseif ns == "" then
- t[#t+1] = tg
+ t[n] = tg
else
- t[#t+1] = ns .. ":" .. tg
+ t[n] = ns .. ":" .. tg
end
end
return t
@@ -8219,8 +8420,10 @@ local function inject_element(root,pattern,whatever,prepend)
else
be, af = edt, cp
end
+ local bn = #be
for i=1,#af do
- be[#be+1] = af[i]
+ bn = bn + 1
+ be[bn] = af[i]
end
if rri then
r.dt[rri].dt = be
@@ -8305,11 +8508,12 @@ local function stripelement(e,nolines,anywhere)
local edt = e.dt
if edt then
if anywhere then
- local t = { }
+ local t, n = { }, 0
for e=1,#edt do
local str = edt[e]
if type(str) ~= "string" then
- t[#t+1] = str
+ n = n + 1
+ t[n] = str
elseif str ~= "" then
-- todo: lpeg for each case
if nolines then
@@ -8317,7 +8521,8 @@ local function stripelement(e,nolines,anywhere)
end
str = gsub(str,"^%s*(.-)%s*$","%1")
if str ~= "" then
- t[#t+1] = str
+ n = n + 1
+ t[n] = str
end
end
end
@@ -8344,9 +8549,10 @@ local function stripelement(e,nolines,anywhere)
end
end
end
- if #edt > 0 then
+ local nedt = #nedt
+ if nedt > 0 then
-- strip end
- local str = edt[#edt]
+ local str = edt[nedt]
if type(str) ~= "string" then
-- nothing
elseif str == "" then
@@ -8359,7 +8565,7 @@ local function stripelement(e,nolines,anywhere)
if str == "" then
remove(edt)
else
- edt[#edt] = str
+ edt[nedt] = str
end
end
end
@@ -8506,15 +8712,8 @@ local function all(collected)
return collected
end
-local function reverse(collected)
- if collected then
- local reversed = { }
- for c=#collected,1,-1 do
- reversed[#reversed+1] = collected[c]
- end
- return reversed
- end
-end
+
+local reverse = table.reversed
local function attribute(collected,name)
if collected and #collected > 0 then
@@ -8605,11 +8804,12 @@ end
local function texts(collected)
if collected then
- local t = { }
+ local t, n = { }, 0
for c=1,#collected do
local e = collection[c]
if e and e.dt then
- t[#t+1] = e.dt
+ n = n + 1
+ t[n] = e.dt
end
end
return t
@@ -8652,14 +8852,15 @@ end
local function tags(collected,nonamespace)
if collected then
- local t = { }
+ local t, n = { }, 0
for c=1,#collected do
local e = collected[c]
local ns, tg = e.ns, e.tg
+ n = n + 1
if nonamespace or ns == "" then
- t[#t+1] = tg
+ t[n] = tg
else
- t[#t+1] = ns .. ":" .. tg
+ t[n] = ns .. ":" .. tg
end
end
return t
@@ -8855,9 +9056,13 @@ end
do
- local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or '~'
+ local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
+
+ if not homedir or homedir == "" then
+ homedir = string.char(127) -- we need a value, later we wil trigger on it
+ end
- homedir = file.collapse_path(homedir)
+ homedir = file.collapsepath(homedir)
ossetenv("HOME", homedir) -- can be used in unix cnf files
ossetenv("USERPROFILE",homedir) -- can be used in windows cnf files
@@ -8876,8 +9081,8 @@ do
local ownbin = environment.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex"
local ownpath = environment.ownpath or os.selfdir
- ownbin = file.collapse_path(ownbin)
- ownpath = file.collapse_path(ownpath)
+ ownbin = file.collapsepath(ownbin)
+ ownpath = file.collapsepath(ownpath)
if not ownpath or ownpath == "" or ownpath == "unset" then
ownpath = args[-1] or arg[-1]
@@ -8949,9 +9154,9 @@ do
local ownpath = environment.ownpath or dir.current()
if ownpath then
- ossetenv('SELFAUTOLOC', file.collapse_path(ownpath))
- ossetenv('SELFAUTODIR', file.collapse_path(ownpath .. "/.."))
- ossetenv('SELFAUTOPARENT', file.collapse_path(ownpath .. "/../.."))
+ ossetenv('SELFAUTOLOC', file.collapsepath(ownpath))
+ ossetenv('SELFAUTODIR', file.collapsepath(ownpath .. "/.."))
+ ossetenv('SELFAUTOPARENT', file.collapsepath(ownpath .. "/../.."))
else
report_resolvers("error: unable to locate ownpath")
os.exit()
@@ -8987,7 +9192,7 @@ if not texroot or texroot == "" then
ossetenv('TEXROOT',texroot)
end
-environment.texroot = file.collapse_path(texroot)
+environment.texroot = file.collapsepath(texroot)
-- Tracing. Todo ...
@@ -9026,7 +9231,7 @@ local lpegCt, lpegCs, lpegP, lpegC, lpegS = lpeg.Ct, lpeg.Cs, lpeg.P, lpeg.C, lp
local type, next = type, next
local ostype = os.type
-local collapse_path = file.collapse_path
+local collapsepath = file.collapsepath
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
local trace_expansions = false trackers.register("resolvers.expansions", function(v) trace_expansions = v end)
@@ -9062,22 +9267,29 @@ local resolvers = resolvers
local dummy_path_expr = "^!*unset/*$"
local function do_first(a,b)
- local t = { }
- for s in gmatch(b,"[^,]+") do t[#t+1] = a .. s end
+ local t, n = { }, 0
+ for s in gmatch(b,"[^,]+") do
+ n = n + 1
+ t[n] = a .. s
+ end
return "{" .. concat(t,",") .. "}"
end
local function do_second(a,b)
- local t = { }
- for s in gmatch(a,"[^,]+") do t[#t+1] = s .. b end
+ local t, n = { }, 0
+ for s in gmatch(a,"[^,]+") do
+ n = n + 1
+ t[n] = s .. b
+ end
return "{" .. concat(t,",") .. "}"
end
local function do_both(a,b)
- local t = { }
+ local t, n = { }, 0
for sa in gmatch(a,"[^,]+") do
for sb in gmatch(b,"[^,]+") do
- t[#t+1] = sa .. sb
+ n = n + 1
+ t[n] = sa .. sb
end
end
return "{" .. concat(t,",") .. "}"
@@ -9101,6 +9313,7 @@ local function splitpathexpr(str, newlist, validate)
report_resolvers("expanding variable '%s'",str)
end
local t, ok, done = newlist or { }, false, false
+ local n = #t
str = lpegmatch(replacer_1,str)
while true do
done = false
@@ -9124,11 +9337,15 @@ local function splitpathexpr(str, newlist, validate)
if validate then
for s in gmatch(str,"[^,]+") do
s = validate(s)
- if s then t[#t+1] = s end
+ if s then
+ n = n + 1
+ t[n] = s
+ end
end
else
for s in gmatch(str,"[^,]+") do
- t[#t+1] = s
+ n = n + 1
+ t[n] = s
end
end
if trace_expansions then
@@ -9141,7 +9358,7 @@ end
local function validate(s)
local isrecursive = find(s,"//$")
- s = collapse_path(s)
+ s = collapsepath(s)
if isrecursive then
s = s .. "//"
end
@@ -9164,10 +9381,14 @@ function resolvers.expandedpathfromlist(pathlist) -- maybe not a list, just a pa
splitpathexpr(pathlist[k],newlist,validate)
end
else
+ local n = 0
for k=1,#pathlist do
for p in gmatch(pathlist[k],"([^,]+)") do
p = validate(p)
- if p ~= "" then newlist[#newlist+1] = p end
+ if p ~= "" then
+ n = n + 1
+ newlist[n] = p
+ end
end
end
end
@@ -9176,16 +9397,42 @@ end
-- We also put some cleanup code here.
-local cleanup -- used recursively
-cleanup = lpeg.replacer {
- { "!", "" },
- { "\\", "/" },
- { "~" , function() return lpegmatch(cleanup,environment.homedir) end },
+
+
+local cleanup = lpeg.replacer {
+ { "!" , "" },
+ { "\\" , "/" },
}
+local homedir
+
function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+ if not homedir then
+ homedir = lpegmatch(cleanup,environment.homedir or "")
+ if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_resolvers("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if find(str,"~") then
+ return "" -- special case
+ else
+ return str and lpegmatch(cleanup,str)
+ end
+ end
+ else
+ cleanup = lpeg.replacer {
+ { "!" , "" },
+ { "\\" , "/" },
+ { "~" , homedir },
+ }
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str)
+ end
+ end
+ end
+ return resolvers.cleanpath(str)
end
-- This one strips quotes and funny tokens.
@@ -9211,7 +9458,6 @@ end
-- we join them and split them after the expansion has taken place. This
-- is more convenient.
-
local cache = { }
local splitter = lpegCt(lpeg.splitat(lpegS(ostype == "windows" and ";" or ":;"))) -- maybe add ,
@@ -9226,15 +9472,17 @@ local function splitconfigurationpath(str) -- beware, this can be either a path
str = gsub(str,"\\","/")
local split = lpegmatch(splitter,str)
found = { }
+ local noffound = 0
for i=1,#split do
local s = split[i]
if not find(s,"^{*unset}*") then
- found[#found+1] = s
+ noffound = noffound + 1
+ found[noffound] = s
end
end
if trace_expansions then
report_resolvers("splitting path specification '%s'",str)
- for k=1,#found do
+ for k=1,noffound do
report_resolvers("% 4i: %s",k,found[k])
end
end
@@ -9357,7 +9605,6 @@ formats['enc'] = 'ENCFONTS' suffixes['enc'] = { 'enc' }
formats['fmt'] = 'TEXFORMATS' suffixes['fmt'] = { 'fmt' }
formats['map'] = 'TEXFONTMAPS' suffixes['map'] = { 'map' }
formats['mp'] = 'MPINPUTS' suffixes['mp'] = { 'mp' }
-formats['ocp'] = 'OCPINPUTS' suffixes['ocp'] = { 'ocp' }
formats['ofm'] = 'OFMFONTS' suffixes['ofm'] = { 'ofm', 'tfm' }
formats['otf'] = 'OPENTYPEFONTS' suffixes['otf'] = { 'otf' }
formats['opl'] = 'OPLFONTS' suffixes['opl'] = { 'opl' }
@@ -9582,7 +9829,7 @@ local function identify()
local cachepath = texmfcaches[k]
if cachepath ~= "" then
cachepath = resolvers.cleanpath(cachepath)
- cachepath = file.collapse_path(cachepath)
+ cachepath = file.collapsepath(cachepath)
local valid = isdir(cachepath)
if valid then
if file.is_readable(cachepath) then
@@ -9921,7 +10168,7 @@ function resolvers.splitmethod(filename)
end
function resolvers.methodhandler(what, filename, filetype) -- ...
- filename = file.collapse_path(filename)
+ filename = file.collapsepath(filename)
local specification = (type(filename) == "string" and resolvers.splitmethod(filename)) or filename -- no or { }, let it bomb
local scheme = specification.scheme
local resolver = resolvers[what]
@@ -9966,7 +10213,7 @@ local lpegP, lpegS, lpegR, lpegC, lpegCc, lpegCs, lpegCt = lpeg.P, lpeg.S, lpeg.
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local filedirname, filebasename, fileextname, filejoin = file.dirname, file.basename, file.extname, file.join
-local collapse_path = file.collapse_path
+local collapsepath = file.collapsepath
local allocate = utilities.storage.allocate
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10169,7 +10416,7 @@ local function identify_configuration_files()
expandvars(cnfpaths) --- hm
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
- local filename = collapse_path(filejoin(cnfpaths[i],luacnfname))
+ local filename = collapsepath(filejoin(cnfpaths[i],luacnfname))
if lfs.isfile(filename) then
specification[#specification+1] = filename
end
@@ -10330,7 +10577,7 @@ local function locate_file_databases()
-- todo: cache:// and tree:// (runtime)
local texmfpaths = resolvers.expandedpathlist('TEXMF')
for i=1,#texmfpaths do
- local path = collapse_path(texmfpaths[i])
+ local path = collapsepath(texmfpaths[i])
local stripped = gsub(path,"^!!","")
local runtime = stripped == path
path = resolvers.cleanpath(path)
@@ -10443,11 +10690,12 @@ end
function resolvers.splitexpansions()
local ie = instance.expansions
for k,v in next, ie do
- local t, h, p = { }, { }, splitconfigurationpath(v)
+ local t, tn, h, p = { }, 0, { }, splitconfigurationpath(v)
for kk=1,#p do
local vv = p[kk]
if vv ~= "" and not h[vv] then
- t[#t+1] = vv
+ tn = tn + 1
+ t[tn] = vv
h[vv] = true
end
end
@@ -10554,7 +10802,8 @@ end
function resolvers.registerextrapath(paths,subpaths)
local ep = instance.extra_paths or { }
- local n = #ep
+ local oldn = #ep
+ local newn = oldn
if paths and paths ~= "" then
if subpaths and subpaths ~= "" then
for p in gmatch(paths,"[^,]+") do
@@ -10562,7 +10811,8 @@ function resolvers.registerextrapath(paths,subpaths)
for s in gmatch(subpaths,"[^,]+") do
local ps = p .. "/" .. s
if not done[ps] then
- ep[#ep+1] = resolvers.cleanpath(ps)
+ newn = newn + 1
+ ep[newn] = resolvers.cleanpath(ps)
done[ps] = true
end
end
@@ -10570,7 +10820,8 @@ function resolvers.registerextrapath(paths,subpaths)
else
for p in gmatch(paths,"[^,]+") do
if not done[p] then
- ep[#ep+1] = resolvers.cleanpath(p)
+ newn = newn + 1
+ ep[newn] = resolvers.cleanpath(p)
done[p] = true
end
end
@@ -10581,16 +10832,17 @@ function resolvers.registerextrapath(paths,subpaths)
for s in gmatch(subpaths,"[^,]+") do
local ps = ep[i] .. "/" .. s
if not done[ps] then
- ep[#ep+1] = resolvers.cleanpath(ps)
+ newn = newn + 1
+ ep[newn] = resolvers.cleanpath(ps)
done[ps] = true
end
end
end
end
- if #ep > 0 then
+ if newn > 0 then
instance.extra_paths = ep -- register paths
end
- if #ep > n then
+ if newn > oldn then
instance.lists = { } -- erase the cache
end
end
@@ -10600,14 +10852,15 @@ local function made_list(instance,list)
if not ep or #ep == 0 then
return list
else
- local done, new = { }, { }
+ local done, new, newn = { }, { }, 0
-- honour . .. ../.. but only when at the start
for k=1,#list do
local v = list[k]
if not done[v] then
if find(v,"^[%.%/]$") then
done[v] = true
- new[#new+1] = v
+ newn = newn + 1
+ new[newn] = v
else
break
end
@@ -10618,7 +10871,8 @@ local function made_list(instance,list)
local v = ep[k]
if not done[v] then
done[v] = true
- new[#new+1] = v
+ newn = newn + 1
+ new[newn] = v
end
end
-- next the formal paths
@@ -10626,7 +10880,8 @@ local function made_list(instance,list)
local v = list[k]
if not done[v] then
done[v] = true
- new[#new+1] = v
+ newn = newn + 1
+ new[newn] = v
end
end
return new
@@ -10637,7 +10892,7 @@ function resolvers.cleanpathlist(str)
local t = resolvers.expandedpathlist(str)
if t then
for i=1,#t do
- t[i] = collapse_path(resolvers.cleanpath(t[i]))
+ t[i] = collapsepath(resolvers.cleanpath(t[i]))
end
end
return t
@@ -10703,7 +10958,7 @@ resolvers.isreadable.tex = resolvers.isreadable.file
-- name/name
local function collect_files(names)
- local filelist = { }
+ local filelist, noffiles = { }, 0
for k=1,#names do
local fname = names[k]
if trace_detail then
@@ -10744,7 +10999,8 @@ local function collect_files(names)
if trace_detail then
report_resolvers("match: kind '%s', search '%s', result '%s'",kind,search,result)
end
- filelist[#filelist+1] = { kind, search, result }
+ noffiles = noffiles + 1
+ filelist[noffiles] = { kind, search, result }
end
else
for kk=1,#blobfile do
@@ -10756,7 +11012,8 @@ local function collect_files(names)
if trace_detail then
report_resolvers("match: kind '%s', search '%s', result '%s'",kind,search,result)
end
- filelist[#filelist+1] = { kind, search, result }
+ noffiles = noffiles + 1
+ filelist[noffiles] = { kind, search, result }
end
end
end
@@ -10766,7 +11023,7 @@ local function collect_files(names)
end
end
end
- return #filelist > 0 and filelist or nil
+ return noffiles > 0 and filelist or nil
end
function resolvers.registerintrees(name)
@@ -10792,7 +11049,7 @@ end
local function collect_instance_files(filename,collected) -- todo : plugin (scanners, checkers etc)
local result = collected or { }
local stamp = nil
- filename = collapse_path(filename)
+ filename = collapsepath(filename)
-- speed up / beware: format problem
if instance.remember then
stamp = filename .. "--" .. instance.engine .. "--" .. instance.progname .. "--" .. instance.format
@@ -11045,7 +11302,7 @@ local function collect_instance_files(filename,collected) -- todo : plugin (scan
end
end
for k=1,#result do
- local rk = collapse_path(result[k])
+ local rk = collapsepath(result[k])
result[k] = rk
resolvers.registerintrees(rk) -- for tracing used files
end
@@ -12439,7 +12696,7 @@ function resolvers.load_tree(tree)
local texos = "texmf-" .. os.platform
local oldroot = environment.texroot
- local newroot = file.collapse_path(tree)
+ local newroot = file.collapsepath(tree)
local newtree = file.join(newroot,texos)
local newpath = file.join(newtree,"bin")
@@ -12668,17 +12925,17 @@ local format = string.format
-- helper for mtxrun
-local quote = string.quote
+local quoted = string.quoted
local function primaryflags()
local trackers = environment.argument("trackers")
local directives = environment.argument("directives")
local flags = ""
if trackers and trackers ~= "" then
- flags = flags .. "--trackers=" .. quote(trackers)
+ flags = flags .. "--trackers=" .. quoted(trackers)
end
if directives and directives ~= "" then
- flags = flags .. "--directives=" .. quote(directives)
+ flags = flags .. "--directives=" .. quoted(directives)
end
return flags
end
@@ -12743,7 +13000,7 @@ function environment.make_format(name)
return
end
-- generate format
- local command = format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quote(usedluastub),quote(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
+ local command = format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
logs.simple("running command: %s\n",command)
os.spawn(command)
-- remove related mem files
@@ -12781,8 +13038,7 @@ function environment.run_format(name,data,more)
logs.simple("using format name: %s",fmtname)
logs.simple("no luc/lua with name: %s",barename)
else
- local q = string.quote
- local command = format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quote(barename),quote(luaname),quote(data),more ~= "" and quote(more) or "")
+ local command = format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quoted(barename),quoted(luaname),quoted(data),more ~= "" and quoted(more) or "")
logs.simple("running command: %s",command)
os.spawn(command)
end
@@ -12813,13 +13069,13 @@ own.libs = { -- order can be made better
'l-unicode.lua',
'l-math.lua',
+ 'util-tab.lua',
+ 'util-sto.lua',
'util-mrg.lua',
'util-lua.lua',
'util-prs.lua',
- 'util-tab.lua',
'util-fmt.lua',
'util-deb.lua',
- 'util-sto.lua',
'trac-inf.lua',
'trac-set.lua',
diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua
index d091fa405..7af51ba30 100644
--- a/scripts/context/stubs/mswin/mtxrun.lua
+++ b/scripts/context/stubs/mswin/mtxrun.lua
@@ -54,7 +54,7 @@ if not modules then modules = { } end modules ['l-string'] = {
local string = string
local sub, gsub, find, match, gmatch, format, char, byte, rep, lower = string.sub, string.gsub, string.find, string.match, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
-local lpegmatch = lpeg.match
+local lpegmatch, S, C, Ct = lpeg.match, lpeg.S, lpeg.C, lpeg.Ct
-- some functions may disappear as they are not used anywhere
@@ -62,145 +62,68 @@ if not string.split then
-- this will be overloaded by a faster lpeg variant
- function string:split(pattern)
- if #self > 0 then
- local t = { }
- for s in gmatch(self..pattern,"(.-)"..pattern) do
- t[#t+1] = s
+ function string.split(str,pattern)
+ local t = { }
+ if #str > 0 then
+ local n = 1
+ for s in gmatch(str..pattern,"(.-)"..pattern) do
+ t[n] = s
+ n = n + 1
end
- return t
- else
- return { }
end
+ return t
end
end
-string.patterns = { }
-
-local escapes = {
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["^"] = "%^", ["$"] = "%$",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%(", [")"] = "%)",
- ["{"] = "%{", ["}"] = "%}"
-}
-
-string.patterns.escapes = escapes
-
-function string:esc() -- variant 2
- return (gsub(self,"(.)",escapes))
-end
-
-function string:unquote()
- return (gsub(self,"^([\"\'])(.*)%1$","%2"))
+function string.unquoted(str)
+ return (gsub(str,"^([\"\'])(.*)%1$","%2"))
end
-function string:quote() -- we could use format("%q")
- return format("%q",self)
+function string.quoted(str)
+ return format("%q",str) -- always "
end
-function string:count(pattern) -- variant 3
+function string.count(str,pattern) -- variant 3
local n = 0
- for _ in gmatch(self,pattern) do
+ for _ in gmatch(str,pattern) do -- not for utf
n = n + 1
end
return n
end
-function string:limit(n,sentinel)
- if #self > n then
+function string.limit(str,n,sentinel)
+ if #str > n then
sentinel = sentinel or " ..."
- return sub(self,1,(n-#sentinel)) .. sentinel
+ return sub(str,1,(n-#sentinel)) .. sentinel
else
- return self
- end
-end
-
-
-do -- roberto's variant:
- local space = lpeg.S(" \t\v\n")
- local nospace = 1 - space
- local stripper = space^0 * lpeg.C((space^0 * nospace^1)^0)
- function string.strip(str)
- return lpegmatch(stripper,str) or ""
- end
-end
-
-function string:is_empty()
- return not find(self,"%S")
-end
-
-function string:enhance(pattern,action)
- local ok, n = true, 0
- while ok do
- ok = false
- self = gsub(self,pattern, function(...)
- ok, n = true, n + 1
- return action(...)
- end)
+ return str
end
- return self, n
end
-if not string.characters then
-
- local function nextchar(str, index)
- index = index + 1
- return (index <= #str) and index or nil, sub(str,index,index)
- end
- function string:characters()
- return nextchar, self, 0
- end
- local function nextbyte(str, index)
- index = index + 1
- return (index <= #str) and index or nil, byte(sub(str,index,index))
- end
- function string:bytes()
- return nextbyte, self, 0
- end
+local space = S(" \t\v\n")
+local nospace = 1 - space
+local stripper = space^0 * C((space^0 * nospace^1)^0) -- roberto's code
+function string.strip(str)
+ return lpegmatch(stripper,str) or ""
end
-function string:rpadd(n,chr)
- local m = n-#self
- if m > 0 then
- return self .. rep(chr or " ",m)
- else
- return self
- end
-end
-
-function string:lpadd(n,chr)
- local m = n-#self
- if m > 0 then
- return rep(chr or " ",m) .. self
- else
- return self
- end
+function string.is_empty(str)
+ return not find(str,"%S")
end
-string.padd = string.rpadd
-
local patterns_escapes = {
- ["-"] = "%-",
- ["."] = "%.",
- ["+"] = "%+",
- ["*"] = "%*",
["%"] = "%%",
- ["("] = "%)",
- [")"] = "%)",
- ["["] = "%[",
- ["]"] = "%]",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
}
-function string:escapedpattern()
- return (gsub(self,".",patterns_escapes))
-end
-
local simple_escapes = {
["-"] = "%-",
["."] = "%.",
@@ -208,24 +131,32 @@ local simple_escapes = {
["*"] = ".*",
}
-function string:partialescapedpattern()
- return (gsub(self,".",simple_escapes))
+function string.escapedpattern(str,simple)
+ if simple then
+ return (gsub(str,".",simple_escapes))
+ else
+ return (gsub(str,".",patterns_escapes))
+ end
end
-function string:tohash()
- local t = { }
- for s in gmatch(self,"([^, ]+)") do -- lpeg
- t[s] = true
+function string.topattern(str,lowercase,strict)
+ if str == "" then
+ return ".*"
+ else
+ str = gsub(str,".",simple_escapes)
+ if lowercase then
+ str = lower(str)
+ end
+ if strict then
+ return "^" .. str .. "$"
+ else
+ return str
+ end
end
- return t
end
-local pattern = lpeg.Ct(lpeg.C(1)^0)
-
-function string:totable()
- return lpegmatch(pattern,self)
-end
+-- The following functions might end up in another namespace.
function string.tabtospace(str,tab)
-- we don't handle embedded newlines
@@ -246,30 +177,17 @@ function string.tabtospace(str,tab)
return str
end
-function string:compactlong() -- strips newlines and leading spaces
- self = gsub(self,"[\n\r]+ *","")
- self = gsub(self,"^ *","")
- return self
-end
-function string:striplong() -- strips newlines and leading spaces
- self = gsub(self,"^%s*","")
- self = gsub(self,"[\n\r]+ *","\n")
- return self
+function string.striplong(str) -- strips all leading spaces
+ str = gsub(str,"^%s*","")
+ str = gsub(str,"[\n\r]+ *","\n")
+ return str
end
-function string:topattern(lowercase,strict)
- if lowercase then
- self = lower(self)
- end
- self = gsub(self,".",simple_escapes)
- if self == "" then
- self = ".*"
- elseif strict then
- self = "^" .. self .. "$"
- end
- return self
-end
+-- obsolete names:
+
+string.quote = string.quoted
+string.unquote = string.unquoted
end -- of closure
@@ -292,15 +210,29 @@ local patterns = lpeg.patterns
local P, R, S, Ct, C, Cs, Cc, V = lpeg.P, lpeg.R, lpeg.S, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.V
local match = lpeg.match
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
local digit, sign = R('09'), S('+-')
local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local utf8byte = R("\128\191")
+local utf8next = R("\128\191")
+local escaped = P("\\") * P(1)
+local squote = P("'")
+local dquote = P('"')
-patterns.utf8byte = utf8byte
patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8byte
-patterns.utf8three = R("\224\239") * utf8byte * utf8byte
-patterns.utf8four = R("\240\244") * utf8byte * utf8byte * utf8byte
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = P('\000\000\254\255') + P('\255\254\000\000') + P('\255\254') + P('\254\255') + P('\239\187\191')
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * P(-1) * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
patterns.digit = digit
patterns.sign = sign
@@ -327,17 +259,24 @@ patterns.nonspace = 1 - patterns.space
patterns.nonspacer = 1 - patterns.spacer
patterns.whitespace = patterns.eol + patterns.spacer
patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.utf8 = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-patterns.utfbom = P('\000\000\254\255') + P('\255\254\000\000') + P('\255\254') + P('\254\255') + P('\239\187\191')
-patterns.validutf8 = patterns.utf8^0 * P(-1) * Cc(true) + Cc(false)
patterns.comma = P(",")
patterns.commaspacer = P(",") * patterns.spacer^0
patterns.period = P(".")
-
-patterns.undouble = P('"')/"" * (1-P('"'))^0 * P('"')/""
-patterns.unsingle = P("'")/"" * (1-P("'"))^0 * P("'")/""
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.undouble = (dquote/"") * ((escaped + (1-dquote))^0) * (dquote/"")
+patterns.unsingle = (squote/"") * ((escaped + (1-squote))^0) * (squote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
patterns.unspacer = ((patterns.spacer^1)/"")^0
+local unquoted = Cs(patterns.unquoted * P(-1)) -- not C
+
+function string.unquoted(str)
+ return match(unquoted,str) or str
+end
+
+
function lpeg.anywhere(pattern) --slightly adapted from website
return P { P(pattern) + 1 * V(1) } -- why so complex?
end
@@ -353,8 +292,8 @@ local content = (empty + nonempty)^1
local capture = Ct(content^0)
-function string:splitlines()
- return match(capture,self)
+function string.splitlines(str)
+ return match(capture,str)
end
patterns.textline = content
@@ -366,12 +305,12 @@ 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 other, any = C((1 - separator)^0), P(1)
+ local any = P(1)
splitter = other * (separator * C(any^0) + "") -- ?
splitters_s[separator] = splitter
else
- local other = C((1 - separator)^0)
splitter = other * (separator * other)^0
splitters_m[separator] = splitter
end
@@ -392,16 +331,15 @@ function lpeg.split(separator,str)
return match(c,str)
end
-function string:split(separator)
+function string.split(str,separator)
local c = cache[separator]
if not c then
c = Ct(splitat(separator))
cache[separator] = c
end
- return match(c,self)
+ return match(c,str)
end
-lpeg.splitters = cache
local cache = { }
@@ -409,22 +347,22 @@ function lpeg.checkedsplit(separator,str)
local c = cache[separator]
if not c then
separator = P(separator)
- local other = C((1 - separator)^0)
+ local other = C((1 - separator)^1)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
return match(c,str)
end
-function string:checkedsplit(separator)
+function string.checkedsplit(str,separator)
local c = cache[separator]
if not c then
separator = P(separator)
- local other = C((1 - separator)^0)
+ local other = C((1 - separator)^1)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
- return match(c,self)
+ return match(c,str)
end
@@ -435,7 +373,9 @@ local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2
local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-patterns.utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
@@ -469,19 +409,25 @@ function lpeg.keeper(str)
end
end
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
function lpeg.replacer(t)
if #t > 0 then
local p
for i=1,#t do
local ti= t[i]
local pp = P(ti[1]) / ti[2]
- p = (p and p + pp ) or pp
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
end
return Cs((p + 1)^0)
end
end
-
local splitters_f, splitters_s = { }, { }
function lpeg.firstofsplit(separator) -- always return value
@@ -505,11 +451,170 @@ function lpeg.secondofsplit(separator) -- nil if not split
end
function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
return P { left * ((1 - left - right) + V(1))^0 * right }
end
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + P(1))^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + P(1))^0)
+
+function string.escapedpattern(str,simple)
+ if simple then
+ return match(s,str)
+ else
+ return match(p,str)
+ end
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -577,24 +682,26 @@ end
-- extra functions, some might go (when not used)
function table.strip(tab)
- local lst = { }
+ local lst, l = { }, 0
for i=1,#tab do
local s = gsub(tab[i],"^%s*(.-)%s*$","%1")
if s == "" then
-- skip this one
else
- lst[#lst+1] = s
+ l = l + 1
+ lst[l] = s
end
end
return lst
end
function table.keys(t)
- local k = { }
+ local keys, k = { }, 0
for key, _ in next, t do
- k[#k+1] = key
+ k = k + 1
+ keys[k] = key
end
- return k
+ return keys
end
local function compare(a,b)
@@ -607,9 +714,10 @@ local function compare(a,b)
end
local function sortedkeys(tab)
- local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed
+ local srt, kind, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
for key,_ in next, tab do
- srt[#srt+1] = key
+ s = s + 1
+ srt[s] = key
if kind == 3 then
-- no further check
else
@@ -632,10 +740,11 @@ local function sortedkeys(tab)
end
local function sortedhashkeys(tab) -- fast one
- local srt = { }
+ local srt, s = { }, 0
for key,_ in next, tab do
if key then
- srt[#srt+1] = key
+ s= s + 1
+ srt[s] = key
end
end
sort(srt)
@@ -649,8 +758,7 @@ local function nothing() end
local function sortedhash(t)
if t then
- local s = sortedhashkeys(t) -- maybe just sortedkeys
- local n = 0
+ local n, s = 0, sortedkeys(t) -- the robust one
local function kv(s)
n = n + 1
local k = s[n]
@@ -666,20 +774,30 @@ table.sortedhash = sortedhash
table.sortedpairs = sortedhash
function table.append(t, list)
- for _,v in next, list do
- insert(t,v)
+ local n = #t
+ for i=1,#list do
+ n = n + 1
+ t[n] = list[i]
end
+ return t
end
function table.prepend(t, list)
- for k,v in next, list do
- insert(t,k,v)
+ 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, ...) -- first one is target
t = t or { }
- local lst = {...}
+ local lst = { ... }
for i=1,#lst do
for k, v in next, lst[i] do
t[k] = v
@@ -689,7 +807,7 @@ function table.merge(t, ...) -- first one is target
end
function table.merged(...)
- local tmp, lst = { }, {...}
+ local tmp, lst = { }, { ... }
for i=1,#lst do
for k, v in next, lst[i] do
tmp[k] = v
@@ -699,22 +817,24 @@ function table.merged(...)
end
function table.imerge(t, ...)
- local lst = {...}
+ local lst, nt = { ... }, #t
for i=1,#lst do
local nst = lst[i]
for j=1,#nst do
- t[#t+1] = nst[j]
+ nt = nt + 1
+ t[nt] = nst[j]
end
end
return t
end
function table.imerged(...)
- local tmp, lst = { }, {...}
+ local tmp, ntmp, lst = { }, 0, {...}
for i=1,#lst do
local nst = lst[i]
for j=1,#nst do
- tmp[#tmp+1] = nst[j]
+ ntmp = ntmp + 1
+ tmp[ntmp] = nst[j]
end
end
return tmp
@@ -790,11 +910,14 @@ function table.tohash(t,value)
end
function table.fromhash(t)
- local h = { }
+ local hsh, h = { }, 0
for k, v in next, t do -- no ipairs here
- if v then h[#h+1] = k end
+ if v then
+ h = h + 1
+ hsh[h] = k
+ end
end
- return h
+ return hsh
end
table.serialize_functions = true
@@ -815,20 +938,23 @@ local function simple_table(t)
n = n + 1
end
if n == #t then
- local tt = { }
+ local tt, nt = { }, 0
for i=1,#t do
local v = t[i]
local tv = type(v)
if tv == "number" then
+ nt = nt + 1
if hexify then
- tt[#tt+1] = format("0x%04X",v)
+ tt[nt] = format("0x%04X",v)
else
- tt[#tt+1] = tostring(v) -- tostring not needed
+ tt[nt] = tostring(v) -- tostring not needed
end
elseif tv == "boolean" then
- tt[#tt+1] = tostring(v)
+ nt = nt + 1
+ tt[nt] = tostring(v)
elseif tv == "string" then
- tt[#tt+1] = format("%q",v)
+ nt = nt + 1
+ tt[nt] = format("%q",v)
else
tt = nil
break
@@ -1123,10 +1249,11 @@ local function serialize(root,name,_handle,_reduce,_noquotes,_hexify)
end
-function table.serialize(root,name,reduce,noquotes,hexify)
- local t = { }
+function table.serialize(root,name,reduce,noquotes,hexify) -- can be faster if flush == false and t as argument
+ local t, n = { }, 0
local function flush(s)
- t[#t+1] = s
+ n = n + 1
+ t[n] = s
end
serialize(root,name,flush,reduce,noquotes,hexify)
return concat(t,"\n")
@@ -1152,12 +1279,13 @@ function table.tofile(filename,root,name,reduce,noquotes,hexify)
if f then
local maxtab = table.tofile_maxtab
if maxtab > 1 then
- local t = { }
+ local t, n = { }, 0
local function flush(s)
- t[#t+1] = s
- if #t > maxtab then
+ n = n + 1
+ t[n] = s
+ if n > maxtab then
f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
- t = { }
+ t, n = { }, 0 -- we could recycle t if needed
end
end
serialize(root,name,flush,reduce,noquotes,hexify)
@@ -1173,52 +1301,66 @@ function table.tofile(filename,root,name,reduce,noquotes,hexify)
end
end
-local function flatten(t,f,complete) -- is this used? meybe a variant with next, ...
- for i=1,#t do
- local v = t[i]
- if type(v) == "table" then
- if complete or type(v[1]) == "table" then
- flatten(v,f,complete)
+local function flattened(t,f,depth)
+ if f == nil then
+ f = { }
+ depth = 0xFFFF
+ elseif tonumber(f) then
+ -- assume then only two arguments are given
+ 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
+ f[k] = v
end
+ end
+ end
+ local n = #f
+ for k=1,#t do
+ local v = t[k]
+ if depth > 0 and type(v) == "table" then
+ flattened(v,f,depth-1)
+ n = #f
else
- f[#f+1] = v
+ n = n + 1
+ f[n] = v
end
end
-end
-
-function table.flatten(t)
- local f = { }
- flatten(t,f,true)
return f
end
-function table.unnest(t) -- bad name
- local f = { }
- flatten(t,f,false)
- return f
-end
-
-table.flattenonelevel = table.unnest
-
--- a better one:
+table.flattened = flattened
-local function flattened(t,f)
- if not f then
+local function unnest(t,f) -- only used in mk, for old times sake
+ if not f then -- and only relevant for token lists
f = { }
end
- for k, v in next, t do
+ for i=1,#t do
+ local v = t[i]
if type(v) == "table" then
- flattened(v,f)
+ if type(v[1]) == "table" then
+ unnest(v,f)
+ else
+ f[#f+1] = v
+ end
else
- f[k] = v
+ f[#f+1] = v
end
end
return f
end
-table.flattened = flattened
+function table.unnest(t) -- bad name
+ return unnest(t)
+end
+
+
local function are_equal(a,b,n,m) -- indexed
if a and b and #a == #b then
@@ -1244,7 +1386,7 @@ end
local function identical(a,b) -- assumes same structure
for ka, va in next, a do
- local vb = b[k]
+ local vb = b[ka]
if va == vb then
-- same
elseif type(va) == "table" and type(vb) == "table" then
@@ -1258,8 +1400,8 @@ local function identical(a,b) -- assumes same structure
return true
end
-table.are_equal = are_equal
table.identical = identical
+table.are_equal = are_equal
-- maybe also make a combined one
@@ -1285,14 +1427,14 @@ function table.contains(t, v)
end
function table.count(t)
- local n, e = 0, next(t)
- while e do
- n, e = n + 1, next(t,e)
+ local n = 0
+ for k, v in next, t do
+ n = n + 1
end
return n
end
-function table.swapped(t,s)
+function table.swapped(t,s) -- hash
local n = { }
if s then
for k, v in next, s do
@@ -1305,52 +1447,34 @@ function table.swapped(t,s)
return n
end
-
-function table.clone(t,p) -- t is optional or nil or table
- if not p then
- t, p = { }, t or { }
- elseif not t then
- t = { }
- end
- setmetatable(t, { __index = function(_,key) return p[key] end }) -- why not __index = p ?
- return t
-end
-
-function table.hexed(t,seperator)
- local tt = { }
- for i=1,#t do tt[i] = format("0x%04X",t[i]) end
- return concat(tt,seperator or " ")
-end
-
-function table.swaphash(h) -- needs another name
- local r = { }
- for k,v in next, h do
- r[v] = lower(gsub(k," ",""))
- end
- return r
-end
-
-function table.reverse(t)
- local tt = { }
- if #t > 0 then
- for i=#t,1,-1 do
- tt[#tt+1] = t[i]
+function table.reversed(t)
+ if t then
+ local tt, tn = { }, #t
+ if tn > 0 then
+ local ttn = 0
+ for i=tn,1,-1 do
+ ttn = ttn + 1
+ tt[ttn] = t[i]
+ end
end
+ return tt
end
- return tt
end
function table.sequenced(t,sep,simple) -- hash only
- local s = { }
+ local s, n = { }, 0
for k, v in sortedhash(t) do
if simple then
if v == true then
- s[#s+1] = k
+ n = n + 1
+ s[n] = k
elseif v and v~= "" then
- s[#s+1] = k .. "=" .. tostring(v)
+ n = n + 1
+ s[n] = k .. "=" .. tostring(v)
end
else
- s[#s+1] = k .. "=" .. tostring(v)
+ n = n + 1
+ s[n] = k .. "=" .. tostring(v)
end
end
return concat(s, sep or " | ")
@@ -1360,7 +1484,7 @@ function table.print(...)
table.tohandle(print,...)
end
--- -- -- obsolete but we keep them for a while and will comment them later -- -- --
+-- -- -- obsolete but we keep them for a while and might comment them later -- -- --
-- roughly: copy-loop : unpack : sub == 0.9 : 0.4 : 0.45 (so in critical apps, use unpack)
@@ -1375,14 +1499,7 @@ function table.is_empty(t)
end
function table.has_one_entry(t)
- local n = next(t)
- return n and not next(t,n)
-end
-
-function table.replace(a,b)
- for k,v in next, b do
- a[k] = v
- end
+ return t and not next(t,next(t))
end
@@ -1627,6 +1744,8 @@ if not modules then modules = { } end modules ['l-number'] = {
license = "see context related readme files"
}
+-- this module will be replaced when we have the bit library
+
local tostring = tostring
local format, floor, insert, match = string.format, math.floor, string.match
local concat, insert = table.concat, table.insert
@@ -1768,10 +1887,11 @@ function set.tolist(n)
if n == 0 or not tabs[n] then
return ""
else
- local t = { }
+ local t, n = { }, 0
for k, v in next, tabs[n] do
if v then
- t[#t+1] = k
+ n = n + 1
+ t[n] = k
end
end
return concat(t," ")
@@ -1950,7 +2070,7 @@ end
-- no need for function anymore as we have more clever code and helpers now
-- this metatable trickery might as well disappear
-os.resolvers = os.resolvers or { }
+os.resolvers = os.resolvers or { } -- will become private
local resolvers = os.resolvers
@@ -2279,7 +2399,7 @@ end
file.isreadable = file.is_readable -- depricated
file.iswritable = file.is_writable -- depricated
--- todo: lpeg
+-- todo: lpeg \\ / .. does not save much
local checkedsplit = string.checkedsplit
@@ -2295,7 +2415,7 @@ end
-- we can hash them weakly
-function file.collapse_path(str,anchor)
+function file.collapsepath(str,anchor)
if anchor and not find(str,"^/") and not find(str,"^%a:") then
str = getcurrentdir() .. "/" .. str
end
@@ -2350,6 +2470,8 @@ function file.collapse_path(str,anchor)
end
end
+file.collapse_path = file.collapsepath
+
function file.robustname(str)
return (gsub(str,"[^%a%d%/%-%.\\]+","-"))
@@ -2782,9 +2904,12 @@ local function glob(str,t)
end
return t
elseif isfile(str) then
- local t = t or { }
- t[#t+1] = str
- return t
+ if t then
+ t[#t+1] = str
+ return t
+ else
+ return { str }
+ end
else
local split = lpegmatch(pattern,str)
if split then
@@ -2812,6 +2937,7 @@ local function globfiles(path,recurse,func,files) -- func == pattern or function
func = function(name) return find(name,s) end
end
files = files or { }
+ local noffiles = #files
for name in walkdir(path) do
if find(name,"^%.") then
--- skip
@@ -2822,12 +2948,9 @@ local function globfiles(path,recurse,func,files) -- func == pattern or function
globfiles(path .. "/" .. name,recurse,func,files)
end
elseif mode == "file" then
- if func then
- if func(name) then
- files[#files+1] = path .. "/" .. name
- end
- else
- files[#files+1] = path .. "/" .. name
+ if not func or func(name) then
+ noffiles = noffiles + 1
+ files[noffiles] = path .. "/" .. name
end
end
end
@@ -3012,8 +3135,12 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
+-- function boolean.tonumber(b)
+-- return b and 1 or 0 -- test and test and return or return
+-- end
+
function boolean.tonumber(b)
- if b then return 1 else return 0 end
+ if b then return 1 else return 0 end -- test and return or return
end
function toboolean(str,tolerant)
@@ -3037,6 +3164,8 @@ function toboolean(str,tolerant)
end
end
+string.toboolean = toboolean
+
function string.is_boolean(str,default)
if type(str) == "string" then
if str == "true" or str == "yes" or str == "on" or str == "t" then
@@ -3048,14 +3177,6 @@ function string.is_boolean(str,default)
return default
end
-function boolean.alwaystrue()
- return true
-end
-
-function boolean.falsetrue()
- return false
-end
-
end -- of closure
@@ -3144,30 +3265,37 @@ function unicode.utftype(f)
end
function unicode.utf16_to_utf8(str, endian) -- maybe a gsub is faster or an lpeg
- local result, tmp, n, m, p = { }, { }, 0, 0, 0
+ local result, tmp, n, m, p, r, t = { }, { }, 0, 0, 0, 0, 0 -- we reuse tmp
-- lf | cr | crlf / (cr:13, lf:10)
local function doit()
if n == 10 then
if p ~= 13 then
- result[#result+1] = concat(tmp)
- tmp = { }
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
+ t = 0
+ end
p = 0
end
elseif n == 13 then
- result[#result+1] = concat(tmp)
- tmp = { }
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
+ t = 0
+ end
p = n
else
- tmp[#tmp+1] = utfchar(n)
+ t = t + 1
+ tmp[t] = utfchar(n)
p = 0
end
end
for l,r in bytepairs(str) do
if r then
if endian then
- n = l*256 + r
+ n = 256*l + r
else
- n = r*256 + l
+ n = 256*r + l
end
if m > 0 then
n = (m-0xD800)*0x400 + (n-0xDC00) + 0x10000
@@ -3180,29 +3308,36 @@ function unicode.utf16_to_utf8(str, endian) -- maybe a gsub is faster or an lpeg
end
end
end
- if #tmp > 0 then
- result[#result+1] = concat(tmp)
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
end
return result
end
function unicode.utf32_to_utf8(str, endian)
- local result = { }
- local tmp, n, m, p = { }, 0, -1, 0
+ local result, tmp, n, m, p, r, t = { }, { }, 0, -1, 0, 0, 0
-- lf | cr | crlf / (cr:13, lf:10)
local function doit()
if n == 10 then
if p ~= 13 then
- result[#result+1] = concat(tmp)
- tmp = { }
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
+ t = 0
+ end
p = 0
end
elseif n == 13 then
- result[#result+1] = concat(tmp)
- tmp = { }
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
+ t = 0
+ end
p = n
else
- tmp[#tmp+1] = utfchar(n)
+ t = t + 1
+ tmp[t] = utfchar(n)
p = 0
end
end
@@ -3210,15 +3345,15 @@ function unicode.utf32_to_utf8(str, endian)
if a and b then
if m < 0 then
if endian then
- m = a*256*256*256 + b*256*256
+ m = 256*256*256*a + 256*256*b
else
- m = b*256 + a
+ m = 256*b + a
end
else
if endian then
- n = m + a*256 + b
+ n = m + 256*a + b
else
- n = m + b*256*256*256 + a*256*256
+ n = m + 256*256*256*b + 256*256*a
end
m = -1
doit()
@@ -3228,13 +3363,14 @@ function unicode.utf32_to_utf8(str, endian)
end
end
if #tmp > 0 then
- result[#result+1] = concat(tmp)
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
end
return result
end
local function little(c)
- local b = byte(c) -- b = c:byte()
+ local b = byte(c)
if b < 0x10000 then
return char(b%256,b/256)
else
@@ -3264,9 +3400,10 @@ function unicode.utf8_to_utf16(str,littleendian)
end
function unicode.utfcodes(str)
- local t = { }
- for k,v in utfvalues(str) do
- t[#t+1] = format("0x%04X",k)
+ local t, n = { }, 0
+ for u in utfvalues(str) do
+ n = n + 1
+ t[n] = format("0x%04X",u)
end
return concat(t,separator or " ")
end
@@ -3324,6 +3461,189 @@ end -- of closure
do -- create closure to overcome 200 locals limit
+if not modules then modules = { } end modules ['util-tab'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+utilities = utilities or {}
+utilities.tables = utilities.tables or { }
+local tables = utilities.tables
+
+local format, gmatch = string.format, string.gmatch
+local concat, insert, remove = table.concat, table.insert, table.remove
+local setmetatable = setmetatable
+
+function tables.definetable(target) -- defines undefined tables
+ local composed, t, n = nil, { }, 0
+ for name in gmatch(target,"([^%.]+)") do
+ n = n + 1
+ if composed then
+ composed = composed .. "." .. name
+ else
+ composed = name
+ end
+ t[n] = format("%s = %s or { }",composed,composed)
+ end
+ return concat(t,"\n")
+end
+
+function tables.accesstable(target)
+ local t = _G
+ for name in gmatch(target,"([^%.]+)") do
+ t = t[name]
+ end
+ return t
+end
+
+function tables.removevalue(t,value) -- todo: n
+ if value then
+ for i=1,#t do
+ if t[i] == value then
+ remove(t,i)
+ -- remove all, so no: return
+ end
+ end
+ end
+end
+
+function tables.insertbeforevalue(t,value,extra)
+ for i=1,#t do
+ if t[i] == extra then
+ remove(t,i)
+ end
+ end
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i,extra)
+ return
+ end
+ end
+ insert(t,1,extra)
+end
+
+function tables.insertaftervalue(t,value,extra)
+ for i=1,#t do
+ if t[i] == extra then
+ remove(t,i)
+ end
+ end
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i+1,extra)
+ return
+ end
+ end
+ insert(t,#t+1,extra)
+end
+
+local _empty_table_ = { __index = function(t,k) return "" end }
+
+function table.setemptymetatable(t)
+ setmetatable(t,_empty_table_)
+end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['util-sto'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local setmetatable, getmetatable = setmetatable, getmetatable
+
+utilities = utilities or { }
+utilities.storage = utilities.storage or { }
+local storage = utilities.storage
+
+function storage.mark(t)
+ if not t then
+ texio.write_nl("fatal error: storage '%s' cannot be marked",t)
+ os.exit()
+ end
+ local m = getmetatable(t)
+ if not m then
+ m = { }
+ setmetatable(t,m)
+ end
+ m.__storage__ = true
+ return t
+end
+
+function storage.allocate(t)
+ t = t or { }
+ local m = getmetatable(t)
+ if not m then
+ m = { }
+ setmetatable(t,m)
+ end
+ m.__storage__ = true
+ return t
+end
+
+function storage.marked(t)
+ local m = getmetatable(t)
+ return m and m.__storage__
+end
+
+function storage.checked(t)
+ if not t then
+ texio.write_nl("fatal error: storage '%s' has not been allocated",t)
+ os.exit()
+ end
+ return t
+end
+
+function setmetatablekey(t,key,value)
+ local m = getmetatable(t)
+ if not m then
+ m = { }
+ setmetatable(t,m)
+ end
+ m[key] = value
+end
+
+function getmetatablekey(t,key,value)
+ local m = getmetatable(t)
+ return m and m[key]
+end
+
+
+function storage.setinitializer(data,initialize)
+ local m = getmetatable(data) or { }
+ m.__index = function(data,k)
+ m.__index = nil -- so that we can access the entries during initializing
+ initialize()
+ return data[k]
+ end
+ setmetatable(data, m)
+end
+
+local keyisvalue = { __index = function(t,k)
+ t[k] = k
+ return k
+end }
+
+function storage.sparse(t)
+ t = t or { }
+ setmetatable(t,keyisvalue)
+ return t
+end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
if not modules then modules = { } end modules ['util-mrg'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -3483,7 +3803,7 @@ utilities.report = utilities.report or print
function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
- local command = "-o " .. string.quote(lucfile) .. " " .. string.quote(luafile)
+ local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
@@ -3496,6 +3816,12 @@ function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: clean
end
+
+
+
+
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3516,7 +3842,7 @@ parsers.patterns = parsers.patterns or { }
local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
local lpegmatch = lpeg.match
local concat, format, gmatch = table.concat, string.format, string.gmatch
-local tostring, type, next = tostring, type, next
+local tostring, type, next, setmetatable = tostring, type, next, setmetatable
local sortedhash = table.sortedhash
local escape, left, right = P("\\"), P('{'), P('}')
@@ -3635,7 +3961,7 @@ end
function parsers.hash_to_string(h,separator,yes,no,strict,omit)
if h then
- local t, s = { }, table.sortedkeys(h)
+ local t, tn, s = { }, 0, table.sortedkeys(h)
omit = omit and table.tohash(omit)
for i=1,#s do
local key = s[i]
@@ -3644,15 +3970,19 @@ function parsers.hash_to_string(h,separator,yes,no,strict,omit)
if type(value) == "boolean" then
if yes and no then
if value then
- t[#t+1] = key .. '=' .. yes
+ tn = tn + 1
+ t[tn] = key .. '=' .. yes
elseif not strict then
- t[#t+1] = key .. '=' .. no
+ tn = tn + 1
+ t[tn] = key .. '=' .. no
end
elseif value or not strict then
- t[#t+1] = key .. '=' .. tostring(value)
+ tn = tn + 1
+ t[tn] = key .. '=' .. tostring(value)
end
else
- t[#t+1] = key .. '=' .. value
+ tn = tn + 1
+ t[tn] = key .. '=' .. value
end
end
end
@@ -3679,10 +4009,11 @@ function parsers.settings_to_set(str,t) -- tohash? -- todo: lpeg -- duplicate an
end
function parsers.simple_hash_to_string(h, separator)
- local t = { }
+ local t, tn = { }, 0
for k, v in sortedhash(h) do
if v then
- t[#t+1] = k
+ tn = tn + 1
+ t[tn] = k
end
end
return concat(t,separator or ",")
@@ -3700,99 +4031,18 @@ end
function parsers.getparameters(self,class,parentclass,settings)
local sc = self[class]
if not sc then
- sc = table.clone(self[parent])
+ sc = { }
self[class] = sc
- end
- parsers.settings_to_hash(settings,sc)
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util-tab'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-utilities = utilities or {}
-utilities.tables = utilities.tables or { }
-local tables = utilities.tables
-
-local format, gmatch = string.format, string.gmatch
-local concat, insert, remove = table.concat, table.insert, table.remove
-local setmetatable = setmetatable
-
-function tables.definetable(target) -- defines undefined tables
- local composed, t = nil, { }
- for name in gmatch(target,"([^%.]+)") do
- if composed then
- composed = composed .. "." .. name
- else
- composed = name
- end
- t[#t+1] = format("%s = %s or { }",composed,composed)
- end
- return concat(t,"\n")
-end
-
-function tables.accesstable(target)
- local t = _G
- for name in gmatch(target,"([^%.]+)") do
- t = t[name]
- end
- return t
-end
-
-function table.removevalue(t,value) -- todo: n
- if value then
- for i=1,#t do
- if t[i] == value then
- remove(t,i)
- -- remove all, so no: return
+ if parentclass then
+ local sp = self[parentclass]
+ if not sp then
+ sp = { }
+ self[parentclass] = sp
end
+ setmetatable(sc, { __index = sp })
end
end
-end
-
-function table.insertbeforevalue(t,value,extra)
- for i=1,#t do
- if t[i] == extra then
- remove(t,i)
- end
- end
- for i=1,#t do
- if t[i] == value then
- insert(t,i,extra)
- return
- end
- end
- insert(t,1,extra)
-end
-
-function table.insertaftervalue(t,value,extra)
- for i=1,#t do
- if t[i] == extra then
- remove(t,i)
- end
- end
- for i=1,#t do
- if t[i] == value then
- insert(t,i+1,extra)
- return
- end
- end
- insert(t,#t+1,extra)
-end
-
-local _empty_table_ = { __index = function(t,k) return "" end }
-
-function table.setemptymetatable(t)
- setmetatable(t,_empty_table_)
+ parsers.settings_to_hash(settings,sc)
end
@@ -3831,9 +4081,9 @@ local number = digit^1 * (case_1 + case_2)
local stripper = Cs((number + 1)^0)
-lpeg.patterns.strip_zeros = stripper
+lpeg.patterns.stripzeros = stripper
-function formatters.strip_zeros(str)
+function formatters.stripzeros(str)
return lpegmatch(stripper,str)
end
@@ -4005,88 +4255,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['util-sto'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local setmetatable, getmetatable = setmetatable, getmetatable
-
-utilities = utilities or { }
-utilities.storage = utilities.storage or { }
-local storage = utilities.storage
-
-function storage.mark(t)
- if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
- end
- local m = getmetatable(t)
- if not m then
- m = { }
- setmetatable(t,m)
- end
- m.__storage__ = true
- return t
-end
-
-function storage.allocate(t)
- t = t or { }
- local m = getmetatable(t)
- if not m then
- m = { }
- setmetatable(t,m)
- end
- m.__storage__ = true
- return t
-end
-
-function storage.marked(t)
- local m = getmetatable(t)
- return m and m.__storage__
-end
-
-function storage.checked(t)
- if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
- end
- return t
-end
-
-function setmetatablekey(t,key,value)
- local m = getmetatable(t)
- if not m then
- m = { }
- setmetatable(t,m)
- end
- m[key] = value
-end
-
-function getmetatablekey(t,key,value)
- local m = getmetatable(t)
- return m and m[key]
-end
-
-
-function storage.setinitializer(data,initialize)
- local m = getmetatable(data) or { }
- m.__index = function(data,k)
- m.__index = nil -- so that we can access the entries during initializing
- initialize()
- return data[k]
- end
- setmetatable(data, m)
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['trac-inf'] = {
version = 1.001,
comment = "companion to trac-inf.mkiv",
@@ -4102,6 +4270,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
local format = string.format
local clock = os.gettimeofday or os.clock -- should go in environment
+local write_nl = texio.write_nl
statistics = statistics or { }
local statistics = statistics
@@ -4197,7 +4366,7 @@ end
function statistics.show(reporter)
if statistics.enable then
- if not reporter then reporter = function(tag,data,n) texio.write_nl(tag .. " " .. data) end end
+ if not reporter then reporter = function(tag,data,n) write_nl(tag .. " " .. data) end end
-- this code will move
local register = statistics.register
register("luatex banner", function()
@@ -4220,18 +4389,24 @@ function statistics.show(reporter)
reporter(s[1],r,n)
end
end
- texio.write_nl("") -- final newline
+ write_nl("") -- final newline
statistics.enable = false
end
end
+
+local template, nn = nil, 0 -- we only calcute it once
+
function statistics.showjobstat(tag,data,n)
if type(data) == "table" then
for i=1,#data do
statistics.showjobstat(tag,data[i],n)
end
else
- texio.write_nl(format("%-15s: %s - %s","mkiv lua stats",tag:rpadd(n," "),data))
+ if not template or n > nn then
+ template, n = format("%%-%ss: %%-%ss - %%s",15,n), nn
+ end
+ write_nl(format(template,"mkiv lua stats",tag,data))
end
end
@@ -4288,7 +4463,7 @@ if not modules then modules = { } end modules ['trac-set'] = { -- might become u
local type, next, tostring = type, next, tostring
local concat = table.concat
-local format, find, lower, gsub, partialescapedpattern = string.format, string.find, string.lower, string.gsub, string.partialescapedpattern
+local format, find, lower, gsub, escapedpattern = string.format, string.find, string.lower, string.gsub, string.escapedpattern
local is_boolean = string.is_boolean
local settings_to_hash = utilities.parsers.settings_to_hash
local allocate = utilities.storage.allocate
@@ -4368,7 +4543,7 @@ local function set(t,what,newvalue)
for name, functions in next, data do
if done[name] then
-- prevent recursion due to wildcards
- elseif find(name,partialescapedpattern(w)) then
+ elseif find(name,escapedpattern(w,true)) then
done[name] = true
for i=1,#functions do
functions[i](value)
@@ -5151,7 +5326,7 @@ local report_resolvers = logs.new("resolvers")
local allocate, mark = utilities.storage.allocate, utilities.storage.mark
local format, sub, match, gsub, find = string.format, string.sub, string.match, string.gsub, string.find
-local unquote, quote = string.unquote, string.quote
+local unquoted, quoted = string.unquoted, string.quoted
local concat = table.concat
-- precautions
@@ -5219,7 +5394,7 @@ function environment.initializearguments(arg)
if index > 0 then
local flag, value = match(argument,"^%-+(.-)=(.-)$")
if flag then
- arguments[flag] = unquote(value or "")
+ arguments[flag] = unquoted(value or "")
else
flag = match(argument,"^%-+(.+)")
if flag then
@@ -5284,19 +5459,21 @@ end
function environment.reconstructcommandline(arg,noquote)
arg = arg or environment.originalarguments
if noquote and #arg == 1 then
+ -- we could just do: return unquoted(resolvers.resolve(arg[i]))
local a = arg[1]
a = resolvers.resolve(a)
- a = unquote(a)
+ a = unquoted(a)
return a
elseif #arg > 0 then
local result = { }
for i=1,#arg do
+ -- we could just do: result[#result+1] = format("%q",unquoted(resolvers.resolve(arg[i])))
local a = arg[i]
a = resolvers.resolve(a)
- a = unquote(a)
+ a = unquoted(a)
a = gsub(a,'"','\\"') -- tricky
if find(a," ") then
- result[#result+1] = quote(a)
+ result[#result+1] = quoted(a)
else
result[#result+1] = a
end
@@ -5307,6 +5484,7 @@ function environment.reconstructcommandline(arg,noquote)
end
end
+
if arg then
-- new, reconstruct quoted snippets (maybe better just remove the " then and add them later)
@@ -6767,7 +6945,7 @@ apply_axis['root'] = function(list)
rt = ll
end
end
- collected[#collected+1] = rt
+ collected[l] = rt
end
return collected
end
@@ -6777,7 +6955,7 @@ apply_axis['self'] = function(list)
end
apply_axis['child'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
local dt = ll.dt
@@ -6786,7 +6964,8 @@ apply_axis['child'] = function(list)
for k=1,#dt do
local dk = dt[k]
if dk.tg then
- collected[#collected+1] = dk
+ c = c + 1
+ collected[c] = dk
dk.ni = k -- refresh
en = en + 1
dk.ei = en
@@ -6798,68 +6977,74 @@ apply_axis['child'] = function(list)
return collected
end
-local function collect(list,collected)
+local function collect(list,collected,c)
local dt = list.dt
if dt then
local en = 0
for k=1,#dt do
local dk = dt[k]
if dk.tg then
- collected[#collected+1] = dk
+ c = c + 1
+ collected[c] = dk
dk.ni = k -- refresh
en = en + 1
dk.ei = en
- collect(dk,collected)
+ c = collect(dk,collected,c)
end
end
list.en = en
end
+ return c
end
apply_axis['descendant'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
- collect(list[l],collected)
+ c = collect(list[l],collected,c)
end
return collected
end
-local function collect(list,collected)
+local function collect(list,collected,c)
local dt = list.dt
if dt then
local en = 0
for k=1,#dt do
local dk = dt[k]
if dk.tg then
- collected[#collected+1] = dk
+ c = c + 1
+ collected[c] = dk
dk.ni = k -- refresh
en = en + 1
dk.ei = en
- collect(dk,collected)
+ c = collect(dk,collected,c)
end
end
list.en = en
end
+ return c
end
apply_axis['descendant-or-self'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
if ll.special ~= true then -- catch double root
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
end
- collect(ll,collected)
+ c = collect(ll,collected,c)
end
return collected
end
apply_axis['ancestor'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
while ll do
ll = ll.__p__
if ll then
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
end
end
end
@@ -6867,14 +7052,16 @@ apply_axis['ancestor'] = function(list)
end
apply_axis['ancestor-or-self'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
while ll do
ll = ll.__p__
if ll then
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
end
end
end
@@ -6882,11 +7069,12 @@ apply_axis['ancestor-or-self'] = function(list)
end
apply_axis['parent'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local pl = list[l].__p__
if pl then
- collected[#collected+1] = pl
+ c = c + 1
+ collected[c] = pl
end
end
return collected
@@ -6909,7 +7097,7 @@ apply_axis['preceding'] = function(list) -- incomplete
end
apply_axis['following-sibling'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
local p = ll.__p__
@@ -6917,7 +7105,8 @@ apply_axis['following-sibling'] = function(list)
for i=ll.ni+1,#d do
local di = d[i]
if type(di) == "table" then
- collected[#collected+1] = di
+ c = c + 1
+ collected[c] = di
end
end
end
@@ -6925,7 +7114,7 @@ apply_axis['following-sibling'] = function(list)
end
apply_axis['preceding-sibling'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
local p = ll.__p__
@@ -6933,7 +7122,8 @@ apply_axis['preceding-sibling'] = function(list)
for i=1,ll.ni-1 do
local di = d[i]
if type(di) == "table" then
- collected[#collected+1] = di
+ c = c + 1
+ collected[c] = di
end
end
end
@@ -6941,7 +7131,7 @@ apply_axis['preceding-sibling'] = function(list)
end
apply_axis['reverse-sibling'] = function(list) -- reverse preceding
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
local p = ll.__p__
@@ -6949,7 +7139,8 @@ apply_axis['reverse-sibling'] = function(list) -- reverse preceding
for i=ll.ni-1,1,-1 do
local di = d[i]
if type(di) == "table" then
- collected[#collected+1] = di
+ c = c + 1
+ collected[c] = di
end
end
end
@@ -6975,7 +7166,7 @@ local function apply_nodes(list,directive,nodes)
return { }
end
else
- local collected, m, p = { }, 0, nil
+ local collected, c, m, p = { }, 0, 0, nil
if not nns then -- only check tag
for l=1,#list do
local ll = list[l]
@@ -6984,11 +7175,13 @@ local function apply_nodes(list,directive,nodes)
if directive then
if ntg == ltg then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
elseif ntg ~= ltg then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
end
end
@@ -7000,11 +7193,13 @@ local function apply_nodes(list,directive,nodes)
if directive then
if lns == nns then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
elseif lns ~= nns then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
end
end
@@ -7018,11 +7213,13 @@ local function apply_nodes(list,directive,nodes)
if directive then
if ok then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
elseif not ok then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
end
end
@@ -7030,7 +7227,7 @@ local function apply_nodes(list,directive,nodes)
return collected
end
else
- local collected, m, p = { }, 0, nil
+ local collected, c, m, p = { }, 0, 0, nil
for l=1,#list do
local ll = list[l]
local ltg = ll.tg
@@ -7047,11 +7244,13 @@ local function apply_nodes(list,directive,nodes)
if directive then
if ok then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
elseif not ok then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
end
end
@@ -7062,12 +7261,13 @@ end
local quit_expression = false
local function apply_expression(list,expression,order)
- local collected = { }
+ local collected, c = { }, 0
quit_expression = false
for l=1,#list do
local ll = list[l]
if expression(list,ll,l,order) then -- nasty, order alleen valid als n=1
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
end
if quit_expression then
break
@@ -7363,7 +7563,7 @@ local function nodesettostring(set,nodetest)
if not ns or ns == "" then ns = "*" end
if not tg or tg == "" then tg = "*" end
tg = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
- t[#t+1] = (directive and tg) or format("not(%s)",tg)
+ t[i] = (directive and tg) or format("not(%s)",tg)
end
if nodetest == false then
return format("not(%s)",concat(t,"|"))
@@ -7382,7 +7582,7 @@ local function tagstostring(list)
local ns, tg = li.ns, li.tg
if not ns or ns == "" then ns = "*" end
if not tg or tg == "" then tg = "*" end
- t[#t+1] = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
+ t[i] = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
end
return concat(t," ")
end
@@ -8102,16 +8302,17 @@ end
function xml.collect_tags(root, pattern, nonamespace)
local collected = xmlapplylpath(root,pattern)
if collected then
- local t = { }
+ local t, n = { }, 0
for c=1,#collected do
local e = collected[c]
local ns, tg = e.ns, e.tg
+ n = n + 1
if nonamespace then
- t[#t+1] = tg
+ t[n] = tg
elseif ns == "" then
- t[#t+1] = tg
+ t[n] = tg
else
- t[#t+1] = ns .. ":" .. tg
+ t[n] = ns .. ":" .. tg
end
end
return t
@@ -8219,8 +8420,10 @@ local function inject_element(root,pattern,whatever,prepend)
else
be, af = edt, cp
end
+ local bn = #be
for i=1,#af do
- be[#be+1] = af[i]
+ bn = bn + 1
+ be[bn] = af[i]
end
if rri then
r.dt[rri].dt = be
@@ -8305,11 +8508,12 @@ local function stripelement(e,nolines,anywhere)
local edt = e.dt
if edt then
if anywhere then
- local t = { }
+ local t, n = { }, 0
for e=1,#edt do
local str = edt[e]
if type(str) ~= "string" then
- t[#t+1] = str
+ n = n + 1
+ t[n] = str
elseif str ~= "" then
-- todo: lpeg for each case
if nolines then
@@ -8317,7 +8521,8 @@ local function stripelement(e,nolines,anywhere)
end
str = gsub(str,"^%s*(.-)%s*$","%1")
if str ~= "" then
- t[#t+1] = str
+ n = n + 1
+ t[n] = str
end
end
end
@@ -8344,9 +8549,10 @@ local function stripelement(e,nolines,anywhere)
end
end
end
- if #edt > 0 then
+ local nedt = #nedt
+ if nedt > 0 then
-- strip end
- local str = edt[#edt]
+ local str = edt[nedt]
if type(str) ~= "string" then
-- nothing
elseif str == "" then
@@ -8359,7 +8565,7 @@ local function stripelement(e,nolines,anywhere)
if str == "" then
remove(edt)
else
- edt[#edt] = str
+ edt[nedt] = str
end
end
end
@@ -8506,15 +8712,8 @@ local function all(collected)
return collected
end
-local function reverse(collected)
- if collected then
- local reversed = { }
- for c=#collected,1,-1 do
- reversed[#reversed+1] = collected[c]
- end
- return reversed
- end
-end
+
+local reverse = table.reversed
local function attribute(collected,name)
if collected and #collected > 0 then
@@ -8605,11 +8804,12 @@ end
local function texts(collected)
if collected then
- local t = { }
+ local t, n = { }, 0
for c=1,#collected do
local e = collection[c]
if e and e.dt then
- t[#t+1] = e.dt
+ n = n + 1
+ t[n] = e.dt
end
end
return t
@@ -8652,14 +8852,15 @@ end
local function tags(collected,nonamespace)
if collected then
- local t = { }
+ local t, n = { }, 0
for c=1,#collected do
local e = collected[c]
local ns, tg = e.ns, e.tg
+ n = n + 1
if nonamespace or ns == "" then
- t[#t+1] = tg
+ t[n] = tg
else
- t[#t+1] = ns .. ":" .. tg
+ t[n] = ns .. ":" .. tg
end
end
return t
@@ -8855,9 +9056,13 @@ end
do
- local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or '~'
+ local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
+
+ if not homedir or homedir == "" then
+ homedir = string.char(127) -- we need a value, later we wil trigger on it
+ end
- homedir = file.collapse_path(homedir)
+ homedir = file.collapsepath(homedir)
ossetenv("HOME", homedir) -- can be used in unix cnf files
ossetenv("USERPROFILE",homedir) -- can be used in windows cnf files
@@ -8876,8 +9081,8 @@ do
local ownbin = environment.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex"
local ownpath = environment.ownpath or os.selfdir
- ownbin = file.collapse_path(ownbin)
- ownpath = file.collapse_path(ownpath)
+ ownbin = file.collapsepath(ownbin)
+ ownpath = file.collapsepath(ownpath)
if not ownpath or ownpath == "" or ownpath == "unset" then
ownpath = args[-1] or arg[-1]
@@ -8949,9 +9154,9 @@ do
local ownpath = environment.ownpath or dir.current()
if ownpath then
- ossetenv('SELFAUTOLOC', file.collapse_path(ownpath))
- ossetenv('SELFAUTODIR', file.collapse_path(ownpath .. "/.."))
- ossetenv('SELFAUTOPARENT', file.collapse_path(ownpath .. "/../.."))
+ ossetenv('SELFAUTOLOC', file.collapsepath(ownpath))
+ ossetenv('SELFAUTODIR', file.collapsepath(ownpath .. "/.."))
+ ossetenv('SELFAUTOPARENT', file.collapsepath(ownpath .. "/../.."))
else
report_resolvers("error: unable to locate ownpath")
os.exit()
@@ -8987,7 +9192,7 @@ if not texroot or texroot == "" then
ossetenv('TEXROOT',texroot)
end
-environment.texroot = file.collapse_path(texroot)
+environment.texroot = file.collapsepath(texroot)
-- Tracing. Todo ...
@@ -9026,7 +9231,7 @@ local lpegCt, lpegCs, lpegP, lpegC, lpegS = lpeg.Ct, lpeg.Cs, lpeg.P, lpeg.C, lp
local type, next = type, next
local ostype = os.type
-local collapse_path = file.collapse_path
+local collapsepath = file.collapsepath
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
local trace_expansions = false trackers.register("resolvers.expansions", function(v) trace_expansions = v end)
@@ -9062,22 +9267,29 @@ local resolvers = resolvers
local dummy_path_expr = "^!*unset/*$"
local function do_first(a,b)
- local t = { }
- for s in gmatch(b,"[^,]+") do t[#t+1] = a .. s end
+ local t, n = { }, 0
+ for s in gmatch(b,"[^,]+") do
+ n = n + 1
+ t[n] = a .. s
+ end
return "{" .. concat(t,",") .. "}"
end
local function do_second(a,b)
- local t = { }
- for s in gmatch(a,"[^,]+") do t[#t+1] = s .. b end
+ local t, n = { }, 0
+ for s in gmatch(a,"[^,]+") do
+ n = n + 1
+ t[n] = s .. b
+ end
return "{" .. concat(t,",") .. "}"
end
local function do_both(a,b)
- local t = { }
+ local t, n = { }, 0
for sa in gmatch(a,"[^,]+") do
for sb in gmatch(b,"[^,]+") do
- t[#t+1] = sa .. sb
+ n = n + 1
+ t[n] = sa .. sb
end
end
return "{" .. concat(t,",") .. "}"
@@ -9101,6 +9313,7 @@ local function splitpathexpr(str, newlist, validate)
report_resolvers("expanding variable '%s'",str)
end
local t, ok, done = newlist or { }, false, false
+ local n = #t
str = lpegmatch(replacer_1,str)
while true do
done = false
@@ -9124,11 +9337,15 @@ local function splitpathexpr(str, newlist, validate)
if validate then
for s in gmatch(str,"[^,]+") do
s = validate(s)
- if s then t[#t+1] = s end
+ if s then
+ n = n + 1
+ t[n] = s
+ end
end
else
for s in gmatch(str,"[^,]+") do
- t[#t+1] = s
+ n = n + 1
+ t[n] = s
end
end
if trace_expansions then
@@ -9141,7 +9358,7 @@ end
local function validate(s)
local isrecursive = find(s,"//$")
- s = collapse_path(s)
+ s = collapsepath(s)
if isrecursive then
s = s .. "//"
end
@@ -9164,10 +9381,14 @@ function resolvers.expandedpathfromlist(pathlist) -- maybe not a list, just a pa
splitpathexpr(pathlist[k],newlist,validate)
end
else
+ local n = 0
for k=1,#pathlist do
for p in gmatch(pathlist[k],"([^,]+)") do
p = validate(p)
- if p ~= "" then newlist[#newlist+1] = p end
+ if p ~= "" then
+ n = n + 1
+ newlist[n] = p
+ end
end
end
end
@@ -9176,16 +9397,42 @@ end
-- We also put some cleanup code here.
-local cleanup -- used recursively
-cleanup = lpeg.replacer {
- { "!", "" },
- { "\\", "/" },
- { "~" , function() return lpegmatch(cleanup,environment.homedir) end },
+
+
+local cleanup = lpeg.replacer {
+ { "!" , "" },
+ { "\\" , "/" },
}
+local homedir
+
function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+ if not homedir then
+ homedir = lpegmatch(cleanup,environment.homedir or "")
+ if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_resolvers("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if find(str,"~") then
+ return "" -- special case
+ else
+ return str and lpegmatch(cleanup,str)
+ end
+ end
+ else
+ cleanup = lpeg.replacer {
+ { "!" , "" },
+ { "\\" , "/" },
+ { "~" , homedir },
+ }
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str)
+ end
+ end
+ end
+ return resolvers.cleanpath(str)
end
-- This one strips quotes and funny tokens.
@@ -9211,7 +9458,6 @@ end
-- we join them and split them after the expansion has taken place. This
-- is more convenient.
-
local cache = { }
local splitter = lpegCt(lpeg.splitat(lpegS(ostype == "windows" and ";" or ":;"))) -- maybe add ,
@@ -9226,15 +9472,17 @@ local function splitconfigurationpath(str) -- beware, this can be either a path
str = gsub(str,"\\","/")
local split = lpegmatch(splitter,str)
found = { }
+ local noffound = 0
for i=1,#split do
local s = split[i]
if not find(s,"^{*unset}*") then
- found[#found+1] = s
+ noffound = noffound + 1
+ found[noffound] = s
end
end
if trace_expansions then
report_resolvers("splitting path specification '%s'",str)
- for k=1,#found do
+ for k=1,noffound do
report_resolvers("% 4i: %s",k,found[k])
end
end
@@ -9357,7 +9605,6 @@ formats['enc'] = 'ENCFONTS' suffixes['enc'] = { 'enc' }
formats['fmt'] = 'TEXFORMATS' suffixes['fmt'] = { 'fmt' }
formats['map'] = 'TEXFONTMAPS' suffixes['map'] = { 'map' }
formats['mp'] = 'MPINPUTS' suffixes['mp'] = { 'mp' }
-formats['ocp'] = 'OCPINPUTS' suffixes['ocp'] = { 'ocp' }
formats['ofm'] = 'OFMFONTS' suffixes['ofm'] = { 'ofm', 'tfm' }
formats['otf'] = 'OPENTYPEFONTS' suffixes['otf'] = { 'otf' }
formats['opl'] = 'OPLFONTS' suffixes['opl'] = { 'opl' }
@@ -9582,7 +9829,7 @@ local function identify()
local cachepath = texmfcaches[k]
if cachepath ~= "" then
cachepath = resolvers.cleanpath(cachepath)
- cachepath = file.collapse_path(cachepath)
+ cachepath = file.collapsepath(cachepath)
local valid = isdir(cachepath)
if valid then
if file.is_readable(cachepath) then
@@ -9921,7 +10168,7 @@ function resolvers.splitmethod(filename)
end
function resolvers.methodhandler(what, filename, filetype) -- ...
- filename = file.collapse_path(filename)
+ filename = file.collapsepath(filename)
local specification = (type(filename) == "string" and resolvers.splitmethod(filename)) or filename -- no or { }, let it bomb
local scheme = specification.scheme
local resolver = resolvers[what]
@@ -9966,7 +10213,7 @@ local lpegP, lpegS, lpegR, lpegC, lpegCc, lpegCs, lpegCt = lpeg.P, lpeg.S, lpeg.
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local filedirname, filebasename, fileextname, filejoin = file.dirname, file.basename, file.extname, file.join
-local collapse_path = file.collapse_path
+local collapsepath = file.collapsepath
local allocate = utilities.storage.allocate
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10169,7 +10416,7 @@ local function identify_configuration_files()
expandvars(cnfpaths) --- hm
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
- local filename = collapse_path(filejoin(cnfpaths[i],luacnfname))
+ local filename = collapsepath(filejoin(cnfpaths[i],luacnfname))
if lfs.isfile(filename) then
specification[#specification+1] = filename
end
@@ -10330,7 +10577,7 @@ local function locate_file_databases()
-- todo: cache:// and tree:// (runtime)
local texmfpaths = resolvers.expandedpathlist('TEXMF')
for i=1,#texmfpaths do
- local path = collapse_path(texmfpaths[i])
+ local path = collapsepath(texmfpaths[i])
local stripped = gsub(path,"^!!","")
local runtime = stripped == path
path = resolvers.cleanpath(path)
@@ -10443,11 +10690,12 @@ end
function resolvers.splitexpansions()
local ie = instance.expansions
for k,v in next, ie do
- local t, h, p = { }, { }, splitconfigurationpath(v)
+ local t, tn, h, p = { }, 0, { }, splitconfigurationpath(v)
for kk=1,#p do
local vv = p[kk]
if vv ~= "" and not h[vv] then
- t[#t+1] = vv
+ tn = tn + 1
+ t[tn] = vv
h[vv] = true
end
end
@@ -10554,7 +10802,8 @@ end
function resolvers.registerextrapath(paths,subpaths)
local ep = instance.extra_paths or { }
- local n = #ep
+ local oldn = #ep
+ local newn = oldn
if paths and paths ~= "" then
if subpaths and subpaths ~= "" then
for p in gmatch(paths,"[^,]+") do
@@ -10562,7 +10811,8 @@ function resolvers.registerextrapath(paths,subpaths)
for s in gmatch(subpaths,"[^,]+") do
local ps = p .. "/" .. s
if not done[ps] then
- ep[#ep+1] = resolvers.cleanpath(ps)
+ newn = newn + 1
+ ep[newn] = resolvers.cleanpath(ps)
done[ps] = true
end
end
@@ -10570,7 +10820,8 @@ function resolvers.registerextrapath(paths,subpaths)
else
for p in gmatch(paths,"[^,]+") do
if not done[p] then
- ep[#ep+1] = resolvers.cleanpath(p)
+ newn = newn + 1
+ ep[newn] = resolvers.cleanpath(p)
done[p] = true
end
end
@@ -10581,16 +10832,17 @@ function resolvers.registerextrapath(paths,subpaths)
for s in gmatch(subpaths,"[^,]+") do
local ps = ep[i] .. "/" .. s
if not done[ps] then
- ep[#ep+1] = resolvers.cleanpath(ps)
+ newn = newn + 1
+ ep[newn] = resolvers.cleanpath(ps)
done[ps] = true
end
end
end
end
- if #ep > 0 then
+ if newn > 0 then
instance.extra_paths = ep -- register paths
end
- if #ep > n then
+ if newn > oldn then
instance.lists = { } -- erase the cache
end
end
@@ -10600,14 +10852,15 @@ local function made_list(instance,list)
if not ep or #ep == 0 then
return list
else
- local done, new = { }, { }
+ local done, new, newn = { }, { }, 0
-- honour . .. ../.. but only when at the start
for k=1,#list do
local v = list[k]
if not done[v] then
if find(v,"^[%.%/]$") then
done[v] = true
- new[#new+1] = v
+ newn = newn + 1
+ new[newn] = v
else
break
end
@@ -10618,7 +10871,8 @@ local function made_list(instance,list)
local v = ep[k]
if not done[v] then
done[v] = true
- new[#new+1] = v
+ newn = newn + 1
+ new[newn] = v
end
end
-- next the formal paths
@@ -10626,7 +10880,8 @@ local function made_list(instance,list)
local v = list[k]
if not done[v] then
done[v] = true
- new[#new+1] = v
+ newn = newn + 1
+ new[newn] = v
end
end
return new
@@ -10637,7 +10892,7 @@ function resolvers.cleanpathlist(str)
local t = resolvers.expandedpathlist(str)
if t then
for i=1,#t do
- t[i] = collapse_path(resolvers.cleanpath(t[i]))
+ t[i] = collapsepath(resolvers.cleanpath(t[i]))
end
end
return t
@@ -10703,7 +10958,7 @@ resolvers.isreadable.tex = resolvers.isreadable.file
-- name/name
local function collect_files(names)
- local filelist = { }
+ local filelist, noffiles = { }, 0
for k=1,#names do
local fname = names[k]
if trace_detail then
@@ -10744,7 +10999,8 @@ local function collect_files(names)
if trace_detail then
report_resolvers("match: kind '%s', search '%s', result '%s'",kind,search,result)
end
- filelist[#filelist+1] = { kind, search, result }
+ noffiles = noffiles + 1
+ filelist[noffiles] = { kind, search, result }
end
else
for kk=1,#blobfile do
@@ -10756,7 +11012,8 @@ local function collect_files(names)
if trace_detail then
report_resolvers("match: kind '%s', search '%s', result '%s'",kind,search,result)
end
- filelist[#filelist+1] = { kind, search, result }
+ noffiles = noffiles + 1
+ filelist[noffiles] = { kind, search, result }
end
end
end
@@ -10766,7 +11023,7 @@ local function collect_files(names)
end
end
end
- return #filelist > 0 and filelist or nil
+ return noffiles > 0 and filelist or nil
end
function resolvers.registerintrees(name)
@@ -10792,7 +11049,7 @@ end
local function collect_instance_files(filename,collected) -- todo : plugin (scanners, checkers etc)
local result = collected or { }
local stamp = nil
- filename = collapse_path(filename)
+ filename = collapsepath(filename)
-- speed up / beware: format problem
if instance.remember then
stamp = filename .. "--" .. instance.engine .. "--" .. instance.progname .. "--" .. instance.format
@@ -11045,7 +11302,7 @@ local function collect_instance_files(filename,collected) -- todo : plugin (scan
end
end
for k=1,#result do
- local rk = collapse_path(result[k])
+ local rk = collapsepath(result[k])
result[k] = rk
resolvers.registerintrees(rk) -- for tracing used files
end
@@ -12439,7 +12696,7 @@ function resolvers.load_tree(tree)
local texos = "texmf-" .. os.platform
local oldroot = environment.texroot
- local newroot = file.collapse_path(tree)
+ local newroot = file.collapsepath(tree)
local newtree = file.join(newroot,texos)
local newpath = file.join(newtree,"bin")
@@ -12668,17 +12925,17 @@ local format = string.format
-- helper for mtxrun
-local quote = string.quote
+local quoted = string.quoted
local function primaryflags()
local trackers = environment.argument("trackers")
local directives = environment.argument("directives")
local flags = ""
if trackers and trackers ~= "" then
- flags = flags .. "--trackers=" .. quote(trackers)
+ flags = flags .. "--trackers=" .. quoted(trackers)
end
if directives and directives ~= "" then
- flags = flags .. "--directives=" .. quote(directives)
+ flags = flags .. "--directives=" .. quoted(directives)
end
return flags
end
@@ -12743,7 +13000,7 @@ function environment.make_format(name)
return
end
-- generate format
- local command = format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quote(usedluastub),quote(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
+ local command = format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
logs.simple("running command: %s\n",command)
os.spawn(command)
-- remove related mem files
@@ -12781,8 +13038,7 @@ function environment.run_format(name,data,more)
logs.simple("using format name: %s",fmtname)
logs.simple("no luc/lua with name: %s",barename)
else
- local q = string.quote
- local command = format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quote(barename),quote(luaname),quote(data),more ~= "" and quote(more) or "")
+ local command = format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quoted(barename),quoted(luaname),quoted(data),more ~= "" and quoted(more) or "")
logs.simple("running command: %s",command)
os.spawn(command)
end
@@ -12813,13 +13069,13 @@ own.libs = { -- order can be made better
'l-unicode.lua',
'l-math.lua',
+ 'util-tab.lua',
+ 'util-sto.lua',
'util-mrg.lua',
'util-lua.lua',
'util-prs.lua',
- 'util-tab.lua',
'util-fmt.lua',
'util-deb.lua',
- 'util-sto.lua',
'trac-inf.lua',
'trac-set.lua',
diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun
index d091fa405..7af51ba30 100644
--- a/scripts/context/stubs/unix/mtxrun
+++ b/scripts/context/stubs/unix/mtxrun
@@ -54,7 +54,7 @@ if not modules then modules = { } end modules ['l-string'] = {
local string = string
local sub, gsub, find, match, gmatch, format, char, byte, rep, lower = string.sub, string.gsub, string.find, string.match, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
-local lpegmatch = lpeg.match
+local lpegmatch, S, C, Ct = lpeg.match, lpeg.S, lpeg.C, lpeg.Ct
-- some functions may disappear as they are not used anywhere
@@ -62,145 +62,68 @@ if not string.split then
-- this will be overloaded by a faster lpeg variant
- function string:split(pattern)
- if #self > 0 then
- local t = { }
- for s in gmatch(self..pattern,"(.-)"..pattern) do
- t[#t+1] = s
+ function string.split(str,pattern)
+ local t = { }
+ if #str > 0 then
+ local n = 1
+ for s in gmatch(str..pattern,"(.-)"..pattern) do
+ t[n] = s
+ n = n + 1
end
- return t
- else
- return { }
end
+ return t
end
end
-string.patterns = { }
-
-local escapes = {
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["^"] = "%^", ["$"] = "%$",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%(", [")"] = "%)",
- ["{"] = "%{", ["}"] = "%}"
-}
-
-string.patterns.escapes = escapes
-
-function string:esc() -- variant 2
- return (gsub(self,"(.)",escapes))
-end
-
-function string:unquote()
- return (gsub(self,"^([\"\'])(.*)%1$","%2"))
+function string.unquoted(str)
+ return (gsub(str,"^([\"\'])(.*)%1$","%2"))
end
-function string:quote() -- we could use format("%q")
- return format("%q",self)
+function string.quoted(str)
+ return format("%q",str) -- always "
end
-function string:count(pattern) -- variant 3
+function string.count(str,pattern) -- variant 3
local n = 0
- for _ in gmatch(self,pattern) do
+ for _ in gmatch(str,pattern) do -- not for utf
n = n + 1
end
return n
end
-function string:limit(n,sentinel)
- if #self > n then
+function string.limit(str,n,sentinel)
+ if #str > n then
sentinel = sentinel or " ..."
- return sub(self,1,(n-#sentinel)) .. sentinel
+ return sub(str,1,(n-#sentinel)) .. sentinel
else
- return self
- end
-end
-
-
-do -- roberto's variant:
- local space = lpeg.S(" \t\v\n")
- local nospace = 1 - space
- local stripper = space^0 * lpeg.C((space^0 * nospace^1)^0)
- function string.strip(str)
- return lpegmatch(stripper,str) or ""
- end
-end
-
-function string:is_empty()
- return not find(self,"%S")
-end
-
-function string:enhance(pattern,action)
- local ok, n = true, 0
- while ok do
- ok = false
- self = gsub(self,pattern, function(...)
- ok, n = true, n + 1
- return action(...)
- end)
+ return str
end
- return self, n
end
-if not string.characters then
-
- local function nextchar(str, index)
- index = index + 1
- return (index <= #str) and index or nil, sub(str,index,index)
- end
- function string:characters()
- return nextchar, self, 0
- end
- local function nextbyte(str, index)
- index = index + 1
- return (index <= #str) and index or nil, byte(sub(str,index,index))
- end
- function string:bytes()
- return nextbyte, self, 0
- end
+local space = S(" \t\v\n")
+local nospace = 1 - space
+local stripper = space^0 * C((space^0 * nospace^1)^0) -- roberto's code
+function string.strip(str)
+ return lpegmatch(stripper,str) or ""
end
-function string:rpadd(n,chr)
- local m = n-#self
- if m > 0 then
- return self .. rep(chr or " ",m)
- else
- return self
- end
-end
-
-function string:lpadd(n,chr)
- local m = n-#self
- if m > 0 then
- return rep(chr or " ",m) .. self
- else
- return self
- end
+function string.is_empty(str)
+ return not find(str,"%S")
end
-string.padd = string.rpadd
-
local patterns_escapes = {
- ["-"] = "%-",
- ["."] = "%.",
- ["+"] = "%+",
- ["*"] = "%*",
["%"] = "%%",
- ["("] = "%)",
- [")"] = "%)",
- ["["] = "%[",
- ["]"] = "%]",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
}
-function string:escapedpattern()
- return (gsub(self,".",patterns_escapes))
-end
-
local simple_escapes = {
["-"] = "%-",
["."] = "%.",
@@ -208,24 +131,32 @@ local simple_escapes = {
["*"] = ".*",
}
-function string:partialescapedpattern()
- return (gsub(self,".",simple_escapes))
+function string.escapedpattern(str,simple)
+ if simple then
+ return (gsub(str,".",simple_escapes))
+ else
+ return (gsub(str,".",patterns_escapes))
+ end
end
-function string:tohash()
- local t = { }
- for s in gmatch(self,"([^, ]+)") do -- lpeg
- t[s] = true
+function string.topattern(str,lowercase,strict)
+ if str == "" then
+ return ".*"
+ else
+ str = gsub(str,".",simple_escapes)
+ if lowercase then
+ str = lower(str)
+ end
+ if strict then
+ return "^" .. str .. "$"
+ else
+ return str
+ end
end
- return t
end
-local pattern = lpeg.Ct(lpeg.C(1)^0)
-
-function string:totable()
- return lpegmatch(pattern,self)
-end
+-- The following functions might end up in another namespace.
function string.tabtospace(str,tab)
-- we don't handle embedded newlines
@@ -246,30 +177,17 @@ function string.tabtospace(str,tab)
return str
end
-function string:compactlong() -- strips newlines and leading spaces
- self = gsub(self,"[\n\r]+ *","")
- self = gsub(self,"^ *","")
- return self
-end
-function string:striplong() -- strips newlines and leading spaces
- self = gsub(self,"^%s*","")
- self = gsub(self,"[\n\r]+ *","\n")
- return self
+function string.striplong(str) -- strips all leading spaces
+ str = gsub(str,"^%s*","")
+ str = gsub(str,"[\n\r]+ *","\n")
+ return str
end
-function string:topattern(lowercase,strict)
- if lowercase then
- self = lower(self)
- end
- self = gsub(self,".",simple_escapes)
- if self == "" then
- self = ".*"
- elseif strict then
- self = "^" .. self .. "$"
- end
- return self
-end
+-- obsolete names:
+
+string.quote = string.quoted
+string.unquote = string.unquoted
end -- of closure
@@ -292,15 +210,29 @@ local patterns = lpeg.patterns
local P, R, S, Ct, C, Cs, Cc, V = lpeg.P, lpeg.R, lpeg.S, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.V
local match = lpeg.match
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
local digit, sign = R('09'), S('+-')
local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local utf8byte = R("\128\191")
+local utf8next = R("\128\191")
+local escaped = P("\\") * P(1)
+local squote = P("'")
+local dquote = P('"')
-patterns.utf8byte = utf8byte
patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8byte
-patterns.utf8three = R("\224\239") * utf8byte * utf8byte
-patterns.utf8four = R("\240\244") * utf8byte * utf8byte * utf8byte
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = P('\000\000\254\255') + P('\255\254\000\000') + P('\255\254') + P('\254\255') + P('\239\187\191')
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * P(-1) * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
patterns.digit = digit
patterns.sign = sign
@@ -327,17 +259,24 @@ patterns.nonspace = 1 - patterns.space
patterns.nonspacer = 1 - patterns.spacer
patterns.whitespace = patterns.eol + patterns.spacer
patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.utf8 = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-patterns.utfbom = P('\000\000\254\255') + P('\255\254\000\000') + P('\255\254') + P('\254\255') + P('\239\187\191')
-patterns.validutf8 = patterns.utf8^0 * P(-1) * Cc(true) + Cc(false)
patterns.comma = P(",")
patterns.commaspacer = P(",") * patterns.spacer^0
patterns.period = P(".")
-
-patterns.undouble = P('"')/"" * (1-P('"'))^0 * P('"')/""
-patterns.unsingle = P("'")/"" * (1-P("'"))^0 * P("'")/""
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.undouble = (dquote/"") * ((escaped + (1-dquote))^0) * (dquote/"")
+patterns.unsingle = (squote/"") * ((escaped + (1-squote))^0) * (squote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
patterns.unspacer = ((patterns.spacer^1)/"")^0
+local unquoted = Cs(patterns.unquoted * P(-1)) -- not C
+
+function string.unquoted(str)
+ return match(unquoted,str) or str
+end
+
+
function lpeg.anywhere(pattern) --slightly adapted from website
return P { P(pattern) + 1 * V(1) } -- why so complex?
end
@@ -353,8 +292,8 @@ local content = (empty + nonempty)^1
local capture = Ct(content^0)
-function string:splitlines()
- return match(capture,self)
+function string.splitlines(str)
+ return match(capture,str)
end
patterns.textline = content
@@ -366,12 +305,12 @@ 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 other, any = C((1 - separator)^0), P(1)
+ local any = P(1)
splitter = other * (separator * C(any^0) + "") -- ?
splitters_s[separator] = splitter
else
- local other = C((1 - separator)^0)
splitter = other * (separator * other)^0
splitters_m[separator] = splitter
end
@@ -392,16 +331,15 @@ function lpeg.split(separator,str)
return match(c,str)
end
-function string:split(separator)
+function string.split(str,separator)
local c = cache[separator]
if not c then
c = Ct(splitat(separator))
cache[separator] = c
end
- return match(c,self)
+ return match(c,str)
end
-lpeg.splitters = cache
local cache = { }
@@ -409,22 +347,22 @@ function lpeg.checkedsplit(separator,str)
local c = cache[separator]
if not c then
separator = P(separator)
- local other = C((1 - separator)^0)
+ local other = C((1 - separator)^1)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
return match(c,str)
end
-function string:checkedsplit(separator)
+function string.checkedsplit(str,separator)
local c = cache[separator]
if not c then
separator = P(separator)
- local other = C((1 - separator)^0)
+ local other = C((1 - separator)^1)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
- return match(c,self)
+ return match(c,str)
end
@@ -435,7 +373,9 @@ local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2
local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-patterns.utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
@@ -469,19 +409,25 @@ function lpeg.keeper(str)
end
end
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
function lpeg.replacer(t)
if #t > 0 then
local p
for i=1,#t do
local ti= t[i]
local pp = P(ti[1]) / ti[2]
- p = (p and p + pp ) or pp
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
end
return Cs((p + 1)^0)
end
end
-
local splitters_f, splitters_s = { }, { }
function lpeg.firstofsplit(separator) -- always return value
@@ -505,11 +451,170 @@ function lpeg.secondofsplit(separator) -- nil if not split
end
function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
return P { left * ((1 - left - right) + V(1))^0 * right }
end
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + P(1))^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + P(1))^0)
+
+function string.escapedpattern(str,simple)
+ if simple then
+ return match(s,str)
+ else
+ return match(p,str)
+ end
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -577,24 +682,26 @@ end
-- extra functions, some might go (when not used)
function table.strip(tab)
- local lst = { }
+ local lst, l = { }, 0
for i=1,#tab do
local s = gsub(tab[i],"^%s*(.-)%s*$","%1")
if s == "" then
-- skip this one
else
- lst[#lst+1] = s
+ l = l + 1
+ lst[l] = s
end
end
return lst
end
function table.keys(t)
- local k = { }
+ local keys, k = { }, 0
for key, _ in next, t do
- k[#k+1] = key
+ k = k + 1
+ keys[k] = key
end
- return k
+ return keys
end
local function compare(a,b)
@@ -607,9 +714,10 @@ local function compare(a,b)
end
local function sortedkeys(tab)
- local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed
+ local srt, kind, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
for key,_ in next, tab do
- srt[#srt+1] = key
+ s = s + 1
+ srt[s] = key
if kind == 3 then
-- no further check
else
@@ -632,10 +740,11 @@ local function sortedkeys(tab)
end
local function sortedhashkeys(tab) -- fast one
- local srt = { }
+ local srt, s = { }, 0
for key,_ in next, tab do
if key then
- srt[#srt+1] = key
+ s= s + 1
+ srt[s] = key
end
end
sort(srt)
@@ -649,8 +758,7 @@ local function nothing() end
local function sortedhash(t)
if t then
- local s = sortedhashkeys(t) -- maybe just sortedkeys
- local n = 0
+ local n, s = 0, sortedkeys(t) -- the robust one
local function kv(s)
n = n + 1
local k = s[n]
@@ -666,20 +774,30 @@ table.sortedhash = sortedhash
table.sortedpairs = sortedhash
function table.append(t, list)
- for _,v in next, list do
- insert(t,v)
+ local n = #t
+ for i=1,#list do
+ n = n + 1
+ t[n] = list[i]
end
+ return t
end
function table.prepend(t, list)
- for k,v in next, list do
- insert(t,k,v)
+ 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, ...) -- first one is target
t = t or { }
- local lst = {...}
+ local lst = { ... }
for i=1,#lst do
for k, v in next, lst[i] do
t[k] = v
@@ -689,7 +807,7 @@ function table.merge(t, ...) -- first one is target
end
function table.merged(...)
- local tmp, lst = { }, {...}
+ local tmp, lst = { }, { ... }
for i=1,#lst do
for k, v in next, lst[i] do
tmp[k] = v
@@ -699,22 +817,24 @@ function table.merged(...)
end
function table.imerge(t, ...)
- local lst = {...}
+ local lst, nt = { ... }, #t
for i=1,#lst do
local nst = lst[i]
for j=1,#nst do
- t[#t+1] = nst[j]
+ nt = nt + 1
+ t[nt] = nst[j]
end
end
return t
end
function table.imerged(...)
- local tmp, lst = { }, {...}
+ local tmp, ntmp, lst = { }, 0, {...}
for i=1,#lst do
local nst = lst[i]
for j=1,#nst do
- tmp[#tmp+1] = nst[j]
+ ntmp = ntmp + 1
+ tmp[ntmp] = nst[j]
end
end
return tmp
@@ -790,11 +910,14 @@ function table.tohash(t,value)
end
function table.fromhash(t)
- local h = { }
+ local hsh, h = { }, 0
for k, v in next, t do -- no ipairs here
- if v then h[#h+1] = k end
+ if v then
+ h = h + 1
+ hsh[h] = k
+ end
end
- return h
+ return hsh
end
table.serialize_functions = true
@@ -815,20 +938,23 @@ local function simple_table(t)
n = n + 1
end
if n == #t then
- local tt = { }
+ local tt, nt = { }, 0
for i=1,#t do
local v = t[i]
local tv = type(v)
if tv == "number" then
+ nt = nt + 1
if hexify then
- tt[#tt+1] = format("0x%04X",v)
+ tt[nt] = format("0x%04X",v)
else
- tt[#tt+1] = tostring(v) -- tostring not needed
+ tt[nt] = tostring(v) -- tostring not needed
end
elseif tv == "boolean" then
- tt[#tt+1] = tostring(v)
+ nt = nt + 1
+ tt[nt] = tostring(v)
elseif tv == "string" then
- tt[#tt+1] = format("%q",v)
+ nt = nt + 1
+ tt[nt] = format("%q",v)
else
tt = nil
break
@@ -1123,10 +1249,11 @@ local function serialize(root,name,_handle,_reduce,_noquotes,_hexify)
end
-function table.serialize(root,name,reduce,noquotes,hexify)
- local t = { }
+function table.serialize(root,name,reduce,noquotes,hexify) -- can be faster if flush == false and t as argument
+ local t, n = { }, 0
local function flush(s)
- t[#t+1] = s
+ n = n + 1
+ t[n] = s
end
serialize(root,name,flush,reduce,noquotes,hexify)
return concat(t,"\n")
@@ -1152,12 +1279,13 @@ function table.tofile(filename,root,name,reduce,noquotes,hexify)
if f then
local maxtab = table.tofile_maxtab
if maxtab > 1 then
- local t = { }
+ local t, n = { }, 0
local function flush(s)
- t[#t+1] = s
- if #t > maxtab then
+ n = n + 1
+ t[n] = s
+ if n > maxtab then
f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
- t = { }
+ t, n = { }, 0 -- we could recycle t if needed
end
end
serialize(root,name,flush,reduce,noquotes,hexify)
@@ -1173,52 +1301,66 @@ function table.tofile(filename,root,name,reduce,noquotes,hexify)
end
end
-local function flatten(t,f,complete) -- is this used? meybe a variant with next, ...
- for i=1,#t do
- local v = t[i]
- if type(v) == "table" then
- if complete or type(v[1]) == "table" then
- flatten(v,f,complete)
+local function flattened(t,f,depth)
+ if f == nil then
+ f = { }
+ depth = 0xFFFF
+ elseif tonumber(f) then
+ -- assume then only two arguments are given
+ 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
+ f[k] = v
end
+ end
+ end
+ local n = #f
+ for k=1,#t do
+ local v = t[k]
+ if depth > 0 and type(v) == "table" then
+ flattened(v,f,depth-1)
+ n = #f
else
- f[#f+1] = v
+ n = n + 1
+ f[n] = v
end
end
-end
-
-function table.flatten(t)
- local f = { }
- flatten(t,f,true)
return f
end
-function table.unnest(t) -- bad name
- local f = { }
- flatten(t,f,false)
- return f
-end
-
-table.flattenonelevel = table.unnest
-
--- a better one:
+table.flattened = flattened
-local function flattened(t,f)
- if not f then
+local function unnest(t,f) -- only used in mk, for old times sake
+ if not f then -- and only relevant for token lists
f = { }
end
- for k, v in next, t do
+ for i=1,#t do
+ local v = t[i]
if type(v) == "table" then
- flattened(v,f)
+ if type(v[1]) == "table" then
+ unnest(v,f)
+ else
+ f[#f+1] = v
+ end
else
- f[k] = v
+ f[#f+1] = v
end
end
return f
end
-table.flattened = flattened
+function table.unnest(t) -- bad name
+ return unnest(t)
+end
+
+
local function are_equal(a,b,n,m) -- indexed
if a and b and #a == #b then
@@ -1244,7 +1386,7 @@ end
local function identical(a,b) -- assumes same structure
for ka, va in next, a do
- local vb = b[k]
+ local vb = b[ka]
if va == vb then
-- same
elseif type(va) == "table" and type(vb) == "table" then
@@ -1258,8 +1400,8 @@ local function identical(a,b) -- assumes same structure
return true
end
-table.are_equal = are_equal
table.identical = identical
+table.are_equal = are_equal
-- maybe also make a combined one
@@ -1285,14 +1427,14 @@ function table.contains(t, v)
end
function table.count(t)
- local n, e = 0, next(t)
- while e do
- n, e = n + 1, next(t,e)
+ local n = 0
+ for k, v in next, t do
+ n = n + 1
end
return n
end
-function table.swapped(t,s)
+function table.swapped(t,s) -- hash
local n = { }
if s then
for k, v in next, s do
@@ -1305,52 +1447,34 @@ function table.swapped(t,s)
return n
end
-
-function table.clone(t,p) -- t is optional or nil or table
- if not p then
- t, p = { }, t or { }
- elseif not t then
- t = { }
- end
- setmetatable(t, { __index = function(_,key) return p[key] end }) -- why not __index = p ?
- return t
-end
-
-function table.hexed(t,seperator)
- local tt = { }
- for i=1,#t do tt[i] = format("0x%04X",t[i]) end
- return concat(tt,seperator or " ")
-end
-
-function table.swaphash(h) -- needs another name
- local r = { }
- for k,v in next, h do
- r[v] = lower(gsub(k," ",""))
- end
- return r
-end
-
-function table.reverse(t)
- local tt = { }
- if #t > 0 then
- for i=#t,1,-1 do
- tt[#tt+1] = t[i]
+function table.reversed(t)
+ if t then
+ local tt, tn = { }, #t
+ if tn > 0 then
+ local ttn = 0
+ for i=tn,1,-1 do
+ ttn = ttn + 1
+ tt[ttn] = t[i]
+ end
end
+ return tt
end
- return tt
end
function table.sequenced(t,sep,simple) -- hash only
- local s = { }
+ local s, n = { }, 0
for k, v in sortedhash(t) do
if simple then
if v == true then
- s[#s+1] = k
+ n = n + 1
+ s[n] = k
elseif v and v~= "" then
- s[#s+1] = k .. "=" .. tostring(v)
+ n = n + 1
+ s[n] = k .. "=" .. tostring(v)
end
else
- s[#s+1] = k .. "=" .. tostring(v)
+ n = n + 1
+ s[n] = k .. "=" .. tostring(v)
end
end
return concat(s, sep or " | ")
@@ -1360,7 +1484,7 @@ function table.print(...)
table.tohandle(print,...)
end
--- -- -- obsolete but we keep them for a while and will comment them later -- -- --
+-- -- -- obsolete but we keep them for a while and might comment them later -- -- --
-- roughly: copy-loop : unpack : sub == 0.9 : 0.4 : 0.45 (so in critical apps, use unpack)
@@ -1375,14 +1499,7 @@ function table.is_empty(t)
end
function table.has_one_entry(t)
- local n = next(t)
- return n and not next(t,n)
-end
-
-function table.replace(a,b)
- for k,v in next, b do
- a[k] = v
- end
+ return t and not next(t,next(t))
end
@@ -1627,6 +1744,8 @@ if not modules then modules = { } end modules ['l-number'] = {
license = "see context related readme files"
}
+-- this module will be replaced when we have the bit library
+
local tostring = tostring
local format, floor, insert, match = string.format, math.floor, string.match
local concat, insert = table.concat, table.insert
@@ -1768,10 +1887,11 @@ function set.tolist(n)
if n == 0 or not tabs[n] then
return ""
else
- local t = { }
+ local t, n = { }, 0
for k, v in next, tabs[n] do
if v then
- t[#t+1] = k
+ n = n + 1
+ t[n] = k
end
end
return concat(t," ")
@@ -1950,7 +2070,7 @@ end
-- no need for function anymore as we have more clever code and helpers now
-- this metatable trickery might as well disappear
-os.resolvers = os.resolvers or { }
+os.resolvers = os.resolvers or { } -- will become private
local resolvers = os.resolvers
@@ -2279,7 +2399,7 @@ end
file.isreadable = file.is_readable -- depricated
file.iswritable = file.is_writable -- depricated
--- todo: lpeg
+-- todo: lpeg \\ / .. does not save much
local checkedsplit = string.checkedsplit
@@ -2295,7 +2415,7 @@ end
-- we can hash them weakly
-function file.collapse_path(str,anchor)
+function file.collapsepath(str,anchor)
if anchor and not find(str,"^/") and not find(str,"^%a:") then
str = getcurrentdir() .. "/" .. str
end
@@ -2350,6 +2470,8 @@ function file.collapse_path(str,anchor)
end
end
+file.collapse_path = file.collapsepath
+
function file.robustname(str)
return (gsub(str,"[^%a%d%/%-%.\\]+","-"))
@@ -2782,9 +2904,12 @@ local function glob(str,t)
end
return t
elseif isfile(str) then
- local t = t or { }
- t[#t+1] = str
- return t
+ if t then
+ t[#t+1] = str
+ return t
+ else
+ return { str }
+ end
else
local split = lpegmatch(pattern,str)
if split then
@@ -2812,6 +2937,7 @@ local function globfiles(path,recurse,func,files) -- func == pattern or function
func = function(name) return find(name,s) end
end
files = files or { }
+ local noffiles = #files
for name in walkdir(path) do
if find(name,"^%.") then
--- skip
@@ -2822,12 +2948,9 @@ local function globfiles(path,recurse,func,files) -- func == pattern or function
globfiles(path .. "/" .. name,recurse,func,files)
end
elseif mode == "file" then
- if func then
- if func(name) then
- files[#files+1] = path .. "/" .. name
- end
- else
- files[#files+1] = path .. "/" .. name
+ if not func or func(name) then
+ noffiles = noffiles + 1
+ files[noffiles] = path .. "/" .. name
end
end
end
@@ -3012,8 +3135,12 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
+-- function boolean.tonumber(b)
+-- return b and 1 or 0 -- test and test and return or return
+-- end
+
function boolean.tonumber(b)
- if b then return 1 else return 0 end
+ if b then return 1 else return 0 end -- test and return or return
end
function toboolean(str,tolerant)
@@ -3037,6 +3164,8 @@ function toboolean(str,tolerant)
end
end
+string.toboolean = toboolean
+
function string.is_boolean(str,default)
if type(str) == "string" then
if str == "true" or str == "yes" or str == "on" or str == "t" then
@@ -3048,14 +3177,6 @@ function string.is_boolean(str,default)
return default
end
-function boolean.alwaystrue()
- return true
-end
-
-function boolean.falsetrue()
- return false
-end
-
end -- of closure
@@ -3144,30 +3265,37 @@ function unicode.utftype(f)
end
function unicode.utf16_to_utf8(str, endian) -- maybe a gsub is faster or an lpeg
- local result, tmp, n, m, p = { }, { }, 0, 0, 0
+ local result, tmp, n, m, p, r, t = { }, { }, 0, 0, 0, 0, 0 -- we reuse tmp
-- lf | cr | crlf / (cr:13, lf:10)
local function doit()
if n == 10 then
if p ~= 13 then
- result[#result+1] = concat(tmp)
- tmp = { }
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
+ t = 0
+ end
p = 0
end
elseif n == 13 then
- result[#result+1] = concat(tmp)
- tmp = { }
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
+ t = 0
+ end
p = n
else
- tmp[#tmp+1] = utfchar(n)
+ t = t + 1
+ tmp[t] = utfchar(n)
p = 0
end
end
for l,r in bytepairs(str) do
if r then
if endian then
- n = l*256 + r
+ n = 256*l + r
else
- n = r*256 + l
+ n = 256*r + l
end
if m > 0 then
n = (m-0xD800)*0x400 + (n-0xDC00) + 0x10000
@@ -3180,29 +3308,36 @@ function unicode.utf16_to_utf8(str, endian) -- maybe a gsub is faster or an lpeg
end
end
end
- if #tmp > 0 then
- result[#result+1] = concat(tmp)
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
end
return result
end
function unicode.utf32_to_utf8(str, endian)
- local result = { }
- local tmp, n, m, p = { }, 0, -1, 0
+ local result, tmp, n, m, p, r, t = { }, { }, 0, -1, 0, 0, 0
-- lf | cr | crlf / (cr:13, lf:10)
local function doit()
if n == 10 then
if p ~= 13 then
- result[#result+1] = concat(tmp)
- tmp = { }
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
+ t = 0
+ end
p = 0
end
elseif n == 13 then
- result[#result+1] = concat(tmp)
- tmp = { }
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
+ t = 0
+ end
p = n
else
- tmp[#tmp+1] = utfchar(n)
+ t = t + 1
+ tmp[t] = utfchar(n)
p = 0
end
end
@@ -3210,15 +3345,15 @@ function unicode.utf32_to_utf8(str, endian)
if a and b then
if m < 0 then
if endian then
- m = a*256*256*256 + b*256*256
+ m = 256*256*256*a + 256*256*b
else
- m = b*256 + a
+ m = 256*b + a
end
else
if endian then
- n = m + a*256 + b
+ n = m + 256*a + b
else
- n = m + b*256*256*256 + a*256*256
+ n = m + 256*256*256*b + 256*256*a
end
m = -1
doit()
@@ -3228,13 +3363,14 @@ function unicode.utf32_to_utf8(str, endian)
end
end
if #tmp > 0 then
- result[#result+1] = concat(tmp)
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
end
return result
end
local function little(c)
- local b = byte(c) -- b = c:byte()
+ local b = byte(c)
if b < 0x10000 then
return char(b%256,b/256)
else
@@ -3264,9 +3400,10 @@ function unicode.utf8_to_utf16(str,littleendian)
end
function unicode.utfcodes(str)
- local t = { }
- for k,v in utfvalues(str) do
- t[#t+1] = format("0x%04X",k)
+ local t, n = { }, 0
+ for u in utfvalues(str) do
+ n = n + 1
+ t[n] = format("0x%04X",u)
end
return concat(t,separator or " ")
end
@@ -3324,6 +3461,189 @@ end -- of closure
do -- create closure to overcome 200 locals limit
+if not modules then modules = { } end modules ['util-tab'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+utilities = utilities or {}
+utilities.tables = utilities.tables or { }
+local tables = utilities.tables
+
+local format, gmatch = string.format, string.gmatch
+local concat, insert, remove = table.concat, table.insert, table.remove
+local setmetatable = setmetatable
+
+function tables.definetable(target) -- defines undefined tables
+ local composed, t, n = nil, { }, 0
+ for name in gmatch(target,"([^%.]+)") do
+ n = n + 1
+ if composed then
+ composed = composed .. "." .. name
+ else
+ composed = name
+ end
+ t[n] = format("%s = %s or { }",composed,composed)
+ end
+ return concat(t,"\n")
+end
+
+function tables.accesstable(target)
+ local t = _G
+ for name in gmatch(target,"([^%.]+)") do
+ t = t[name]
+ end
+ return t
+end
+
+function tables.removevalue(t,value) -- todo: n
+ if value then
+ for i=1,#t do
+ if t[i] == value then
+ remove(t,i)
+ -- remove all, so no: return
+ end
+ end
+ end
+end
+
+function tables.insertbeforevalue(t,value,extra)
+ for i=1,#t do
+ if t[i] == extra then
+ remove(t,i)
+ end
+ end
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i,extra)
+ return
+ end
+ end
+ insert(t,1,extra)
+end
+
+function tables.insertaftervalue(t,value,extra)
+ for i=1,#t do
+ if t[i] == extra then
+ remove(t,i)
+ end
+ end
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i+1,extra)
+ return
+ end
+ end
+ insert(t,#t+1,extra)
+end
+
+local _empty_table_ = { __index = function(t,k) return "" end }
+
+function table.setemptymetatable(t)
+ setmetatable(t,_empty_table_)
+end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['util-sto'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local setmetatable, getmetatable = setmetatable, getmetatable
+
+utilities = utilities or { }
+utilities.storage = utilities.storage or { }
+local storage = utilities.storage
+
+function storage.mark(t)
+ if not t then
+ texio.write_nl("fatal error: storage '%s' cannot be marked",t)
+ os.exit()
+ end
+ local m = getmetatable(t)
+ if not m then
+ m = { }
+ setmetatable(t,m)
+ end
+ m.__storage__ = true
+ return t
+end
+
+function storage.allocate(t)
+ t = t or { }
+ local m = getmetatable(t)
+ if not m then
+ m = { }
+ setmetatable(t,m)
+ end
+ m.__storage__ = true
+ return t
+end
+
+function storage.marked(t)
+ local m = getmetatable(t)
+ return m and m.__storage__
+end
+
+function storage.checked(t)
+ if not t then
+ texio.write_nl("fatal error: storage '%s' has not been allocated",t)
+ os.exit()
+ end
+ return t
+end
+
+function setmetatablekey(t,key,value)
+ local m = getmetatable(t)
+ if not m then
+ m = { }
+ setmetatable(t,m)
+ end
+ m[key] = value
+end
+
+function getmetatablekey(t,key,value)
+ local m = getmetatable(t)
+ return m and m[key]
+end
+
+
+function storage.setinitializer(data,initialize)
+ local m = getmetatable(data) or { }
+ m.__index = function(data,k)
+ m.__index = nil -- so that we can access the entries during initializing
+ initialize()
+ return data[k]
+ end
+ setmetatable(data, m)
+end
+
+local keyisvalue = { __index = function(t,k)
+ t[k] = k
+ return k
+end }
+
+function storage.sparse(t)
+ t = t or { }
+ setmetatable(t,keyisvalue)
+ return t
+end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
if not modules then modules = { } end modules ['util-mrg'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -3483,7 +3803,7 @@ utilities.report = utilities.report or print
function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
- local command = "-o " .. string.quote(lucfile) .. " " .. string.quote(luafile)
+ local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
@@ -3496,6 +3816,12 @@ function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: clean
end
+
+
+
+
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3516,7 +3842,7 @@ parsers.patterns = parsers.patterns or { }
local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
local lpegmatch = lpeg.match
local concat, format, gmatch = table.concat, string.format, string.gmatch
-local tostring, type, next = tostring, type, next
+local tostring, type, next, setmetatable = tostring, type, next, setmetatable
local sortedhash = table.sortedhash
local escape, left, right = P("\\"), P('{'), P('}')
@@ -3635,7 +3961,7 @@ end
function parsers.hash_to_string(h,separator,yes,no,strict,omit)
if h then
- local t, s = { }, table.sortedkeys(h)
+ local t, tn, s = { }, 0, table.sortedkeys(h)
omit = omit and table.tohash(omit)
for i=1,#s do
local key = s[i]
@@ -3644,15 +3970,19 @@ function parsers.hash_to_string(h,separator,yes,no,strict,omit)
if type(value) == "boolean" then
if yes and no then
if value then
- t[#t+1] = key .. '=' .. yes
+ tn = tn + 1
+ t[tn] = key .. '=' .. yes
elseif not strict then
- t[#t+1] = key .. '=' .. no
+ tn = tn + 1
+ t[tn] = key .. '=' .. no
end
elseif value or not strict then
- t[#t+1] = key .. '=' .. tostring(value)
+ tn = tn + 1
+ t[tn] = key .. '=' .. tostring(value)
end
else
- t[#t+1] = key .. '=' .. value
+ tn = tn + 1
+ t[tn] = key .. '=' .. value
end
end
end
@@ -3679,10 +4009,11 @@ function parsers.settings_to_set(str,t) -- tohash? -- todo: lpeg -- duplicate an
end
function parsers.simple_hash_to_string(h, separator)
- local t = { }
+ local t, tn = { }, 0
for k, v in sortedhash(h) do
if v then
- t[#t+1] = k
+ tn = tn + 1
+ t[tn] = k
end
end
return concat(t,separator or ",")
@@ -3700,99 +4031,18 @@ end
function parsers.getparameters(self,class,parentclass,settings)
local sc = self[class]
if not sc then
- sc = table.clone(self[parent])
+ sc = { }
self[class] = sc
- end
- parsers.settings_to_hash(settings,sc)
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util-tab'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-utilities = utilities or {}
-utilities.tables = utilities.tables or { }
-local tables = utilities.tables
-
-local format, gmatch = string.format, string.gmatch
-local concat, insert, remove = table.concat, table.insert, table.remove
-local setmetatable = setmetatable
-
-function tables.definetable(target) -- defines undefined tables
- local composed, t = nil, { }
- for name in gmatch(target,"([^%.]+)") do
- if composed then
- composed = composed .. "." .. name
- else
- composed = name
- end
- t[#t+1] = format("%s = %s or { }",composed,composed)
- end
- return concat(t,"\n")
-end
-
-function tables.accesstable(target)
- local t = _G
- for name in gmatch(target,"([^%.]+)") do
- t = t[name]
- end
- return t
-end
-
-function table.removevalue(t,value) -- todo: n
- if value then
- for i=1,#t do
- if t[i] == value then
- remove(t,i)
- -- remove all, so no: return
+ if parentclass then
+ local sp = self[parentclass]
+ if not sp then
+ sp = { }
+ self[parentclass] = sp
end
+ setmetatable(sc, { __index = sp })
end
end
-end
-
-function table.insertbeforevalue(t,value,extra)
- for i=1,#t do
- if t[i] == extra then
- remove(t,i)
- end
- end
- for i=1,#t do
- if t[i] == value then
- insert(t,i,extra)
- return
- end
- end
- insert(t,1,extra)
-end
-
-function table.insertaftervalue(t,value,extra)
- for i=1,#t do
- if t[i] == extra then
- remove(t,i)
- end
- end
- for i=1,#t do
- if t[i] == value then
- insert(t,i+1,extra)
- return
- end
- end
- insert(t,#t+1,extra)
-end
-
-local _empty_table_ = { __index = function(t,k) return "" end }
-
-function table.setemptymetatable(t)
- setmetatable(t,_empty_table_)
+ parsers.settings_to_hash(settings,sc)
end
@@ -3831,9 +4081,9 @@ local number = digit^1 * (case_1 + case_2)
local stripper = Cs((number + 1)^0)
-lpeg.patterns.strip_zeros = stripper
+lpeg.patterns.stripzeros = stripper
-function formatters.strip_zeros(str)
+function formatters.stripzeros(str)
return lpegmatch(stripper,str)
end
@@ -4005,88 +4255,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['util-sto'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local setmetatable, getmetatable = setmetatable, getmetatable
-
-utilities = utilities or { }
-utilities.storage = utilities.storage or { }
-local storage = utilities.storage
-
-function storage.mark(t)
- if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
- end
- local m = getmetatable(t)
- if not m then
- m = { }
- setmetatable(t,m)
- end
- m.__storage__ = true
- return t
-end
-
-function storage.allocate(t)
- t = t or { }
- local m = getmetatable(t)
- if not m then
- m = { }
- setmetatable(t,m)
- end
- m.__storage__ = true
- return t
-end
-
-function storage.marked(t)
- local m = getmetatable(t)
- return m and m.__storage__
-end
-
-function storage.checked(t)
- if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
- end
- return t
-end
-
-function setmetatablekey(t,key,value)
- local m = getmetatable(t)
- if not m then
- m = { }
- setmetatable(t,m)
- end
- m[key] = value
-end
-
-function getmetatablekey(t,key,value)
- local m = getmetatable(t)
- return m and m[key]
-end
-
-
-function storage.setinitializer(data,initialize)
- local m = getmetatable(data) or { }
- m.__index = function(data,k)
- m.__index = nil -- so that we can access the entries during initializing
- initialize()
- return data[k]
- end
- setmetatable(data, m)
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['trac-inf'] = {
version = 1.001,
comment = "companion to trac-inf.mkiv",
@@ -4102,6 +4270,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
local format = string.format
local clock = os.gettimeofday or os.clock -- should go in environment
+local write_nl = texio.write_nl
statistics = statistics or { }
local statistics = statistics
@@ -4197,7 +4366,7 @@ end
function statistics.show(reporter)
if statistics.enable then
- if not reporter then reporter = function(tag,data,n) texio.write_nl(tag .. " " .. data) end end
+ if not reporter then reporter = function(tag,data,n) write_nl(tag .. " " .. data) end end
-- this code will move
local register = statistics.register
register("luatex banner", function()
@@ -4220,18 +4389,24 @@ function statistics.show(reporter)
reporter(s[1],r,n)
end
end
- texio.write_nl("") -- final newline
+ write_nl("") -- final newline
statistics.enable = false
end
end
+
+local template, nn = nil, 0 -- we only calcute it once
+
function statistics.showjobstat(tag,data,n)
if type(data) == "table" then
for i=1,#data do
statistics.showjobstat(tag,data[i],n)
end
else
- texio.write_nl(format("%-15s: %s - %s","mkiv lua stats",tag:rpadd(n," "),data))
+ if not template or n > nn then
+ template, n = format("%%-%ss: %%-%ss - %%s",15,n), nn
+ end
+ write_nl(format(template,"mkiv lua stats",tag,data))
end
end
@@ -4288,7 +4463,7 @@ if not modules then modules = { } end modules ['trac-set'] = { -- might become u
local type, next, tostring = type, next, tostring
local concat = table.concat
-local format, find, lower, gsub, partialescapedpattern = string.format, string.find, string.lower, string.gsub, string.partialescapedpattern
+local format, find, lower, gsub, escapedpattern = string.format, string.find, string.lower, string.gsub, string.escapedpattern
local is_boolean = string.is_boolean
local settings_to_hash = utilities.parsers.settings_to_hash
local allocate = utilities.storage.allocate
@@ -4368,7 +4543,7 @@ local function set(t,what,newvalue)
for name, functions in next, data do
if done[name] then
-- prevent recursion due to wildcards
- elseif find(name,partialescapedpattern(w)) then
+ elseif find(name,escapedpattern(w,true)) then
done[name] = true
for i=1,#functions do
functions[i](value)
@@ -5151,7 +5326,7 @@ local report_resolvers = logs.new("resolvers")
local allocate, mark = utilities.storage.allocate, utilities.storage.mark
local format, sub, match, gsub, find = string.format, string.sub, string.match, string.gsub, string.find
-local unquote, quote = string.unquote, string.quote
+local unquoted, quoted = string.unquoted, string.quoted
local concat = table.concat
-- precautions
@@ -5219,7 +5394,7 @@ function environment.initializearguments(arg)
if index > 0 then
local flag, value = match(argument,"^%-+(.-)=(.-)$")
if flag then
- arguments[flag] = unquote(value or "")
+ arguments[flag] = unquoted(value or "")
else
flag = match(argument,"^%-+(.+)")
if flag then
@@ -5284,19 +5459,21 @@ end
function environment.reconstructcommandline(arg,noquote)
arg = arg or environment.originalarguments
if noquote and #arg == 1 then
+ -- we could just do: return unquoted(resolvers.resolve(arg[i]))
local a = arg[1]
a = resolvers.resolve(a)
- a = unquote(a)
+ a = unquoted(a)
return a
elseif #arg > 0 then
local result = { }
for i=1,#arg do
+ -- we could just do: result[#result+1] = format("%q",unquoted(resolvers.resolve(arg[i])))
local a = arg[i]
a = resolvers.resolve(a)
- a = unquote(a)
+ a = unquoted(a)
a = gsub(a,'"','\\"') -- tricky
if find(a," ") then
- result[#result+1] = quote(a)
+ result[#result+1] = quoted(a)
else
result[#result+1] = a
end
@@ -5307,6 +5484,7 @@ function environment.reconstructcommandline(arg,noquote)
end
end
+
if arg then
-- new, reconstruct quoted snippets (maybe better just remove the " then and add them later)
@@ -6767,7 +6945,7 @@ apply_axis['root'] = function(list)
rt = ll
end
end
- collected[#collected+1] = rt
+ collected[l] = rt
end
return collected
end
@@ -6777,7 +6955,7 @@ apply_axis['self'] = function(list)
end
apply_axis['child'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
local dt = ll.dt
@@ -6786,7 +6964,8 @@ apply_axis['child'] = function(list)
for k=1,#dt do
local dk = dt[k]
if dk.tg then
- collected[#collected+1] = dk
+ c = c + 1
+ collected[c] = dk
dk.ni = k -- refresh
en = en + 1
dk.ei = en
@@ -6798,68 +6977,74 @@ apply_axis['child'] = function(list)
return collected
end
-local function collect(list,collected)
+local function collect(list,collected,c)
local dt = list.dt
if dt then
local en = 0
for k=1,#dt do
local dk = dt[k]
if dk.tg then
- collected[#collected+1] = dk
+ c = c + 1
+ collected[c] = dk
dk.ni = k -- refresh
en = en + 1
dk.ei = en
- collect(dk,collected)
+ c = collect(dk,collected,c)
end
end
list.en = en
end
+ return c
end
apply_axis['descendant'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
- collect(list[l],collected)
+ c = collect(list[l],collected,c)
end
return collected
end
-local function collect(list,collected)
+local function collect(list,collected,c)
local dt = list.dt
if dt then
local en = 0
for k=1,#dt do
local dk = dt[k]
if dk.tg then
- collected[#collected+1] = dk
+ c = c + 1
+ collected[c] = dk
dk.ni = k -- refresh
en = en + 1
dk.ei = en
- collect(dk,collected)
+ c = collect(dk,collected,c)
end
end
list.en = en
end
+ return c
end
apply_axis['descendant-or-self'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
if ll.special ~= true then -- catch double root
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
end
- collect(ll,collected)
+ c = collect(ll,collected,c)
end
return collected
end
apply_axis['ancestor'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
while ll do
ll = ll.__p__
if ll then
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
end
end
end
@@ -6867,14 +7052,16 @@ apply_axis['ancestor'] = function(list)
end
apply_axis['ancestor-or-self'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
while ll do
ll = ll.__p__
if ll then
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
end
end
end
@@ -6882,11 +7069,12 @@ apply_axis['ancestor-or-self'] = function(list)
end
apply_axis['parent'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local pl = list[l].__p__
if pl then
- collected[#collected+1] = pl
+ c = c + 1
+ collected[c] = pl
end
end
return collected
@@ -6909,7 +7097,7 @@ apply_axis['preceding'] = function(list) -- incomplete
end
apply_axis['following-sibling'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
local p = ll.__p__
@@ -6917,7 +7105,8 @@ apply_axis['following-sibling'] = function(list)
for i=ll.ni+1,#d do
local di = d[i]
if type(di) == "table" then
- collected[#collected+1] = di
+ c = c + 1
+ collected[c] = di
end
end
end
@@ -6925,7 +7114,7 @@ apply_axis['following-sibling'] = function(list)
end
apply_axis['preceding-sibling'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
local p = ll.__p__
@@ -6933,7 +7122,8 @@ apply_axis['preceding-sibling'] = function(list)
for i=1,ll.ni-1 do
local di = d[i]
if type(di) == "table" then
- collected[#collected+1] = di
+ c = c + 1
+ collected[c] = di
end
end
end
@@ -6941,7 +7131,7 @@ apply_axis['preceding-sibling'] = function(list)
end
apply_axis['reverse-sibling'] = function(list) -- reverse preceding
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
local p = ll.__p__
@@ -6949,7 +7139,8 @@ apply_axis['reverse-sibling'] = function(list) -- reverse preceding
for i=ll.ni-1,1,-1 do
local di = d[i]
if type(di) == "table" then
- collected[#collected+1] = di
+ c = c + 1
+ collected[c] = di
end
end
end
@@ -6975,7 +7166,7 @@ local function apply_nodes(list,directive,nodes)
return { }
end
else
- local collected, m, p = { }, 0, nil
+ local collected, c, m, p = { }, 0, 0, nil
if not nns then -- only check tag
for l=1,#list do
local ll = list[l]
@@ -6984,11 +7175,13 @@ local function apply_nodes(list,directive,nodes)
if directive then
if ntg == ltg then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
elseif ntg ~= ltg then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
end
end
@@ -7000,11 +7193,13 @@ local function apply_nodes(list,directive,nodes)
if directive then
if lns == nns then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
elseif lns ~= nns then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
end
end
@@ -7018,11 +7213,13 @@ local function apply_nodes(list,directive,nodes)
if directive then
if ok then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
elseif not ok then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
end
end
@@ -7030,7 +7227,7 @@ local function apply_nodes(list,directive,nodes)
return collected
end
else
- local collected, m, p = { }, 0, nil
+ local collected, c, m, p = { }, 0, 0, nil
for l=1,#list do
local ll = list[l]
local ltg = ll.tg
@@ -7047,11 +7244,13 @@ local function apply_nodes(list,directive,nodes)
if directive then
if ok then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
elseif not ok then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
end
end
@@ -7062,12 +7261,13 @@ end
local quit_expression = false
local function apply_expression(list,expression,order)
- local collected = { }
+ local collected, c = { }, 0
quit_expression = false
for l=1,#list do
local ll = list[l]
if expression(list,ll,l,order) then -- nasty, order alleen valid als n=1
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
end
if quit_expression then
break
@@ -7363,7 +7563,7 @@ local function nodesettostring(set,nodetest)
if not ns or ns == "" then ns = "*" end
if not tg or tg == "" then tg = "*" end
tg = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
- t[#t+1] = (directive and tg) or format("not(%s)",tg)
+ t[i] = (directive and tg) or format("not(%s)",tg)
end
if nodetest == false then
return format("not(%s)",concat(t,"|"))
@@ -7382,7 +7582,7 @@ local function tagstostring(list)
local ns, tg = li.ns, li.tg
if not ns or ns == "" then ns = "*" end
if not tg or tg == "" then tg = "*" end
- t[#t+1] = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
+ t[i] = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
end
return concat(t," ")
end
@@ -8102,16 +8302,17 @@ end
function xml.collect_tags(root, pattern, nonamespace)
local collected = xmlapplylpath(root,pattern)
if collected then
- local t = { }
+ local t, n = { }, 0
for c=1,#collected do
local e = collected[c]
local ns, tg = e.ns, e.tg
+ n = n + 1
if nonamespace then
- t[#t+1] = tg
+ t[n] = tg
elseif ns == "" then
- t[#t+1] = tg
+ t[n] = tg
else
- t[#t+1] = ns .. ":" .. tg
+ t[n] = ns .. ":" .. tg
end
end
return t
@@ -8219,8 +8420,10 @@ local function inject_element(root,pattern,whatever,prepend)
else
be, af = edt, cp
end
+ local bn = #be
for i=1,#af do
- be[#be+1] = af[i]
+ bn = bn + 1
+ be[bn] = af[i]
end
if rri then
r.dt[rri].dt = be
@@ -8305,11 +8508,12 @@ local function stripelement(e,nolines,anywhere)
local edt = e.dt
if edt then
if anywhere then
- local t = { }
+ local t, n = { }, 0
for e=1,#edt do
local str = edt[e]
if type(str) ~= "string" then
- t[#t+1] = str
+ n = n + 1
+ t[n] = str
elseif str ~= "" then
-- todo: lpeg for each case
if nolines then
@@ -8317,7 +8521,8 @@ local function stripelement(e,nolines,anywhere)
end
str = gsub(str,"^%s*(.-)%s*$","%1")
if str ~= "" then
- t[#t+1] = str
+ n = n + 1
+ t[n] = str
end
end
end
@@ -8344,9 +8549,10 @@ local function stripelement(e,nolines,anywhere)
end
end
end
- if #edt > 0 then
+ local nedt = #nedt
+ if nedt > 0 then
-- strip end
- local str = edt[#edt]
+ local str = edt[nedt]
if type(str) ~= "string" then
-- nothing
elseif str == "" then
@@ -8359,7 +8565,7 @@ local function stripelement(e,nolines,anywhere)
if str == "" then
remove(edt)
else
- edt[#edt] = str
+ edt[nedt] = str
end
end
end
@@ -8506,15 +8712,8 @@ local function all(collected)
return collected
end
-local function reverse(collected)
- if collected then
- local reversed = { }
- for c=#collected,1,-1 do
- reversed[#reversed+1] = collected[c]
- end
- return reversed
- end
-end
+
+local reverse = table.reversed
local function attribute(collected,name)
if collected and #collected > 0 then
@@ -8605,11 +8804,12 @@ end
local function texts(collected)
if collected then
- local t = { }
+ local t, n = { }, 0
for c=1,#collected do
local e = collection[c]
if e and e.dt then
- t[#t+1] = e.dt
+ n = n + 1
+ t[n] = e.dt
end
end
return t
@@ -8652,14 +8852,15 @@ end
local function tags(collected,nonamespace)
if collected then
- local t = { }
+ local t, n = { }, 0
for c=1,#collected do
local e = collected[c]
local ns, tg = e.ns, e.tg
+ n = n + 1
if nonamespace or ns == "" then
- t[#t+1] = tg
+ t[n] = tg
else
- t[#t+1] = ns .. ":" .. tg
+ t[n] = ns .. ":" .. tg
end
end
return t
@@ -8855,9 +9056,13 @@ end
do
- local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or '~'
+ local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
+
+ if not homedir or homedir == "" then
+ homedir = string.char(127) -- we need a value, later we wil trigger on it
+ end
- homedir = file.collapse_path(homedir)
+ homedir = file.collapsepath(homedir)
ossetenv("HOME", homedir) -- can be used in unix cnf files
ossetenv("USERPROFILE",homedir) -- can be used in windows cnf files
@@ -8876,8 +9081,8 @@ do
local ownbin = environment.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex"
local ownpath = environment.ownpath or os.selfdir
- ownbin = file.collapse_path(ownbin)
- ownpath = file.collapse_path(ownpath)
+ ownbin = file.collapsepath(ownbin)
+ ownpath = file.collapsepath(ownpath)
if not ownpath or ownpath == "" or ownpath == "unset" then
ownpath = args[-1] or arg[-1]
@@ -8949,9 +9154,9 @@ do
local ownpath = environment.ownpath or dir.current()
if ownpath then
- ossetenv('SELFAUTOLOC', file.collapse_path(ownpath))
- ossetenv('SELFAUTODIR', file.collapse_path(ownpath .. "/.."))
- ossetenv('SELFAUTOPARENT', file.collapse_path(ownpath .. "/../.."))
+ ossetenv('SELFAUTOLOC', file.collapsepath(ownpath))
+ ossetenv('SELFAUTODIR', file.collapsepath(ownpath .. "/.."))
+ ossetenv('SELFAUTOPARENT', file.collapsepath(ownpath .. "/../.."))
else
report_resolvers("error: unable to locate ownpath")
os.exit()
@@ -8987,7 +9192,7 @@ if not texroot or texroot == "" then
ossetenv('TEXROOT',texroot)
end
-environment.texroot = file.collapse_path(texroot)
+environment.texroot = file.collapsepath(texroot)
-- Tracing. Todo ...
@@ -9026,7 +9231,7 @@ local lpegCt, lpegCs, lpegP, lpegC, lpegS = lpeg.Ct, lpeg.Cs, lpeg.P, lpeg.C, lp
local type, next = type, next
local ostype = os.type
-local collapse_path = file.collapse_path
+local collapsepath = file.collapsepath
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
local trace_expansions = false trackers.register("resolvers.expansions", function(v) trace_expansions = v end)
@@ -9062,22 +9267,29 @@ local resolvers = resolvers
local dummy_path_expr = "^!*unset/*$"
local function do_first(a,b)
- local t = { }
- for s in gmatch(b,"[^,]+") do t[#t+1] = a .. s end
+ local t, n = { }, 0
+ for s in gmatch(b,"[^,]+") do
+ n = n + 1
+ t[n] = a .. s
+ end
return "{" .. concat(t,",") .. "}"
end
local function do_second(a,b)
- local t = { }
- for s in gmatch(a,"[^,]+") do t[#t+1] = s .. b end
+ local t, n = { }, 0
+ for s in gmatch(a,"[^,]+") do
+ n = n + 1
+ t[n] = s .. b
+ end
return "{" .. concat(t,",") .. "}"
end
local function do_both(a,b)
- local t = { }
+ local t, n = { }, 0
for sa in gmatch(a,"[^,]+") do
for sb in gmatch(b,"[^,]+") do
- t[#t+1] = sa .. sb
+ n = n + 1
+ t[n] = sa .. sb
end
end
return "{" .. concat(t,",") .. "}"
@@ -9101,6 +9313,7 @@ local function splitpathexpr(str, newlist, validate)
report_resolvers("expanding variable '%s'",str)
end
local t, ok, done = newlist or { }, false, false
+ local n = #t
str = lpegmatch(replacer_1,str)
while true do
done = false
@@ -9124,11 +9337,15 @@ local function splitpathexpr(str, newlist, validate)
if validate then
for s in gmatch(str,"[^,]+") do
s = validate(s)
- if s then t[#t+1] = s end
+ if s then
+ n = n + 1
+ t[n] = s
+ end
end
else
for s in gmatch(str,"[^,]+") do
- t[#t+1] = s
+ n = n + 1
+ t[n] = s
end
end
if trace_expansions then
@@ -9141,7 +9358,7 @@ end
local function validate(s)
local isrecursive = find(s,"//$")
- s = collapse_path(s)
+ s = collapsepath(s)
if isrecursive then
s = s .. "//"
end
@@ -9164,10 +9381,14 @@ function resolvers.expandedpathfromlist(pathlist) -- maybe not a list, just a pa
splitpathexpr(pathlist[k],newlist,validate)
end
else
+ local n = 0
for k=1,#pathlist do
for p in gmatch(pathlist[k],"([^,]+)") do
p = validate(p)
- if p ~= "" then newlist[#newlist+1] = p end
+ if p ~= "" then
+ n = n + 1
+ newlist[n] = p
+ end
end
end
end
@@ -9176,16 +9397,42 @@ end
-- We also put some cleanup code here.
-local cleanup -- used recursively
-cleanup = lpeg.replacer {
- { "!", "" },
- { "\\", "/" },
- { "~" , function() return lpegmatch(cleanup,environment.homedir) end },
+
+
+local cleanup = lpeg.replacer {
+ { "!" , "" },
+ { "\\" , "/" },
}
+local homedir
+
function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+ if not homedir then
+ homedir = lpegmatch(cleanup,environment.homedir or "")
+ if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_resolvers("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if find(str,"~") then
+ return "" -- special case
+ else
+ return str and lpegmatch(cleanup,str)
+ end
+ end
+ else
+ cleanup = lpeg.replacer {
+ { "!" , "" },
+ { "\\" , "/" },
+ { "~" , homedir },
+ }
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str)
+ end
+ end
+ end
+ return resolvers.cleanpath(str)
end
-- This one strips quotes and funny tokens.
@@ -9211,7 +9458,6 @@ end
-- we join them and split them after the expansion has taken place. This
-- is more convenient.
-
local cache = { }
local splitter = lpegCt(lpeg.splitat(lpegS(ostype == "windows" and ";" or ":;"))) -- maybe add ,
@@ -9226,15 +9472,17 @@ local function splitconfigurationpath(str) -- beware, this can be either a path
str = gsub(str,"\\","/")
local split = lpegmatch(splitter,str)
found = { }
+ local noffound = 0
for i=1,#split do
local s = split[i]
if not find(s,"^{*unset}*") then
- found[#found+1] = s
+ noffound = noffound + 1
+ found[noffound] = s
end
end
if trace_expansions then
report_resolvers("splitting path specification '%s'",str)
- for k=1,#found do
+ for k=1,noffound do
report_resolvers("% 4i: %s",k,found[k])
end
end
@@ -9357,7 +9605,6 @@ formats['enc'] = 'ENCFONTS' suffixes['enc'] = { 'enc' }
formats['fmt'] = 'TEXFORMATS' suffixes['fmt'] = { 'fmt' }
formats['map'] = 'TEXFONTMAPS' suffixes['map'] = { 'map' }
formats['mp'] = 'MPINPUTS' suffixes['mp'] = { 'mp' }
-formats['ocp'] = 'OCPINPUTS' suffixes['ocp'] = { 'ocp' }
formats['ofm'] = 'OFMFONTS' suffixes['ofm'] = { 'ofm', 'tfm' }
formats['otf'] = 'OPENTYPEFONTS' suffixes['otf'] = { 'otf' }
formats['opl'] = 'OPLFONTS' suffixes['opl'] = { 'opl' }
@@ -9582,7 +9829,7 @@ local function identify()
local cachepath = texmfcaches[k]
if cachepath ~= "" then
cachepath = resolvers.cleanpath(cachepath)
- cachepath = file.collapse_path(cachepath)
+ cachepath = file.collapsepath(cachepath)
local valid = isdir(cachepath)
if valid then
if file.is_readable(cachepath) then
@@ -9921,7 +10168,7 @@ function resolvers.splitmethod(filename)
end
function resolvers.methodhandler(what, filename, filetype) -- ...
- filename = file.collapse_path(filename)
+ filename = file.collapsepath(filename)
local specification = (type(filename) == "string" and resolvers.splitmethod(filename)) or filename -- no or { }, let it bomb
local scheme = specification.scheme
local resolver = resolvers[what]
@@ -9966,7 +10213,7 @@ local lpegP, lpegS, lpegR, lpegC, lpegCc, lpegCs, lpegCt = lpeg.P, lpeg.S, lpeg.
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local filedirname, filebasename, fileextname, filejoin = file.dirname, file.basename, file.extname, file.join
-local collapse_path = file.collapse_path
+local collapsepath = file.collapsepath
local allocate = utilities.storage.allocate
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10169,7 +10416,7 @@ local function identify_configuration_files()
expandvars(cnfpaths) --- hm
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
- local filename = collapse_path(filejoin(cnfpaths[i],luacnfname))
+ local filename = collapsepath(filejoin(cnfpaths[i],luacnfname))
if lfs.isfile(filename) then
specification[#specification+1] = filename
end
@@ -10330,7 +10577,7 @@ local function locate_file_databases()
-- todo: cache:// and tree:// (runtime)
local texmfpaths = resolvers.expandedpathlist('TEXMF')
for i=1,#texmfpaths do
- local path = collapse_path(texmfpaths[i])
+ local path = collapsepath(texmfpaths[i])
local stripped = gsub(path,"^!!","")
local runtime = stripped == path
path = resolvers.cleanpath(path)
@@ -10443,11 +10690,12 @@ end
function resolvers.splitexpansions()
local ie = instance.expansions
for k,v in next, ie do
- local t, h, p = { }, { }, splitconfigurationpath(v)
+ local t, tn, h, p = { }, 0, { }, splitconfigurationpath(v)
for kk=1,#p do
local vv = p[kk]
if vv ~= "" and not h[vv] then
- t[#t+1] = vv
+ tn = tn + 1
+ t[tn] = vv
h[vv] = true
end
end
@@ -10554,7 +10802,8 @@ end
function resolvers.registerextrapath(paths,subpaths)
local ep = instance.extra_paths or { }
- local n = #ep
+ local oldn = #ep
+ local newn = oldn
if paths and paths ~= "" then
if subpaths and subpaths ~= "" then
for p in gmatch(paths,"[^,]+") do
@@ -10562,7 +10811,8 @@ function resolvers.registerextrapath(paths,subpaths)
for s in gmatch(subpaths,"[^,]+") do
local ps = p .. "/" .. s
if not done[ps] then
- ep[#ep+1] = resolvers.cleanpath(ps)
+ newn = newn + 1
+ ep[newn] = resolvers.cleanpath(ps)
done[ps] = true
end
end
@@ -10570,7 +10820,8 @@ function resolvers.registerextrapath(paths,subpaths)
else
for p in gmatch(paths,"[^,]+") do
if not done[p] then
- ep[#ep+1] = resolvers.cleanpath(p)
+ newn = newn + 1
+ ep[newn] = resolvers.cleanpath(p)
done[p] = true
end
end
@@ -10581,16 +10832,17 @@ function resolvers.registerextrapath(paths,subpaths)
for s in gmatch(subpaths,"[^,]+") do
local ps = ep[i] .. "/" .. s
if not done[ps] then
- ep[#ep+1] = resolvers.cleanpath(ps)
+ newn = newn + 1
+ ep[newn] = resolvers.cleanpath(ps)
done[ps] = true
end
end
end
end
- if #ep > 0 then
+ if newn > 0 then
instance.extra_paths = ep -- register paths
end
- if #ep > n then
+ if newn > oldn then
instance.lists = { } -- erase the cache
end
end
@@ -10600,14 +10852,15 @@ local function made_list(instance,list)
if not ep or #ep == 0 then
return list
else
- local done, new = { }, { }
+ local done, new, newn = { }, { }, 0
-- honour . .. ../.. but only when at the start
for k=1,#list do
local v = list[k]
if not done[v] then
if find(v,"^[%.%/]$") then
done[v] = true
- new[#new+1] = v
+ newn = newn + 1
+ new[newn] = v
else
break
end
@@ -10618,7 +10871,8 @@ local function made_list(instance,list)
local v = ep[k]
if not done[v] then
done[v] = true
- new[#new+1] = v
+ newn = newn + 1
+ new[newn] = v
end
end
-- next the formal paths
@@ -10626,7 +10880,8 @@ local function made_list(instance,list)
local v = list[k]
if not done[v] then
done[v] = true
- new[#new+1] = v
+ newn = newn + 1
+ new[newn] = v
end
end
return new
@@ -10637,7 +10892,7 @@ function resolvers.cleanpathlist(str)
local t = resolvers.expandedpathlist(str)
if t then
for i=1,#t do
- t[i] = collapse_path(resolvers.cleanpath(t[i]))
+ t[i] = collapsepath(resolvers.cleanpath(t[i]))
end
end
return t
@@ -10703,7 +10958,7 @@ resolvers.isreadable.tex = resolvers.isreadable.file
-- name/name
local function collect_files(names)
- local filelist = { }
+ local filelist, noffiles = { }, 0
for k=1,#names do
local fname = names[k]
if trace_detail then
@@ -10744,7 +10999,8 @@ local function collect_files(names)
if trace_detail then
report_resolvers("match: kind '%s', search '%s', result '%s'",kind,search,result)
end
- filelist[#filelist+1] = { kind, search, result }
+ noffiles = noffiles + 1
+ filelist[noffiles] = { kind, search, result }
end
else
for kk=1,#blobfile do
@@ -10756,7 +11012,8 @@ local function collect_files(names)
if trace_detail then
report_resolvers("match: kind '%s', search '%s', result '%s'",kind,search,result)
end
- filelist[#filelist+1] = { kind, search, result }
+ noffiles = noffiles + 1
+ filelist[noffiles] = { kind, search, result }
end
end
end
@@ -10766,7 +11023,7 @@ local function collect_files(names)
end
end
end
- return #filelist > 0 and filelist or nil
+ return noffiles > 0 and filelist or nil
end
function resolvers.registerintrees(name)
@@ -10792,7 +11049,7 @@ end
local function collect_instance_files(filename,collected) -- todo : plugin (scanners, checkers etc)
local result = collected or { }
local stamp = nil
- filename = collapse_path(filename)
+ filename = collapsepath(filename)
-- speed up / beware: format problem
if instance.remember then
stamp = filename .. "--" .. instance.engine .. "--" .. instance.progname .. "--" .. instance.format
@@ -11045,7 +11302,7 @@ local function collect_instance_files(filename,collected) -- todo : plugin (scan
end
end
for k=1,#result do
- local rk = collapse_path(result[k])
+ local rk = collapsepath(result[k])
result[k] = rk
resolvers.registerintrees(rk) -- for tracing used files
end
@@ -12439,7 +12696,7 @@ function resolvers.load_tree(tree)
local texos = "texmf-" .. os.platform
local oldroot = environment.texroot
- local newroot = file.collapse_path(tree)
+ local newroot = file.collapsepath(tree)
local newtree = file.join(newroot,texos)
local newpath = file.join(newtree,"bin")
@@ -12668,17 +12925,17 @@ local format = string.format
-- helper for mtxrun
-local quote = string.quote
+local quoted = string.quoted
local function primaryflags()
local trackers = environment.argument("trackers")
local directives = environment.argument("directives")
local flags = ""
if trackers and trackers ~= "" then
- flags = flags .. "--trackers=" .. quote(trackers)
+ flags = flags .. "--trackers=" .. quoted(trackers)
end
if directives and directives ~= "" then
- flags = flags .. "--directives=" .. quote(directives)
+ flags = flags .. "--directives=" .. quoted(directives)
end
return flags
end
@@ -12743,7 +13000,7 @@ function environment.make_format(name)
return
end
-- generate format
- local command = format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quote(usedluastub),quote(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
+ local command = format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
logs.simple("running command: %s\n",command)
os.spawn(command)
-- remove related mem files
@@ -12781,8 +13038,7 @@ function environment.run_format(name,data,more)
logs.simple("using format name: %s",fmtname)
logs.simple("no luc/lua with name: %s",barename)
else
- local q = string.quote
- local command = format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quote(barename),quote(luaname),quote(data),more ~= "" and quote(more) or "")
+ local command = format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quoted(barename),quoted(luaname),quoted(data),more ~= "" and quoted(more) or "")
logs.simple("running command: %s",command)
os.spawn(command)
end
@@ -12813,13 +13069,13 @@ own.libs = { -- order can be made better
'l-unicode.lua',
'l-math.lua',
+ 'util-tab.lua',
+ 'util-sto.lua',
'util-mrg.lua',
'util-lua.lua',
'util-prs.lua',
- 'util-tab.lua',
'util-fmt.lua',
'util-deb.lua',
- 'util-sto.lua',
'trac-inf.lua',
'trac-set.lua',
diff --git a/tex/context/base/back-exp.lua b/tex/context/base/back-exp.lua
index 83c7b6198..28cb5c18c 100644
--- a/tex/context/base/back-exp.lua
+++ b/tex/context/base/back-exp.lua
@@ -740,6 +740,7 @@ end
local function collapsetree()
for k, v in next, treehash do
local d = v[1].data
+ local nd = #d
for i=2,#v do
local vi = v[i]
local vd = vi.data
@@ -753,26 +754,35 @@ local function collapsetree()
-- experiment, should be improved
-- can be simplified ... lpn instead of done
if done then
- d[#d+1] = joiner_1
+ nd = nd + 1
+ d[nd] = joiner_1
else
done = true
local pn = vi.parnumber
if not pn then
- d[#d+1], lpn = joiner_2, nil
+ nd = nd + 1
+ d[nd] = joiner_2
+ lpn = nil
elseif not lpn then
- d[#d+1], lpn = joiner_3, pn
+ nd = nd + 1
+ d[nd] = joiner_3
+ lpn = pn
elseif pn and pn ~= lpn then
- d[#d+1], lpn = makebreaknode(vi), pn
+ nd = nd + 1
+ d[nd] = makebreaknode(vi)
+ lpn = pn
else
- -- d[#d+1] = joiner_4 -- we need to be more clever
+ -- nd = nd + 1
+ -- d[nd] = joiner_4 -- we need to be more clever
end
end
else
-- lpn = nil
end
-if vdj ~= "" then
- d[#d+1] = vdj -- hm, any?
-end
+ if vdj ~= "" then
+ nd = nd + 1
+ d[nd] = vdj -- hm, any?
+ end
vd[j] = false
end
v[i].collapsed = true
@@ -784,19 +794,21 @@ local function prunetree(tree)
if not tree.collapsed then
local data = tree.data
if data then
- local p = { }
+ local p, np = { }, 0
for i=1,#data do
local d = data[i]
if type(d) == "table" then
if not d.collapsed then
prunetree(d)
- p[#p+1] = d
+ np = np + 1
+ p[np] = d
end
elseif type(d) == "string" then
- p[#p+1] = d
+ np = np + 1
+ p[np] = d
end
end
- tree.data = #p > 0 and p
+ tree.data = np > 0 and p
end
end
end
diff --git a/tex/context/base/back-ini.lua b/tex/context/base/back-ini.lua
index dadaaa837..1bceea691 100644
--- a/tex/context/base/back-ini.lua
+++ b/tex/context/base/back-ini.lua
@@ -117,6 +117,8 @@ backends.codeinjections = {
finishreference = nothing,
+ getoutputfilename = nothing,
+
}
backends.registrations = {
diff --git a/tex/context/base/back-pdf.lua b/tex/context/base/back-pdf.lua
index 425e1ad15..c9c0982f0 100644
--- a/tex/context/base/back-pdf.lua
+++ b/tex/context/base/back-pdf.lua
@@ -464,4 +464,13 @@ function codeinjections.setfigurealternative(data,figure)
end
end
+local outputfilename
+
+function codeinjections.getoutputfilename()
+ if not outputfilename then
+ outputfilename = file.addsuffix(tex.jobname,"pdf")
+ end
+ return outputfilename
+end
+
backends.install("pdf")
diff --git a/tex/context/base/back-pdf.mkiv b/tex/context/base/back-pdf.mkiv
index 94b93cb39..1a99a91a2 100644
--- a/tex/context/base/back-pdf.mkiv
+++ b/tex/context/base/back-pdf.mkiv
@@ -90,6 +90,8 @@
\def\pdfbackendcurrentresources {\ctxlua{lpdf.collectedresources()}}
+\def\pdfcolor #1{\ctxlua{lpdf.pdfcolor(\thecolorattribute{#1})}} \let\PDFcolor\pdfcolor
+
%D Let's block these:
\let\pdfcatalog \relax \newtoks\pdfcatalog
diff --git a/tex/context/base/bibl-bib.lua b/tex/context/base/bibl-bib.lua
index 5e759eff2..f301d9689 100644
--- a/tex/context/base/bibl-bib.lua
+++ b/tex/context/base/bibl-bib.lua
@@ -198,12 +198,12 @@ function bibtex.toxml(session,options)
-- we can always speed this up if needed
-- format slows down things a bit but who cares
statistics.starttiming(bibtex)
- local result = { }
+ local result, r = { }, 0
local options = settings_to_hash(options)
local convert = options.convert -- todo: interface
local strip = options.strip -- todo: interface
local entries = session.entries
- result[#result+1] = format("<?xml version='1.0' standalone='yes'?>")
+ r = r + 1 ; result[r] = format("<?xml version='1.0' standalone='yes'?>")
result[#result+1] = format("<bibtex>")
for id, categories in next, session.data do
id = lower(gsub(id,"^@",""))
@@ -223,14 +223,14 @@ function bibtex.toxml(session,options)
-- kind of hackery ... bibtex databases are quite unportable
value = lpegmatch(filter,value) or value
end
- result[#result+1] = format(" <field name='%s'>%s</field>",key,value)
+ r = r + 1 ; result[r] = format(" <field name='%s'>%s</field>",key,value)
end
end
- result[#result+1] = format("</entry>")
+ r = r + 1 ; result[r] = format("</entry>")
end
end
end
- result[#result+1] = format("</bibtex>")
+ r = r + 1 ; result[r] = format("</bibtex>")
result = concat(result,"\n")
-- alternatively we could use lxml.convert
session.xml = xml.convert(result, {
diff --git a/tex/context/base/bibl-tra.lua b/tex/context/base/bibl-tra.lua
index afc42a610..87300aa74 100644
--- a/tex/context/base/bibl-tra.lua
+++ b/tex/context/base/bibl-tra.lua
@@ -126,7 +126,7 @@ end
function hacks.resolve(prefix,block,reference) -- maybe already feed it split
local subset = references.collected[prefix or ""] or references.collected[""]
if subset then
- local result, done = { }, { }
+ local result, nofresult, done = { }, 0, { }
block = tonumber(block)
for rest in gmatch(reference,"([^,%s]+)") do
local blk, tag, found = block, nil, nil
@@ -152,7 +152,8 @@ function hacks.resolve(prefix,block,reference) -- maybe already feed it split
if found then
local current = found.entries and found.entries.text
if current and not done[current] then
- result[#result+1] = { blk, rest, current }
+ nofresult = nofresult + 1
+ result[nofresult] = { blk, rest, current }
done[current] = true
end
end
@@ -160,8 +161,8 @@ function hacks.resolve(prefix,block,reference) -- maybe already feed it split
-- todo: ranges so the interface will change
sort(result,compare)
local first, last, firsti, lasti, firstr, lastr
- local collected = { }
- for i=1,#result do
+ local collected, nofcollected = { }, 0
+ for i=1,nofresult do
local r = result[i]
local current = r[3]
if not first then
@@ -170,11 +171,14 @@ function hacks.resolve(prefix,block,reference) -- maybe already feed it split
last, lasti, lastr = current, i, r
else
if last > first + 1 then
- collected[#collected+1] = { firstr[1], firstr[2], lastr[1], lastr[2] }
+ nofcollected = nofcollected + 1
+ collected[nofcollected] = { firstr[1], firstr[2], lastr[1], lastr[2] }
else
- collected[#collected+1] = { firstr[1], firstr[2] }
+ nofcollected = nofcollected + 1
+ collected[nofcollected] = { firstr[1], firstr[2] }
if last > first then
- collected[#collected+1] = { lastr[1], lastr[2] }
+ nofcollected = nofcollected + 1
+ collected[nofcollected] = { lastr[1], lastr[2] }
end
end
first, last, firsti, lasti, firstr, lastr = current, current, i, i, r, r
@@ -182,16 +186,19 @@ function hacks.resolve(prefix,block,reference) -- maybe already feed it split
end
if first then
if last > first + 1 then
- collected[#collected+1] = { firstr[1], firstr[2], lastr[1], lastr[2] }
+ nofcollected = nofcollected + 1
+ collected[nofcollected] = { firstr[1], firstr[2], lastr[1], lastr[2] }
else
- collected[#collected+1] = { firstr[1], firstr[2] }
+ nofcollected = nofcollected + 1
+ collected[nofcollected] = { firstr[1], firstr[2] }
if last > first then
- collected[#collected+1] = { lastr[1], lastr[2] }
+ nofcollected = nofcollected + 1
+ collected[nofcollected] = { lastr[1], lastr[2] }
end
end
end
- if #collected > 0 then
- for i=1,#collected do
+ if nofcollected > 0 then
+ for i=1,nofcollected do
local c = collected[i]
if c[3] then
context.dowithbibtexnumrefrange(#collected,i,prefix,c[1],c[2],c[3],c[4])
diff --git a/tex/context/base/blob-ini.lua b/tex/context/base/blob-ini.lua
index fec304f7d..537e8bdd3 100644
--- a/tex/context/base/blob-ini.lua
+++ b/tex/context/base/blob-ini.lua
@@ -120,15 +120,18 @@ function blobs.append(t,str)
local list = t.list
if kind == "string" then
local pars = lpegmatch(ctxtextcapture,str)
+ local noflist = #list
for p=1,#pars do
local str = pars[p]
if #str == 0 then
- list[#list+1 ] = { head = nil, tail = nil }
+ noflist = noflist + 1
+ list[noflist] = { head = nil, tail = nil }
else
- local l = list[#list]
+ local l = list[noflist]
if not l then
l = { head = nil, tail = nil }
- list[#list+1 ] = l
+ noflist = noflist + 1
+ list[noflist] = l
end
local head, tail = tonodes(str,nil,nil)
if head then
diff --git a/tex/context/base/buff-ini.lua b/tex/context/base/buff-ini.lua
index cb41b48cf..7c916f60e 100644
--- a/tex/context/base/buff-ini.lua
+++ b/tex/context/base/buff-ini.lua
@@ -27,6 +27,7 @@ local utfbyte, utffind, utfgsub = utf.byte, utf.find, utf.gsub
local type, next = type, next
local huge = math.huge
local byte, sub, find, char, gsub, rep, lower, format, gmatch, match, count = string.byte, string.sub, string.find, string.char, string.gsub, string.rep, string.lower, string.format, string.gmatch, string.match, string.count
+local splitlines, escapedpattern = string.splitlines, string.escapedpattern
local utfcharacters, utfvalues = string.utfcharacters, string.utfvalues
local ctxcatcodes = tex.ctxcatcodes
local variables = interfaces.variables
@@ -92,7 +93,7 @@ function buffers.grab(name,begintag,endtag,bufferdata)
end
dn = gsub(dn,"[\010\013]$","")
if flags.storeastable then
- dn = dn:splitlines()
+ dn = splitlines(dn)
end
end
data[name] = dn
@@ -178,7 +179,7 @@ function buffers.range(lines,first,last,range) -- 1,3 1,+3 fromhere,tothere
else
for i=first,last do
if find(lines[i],r_first) then
- first, strip = i + 1
+ first = i + 1
break
end
end
@@ -212,7 +213,7 @@ function buffers.type(name,realign,range)
local action = buffers.typeline
if lines then
if type(lines) == "string" then
- lines = lines:splitlines()
+ lines = splitlines(lines)
data[name] = lines
end
if realign then
@@ -260,7 +261,7 @@ function buffers.typefile(name,realign,range,regime) -- still somewhat messy, si
str = regimes.translate(str,regime)
end
if str and str~= "" then
- local lines = str:splitlines()
+ local lines = splitlines(str)
if realign then
lines = buffers.realign(lines,realign)
end
@@ -384,11 +385,12 @@ function buffers.collect(names,separator) -- no print
if type(names) == "string" then
names = settings_to_array(names)
end
- local t = { }
+ local t, n = { }, 0
for i=1,#names do
local c = content(names[i],separator)
if c ~= "" then
- t[#t+1] = c
+ n = n + 1
+ t[n] = c
end
end
return concat(t,separator or "\r") -- "\n" is safer due to comments and such
@@ -397,7 +399,7 @@ end
function buffers.feedback(names,separator)
-- don't change the texprint into texsprint as it fails on mp buffers
-- because (p<nl>enddef) becomes penddef then
- texprint(ctxcatcodes,string.splitlines(buffers.collect(names,separator)))
+ texprint(ctxcatcodes,splitlines(buffers.collect(names,separator)))
end
local function tobyte(c)
@@ -689,7 +691,7 @@ function buffers.realign(name,forced_n) -- no, auto, <number>
if type(name) == "string" then
d = data[name]
if type(d) == "string" then
- d = d:splitlines()
+ d = splitlines(d)
end
else
d = name -- already a buffer
@@ -760,7 +762,7 @@ function buffers.setescapepair(name,pair)
start, stop = "/BTEX", "/ETEX"
else
pair = string.split(pair,",")
- start, stop = string.esc(pair[1] or ""), string.esc(pair[2] or "")
+ start, stop = escapedpattern(pair[1] or ""), escapedpattern(pair[2] or "")
end
if start ~= "" then
local pattern
diff --git a/tex/context/base/catc-ctx.tex b/tex/context/base/catc-ctx.tex
index 77e8fe88c..79e89a69b 100644
--- a/tex/context/base/catc-ctx.tex
+++ b/tex/context/base/catc-ctx.tex
@@ -183,7 +183,6 @@
\catcode`\\ = 0
\catcode`\{ = 1
\catcode`\} = 2
- \catcode`\% = 14
\stopcatcodetable
\letcatcodecommand \ctxcatcodes `\| \relax
diff --git a/tex/context/base/char-def.lua b/tex/context/base/char-def.lua
index 4c72c4772..c496b4a7a 100644
--- a/tex/context/base/char-def.lua
+++ b/tex/context/base/char-def.lua
@@ -83872,8 +83872,8 @@ characters.data={
description="<CJK Ideograph Extension A>",
direction="l",
linebreak="id",
- unicodeslot=0x3400,
- range= 0x4DB5,
+--unicodeslot=0x3400,
+ range={ first=0x3400, last=0x4DB5 },
},
[0x4DC0]={
category="so",
@@ -84329,8 +84329,8 @@ characters.data={
description="<CJK Ideograph>",
direction="l",
linebreak="id",
- unicodeslot=0x4E00,
- range=0x9FBB,
+--unicodeslot=0x4E00,
+ range={ first=0x4E00, last=0x9FBB },
},
[0xA000]={
category="lo",
@@ -95001,8 +95001,8 @@ characters.data={
description="<Hangul Syllable>",
direction="l",
linebreak="h2",
- unicodeslot=0xAC00,
- range=0xD7A3,
+--unicodeslot=0xAC00,
+ range={ first=0xAC00, last=0xD7A3 },
},
[0xD800]={
category="cs",
@@ -133602,8 +133602,8 @@ characters.data={
description="<CJK Ideograph Extension B>",
direction="l",
linebreak="id",
- unicodeslot=0x20000,
- range=0x2A6D6,
+--unicodeslot=0x20000,
+ range={ first=0x20000, last=0x2A6D6 },
},
[0x2F800]={
category="lo",
diff --git a/tex/context/base/char-ini.lua b/tex/context/base/char-ini.lua
index 0cce35a1a..868e25b3f 100644
--- a/tex/context/base/char-ini.lua
+++ b/tex/context/base/char-ini.lua
@@ -48,10 +48,13 @@ else
end
if not characters.ranges then
- local ranges = allocate { }
+ local ranges, r = allocate { }, 0
characters.ranges = ranges
for k, v in next, data do
- ranges[#ranges+1] = k
+ if v.range then
+ r = r + 1
+ ranges[r] = v
+ end
end
end
@@ -75,6 +78,10 @@ end
characters.tonumber = chartonumber
+local private = {
+ description = "PRIVATE SLOT",
+}
+
setmetatablekey(data, "__index", function(t,k)
if type(k) == "string" then
k = lpegmatch(pattern,k) or utfbyte(k)
@@ -86,19 +93,23 @@ setmetatablekey(data, "__index", function(t,k)
-- goes to ranges
end
else
- return nil
+ return private
end
end
- for r=1,#ranges do
- local rr = ranges[r] -- first in range
- if k > rr and k <= data[rr].range then
- t[k] = t[rr]
- return t[k]
+ if k < 0xF0000 then
+ for r=1,#ranges do
+ local rr = ranges[r].range
+ if k >= rr.first and k <= rr.last then
+ t[k] = rr
+ return rr
+ end
end
end
- return nil
+ return private -- handy for when we loop over characters in fonts and check for a property
end )
+--~ setmetatable(data,{ __index = function(t,k) return "" end }) -- quite old, obsolete
+
characters.blocks = allocate {
["aegeannumbers"] = { 0x10100, 0x1013F, "Aegean Numbers" },
["alphabeticpresentationforms"] = { 0x0FB00, 0x0FB4F, "Alphabetic Presentation Forms" },
@@ -380,8 +391,6 @@ characters.bidi = allocate {
on = "Other Neutrals",
}
-table.setemptymetatable(data) -- so each key resolves to ""
-
--[[ldx--
<p>At this point we assume that the big data table is loaded. From this
table we derive a few more.</p>
@@ -445,13 +454,14 @@ if texsetcatcode then
report_defining("defining active character commands")
end
- local activated = { }
+ local activated, a = { }, 0
for u, chr in next, data do -- these will be commands
local fallback = chr.fallback
if fallback then
texsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\checkedchar{",u,"}{",fallback,"}}}") -- no texprint
- activated[#activated+1] = u
+ a = a + 1
+ activated[a] = u
else
local contextname = chr.contextname
if contextname then
@@ -464,7 +474,8 @@ if texsetcatcode then
end
elseif is_command[category] then
texsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\"..contextname,"}}") -- no texprint
- activated[#activated+1] = u
+ a = a + 1
+ activated[a] = u
end
end
end
@@ -481,8 +492,9 @@ if texsetcatcode then
if not chr.fallback and is_letter[chr.category] and u >= 128 and u <= 65536 then
texsetcatcode(u,11)
end
- if chr.range then
- for i=1,u,chr.range do
+ local range = chr.range
+ if range then
+ for i=1,range.first,range.last do
texsetcatcode(i,11)
end
end
@@ -521,14 +533,15 @@ else -- char-obs
local template_b = "\\chardef\\l=11\\chardef\\a=13\\let\\c\\catcode%s\\let\\a\\undefined\\let\\l\\undefined\\let\\c\\undefined"
function characters.define(tobelettered, tobeactivated) -- catcodetables
- local lettered, activated = { }, { }
+ local lettered, activated, l, a = { }, { }, 0, 0
for u, chr in next, data do
-- we can use a macro instead of direct settings
local fallback = chr.fallback
if fallback then
-- texprint(format("{\\catcode %s=13\\unexpanded\\gdef %s{\\checkedchar{%s}{%s}}}",u,utfchar(u),u,fallback))
texsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\checkedchar{",u,"}{",fallback,"}}}") -- no texprint
- activated[#activated+1] = "\\c"..u.."\\a"
+ a = a + 1
+ activated[a] = "\\c"..u.."\\a"
else
local contextname = chr.contextname
local category = chr.category
@@ -541,28 +554,35 @@ else -- char-obs
else
texprint(ctxcatcodes,format("\\let\\%s=%s",contextname,utfchar(u)))
if is_letter[category] then
- lettered[#lettered+1] = "\\c"..u.."\\l"
+ l = l + 1
+ lettered[l] = "\\c"..u.."\\l"
end
end
elseif is_command[category] then
-- this might change: contextcommand ipv contextname
-- texprint(format("{\\catcode %s=13\\unexpanded\\gdef %s{\\%s}}",u,utfchar(u),contextname))
texsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\"..contextname,"}}") -- no texprint
- activated[#activated+1] = "\\c"..u.."\\a"
+ a = a + 1
+ activated[a] = "\\c"..u.."\\a"
end
elseif is_letter[category] then
if u >= 128 and u <= 65536 then -- catch private mess
- lettered[#lettered+1] = "\\c"..u.."\\l"
+ l = l + 1
+ lettered[l] = "\\c"..u.."\\l"
end
end
end
- if chr.range then
- lettered[#lettered+1] = format('\\dofastrecurse{"%05X}{"%05X}{1}{\\c\\fastrecursecounter\\l}',u,chr.range)
+ local range = chr.range
+ if range then
+ l = l + 1
+ lettered[l] = format('\\dofastrecurse{"%05X}{"%05X}{1}{\\c\\fastrecursecounter\\l}',range.first,range.last)
end
end
-- if false then
- lettered[#lettered+1] = "\\c"..0x200C.."\\l" -- non-joiner
- lettered[#lettered+1] = "\\c"..0x200D.."\\l" -- joiner
+ l = l + 1
+ lettered[l] = "\\c"..0x200C.."\\l" -- non-joiner
+ l = l + 1
+ lettered[l] = "\\c"..0x200D.."\\l" -- joiner
-- fi
if tobelettered then
lettered = concat(lettered)
@@ -617,10 +637,13 @@ if texsetcatcode then
if cc == "lu" then
texsetsfcode(code,999)
end
- elseif cc == "lo" and chr.range then
- for i=code,chr.range do
- texsetcatcode(code,11) -- letter
- texsetlccode(code,code,code) -- self self
+ elseif cc == "lo" then
+ local range = chr.range
+ if range then
+ for i=range.first,range.last do
+ texsetcatcode(i,11) -- letter
+ texsetlccode(i,i,i) -- self self
+ end
end
end
end
@@ -640,8 +663,11 @@ else -- char-obs
if cc == "lu" then
texprint(ctxcatcodes,"\\sfcode ",code,"999 ")
end
- if cc == "lo" and chr.range then
- texsprint(ctxcatcodes,format('\\dofastrecurse{"%05X}{"%05X}{1}{\\setcclcucself\\fastrecursecounter}',code,chr.range))
+ if cc == "lo" then
+ local range = chr.range
+ if range then
+ texsprint(ctxcatcodes,format('\\dofastrecurse{"%05X}{"%05X}{1}{\\setcclcucself\\fastrecursecounter}',range.first,range.last))
+ end
end
end
end
@@ -770,12 +796,13 @@ setmetatable(specialchars, { __index = function(t,u)
local c = data[utfbyte(u)]
local s = c and c.specials
if s then
- local t = { }
+ local t, tn = { }, 0
for i=2,#s do
local si = s[i]
local c = data[si]
if is_letter[c.category] then
- t[#t+1] = utfchar(si)
+ tn = tn + 1
+ t[tn] = utfchar(si)
end
end
c = concat(t)
@@ -789,27 +816,30 @@ setmetatable(specialchars, { __index = function(t,u)
end } )
function characters.lower(str)
- local new = { }
+ local new, n = { }, 0
for u in utfvalues(str) do
- new[#new+1] = utfchar(lccodes[u])
+ n = n + 1
+ new[n] = utfchar(lccodes[u])
end
return concat(new)
end
function characters.upper(str)
- local new = { }
+ local new, n = { }, 0
for u in utfvalues(str) do
- new[#new+1] = utfchar(uccodes[u])
+ n = n + 1
+ new[n] = utfchar(uccodes[u])
end
return concat(new)
end
function characters.lettered(str)
- local new = { }
+ local new, n = { }, 0
for u in utfvalues(str) do
local d = data[u]
if is_letter[d.category] then
- new[#new+1] = utfchar(lccodes[u])
+ n = n + 1
+ new[n] = utfchar(lccodes[u])
end
end
return concat(new)
diff --git a/tex/context/base/char-utf.lua b/tex/context/base/char-utf.lua
index b3ed728f1..7384f98c3 100644
--- a/tex/context/base/char-utf.lua
+++ b/tex/context/base/char-utf.lua
@@ -101,20 +101,22 @@ end
--~ if initialize then -- saves a call
--~ initialize()
--~ end
---~ local tokens, first, done = { }, false, false
+--~ local tokens, n, first, done = { }, 0, false, false
--~ for second in utfcharacters(str) do
--~ local cgf = graphemes[first]
--~ if cgf and cgf[second] then
--~ first, done = cgf[second], true
--~ elseif first then
---~ tokens[#tokens+1] = first
+--~ n + n + 1
+--~ tokens[n] = first
--~ first = second
--~ else
--~ first = second
--~ end
--~ end
--~ if done then
---~ tokens[#tokens+1] = first
+--~ n + n + 1
+--~ tokens[n] = first
--~ return concat(tokens)
--~ end
--~ end
@@ -194,17 +196,19 @@ not collecting tokens is not only faster but also saves garbage collecting.
function utffilters.collapse(str) -- not really tested (we could preallocate a table)
if utffilters.collapsing and str then
- if #str > 1 then
+ local nstr = #str
+ if nstr > 1 then
if initialize then -- saves a call
initialize()
end
- local tokens, first, done, n = { }, false, false, 0
+ local tokens, t, first, done, n = { }, 0, false, false, 0
for second in utfcharacters(str) do
if done then
local crs = high[second]
if crs then
if first then
- tokens[#tokens+1] = first
+ t = t + 1
+ tokens[t] = first
end
first = crs
else
@@ -212,7 +216,8 @@ function utffilters.collapse(str) -- not really tested (we could preallocate a t
if cgf and cgf[second] then
first = cgf[second]
elseif first then
- tokens[#tokens+1] = first
+ t = t + 1
+ tokens[t] = first
first = second
else
first = second
@@ -225,13 +230,17 @@ function utffilters.collapse(str) -- not really tested (we could preallocate a t
if n == 1 then
break
else
- tokens[#tokens+1], n = s, n - 1
+ t = t + 1
+ tokens[t] = s
+ n = n -1
end
end
if first then
- tokens[#tokens+1] = first
+ t = t + 1
+ tokens[t] = first
end
- first, done = crs, true
+ first = crs
+ done = true
else
local cgf = graphemes[first]
if cgf and cgf[second] then
@@ -239,21 +248,26 @@ function utffilters.collapse(str) -- not really tested (we could preallocate a t
if n == 1 then
break
else
- tokens[#tokens+1], n = s, n -1
+ t = t + 1
+ tokens[t] = s
+ n = n -1
end
end
- first, done = cgf[second], true
+ first = cgf[second]
+ done = true
else
- first, n = second, n + 1
+ first = second
+ n = n + 1
end
end
end
end
if done then
- tokens[#tokens+1] = first
+ t = t + 1
+ tokens[t] = first
return concat(tokens) -- seldom called
end
- elseif #str > 0 then
+ elseif nstr > 0 then
return high[str] or str
end
end
@@ -275,9 +289,10 @@ commands = commands or { }
--ldx]]--
function utf.split(str)
- local t = { }
+ local t, n = { }, 0
for snippet in utfcharacters(str) do
- t[#t+1] = snippet
+ n = n + 1
+ t[n+1] = snippet
end
return t
end
diff --git a/tex/context/base/chem-str.lua b/tex/context/base/chem-str.lua
index f574a8ac4..0e5f36434 100644
--- a/tex/context/base/chem-str.lua
+++ b/tex/context/base/chem-str.lua
@@ -214,6 +214,7 @@ local pattern =
local function process(spec,text,n,rulethickness,rulecolor,offset)
insert(stack,{ spec=spec, text=text, n=n })
local txt = #stack
+ local m = #metacode
for i=1,#spec do
local s = spec[i]
local d = definitions[s]
@@ -226,7 +227,7 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
local rep, operation, special, index, upto, set, text = lpegmatch(pattern,s)
if operation == "pb" then
insert(pstack,kind)
- metacode[#metacode+1] = syntax.pb.direct
+ m = m + 1 ; metacode[m] = syntax.pb.direct
if keys[special] == "text" and index then
if keys["c"..special] == "text" then -- can be option: auto ...
metacode[#metacode+1] = format('chem_c%s(%s,%s,"");',special,bonds,index)
@@ -236,21 +237,21 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
end
elseif operation == "save" then
insert(pstack,kind)
- metacode[#metacode+1] = syntax.save.direct
+ m = m + 1 ; metacode[m] = syntax.save.direct
elseif operation == "pe" or operation == "restore" then
kind = remove(pstack)
local ss = syntax[kind]
local prev = bonds or 6
keys, bonds, max, rot = ss.keys, ss.n, ss.max, 1
- metacode[#metacode+1] = syntax[operation].direct
- metacode[#metacode+1] = format("chem_set(%s,%s) ;",prev,bonds)
+ m = m + 1 ; metacode[m] = syntax[operation].direct
+ m = m + 1 ; metacode[m] = format("chem_set(%s,%s) ;",prev,bonds)
elseif operation == "front" then
if syntax[kind .. "_front"] then
kind = kind .. "_front"
local ss = syntax[kind]
local prev = bonds or 6
keys, bonds, max, rot = ss.keys, ss.n, ss.max, 1
- metacode[#metacode+1] = format("chem_set(%s,%s) ;",prev,bonds)
+ m = m + 1 ; metacode[m] = format("chem_set(%s,%s) ;",prev,bonds)
end
elseif operation then
local ss = syntax[operation]
@@ -260,18 +261,18 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
local sa = ss.arguments
if sa == 1 then
local one ; txt, one = fetch(txt)
- metacode[#metacode+1] = format(ds,one or "")
+ m = m + 1 ; metacode[m] = format(ds,one or "")
elseif sa ==2 then
local one ; txt, one = fetch(txt)
local two ; txt, two = fetch(txt)
- metacode[#metacode+1] = format(ds,one or "",two or "")
+ m = m + 1 ; metacode[m] = format(ds,one or "",two or "")
else
- metacode[#metacode+1] = ds
+ m = m + 1 ; metacode[m] = ds
end
elseif ss.keys then
local prev = bonds or 6
kind, keys, bonds, max, rot = s, ss.keys, ss.n, ss.max, 1
- metacode[#metacode+1] = format("chem_set(%s,%s) ;",prev,bonds)
+ m = m + 1 ; metacode[m] = format("chem_set(%s,%s) ;",prev,bonds)
end
else
local what = keys[operation]
@@ -279,31 +280,31 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
if set then
for i=1,#set do
local si = set[i]
- metacode[#metacode+1] = format("chem_%s(%s,%s,%s,%s,%s);",operation,bonds,si,si,rulethickness,rulecolor)
+ m = m + 1 ; metacode[m] = format("chem_%s(%s,%s,%s,%s,%s);",operation,bonds,si,si,rulethickness,rulecolor)
end
elseif upto then
- metacode[#metacode+1] = format("chem_%s(%s,%s,%s,%s,%s);",operation,bonds,index,upto,rulethickness,rulecolor)
+ m = m + 1 ; metacode[m] = format("chem_%s(%s,%s,%s,%s,%s);",operation,bonds,index,upto,rulethickness,rulecolor)
elseif index then
- metacode[#metacode+1] = format("chem_%s(%s,%s,%s,%s,%s);",operation,bonds,index,index,rulethickness,rulecolor)
+ m = m + 1 ; metacode[m] = format("chem_%s(%s,%s,%s,%s,%s);",operation,bonds,index,index,rulethickness,rulecolor)
else
- metacode[#metacode+1] = format("chem_%s(%s,%s,%s,%s,%s);",operation,bonds,1,max,rulethickness,rulecolor)
+ m = m + 1 ; metacode[m] = format("chem_%s(%s,%s,%s,%s,%s);",operation,bonds,1,max,rulethickness,rulecolor)
end
elseif what == "number" then
if set then
for i=1,#set do
local si = set[i]
- metacode[#metacode+1] = format('chem_%s(%s,%s,"\\dochemicaltext{%s}");',operation,bonds,si,si)
+ m = m + 1 ; metacode[m] = format('chem_%s(%s,%s,"\\dochemicaltext{%s}");',operation,bonds,si,si)
end
elseif upto then
for i=index,upto do
local si = set[i]
- metacode[#metacode+1] = format('chem_%s(%s,%s,"\\dochemicaltext{%s}");',operation,bonds,si,si)
+ m = m + 1 ; metacode[m] = format('chem_%s(%s,%s,"\\dochemicaltext{%s}");',operation,bonds,si,si)
end
elseif index then
- metacode[#metacode+1] = format('chem_%s(%s,%s,"\\dochemicaltext{%s}");',operation,bonds,index,index)
+ m = m + 1 ; metacode[m] = format('chem_%s(%s,%s,"\\dochemicaltext{%s}");',operation,bonds,index,index)
else
for i=1,max do
- metacode[#metacode+1] = format('chem_%s(%s,%s,"\\dochemicaltext{%s}");',operation,bonds,i,i)
+ m = m + 1 ; metacode[m] = format('chem_%s(%s,%s,"\\dochemicaltext{%s}");',operation,bonds,i,i)
end
end
elseif what == "text" then
@@ -318,7 +319,7 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
if t then
local a = align and align[si]
if a then a = "." .. a else a = "" end
- metacode[#metacode+1] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,a,bonds,si,molecule(apply(t)))
+ m = m + 1 ; metacode[m] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,a,bonds,si,molecule(apply(t)))
end
end
elseif upto then
@@ -328,14 +329,14 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
if t then
local s = align and align[i]
if s then s = "." .. s else s = "" end
- metacode[#metacode+1] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,s,bonds,i,molecule(apply(t)))
+ m = m + 1 ; metacode[m] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,s,bonds,i,molecule(apply(t)))
end
end
elseif index == 0 then
local t = text
if not t then txt, t = fetch(txt) end
if t then
- metacode[#metacode+1] = format('chem_%s_zero("\\dochemicaltext{%s}");',operation,molecule(apply(t)))
+ m = m + 1 ; metacode[m] = format('chem_%s_zero("\\dochemicaltext{%s}");',operation,molecule(apply(t)))
end
elseif index then
local t = text
@@ -343,7 +344,7 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
if t then
local s = align and align[index]
if s then s = "." .. s else s = "" end
- metacode[#metacode+1] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,s,bonds,index,molecule(apply(t)))
+ m = m + 1 ; metacode[m] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,s,bonds,index,molecule(apply(t)))
end
else
for i=1,max do
@@ -352,21 +353,21 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
if t then
local s = align and align[i]
if s then s = "." .. s else s = "" end
- metacode[#metacode+1] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,s,bonds,i,molecule(apply(t)))
+ m = m + 1 ; metacode[m] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,s,bonds,i,molecule(apply(t)))
end
end
end
elseif what == "transform" then
if index then
for r=1,rep do
- metacode[#metacode+1] = format('chem_%s(%s,%s);',operation,bonds,index)
+ m = m + 1 ; metacode[m] = format('chem_%s(%s,%s);',operation,bonds,index)
end
if operation == "rot" then
rot = index
end
end
elseif what == "fixed" then
- metacode[#metacode+1] = format("chem_%s(%s,%s,%s);",operation,bonds,rulethickness,rulecolor)
+ m = m + 1 ; metacode[m] = format("chem_%s(%s,%s,%s);",operation,bonds,rulethickness,rulecolor)
end
end
end
diff --git a/tex/context/base/colo-ini.lua b/tex/context/base/colo-ini.lua
index 77b2ea888..cf8a997cf 100644
--- a/tex/context/base/colo-ini.lua
+++ b/tex/context/base/colo-ini.lua
@@ -345,24 +345,22 @@ function colors.registerspotcolor(parent, str)
end
function colors.definemultitonecolor(name,multispec,colorspec,selfspec)
- local dd, pp, nn = { }, { }, { }
+ local dd, pp, nn, max = { }, { }, { }, 0
for k,v in gmatch(multispec,"(%a+)=([^%,]*)") do
- dd[#dd+1] = k
- pp[#pp+1] = v
- nn[#nn+1] = k
- nn[#nn+1] = format("%1.3g",tonumber(v) or 0) -- 0 can't happen
+ max = max + 1
+ dd[max] = k
+ pp[max] = v
+ nn[max] = format("%s_%1.3g",k,tonumber(v) or 0) -- 0 can't happen
end
---~ v = tonumber(v) * p
- local nof = #dd
- if nof > 0 then
+ if max > 0 then
dd, pp, nn = concat(dd,','), concat(pp,','), concat(nn,'_')
local parent = gsub(lower(nn),"[^%d%a%.]+","_")
colors.defineprocesscolor(parent,colorspec..","..selfspec,true,true)
local cp = attributes_list[a_color][parent]
if cp then
- do_registerspotcolor(parent, name, cp, "", nof, dd, pp)
- do_registermultitonecolor(parent, name, cp, "", nof, dd, pp)
- definecolor(name, register_color(name, 'spot', parent, nof, dd, pp), true)
+ do_registerspotcolor(parent, name, cp, "", max, dd, pp)
+ do_registermultitonecolor(parent, name, cp, "", max, dd, pp)
+ definecolor(name, register_color(name, 'spot', parent, max, dd, pp), true)
local t = settings_to_hash_strict(selfspec)
if t and t.a and t.t then
definetransparent(name, transparencies.register(name,transparent[t.a] or tonumber(t.a) or 1,tonumber(t.t) or 1), global)
@@ -412,7 +410,7 @@ end
function colors.formatcolor(ca,separator)
local cv = colors.value(ca)
if cv then
- local c, f, t, model = { }, 13, 13, cv[1]
+ local c, cn, f, t, model = { }, 0, 13, 13, cv[1]
if model == 2 then
f, t = 2, 2
elseif model == 3 then
@@ -421,7 +419,8 @@ function colors.formatcolor(ca,separator)
f, t = 6, 9
end
for i=f,t do
- c[#c+1] = format("%0.3f",cv[i])
+ cn = cn + 1
+ c[cn] = format("%0.3f",cv[i])
end
return concat(c,separator)
else
diff --git a/tex/context/base/cont-new.tex b/tex/context/base/cont-new.tex
index f429b372f..bfb881759 100644
--- a/tex/context/base/cont-new.tex
+++ b/tex/context/base/cont-new.tex
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2010.10.22 16:46}
+\newcontextversion{2010.10.29 11:35}
%D This file is loaded at runtime, thereby providing an
%D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/context.tex b/tex/context/base/context.tex
index 3ec7d4bc8..94e5edbcc 100644
--- a/tex/context/base/context.tex
+++ b/tex/context/base/context.tex
@@ -20,7 +20,7 @@
%D your styles an modules.
\edef\contextformat {\jobname}
-\edef\contextversion{2010.10.22 16:46}
+\edef\contextversion{2010.10.29 11:35}
%D For those who want to use this:
diff --git a/tex/context/base/core-con.lua b/tex/context/base/core-con.lua
index 8f90eac16..efdb0e1bc 100644
--- a/tex/context/base/core-con.lua
+++ b/tex/context/base/core-con.lua
@@ -435,71 +435,71 @@ local vector = {
local function tochinese(n,name) -- normal, caps, all
-- improved version by Li Yanrui
- local result = { }
+ local result, r = { }, 0
local vector = vector[name] or vector.normal
while true do
if n == 0 then
break
elseif n >= 100000000 then
local m = floor(n/100000000)
- result[#result+1] = tochinese(m,name)
- result[#result+1] = vector[100000000]
+ r = r + 1 ; result[r] = tochinese(m,name)
+ r = r + 1 ; result[r] = vector[100000000]
local z = n - m * 100000000
- if z > 0 and z < 10000000 then result[#result+1] = vector[0] end
+ if z > 0 and z < 10000000 then r = r + 1 ; result[r] = vector[0] end
n = n % 100000000
elseif n >= 10000000 then
local m = floor(n/10000)
- result[#result+1] = tochinese(m,name)
- result[#result+1] = vector[10000]
+ r = r + 1 ; result[r] = tochinese(m,name)
+ r = r + 1 ; result[r] = vector[10000]
local z = n - m * 10000
- if z > 0 and z < 1000 then result[#result+1] = vector[0] end
+ if z > 0 and z < 1000 then r = r + 1 ; result[r] = vector[0] end
n = n % 10000
elseif n >= 1000000 then
local m = floor(n/10000)
- result[#result+1] = tochinese(m,name)
- result[#result+1] = vector[10000]
+ r = r + 1 ; result[r] = tochinese(m,name)
+ r = r + 1 ; result[r] = vector[10000]
local z = n - m * 10000
- if z > 0 and z < 1000 then result[#result+1] = vector[0] end
+ if z > 0 and z < 1000 then r = r + 1 ; result[r] = vector[0] end
n = n % 10000
elseif n >= 100000 then
local m = floor(n/10000)
- result[#result+1] = tochinese(m,name)
- result[#result+1] = vector[10000]
+ r = r + 1 ; result[r] = tochinese(m,name)
+ r = r + 1 ; result[r] = vector[10000]
local z = n - m * 10000
- if z > 0 and z < 1000 then result[#result+1] = vector[0] end
+ if z > 0 and z < 1000 then r = r + 1 ; result[r] = vector[0] end
n = n % 10000
elseif n >= 10000 then
local m = floor(n/10000)
- result[#result+1] = vector[m]
- result[#result+1] = vector[10000]
+ r = r + 1 ; result[r] = vector[m]
+ r = r + 1 ; result[r] = vector[10000]
local z = n - m * 10000
- if z > 0 and z < 1000 then result[#result+1] = vector[0] end
+ if z > 0 and z < 1000 then r = r + 1 ; result[r] = vector[0] end
n = n % 10000
elseif n >= 1000 then
local m = floor(n/1000)
- result[#result+1] = vector[m]
- result[#result+1] = vector[1000]
+ r = r + 1 ; result[r] = vector[m]
+ r = r + 1 ; result[r] = vector[1000]
local z = n - m * 1000
- if z > 0 and z < 100 then result[#result+1] = vector[0] end
+ if z > 0 and z < 100 then r = r + 1 ; result[r] = vector[0] end
n = n % 1000
elseif n >= 100 then
local m = floor(n/100)
- result[#result+1] = vector[m]
- result[#result+1] = vector[100]
+ r = r + 1 ; result[r] = vector[m]
+ r = r + 1 ; result[r] = vector[100]
local z = n - m * 100
- if z > 0 and z < 10 then result[#result+1] = vector[0] end
+ if z > 0 and z < 10 then r = r + 1 ; result[r] = vector[0] end
n = n % 100
elseif n >= 10 then
local m = floor(n/10)
if m > 1 and vector[m*10] then
- result[#result+1] = vector[m*10]
+ r = r + 1 ; result[r] = vector[m*10]
else
- result[#result+1] = vector[m]
- result[#result+1] = vector[10]
+ r = r + 1 ; result[r] = vector[m]
+ r = r + 1 ; result[r] = vector[10]
end
n = n % 10
else
- result[#result+1] = vector[n]
+ r = r + 1 ; result[r] = vector[n]
break
end
end
diff --git a/tex/context/base/core-ctx.lua b/tex/context/base/core-ctx.lua
index b1427f0e0..111c125da 100644
--- a/tex/context/base/core-ctx.lua
+++ b/tex/context/base/core-ctx.lua
@@ -56,7 +56,7 @@ local function found(name) -- used in resolve
end
local function resolve(name) -- used a few times later on
- local filename = file.collapse_path(name)
+ local filename = file.collapsepath(name)
local prepname = islocal and found(file.basename(name))
if prepname then
return prepname
diff --git a/tex/context/base/core-sys.lua b/tex/context/base/core-sys.lua
index e4e49762d..47a5c340d 100644
--- a/tex/context/base/core-sys.lua
+++ b/tex/context/base/core-sys.lua
@@ -20,5 +20,6 @@ function commands.updatefilenames(inputfilename,outputfilename)
end
statistics.register("result saved in file", function()
+ -- suffix will be fetched from backend
return string.format( "%s.%s", environment.outputfilename, (tex.pdfoutput>0 and "pdf") or "dvi")
end)
diff --git a/tex/context/base/data-env.lua b/tex/context/base/data-env.lua
index ea6faeb6c..ac476593d 100644
--- a/tex/context/base/data-env.lua
+++ b/tex/context/base/data-env.lua
@@ -21,7 +21,6 @@ formats['enc'] = 'ENCFONTS' suffixes['enc'] = { 'enc' }
formats['fmt'] = 'TEXFORMATS' suffixes['fmt'] = { 'fmt' }
formats['map'] = 'TEXFONTMAPS' suffixes['map'] = { 'map' }
formats['mp'] = 'MPINPUTS' suffixes['mp'] = { 'mp' }
-formats['ocp'] = 'OCPINPUTS' suffixes['ocp'] = { 'ocp' }
formats['ofm'] = 'OFMFONTS' suffixes['ofm'] = { 'ofm', 'tfm' }
formats['otf'] = 'OPENTYPEFONTS' suffixes['otf'] = { 'otf' }
formats['opl'] = 'OPLFONTS' suffixes['opl'] = { 'opl' }
diff --git a/tex/context/base/data-exp.lua b/tex/context/base/data-exp.lua
index 6d15a1cd7..98fbe9f95 100644
--- a/tex/context/base/data-exp.lua
+++ b/tex/context/base/data-exp.lua
@@ -13,7 +13,7 @@ local lpegCt, lpegCs, lpegP, lpegC, lpegS = lpeg.Ct, lpeg.Cs, lpeg.P, lpeg.C, lp
local type, next = type, next
local ostype = os.type
-local collapse_path = file.collapse_path
+local collapsepath = file.collapsepath
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
local trace_expansions = false trackers.register("resolvers.expansions", function(v) trace_expansions = v end)
@@ -49,22 +49,29 @@ local resolvers = resolvers
local dummy_path_expr = "^!*unset/*$"
local function do_first(a,b)
- local t = { }
- for s in gmatch(b,"[^,]+") do t[#t+1] = a .. s end
+ local t, n = { }, 0
+ for s in gmatch(b,"[^,]+") do
+ n = n + 1
+ t[n] = a .. s
+ end
return "{" .. concat(t,",") .. "}"
end
local function do_second(a,b)
- local t = { }
- for s in gmatch(a,"[^,]+") do t[#t+1] = s .. b end
+ local t, n = { }, 0
+ for s in gmatch(a,"[^,]+") do
+ n = n + 1
+ t[n] = s .. b
+ end
return "{" .. concat(t,",") .. "}"
end
local function do_both(a,b)
- local t = { }
+ local t, n = { }, 0
for sa in gmatch(a,"[^,]+") do
for sb in gmatch(b,"[^,]+") do
- t[#t+1] = sa .. sb
+ n = n + 1
+ t[n] = sa .. sb
end
end
return "{" .. concat(t,",") .. "}"
@@ -88,6 +95,7 @@ local function splitpathexpr(str, newlist, validate)
report_resolvers("expanding variable '%s'",str)
end
local t, ok, done = newlist or { }, false, false
+ local n = #t
str = lpegmatch(replacer_1,str)
while true do
done = false
@@ -111,11 +119,15 @@ local function splitpathexpr(str, newlist, validate)
if validate then
for s in gmatch(str,"[^,]+") do
s = validate(s)
- if s then t[#t+1] = s end
+ if s then
+ n = n + 1
+ t[n] = s
+ end
end
else
for s in gmatch(str,"[^,]+") do
- t[#t+1] = s
+ n = n + 1
+ t[n] = s
end
end
if trace_expansions then
@@ -128,7 +140,7 @@ end
local function validate(s)
local isrecursive = find(s,"//$")
- s = collapse_path(s)
+ s = collapsepath(s)
if isrecursive then
s = s .. "//"
end
@@ -151,11 +163,14 @@ function resolvers.expandedpathfromlist(pathlist) -- maybe not a list, just a pa
splitpathexpr(pathlist[k],newlist,validate)
end
else
+ local n = 0
for k=1,#pathlist do
for p in gmatch(pathlist[k],"([^,]+)") do
---~ p = collapse_path(p)
p = validate(p)
- if p ~= "" then newlist[#newlist+1] = p end
+ if p ~= "" then
+ n = n + 1
+ newlist[n] = p
+ end
end
end
end
@@ -164,16 +179,63 @@ end
-- We also put some cleanup code here.
-local cleanup -- used recursively
+--~ local cleanup -- used recursively
+--~ local homedir
+
+--~ cleanup = lpeg.replacer {
+--~ {
+--~ "!",
+--~ ""
+--~ },
+--~ {
+--~ "\\",
+--~ "/"
+--~ },
+--~ {
+--~ "~" ,
+--~ function()
+--~ return lpegmatch(cleanup,environment.homedir)
+--~ end
+--~ },
+--~ }
+
+--~ function resolvers.cleanpath(str)
+--~ return str and lpegmatch(cleanup,str)
+--~ end
-cleanup = lpeg.replacer {
- { "!", "" },
- { "\\", "/" },
- { "~" , function() return lpegmatch(cleanup,environment.homedir) end },
+local cleanup = lpeg.replacer {
+ { "!" , "" },
+ { "\\" , "/" },
}
+local homedir
+
function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+ if not homedir then
+ homedir = lpegmatch(cleanup,environment.homedir or "")
+ if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_resolvers("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if find(str,"~") then
+ return "" -- special case
+ else
+ return str and lpegmatch(cleanup,str)
+ end
+ end
+ else
+ cleanup = lpeg.replacer {
+ { "!" , "" },
+ { "\\" , "/" },
+ { "~" , homedir },
+ }
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str)
+ end
+ end
+ end
+ return resolvers.cleanpath(str)
end
-- This one strips quotes and funny tokens.
@@ -203,8 +265,6 @@ end
-- we join them and split them after the expansion has taken place. This
-- is more convenient.
---~ local checkedsplit = string.checkedsplit
-
local cache = { }
local splitter = lpegCt(lpeg.splitat(lpegS(ostype == "windows" and ";" or ":;"))) -- maybe add ,
@@ -219,15 +279,17 @@ local function splitconfigurationpath(str) -- beware, this can be either a path
str = gsub(str,"\\","/")
local split = lpegmatch(splitter,str)
found = { }
+ local noffound = 0
for i=1,#split do
local s = split[i]
if not find(s,"^{*unset}*") then
- found[#found+1] = s
+ noffound = noffound + 1
+ found[noffound] = s
end
end
if trace_expansions then
report_resolvers("splitting path specification '%s'",str)
- for k=1,#found do
+ for k=1,noffound do
report_resolvers("% 4i: %s",k,found[k])
end
end
diff --git a/tex/context/base/data-ini.lua b/tex/context/base/data-ini.lua
index 9550c1e78..ed36b6992 100644
--- a/tex/context/base/data-ini.lua
+++ b/tex/context/base/data-ini.lua
@@ -65,9 +65,13 @@ end
do
- local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or '~'
+ local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
- homedir = file.collapse_path(homedir)
+ if not homedir or homedir == "" then
+ homedir = string.char(127) -- we need a value, later we wil trigger on it
+ end
+
+ homedir = file.collapsepath(homedir)
ossetenv("HOME", homedir) -- can be used in unix cnf files
ossetenv("USERPROFILE",homedir) -- can be used in windows cnf files
@@ -86,8 +90,8 @@ do
local ownbin = environment.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex"
local ownpath = environment.ownpath or os.selfdir
- ownbin = file.collapse_path(ownbin)
- ownpath = file.collapse_path(ownpath)
+ ownbin = file.collapsepath(ownbin)
+ ownpath = file.collapsepath(ownpath)
if not ownpath or ownpath == "" or ownpath == "unset" then
ownpath = args[-1] or arg[-1]
@@ -159,9 +163,9 @@ do
local ownpath = environment.ownpath or dir.current()
if ownpath then
- ossetenv('SELFAUTOLOC', file.collapse_path(ownpath))
- ossetenv('SELFAUTODIR', file.collapse_path(ownpath .. "/.."))
- ossetenv('SELFAUTOPARENT', file.collapse_path(ownpath .. "/../.."))
+ ossetenv('SELFAUTOLOC', file.collapsepath(ownpath))
+ ossetenv('SELFAUTODIR', file.collapsepath(ownpath .. "/.."))
+ ossetenv('SELFAUTOPARENT', file.collapsepath(ownpath .. "/../.."))
else
report_resolvers("error: unable to locate ownpath")
os.exit()
@@ -197,7 +201,7 @@ if not texroot or texroot == "" then
ossetenv('TEXROOT',texroot)
end
-environment.texroot = file.collapse_path(texroot)
+environment.texroot = file.collapsepath(texroot)
-- Tracing. Todo ...
diff --git a/tex/context/base/data-met.lua b/tex/context/base/data-met.lua
index 06c810fc4..b51c8b57b 100644
--- a/tex/context/base/data-met.lua
+++ b/tex/context/base/data-met.lua
@@ -34,7 +34,7 @@ function resolvers.splitmethod(filename)
end
function resolvers.methodhandler(what, filename, filetype) -- ...
- filename = file.collapse_path(filename)
+ filename = file.collapsepath(filename)
local specification = (type(filename) == "string" and resolvers.splitmethod(filename)) or filename -- no or { }, let it bomb
local scheme = specification.scheme
local resolver = resolvers[what]
diff --git a/tex/context/base/data-res.lua b/tex/context/base/data-res.lua
index 97ab8ce5d..8e3428b2f 100644
--- a/tex/context/base/data-res.lua
+++ b/tex/context/base/data-res.lua
@@ -23,7 +23,7 @@ local lpegP, lpegS, lpegR, lpegC, lpegCc, lpegCs, lpegCt = lpeg.P, lpeg.S, lpeg.
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local filedirname, filebasename, fileextname, filejoin = file.dirname, file.basename, file.extname, file.join
-local collapse_path = file.collapse_path
+local collapsepath = file.collapsepath
local allocate = utilities.storage.allocate
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -148,7 +148,6 @@ local function expandvars(lst) -- simple vars
var = gsub(var,"%$([%a%d%_%-]+)",resolve)
var = gsub(var,";+",";")
var = gsub(var,";[!{}/\\]+;",";")
---~ var = gsub(var,"~",resolvers.homedir)
lst[k] = var
end
end
@@ -170,7 +169,6 @@ local function expandedvariable(var) -- simple vars
var = gsub(var,"%$([%a%d%_%-]+)",resolve)
var = gsub(var,";+",";")
var = gsub(var,";[!{}/\\]+;",";")
---~ var = gsub(var,"~",resolvers.homedir)
return var
end
@@ -228,7 +226,7 @@ local function identify_configuration_files()
expandvars(cnfpaths) --- hm
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
- local filename = collapse_path(filejoin(cnfpaths[i],luacnfname))
+ local filename = collapsepath(filejoin(cnfpaths[i],luacnfname))
if lfs.isfile(filename) then
specification[#specification+1] = filename
end
@@ -389,7 +387,7 @@ local function locate_file_databases()
-- todo: cache:// and tree:// (runtime)
local texmfpaths = resolvers.expandedpathlist('TEXMF')
for i=1,#texmfpaths do
- local path = collapse_path(texmfpaths[i])
+ local path = collapsepath(texmfpaths[i])
local stripped = gsub(path,"^!!","")
local runtime = stripped == path
path = resolvers.cleanpath(path)
@@ -502,11 +500,12 @@ end
function resolvers.splitexpansions()
local ie = instance.expansions
for k,v in next, ie do
- local t, h, p = { }, { }, splitconfigurationpath(v)
+ local t, tn, h, p = { }, 0, { }, splitconfigurationpath(v)
for kk=1,#p do
local vv = p[kk]
if vv ~= "" and not h[vv] then
- t[#t+1] = vv
+ tn = tn + 1
+ t[tn] = vv
h[vv] = true
end
end
@@ -613,7 +612,8 @@ end
function resolvers.registerextrapath(paths,subpaths)
local ep = instance.extra_paths or { }
- local n = #ep
+ local oldn = #ep
+ local newn = oldn
if paths and paths ~= "" then
if subpaths and subpaths ~= "" then
for p in gmatch(paths,"[^,]+") do
@@ -621,7 +621,8 @@ function resolvers.registerextrapath(paths,subpaths)
for s in gmatch(subpaths,"[^,]+") do
local ps = p .. "/" .. s
if not done[ps] then
- ep[#ep+1] = resolvers.cleanpath(ps)
+ newn = newn + 1
+ ep[newn] = resolvers.cleanpath(ps)
done[ps] = true
end
end
@@ -629,7 +630,8 @@ function resolvers.registerextrapath(paths,subpaths)
else
for p in gmatch(paths,"[^,]+") do
if not done[p] then
- ep[#ep+1] = resolvers.cleanpath(p)
+ newn = newn + 1
+ ep[newn] = resolvers.cleanpath(p)
done[p] = true
end
end
@@ -640,16 +642,17 @@ function resolvers.registerextrapath(paths,subpaths)
for s in gmatch(subpaths,"[^,]+") do
local ps = ep[i] .. "/" .. s
if not done[ps] then
- ep[#ep+1] = resolvers.cleanpath(ps)
+ newn = newn + 1
+ ep[newn] = resolvers.cleanpath(ps)
done[ps] = true
end
end
end
end
- if #ep > 0 then
+ if newn > 0 then
instance.extra_paths = ep -- register paths
end
- if #ep > n then
+ if newn > oldn then
instance.lists = { } -- erase the cache
end
end
@@ -659,14 +662,15 @@ local function made_list(instance,list)
if not ep or #ep == 0 then
return list
else
- local done, new = { }, { }
+ local done, new, newn = { }, { }, 0
-- honour . .. ../.. but only when at the start
for k=1,#list do
local v = list[k]
if not done[v] then
if find(v,"^[%.%/]$") then
done[v] = true
- new[#new+1] = v
+ newn = newn + 1
+ new[newn] = v
else
break
end
@@ -677,7 +681,8 @@ local function made_list(instance,list)
local v = ep[k]
if not done[v] then
done[v] = true
- new[#new+1] = v
+ newn = newn + 1
+ new[newn] = v
end
end
-- next the formal paths
@@ -685,7 +690,8 @@ local function made_list(instance,list)
local v = list[k]
if not done[v] then
done[v] = true
- new[#new+1] = v
+ newn = newn + 1
+ new[newn] = v
end
end
return new
@@ -696,7 +702,7 @@ function resolvers.cleanpathlist(str)
local t = resolvers.expandedpathlist(str)
if t then
for i=1,#t do
- t[i] = collapse_path(resolvers.cleanpath(t[i]))
+ t[i] = collapsepath(resolvers.cleanpath(t[i]))
end
end
return t
@@ -762,7 +768,7 @@ resolvers.isreadable.tex = resolvers.isreadable.file
-- name/name
local function collect_files(names)
- local filelist = { }
+ local filelist, noffiles = { }, 0
for k=1,#names do
local fname = names[k]
if trace_detail then
@@ -803,7 +809,8 @@ local function collect_files(names)
if trace_detail then
report_resolvers("match: kind '%s', search '%s', result '%s'",kind,search,result)
end
- filelist[#filelist+1] = { kind, search, result }
+ noffiles = noffiles + 1
+ filelist[noffiles] = { kind, search, result }
end
else
for kk=1,#blobfile do
@@ -815,7 +822,8 @@ local function collect_files(names)
if trace_detail then
report_resolvers("match: kind '%s', search '%s', result '%s'",kind,search,result)
end
- filelist[#filelist+1] = { kind, search, result }
+ noffiles = noffiles + 1
+ filelist[noffiles] = { kind, search, result }
end
end
end
@@ -825,7 +833,7 @@ local function collect_files(names)
end
end
end
- return #filelist > 0 and filelist or nil
+ return noffiles > 0 and filelist or nil
end
function resolvers.registerintrees(name)
@@ -851,7 +859,7 @@ end
local function collect_instance_files(filename,collected) -- todo : plugin (scanners, checkers etc)
local result = collected or { }
local stamp = nil
- filename = collapse_path(filename)
+ filename = collapsepath(filename)
-- speed up / beware: format problem
if instance.remember then
stamp = filename .. "--" .. instance.engine .. "--" .. instance.progname .. "--" .. instance.format
@@ -1107,7 +1115,7 @@ local function collect_instance_files(filename,collected) -- todo : plugin (scan
end
end
for k=1,#result do
- local rk = collapse_path(result[k])
+ local rk = collapsepath(result[k])
result[k] = rk
resolvers.registerintrees(rk) -- for tracing used files
end
diff --git a/tex/context/base/data-sch.lua b/tex/context/base/data-sch.lua
index 232722749..c8d209798 100644
--- a/tex/context/base/data-sch.lua
+++ b/tex/context/base/data-sch.lua
@@ -116,21 +116,23 @@ schemes.install('https')
schemes.install('ftp')
statistics.register("scheme handling time", function()
- local l, r = { }, { }
+ local l, r, nl, nr = { }, { }, 0, 0
for k, v in table.sortedhash(loaded) do
if v > 0 then
- l[#l+1] = k .. ":" .. v
+ nl = nl + 1
+ l[nl] = k .. ":" .. v
end
end
for k, v in table.sortedhash(reused) do
if v > 0 then
- r[#r+1] = k .. ":" .. v
+ nr = nr + 1
+ r[nr] = k .. ":" .. v
end
end
- local n = #l + #r
+ local n = nl + nr
if n > 0 then
- l = (#l > 0 and concat(l)) or "none"
- r = (#r > 0 and concat(r)) or "none"
+ l = (nl > 0 and concat(l)) or "none"
+ r = (nr > 0 and concat(r)) or "none"
return format("%s seconds, %s processed, threshold %s seconds, loaded: %s, reused: %s",
statistics.elapsedtime(schemes), n, schemes.threshold, l, r)
else
diff --git a/tex/context/base/data-tmf.lua b/tex/context/base/data-tmf.lua
index d98e0ec66..e343e041b 100644
--- a/tex/context/base/data-tmf.lua
+++ b/tex/context/base/data-tmf.lua
@@ -22,7 +22,7 @@ function resolvers.load_tree(tree)
local texos = "texmf-" .. os.platform
local oldroot = environment.texroot
- local newroot = file.collapse_path(tree)
+ local newroot = file.collapsepath(tree)
local newtree = file.join(newroot,texos)
local newpath = file.join(newtree,"bin")
diff --git a/tex/context/base/data-tmp.lua b/tex/context/base/data-tmp.lua
index 526d271bd..5ed6e4e1c 100644
--- a/tex/context/base/data-tmp.lua
+++ b/tex/context/base/data-tmp.lua
@@ -72,7 +72,7 @@ local function identify()
local cachepath = texmfcaches[k]
if cachepath ~= "" then
cachepath = resolvers.cleanpath(cachepath)
- cachepath = file.collapse_path(cachepath)
+ cachepath = file.collapsepath(cachepath)
local valid = isdir(cachepath)
if valid then
if file.is_readable(cachepath) then
diff --git a/tex/context/base/font-ctx.lua b/tex/context/base/font-ctx.lua
index 8802ccb64..6101644e0 100644
--- a/tex/context/base/font-ctx.lua
+++ b/tex/context/base/font-ctx.lua
@@ -26,11 +26,13 @@ local report_define = logs.new("define fonts")
local report_usage = logs.new("fonts usage")
local report_mapfiles = logs.new("mapfiles")
-local fonts = fonts
-local tfm = fonts.tfm
-local fontdata = fonts.identifiers
-local definers = fonts.definers
-local specifiers = definers.specifiers
+local fonts = fonts
+local tfm = fonts.tfm
+local fontdata = fonts.identifiers
+local definers = fonts.definers
+local specifiers = definers.specifiers
+local currentfont = font.current
+local texattribute = tex.attribute
specifiers.contextsetups = specifiers.contextsetups or { }
specifiers.contextnumbers = specifiers.contextnumbers or { }
@@ -226,31 +228,28 @@ specifiers.contextnumber = contextnumber
specifiers.mergecontext = mergecontext
specifiers.registercontext = registercontext
-local current_font = font.current
-local tex_attribute = tex.attribute
-
local cache = { } -- concat might be less efficient than nested tables
function fonts.withset(name,what)
- local zero = tex_attribute[0]
+ local zero = texattribute[0]
local hash = zero .. "+" .. name .. "*" .. what
local done = cache[hash]
if not done then
done = mergecontext(zero,name,what)
cache[hash] = done
end
- tex_attribute[0] = done
+ texattribute[0] = done
end
function fonts.withfnt(name,what)
- local font = current_font()
+ local font = currentfont()
local hash = font .. "*" .. name .. "*" .. what
local done = cache[hash]
if not done then
done = registercontext(font,name,what)
cache[hash] = done
end
- tex_attribute[0] = done
+ texattribute[0] = done
end
function specifiers.showcontext(name)
@@ -579,7 +578,7 @@ end
local p, f = 1, "%0.1fpt" -- normally this value is changed only once
-local stripper = lpeg.patterns.strip_zeros
+local stripper = lpeg.patterns.stripzeros
function fonts.nbfs(amount,precision)
if precision ~= p then
@@ -663,8 +662,8 @@ fonts.map.reset() -- resets the default file
local nounicode = byte("?")
-local function nametoslot(name) -- maybe some day rawdata
- local tfmdata = fonts.ids[font.current()]
+local function nametoslot(name,all) -- maybe some day rawdata
+ local tfmdata = fontdata[currentfont()]
local shared = tfmdata and tfmdata.shared
local fntdata = shared and shared.otfdata or shared.afmdata
if fntdata then
@@ -673,7 +672,9 @@ local function nametoslot(name) -- maybe some day rawdata
return nounicode
elseif type(unicode) == "number" then
return unicode
- else -- multiple unicodes
+ elseif all then
+ return unicode
+ else
return unicode[1]
end
end
@@ -682,11 +683,12 @@ end
fonts.nametoslot = nametoslot
-function fonts.char(n) -- todo: afm en tfm
+function fonts.char(n,all) -- todo: afm en tfm
if type(n) == "string" then
- n = nametoslot(n)
+ n = nametoslot(n,all)
end
- if type(n) == "number" then
+ -- if type(n) == "number" then
+ if n then
context.char(n)
end
end
@@ -702,7 +704,7 @@ fonts.afm.char = fonts.char
-- this will change ...
function fonts.showchardata(n)
- local tfmdata = fonts.ids[font.current()]
+ local tfmdata = fontdata[currentfont()]
if tfmdata then
if type(n) == "string" then
n = utf.byte(n)
@@ -715,7 +717,7 @@ function fonts.showchardata(n)
end
function fonts.showfontparameters()
- local tfmdata = fonts.ids[font.current()]
+ local tfmdata = fontdata[currentfont()]
if tfmdata then
local parameters, mathconstants = tfmdata.parameters, tfmdata.MathConstants
local hasparameters, hasmathconstants = parameters and next(parameters), mathconstants and next(mathconstants)
@@ -733,9 +735,10 @@ end
function fonts.reportdefinedfonts()
if trace_usage then
- local t = { }
- for id, data in table.sortedhash(fonts.ids) do
- t[#t+1] = {
+ local t, tn = { }, 0
+ for id, data in table.sortedhash(fontdata) do
+ tn = tn + 1
+ t[tn] = {
format("%03i",id),
format("%09i",data.size or 0),
data.type or "real",
@@ -755,7 +758,7 @@ function fonts.reportdefinedfonts()
report_usage()
report_usage("defined fonts:")
report_usage()
- for k=1,#t do
+ for k=1,tn do
report_usage(t[k])
end
end
@@ -766,20 +769,20 @@ luatex.registerstopactions(fonts.reportdefinedfonts)
function fonts.reportusedfeatures()
-- numbers, setups, merged
if trace_usage then
- local t = { }
- for i=1,#numbers do
+ local t, n = { }, #numbers
+ for i=1,n do
local name = numbers[i]
local setup = setups[name]
local n = setup.number
setup.number = nil -- we have no reason to show this
- t[#t+1] = { i, name, table.sequenced(setup,false,true) } -- simple mode
+ t[i] = { i, name, table.sequenced(setup,false,true) } -- simple mode
setup.number = n -- restore it (normally not needed as we're done anyway)
end
formatcolumns(t," ")
report_usage()
report_usage("defined featuresets:")
report_usage()
- for k=1,#t do
+ for k=1,n do
report_usage(t[k])
end
end
@@ -844,3 +847,7 @@ function fonts.definetypeface(name,t)
local settings = table.sequenced({ features= t.features },",")
context.dofastdefinetypeface(name, shortcut, shape, size, settings)
end
+
+function fonts.current(id) -- todo: also handle name
+ return fontdata[currentfont()] or fontdata[0]
+end
diff --git a/tex/context/base/font-def.lua b/tex/context/base/font-def.lua
index 713e5b68d..2f530f022 100644
--- a/tex/context/base/font-def.lua
+++ b/tex/context/base/font-def.lua
@@ -170,14 +170,15 @@ local sortedhashkeys = table.sortedhashkeys
function tfm.hashfeatures(specification)
local features = specification.features
if features then
- local t = { }
+ local t, tn = { }, 0
local normal = features.normal
if normal and next(normal) then
local f = sortedhashkeys(normal)
for i=1,#f do
local v = f[i]
if v ~= "number" and v ~= "features" then -- i need to figure this out, features
- t[#t+1] = v .. '=' .. tostring(normal[v])
+ tn = tn + 1
+ t[tn] = v .. '=' .. tostring(normal[v])
end
end
end
@@ -186,13 +187,15 @@ function tfm.hashfeatures(specification)
local f = sortedhashkeys(vtf)
for i=1,#f do
local v = f[i]
- t[#t+1] = v .. '=' .. tostring(vtf[v])
+ tn = tn + 1
+ t[tn] = v .. '=' .. tostring(vtf[v])
end
end
---~ if specification.mathsize then
---~ t[#t+1] = "mathsize=" .. specification.mathsize
---~ end
- if #t > 0 then
+ --~ if specification.mathsize then
+ --~ tn = tn + 1
+ --~ t[tn] = "mathsize=" .. specification.mathsize
+ --~ end
+ if tn > 0 then
return concat(t,"+")
end
end
diff --git a/tex/context/base/font-enh.lua b/tex/context/base/font-enh.lua
index 27e4e8b75..183ca848b 100644
--- a/tex/context/base/font-enh.lua
+++ b/tex/context/base/font-enh.lua
@@ -33,20 +33,26 @@ supplied by <l n='luatex'/>.</p>
-- auto complete font with missing composed characters
-table.insert(fonts.manipulators,"compose")
-
-function fonts.initializers.common.compose(tfmdata,value)
- if value then
- fonts.vf.aux.compose_characters(tfmdata)
- end
-end
-
-- tfm features, experimental
tfm.features = tfm.features or { }
tfm.features.list = tfm.features.list or { }
tfm.features.default = tfm.features.default or { }
+local initializers = fonts.initializers
+local triggers = fonts.triggers
+local manipulators = fonts.manipulators
+local featurelist = tfm.features.list
+local defaultfeaturelist = tfm.features.default
+
+table.insert(manipulators,"compose")
+
+function initializers.common.compose(tfmdata,value)
+ if value then
+ fonts.vf.aux.compose_characters(tfmdata)
+ end
+end
+
function tfm.enhance(tfmdata,specification)
-- we don't really share tfm data because we always reload
-- but this is more in sycn with afm and such
@@ -72,52 +78,67 @@ function tfm.setfeatures(tfmdata)
local features = shared.features
if features and next(features) then
local mode = tfmdata.mode or features.mode or "base"
- local fi = fonts.initializers[mode]
+ local fi = initializers[mode]
if fi and fi.tfm then
local function initialize(list) -- using tex lig and kerning
if list then
+ -- fi adapts !
for i=1,#list do
local f = list[i]
local value = features[f]
- if value and fi.tfm[f] then -- brr
- if tfm.trace_features then
- report_define("initializing feature %s to %s for mode %s for font %s",f,tostring(value),mode or 'unknown',tfmdata.name or 'unknown')
+ if value then
+ local fitfmf = fi.tfm[f] -- brr
+ if fitfmf then
+ if tfm.trace_features then
+ report_define("initializing feature %s to %s for mode %s for font %s",f,tostring(value),mode or 'unknown',tfmdata.name or 'unknown')
+ end
+ fitfmf(tfmdata,value)
+ mode = tfmdata.mode or features.mode or "base"
+ fi = initializers[mode]
end
- fi.tfm[f](tfmdata,value)
- mode = tfmdata.mode or features.mode or "base"
- fi = fonts.initializers[mode]
end
end
end
end
- initialize(fonts.triggers)
- initialize(tfm.features.list)
- initialize(fonts.manipulators)
+ initialize(triggers)
+ initialize(featurelist)
+ initialize(manipulators)
end
local fm = fonts.methods[mode]
- if fm and fm.tfm then
- local function register(list) -- node manipulations
- if list then
- for i=1,#list do
- local f = list[i]
- if features[f] and fm.tfm[f] then -- brr
- if not shared.processors then -- maybe also predefine
- shared.processors = { fm.tfm[f] }
- else
- shared.processors[#shared.processors+1] = fm.tfm[f]
+ if fm then
+ local fmtfm = fm.tfm
+ if fmtfm then
+ local function register(list) -- node manipulations
+ if list then
+ local sp = shared.processors
+ local ns = sp and #sp
+ for i=1,#list do
+ local f = list[i]
+ if features[f] then
+ local fmtfmf = fmtfm[f]
+ if not fmtfmf then
+ -- brr
+ elseif not sp then
+ sp = { fmtfmf }
+ ns = 1
+ shared.processors = sp
+ else
+ ns = ns + 1
+ sp[ns] = fmtfmf
+ end
end
end
end
end
+ register(featurelist)
end
- register(tfm.features.list)
end
end
end
function tfm.features.register(name,default)
- tfm.features.list[#tfm.features.list+1] = name
- tfm.features.default[name] = default
+ featurelist[#tfm.features.list+1] = name
+ defaultfeaturelist[name] = default
end
function tfm.reencode(tfmdata,encoding)
@@ -143,8 +164,8 @@ end
tfm.features.register('reencode')
-fonts.initializers.base.tfm.reencode = tfm.reencode
-fonts.initializers.node.tfm.reencode = tfm.reencode
+initializers.base.tfm.reencode = tfm.reencode
+initializers.node.tfm.reencode = tfm.reencode
fonts.enc = fonts.enc or { }
fonts.enc.remappings = fonts.enc.remappings or { }
@@ -173,8 +194,8 @@ end
tfm.features.register('remap')
-fonts.initializers.base.tfm.remap = tfm.remap
-fonts.initializers.node.tfm.remap = tfm.remap
+initializers.base.tfm.remap = tfm.remap
+initializers.node.tfm.remap = tfm.remap
--~ obsolete
--~
diff --git a/tex/context/base/font-ext.lua b/tex/context/base/font-ext.lua
index 79d0f0955..c17516653 100644
--- a/tex/context/base/font-ext.lua
+++ b/tex/context/base/font-ext.lua
@@ -164,21 +164,6 @@ vectors['default'] = {
vectors['quality'] = vectors['default'] -- metatable ?
---~ function table.locator(...)
---~ local k = { ... }
---~ return function(t)
---~ for i=1,#k do
---~ t = t[k[i]]
---~ if not k then
---~ return false
---~ end
---~ end
---~ return t
---~ end
---~ end
-
---~ local locate = table.locator { "goodies", "expansions" }
-
function initializers.common.expansion(tfmdata,value)
if value then
local class, vector = get_class_and_vector(tfmdata,value,"expansions")
diff --git a/tex/context/base/font-log.lua b/tex/context/base/font-log.lua
index 3f9e111b3..e16a945f9 100644
--- a/tex/context/base/font-log.lua
+++ b/tex/context/base/font-log.lua
@@ -37,12 +37,13 @@ function logger.save(tfmtable,source,specification) -- save file name in spec he
end
function logger.report(complete)
- local t = { }
+ local t, n = { }, 0
for name, used in table.sortedhash(fonts.used) do
+ n = n + 1
if complete then
- t[#t+1] = used .. "->" .. file.basename(name)
+ t[n] = used .. "->" .. file.basename(name)
else
- t[#t+1] = file.basename(name)
+ t[n] = file.basename(name)
end
end
return t
diff --git a/tex/context/base/font-map.lua b/tex/context/base/font-map.lua
index 46e84ada2..569f3df81 100644
--- a/tex/context/base/font-map.lua
+++ b/tex/context/base/font-map.lua
@@ -219,21 +219,23 @@ fonts.map.addtounicode = function(data,filename)
originals[index], tounicode[index], ns = unicode, tounicode16(unicode), ns + 1
end
else
- local t = { }
+ local t, n = { }, 0
for l=1,nplit do
local base = split[l]
local u = unicodes[base] or (aglmap and aglmap[base])
if not u then
break
elseif type(u) == "table" then
- t[#t+1] = u[1]
+ n = n + 1
+ t[n] = u[1]
else
- t[#t+1] = u
+ n = n + 1
+ t[n] = u
end
end
- if #t == 0 then -- done then
+ if n == 0 then -- done then
-- nothing
- elseif #t == 1 then
+ elseif n == 1 then
originals[index], tounicode[index], nl, unicode = t[1], tounicode16(t[1]), nl + 1, true
else
originals[index], tounicode[index], nl, unicode = t, tounicode16sequence(t), nl + 1, true
diff --git a/tex/context/base/font-mis.lua b/tex/context/base/font-mis.lua
index 911ffd3fb..964378a8a 100644
--- a/tex/context/base/font-mis.lua
+++ b/tex/context/base/font-mis.lua
@@ -11,7 +11,7 @@ local lower, strip = string.lower, string.strip
fonts.otf = fonts.otf or { }
-fonts.otf.version = fonts.otf.version or 2.705
+fonts.otf.version = fonts.otf.version or 2.706
fonts.otf.cache = containers.define("fonts", "otf", fonts.otf.version, true)
function fonts.otf.loadcached(filename,format,sub)
diff --git a/tex/context/base/font-otf.lua b/tex/context/base/font-otf.lua
index 085950dfc..2a19dc5f6 100644
--- a/tex/context/base/font-otf.lua
+++ b/tex/context/base/font-otf.lua
@@ -13,13 +13,13 @@ if not modules then modules = { } end modules ['font-otf'] = {
local utf = unicode.utf8
-local concat, utfbyte = table.concat, utf.byte
+local utfbyte = utf.byte
local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
local type, next, tonumber, tostring = type, next, tonumber, tostring
local abs = math.abs
local getn = table.getn
local lpegmatch = lpeg.match
-local reverse = table.reverse
+local reversed, concat = table.reversed, table.concat
local ioflush = io.flush
local allocate = utilities.storage.allocate
@@ -57,7 +57,7 @@ local definers = fonts.definers
otf.glists = { "gsub", "gpos" }
-otf.version = 2.705 -- beware: also sync font-mis.lua
+otf.version = 2.706 -- beware: also sync font-mis.lua
otf.cache = containers.define("fonts", "otf", otf.version, true)
local loadmethod = "table" -- table, mixed, sparse
@@ -968,6 +968,7 @@ actions["prepare unicodes"] = function(data,filename,raw)
local luatex = data.luatex
local indices, unicodes, multiples, internals = { }, { }, { }, { }
local mapmap = data.map or raw.map
+ local mapenc = nil -- will go away
if not mapmap then
report_otf("no map in %s",filename)
mapmap = { }
@@ -977,6 +978,7 @@ actions["prepare unicodes"] = function(data,filename,raw)
mapmap = { }
data.map.map = mapmap
else
+ mapenc = mapmap.enc -- will go away
mapmap = mapmap.map
end
local criterium = fonts.privateoffset
@@ -1000,41 +1002,53 @@ actions["prepare unicodes"] = function(data,filename,raw)
indices[unicode] = index
unicodes[name] = unicode
end
+ -- maybe deal with altuni here in the future but first we need
+ -- to encounter a proper font that sets them
else
-- message that something is wrong
end
end
end
-- beware: the indices table is used to initialize the tfm table
- for unicode, index in next, mapmap do
- if not internals[index] then
- local name = glyphs[index].name
- if name then
- local un = unicodes[name]
- if not un then
- unicodes[name] = unicode -- or 0
- elseif type(un) == "number" then -- tonumber(un)
- if un ~= unicode then
- multiples[#multiples+1] = name
- unicodes[name] = { un, unicode }
- indices[unicode] = index
- end
- else
- local ok = false
- for u=1,#un do
- if un[u] == unicode then
- ok = true
- break
+ local encname = lower(data.enc_name or (mapenc and mapenc[1] and mapenc[1].enc_name) or "") -- mapenc will go away
+ -- will become: local encname = lower(data.enc_name or "")
+ if encname == "" or encname == "unicodebmp" or encname == "unicodefull" then -- maybe find(encname,"unicode")
+ if trace_loading then
+ report_otf("using extra unicode map")
+ end
+ -- ok -- we can also consider using the altuni
+ for unicode, index in next, mapmap do
+ if not internals[index] then
+ local name = glyphs[index].name
+ if name then
+ local un = unicodes[name]
+ if not un then
+ unicodes[name] = unicode -- or 0
+ elseif type(un) == "number" then -- tonumber(un)
+ if un ~= unicode then
+ multiples[#multiples+1] = name
+ unicodes[name] = { un, unicode }
+ indices[unicode] = index
+ end
+ else
+ local ok = false
+ for u=1,#un do
+ if un[u] == unicode then
+ ok = true
+ break
+ end
+ end
+ if not ok then
+ multiples[#multiples+1] = name
+ un[#un+1] = unicode
+ indices[unicode] = index
end
- end
- if not ok then
- multiples[#multiples+1] = name
- un[#un+1] = unicode
- indices[unicode] = index
end
end
end
end
+ else
+ report_otf("warning: non unicode map '%s', only using glyph unicode data",encname or "whatever")
end
if trace_loading then
if #multiples > 0 then
@@ -1063,7 +1077,7 @@ actions["reorganize lookups"] = function(data,filename,raw)
for _, vv in next, v.rules do
local c = vv.coverage
if c and c.before then
- c.before = reverse(c.before)
+ c.before = reversed(c.before)
end
end
end
@@ -1582,8 +1596,8 @@ local function copytotfm(data,cache_id) -- we can save a copy when we reorder th
local glyphs, pfminfo, metadata = data.glyphs or { }, data.pfminfo or { }, data.metadata or { }
local luatex = data.luatex
local unicodes = luatex.unicodes -- names to unicodes
- local indices = luatex.indices local mode = data.mode or "base"
-
+ local indices = luatex.indices
+ local mode = data.mode or "base"
local characters, parameters, math_parameters, descriptions = { }, { }, { }, { }
local designsize = metadata.designsize or metadata.design_size or 100
if designsize == 0 then
diff --git a/tex/context/base/font-otn.lua b/tex/context/base/font-otn.lua
index 2bccc3c1b..ec246d20d 100644
--- a/tex/context/base/font-otn.lua
+++ b/tex/context/base/font-otn.lua
@@ -176,7 +176,7 @@ local zwj = 0x200D
local wildcard = "*"
local default = "dflt"
-local split_at_space = lpeg.splitters[" "] or lpeg.Ct(lpeg.splitat(" ")) -- no trailing or multiple spaces anyway
+local split_at_space = lpeg.Ct(lpeg.splitat(" ")) -- no trailing or multiple spaces anyway
local nodecodes = nodes.nodecodes
local whatcodes = nodes.whatcodes
@@ -282,9 +282,9 @@ local function gref(n)
local num, nam = { }, { }
for i=1,#n do
local ni = n[i]
- num[#num+1] = format("U+%04X",ni)
- local dni = descriptions[ni]
- nam[#num] = (dni and dni.name) or "?"
+ local di = descriptions[ni]
+ num[i] = format("U+%04X",ni)
+ nam[i] = di and di.name or "?"
end
return format("%s (%s)",concat(num," "), concat(nam," "))
end
@@ -2254,13 +2254,14 @@ otf.features.prepare = { }
local function split(replacement,original,cache,unicodes)
-- we can cache this too, but not the same (although unicode is a unique enough hash)
- local o, t, n = { }, { }, 0
+ local o, t, n, no = { }, { }, 0, 0
for s in gmatch(original,"[^ ]+") do
local us = unicodes[s]
+ no = no + 1
if type(us) == "number" then -- tonumber(us)
- o[#o+1] = us
+ o[no] = us
else
- o[#o+1] = us[1]
+ o[no] = us[1]
end
end
for s in gmatch(replacement,"[^ ]+") do
@@ -2277,9 +2278,11 @@ end
local function uncover(covers,result,cache,unicodes)
-- lpeg hardly faster (.005 sec on mk)
+ local nofresults = #result
for n=1,#covers do
local c = covers[n]
local cc = cache[c]
+ nofresults = nofresults + 1
if not cc then
local t = { }
for s in gmatch(c,"[^ ]+") do
@@ -2293,9 +2296,9 @@ local function uncover(covers,result,cache,unicodes)
end
end
cache[c] = t
- result[#result+1] = t
+ result[nofresults] = t
else
- result[#result+1] = cc
+ result[nofresults] = cc
end
end
end
@@ -2337,16 +2340,17 @@ local function prepare_lookups(tfmdata)
--~ end
end,
multiple = function (p,lookup,glyph,unicode)
- local old, new = unicode, { }
+ local old, new, nnew = unicode, { }, 0
local m = multiple[lookup]
if not m then m = { } multiple[lookup] = m end
m[old] = new
for pc in gmatch(p[2],"[^ ]+") do
local upc = unicodes[pc]
+ nnew = nnew + 1
if type(upc) == "number" then
- new[#new+1] = upc
+ new[nnew] = upc
else
- new[#new+1] = upc[1]
+ new[nnew] = upc[1]
end
end
--~ if trace_lookups then
@@ -2354,16 +2358,17 @@ local function prepare_lookups(tfmdata)
--~ end
end,
alternate = function(p,lookup,glyph,unicode)
- local old, new = unicode, { }
+ local old, new, nnew = unicode, { }, 0
local a = alternate[lookup]
if not a then a = { } alternate[lookup] = a end
a[old] = new
for pc in gmatch(p[2],"[^ ]+") do
local upc = unicodes[pc]
+ nnew = nnew + 1
if type(upc) == "number" then
- new[#new+1] = upc
+ new[nnew] = upc
else
- new[#new+1] = upc[1]
+ new[nnew] = upc[1]
end
end
--~ if trace_lookups then
@@ -2557,7 +2562,7 @@ local function prepare_contextchains(tfmdata)
contexts = { }
contextchain[lookupname] = contexts
end
- local t = { }
+ local t, nt = { }, 0
for nofrules=1,#rules do -- does #rules>1 happen often?
local rule = rules[nofrules]
local coverage = rule.coverage
@@ -2573,7 +2578,8 @@ local function prepare_contextchains(tfmdata)
uncover(after,sequence,cache,unicodes)
end
if sequence[1] then
- t[#t+1] = { nofrules, lookuptype, sequence, start, stop, rule.lookups }
+ nt = nt + 1
+ t[nt] = { nofrules, lookuptype, sequence, start, stop, rule.lookups }
for unic, _ in next, sequence[start] do
local cu = contexts[unic]
if not cu then
@@ -2593,7 +2599,7 @@ local function prepare_contextchains(tfmdata)
contexts = { }
reversecontextchain[lookupname] = contexts
end
- local t = { }
+ local t, nt = { }, 0
for nofrules=1,#rules do
local rule = rules[nofrules]
local reversecoverage = rule.reversecoverage
@@ -2613,7 +2619,8 @@ local function prepare_contextchains(tfmdata)
end
if sequence[1] then
-- this is different from normal coverage, we assume only replacements
- t[#t+1] = { nofrules, lookuptype, sequence, start, stop, rule.lookups, replacements }
+ nt = nt + 1
+ t[nt] = { nofrules, lookuptype, sequence, start, stop, rule.lookups, replacements }
for unic, _ in next, sequence[start] do
local cu = contexts[unic]
if not cu then
@@ -2633,7 +2640,7 @@ local function prepare_contextchains(tfmdata)
contexts = { }
contextchain[lookupname] = contexts
end
- local t = { }
+ local t, nt = { }, 0
for nofrules=1,#rules do
-- nearly the same as coverage so we could as well rename it
local rule = rules[nofrules]
@@ -2653,7 +2660,8 @@ local function prepare_contextchains(tfmdata)
uncover(back,sequence,cache,unicodes)
end
if sequence[1] then
- t[#t+1] = { nofrules, lookuptype, sequence, start, stop, rule.lookups }
+ nt = nt + 1
+ t[nt] = { nofrules, lookuptype, sequence, start, stop, rule.lookups }
for unic, _ in next, sequence[start] do
local cu = contexts[unic]
if not cu then
diff --git a/tex/context/base/font-ott.lua b/tex/context/base/font-ott.lua
index a5a0df37e..ec915b878 100644
--- a/tex/context/base/font-ott.lua
+++ b/tex/context/base/font-ott.lua
@@ -638,9 +638,18 @@ local baselines = allocate {
['romn'] = 'Roman baseline'
}
-local verbosescripts = allocate(table.swaphash(scripts ))
-local verboselanguages = allocate(table.swaphash(languages))
-local verbosefeatures = allocate(table.swaphash(features ))
+
+local function swap(h) -- can be a tables.swap when we get a better name
+ local r = { }
+ for k, v in next, h do
+ r[v] = lower(gsub(k," ",""))
+ end
+ return r
+end
+
+local verbosescripts = allocate(swap(scripts ))
+local verboselanguages = allocate(swap(languages))
+local verbosefeatures = allocate(swap(features ))
tables.scripts = scripts
tables.languages = languages
@@ -661,12 +670,6 @@ for k, v in next, verbosefeatures do
verbosefeatures[lower(k)] = v
end
--- can be sped up by local tables
-
-function tables.totag(id) -- not used
- return format("%4s",lower(id))
-end
-
local function resolve(tab,id)
if tab and id then
id = lower(id)
diff --git a/tex/context/base/font-syn.lua b/tex/context/base/font-syn.lua
index 7cd4b2a37..a0dbd4f7e 100644
--- a/tex/context/base/font-syn.lua
+++ b/tex/context/base/font-syn.lua
@@ -6,17 +6,6 @@ if not modules then modules = { } end modules ['font-syn'] = {
license = "see context related readme files"
}
-local keyisvalue = { __index = function(t,k)
- t[k] = k
- return k
-end }
-
-function table.initialysparse(t)
- t = t or { }
- setmetatable(t,keyisvalue)
- return t
-end
-
-- todo: subs in lookups requests
local utf = unicode.utf8
@@ -29,6 +18,7 @@ local utfgsub, utflower = utf.gsub, utf.lower
local unpack = unpack or table.unpack
local allocate = utilities.storage.allocate
+local sparse = utilities.storage.sparse
local trace_names = false trackers.register("fonts.names", function(v) trace_names = v end)
local trace_warnings = false trackers.register("fonts.warnings", function(v) trace_warnings = v end)
@@ -90,7 +80,7 @@ local weights = Cs ( -- not extra
+ P("regular") / "normal"
)
-local normalized_weights = table.initialysparse {
+local normalized_weights = sparse {
regular = "normal",
}
@@ -105,7 +95,7 @@ local styles = Cs (
+ P("ita") / "italic"
)
-local normalized_styles = table.initialysparse {
+local normalized_styles = sparse {
reverseoblique = "reverseitalic",
regular = "normal",
oblique = "italic",
@@ -120,7 +110,7 @@ local widths = Cs(
+ P("book") / "normal"
)
-local normalized_widths = table.initialysparse()
+local normalized_widths = sparse()
local variants = Cs( -- fax casual
P("smallcaps")
@@ -128,7 +118,7 @@ local variants = Cs( -- fax casual
+ P("caps") / "smallcaps"
)
-local normalized_variants = table.initialysparse()
+local normalized_variants = sparse()
local any = P(1)
@@ -247,7 +237,7 @@ filters.paths = { }
filters.names = { }
function names.getpaths(trace)
- local hash, result = { }, { }
+ local hash, result, r = { }, { }, 0
local function collect(t,where)
for i=1, #t do
local v = resolvers.cleanpath(t[i])
@@ -255,7 +245,9 @@ function names.getpaths(trace)
local key = lower(v)
report_names("adding path from %s: %s",where,v)
if not hash[key] then
- hash[key], result[#result+1] = true, v
+ r = r + 1
+ result[r] = v
+ hash[key] = true
end
end
end
@@ -783,7 +775,7 @@ local function addfilenames()
end
local function rejectclashes() -- just to be sure, so no explicit afm will be found then
- local specifications, used, okay = names.data.specifications, { }, { }
+ local specifications, used, okay, o = names.data.specifications, { }, { }, 0
for i=1,#specifications do
local s = specifications[i]
local f = s.fontname
@@ -794,10 +786,13 @@ local function rejectclashes() -- just to be sure, so no explicit afm will be fo
report_names( "fontname '%s' clashes, rejecting '%s' in favor of '%s'",f,fnm,fnd)
end
else
- used[f], okay[#okay+1] = fnm, s
+ used[f] = fnm
+ o = o + 1
+ okay[o] = s
end
else
- okay[#okay+1] = s
+ o = o + 1
+ okay[o] = s
end
end
local d = #specifications - #okay
@@ -1333,7 +1328,7 @@ local function heuristic(name,weight,style,width,variant,all) -- todo: fallbacks
if nf then
local t = { }
for i=1,nf do
- t[#t+1] = format("'%s'",found[i].fontname)
+ t[i] = format("'%s'",found[i].fontname)
end
report_names("name '%s' resolved to %s instances: %s",name,nf,concat(t," "))
else
@@ -1388,7 +1383,6 @@ end
function names.collectfiles(askedname,reload) -- no all
if askedname and askedname ~= "" and names.enabled then
---~ askedname = lower(askedname) -- or cleanname
askedname = cleanname(askedname) -- or cleanname
names.load(reload)
local list = { }
@@ -1396,10 +1390,8 @@ function names.collectfiles(askedname,reload) -- no all
local specifications = names.data.specifications
for i=1,#specifications do
local s = specifications[i]
---~ if find(lower(basename(s.filename)),askedname) then
if find(cleanname(basename(s.filename)),askedname) then
list[#list+1] = s
-
end
end
return list
@@ -1495,20 +1487,22 @@ function names.lookup(pattern,name,reload) -- todo: find
end
if lookups then
for key, value in gmatch(pattern,"([^=,]+)=([^=,]+)") do
- local t = { }
+ local t, n = { }, 0
if find(value,"*") then
value = string.topattern(value)
for i=1,#lookups do
local s = lookups[i]
if find(s[key],value) then
- t[#t+1] = lookups[i]
+ n = n + 1
+ t[n] = lookups[i]
end
end
else
for i=1,#lookups do
local s = lookups[i]
if s[key] == value then
- t[#t+1] = lookups[i]
+ n = n + 1
+ t[n] = lookups[i]
end
end
end
diff --git a/tex/context/base/font-tfm.lua b/tex/context/base/font-tfm.lua
index 4d80f07e1..7a16b284f 100644
--- a/tex/context/base/font-tfm.lua
+++ b/tex/context/base/font-tfm.lua
@@ -564,13 +564,13 @@ function tfm.scale(tfmtable, scaledpoints, relativeid)
local ivc = vc[i]
local key = ivc[1]
if key == "right" then
- tt[#tt+1] = { key, ivc[2]*hdelta }
+ tt[i] = { key, ivc[2]*hdelta }
elseif key == "down" then
- tt[#tt+1] = { key, ivc[2]*vdelta }
+ tt[i] = { key, ivc[2]*vdelta }
elseif key == "rule" then
- tt[#tt+1] = { key, ivc[2]*vdelta, ivc[3]*hdelta }
+ tt[i] = { key, ivc[2]*vdelta, ivc[3]*hdelta }
else -- not comment
- tt[#tt+1] = ivc -- shared since in cache and untouched
+ tt[i] = ivc -- shared since in cache and untouched
end
end
chr.commands = tt
diff --git a/tex/context/base/font-xtx.lua b/tex/context/base/font-xtx.lua
index 5a31d8c5e..5e9fea12f 100644
--- a/tex/context/base/font-xtx.lua
+++ b/tex/context/base/font-xtx.lua
@@ -74,7 +74,7 @@ local function colonized(specification) -- xetex mode
list = { }
lpegmatch(pattern,specification.specification)
-- for k, v in next, list do
- -- list[k] = v:is_boolean()
+ -- list[k] = is_boolean(v)
-- if type(list[a]) == "nil" then
-- list[k] = v
-- end
diff --git a/tex/context/base/grph-inc.lua b/tex/context/base/grph-inc.lua
index 240a84e6b..e4256af32 100644
--- a/tex/context/base/grph-inc.lua
+++ b/tex/context/base/grph-inc.lua
@@ -44,7 +44,7 @@ local texbox = tex.box
local contains = table.contains
local concat = table.concat
local todimen = string.todimen
-local settings_to_array = utilities.parsers.settings_to_array
+local settings_to_array, settings_to_hash = utilities.parsers.settings_to_array, utilities.parsers.settings_to_hash
local allocate = utilities.storage.allocate
local variables = interfaces.variables
@@ -215,7 +215,7 @@ function figures.setpaths(locationset,pathlist)
-- this function can be called each graphic so we provide this optimization
return
end
- local iv, t, h = interfaces.variables, figures.paths, locationset:tohash()
+ local iv, t, h = interfaces.variables, figures.paths, settings_to_hash(locationset)
if last_locationset ~= locationset then
-- change == reset (actually, a 'reset' would indeed reset
if h[iv["local"]] then
@@ -359,114 +359,135 @@ local defaultprefix = "m_k_i_v_"
-- todo: local path or cache path
+local function forbiddenname(filename)
+ if not filename or filename == "" then
+ return false
+ end
+ local expandedfullname = file.collapsepath(filename,true)
+ local expandedinputname = file.collapsepath(file.addsuffix(environment.jobfilename,environment.jobfilesuffix),true)
+ if expandedfullname == expandedinputname then
+ report_graphics("skipping graphic with same name as input filename (%s), enforce suffix",expandedinputname)
+ return true
+ end
+ local expandedoutputname = file.collapsepath(codeinjections.getoutputfilename(),true)
+ if expandedfullname == expandedoutputname then
+ report_graphics("skipping graphic with same name as output filename (%s), enforce suffix",expandedoutputname)
+ return true
+ end
+end
+
local function register(askedname,specification)
if specification then
- local format = specification.format
- if format then
- local conversion = specification.conversion
- local resolution = specification.resolution
- if conversion == "" then
- conversion = nil
- end
- if resolution == "" then
- resolution = nil
- end
- local newformat = conversion
- if not newformat or newformat == "" then
- newformat = defaultformat
- end
- if trace_conversion then
- report_graphics("checking conversion of '%s': old format '%s', new format '%s', conversion '%s', resolution '%s'",
- askedname,format,newformat,conversion or "default",resolution or "default")
- end
- local converter = (newformat ~= format) and converters[format]
- if converter then
- if converter[newformat] then
- converter = converter[newformat]
- else
+ if forbiddenname(specification.fullname) then
+ specification = { }
+ else
+ local format = specification.format
+ if format then
+ local conversion = specification.conversion
+ local resolution = specification.resolution
+ if conversion == "" then
+ conversion = nil
+ end
+ if resolution == "" then
+ resolution = nil
+ end
+ local newformat = conversion
+ if not newformat or newformat == "" then
newformat = defaultformat
+ end
+ if trace_conversion then
+ report_graphics("checking conversion of '%s': old format '%s', new format '%s', conversion '%s', resolution '%s'",
+ askedname,format,newformat,conversion or "default",resolution or "default")
+ end
+ local converter = (newformat ~= format) and converters[format]
+ if converter then
if converter[newformat] then
converter = converter[newformat]
else
- converter = nil
newformat = defaultformat
+ if converter[newformat] then
+ converter = converter[newformat]
+ else
+ converter = nil
+ newformat = defaultformat
+ end
end
+ elseif trace_conversion then
+ report_graphics("no converter for '%s' -> '%s'",format,newformat)
end
- elseif trace_conversion then
- report_graphics("no converter for '%s' -> '%s'",format,newformat)
- end
- if converter then
- local oldname = specification.fullname
-local oldname = specification.foundname
- local newpath = file.dirname(oldname)
- local oldbase = file.basename(oldname)
- local newbase = file.removesuffix(oldbase)
- local fc = specification.cache or figures.cachepaths.path
- if fc and fc ~= "" and fc ~= "." then
- newpath = fc
- else
- newbase = defaultprefix .. newbase
- end
- if not file.is_writable(newpath) then
- if trace_conversion then
- report_graphics("[ath '%s'is not writable, forcing conversion path '.' ",newpath)
+ if converter then
+ -- local oldname = specification.fullname
+ local oldname = specification.foundname
+ local newpath = file.dirname(oldname)
+ local oldbase = file.basename(oldname)
+ local newbase = file.removesuffix(oldbase)
+ local fc = specification.cache or figures.cachepaths.path
+ if fc and fc ~= "" and fc ~= "." then
+ newpath = fc
+ else
+ newbase = defaultprefix .. newbase
end
- newpath = "."
- end
- local subpath = specification.subpath or figures.cachepaths.subpath
- if subpath and subpath ~= "" and subpath ~= "." then
- newpath = newpath .. "/" .. subpath
- end
- local prefix = specification.prefix or figures.cachepaths.prefix
- if prefix and prefix ~= "" then
- newbase = prefix .. newbase
- end
- if resolution and resolution ~= "" then -- the order might change
- newbase = newbase .. "_" .. resolution
- end
- local newbase = file.addsuffix(newbase,newformat)
- local newname = file.join(newpath,newbase)
- dir.makedirs(newpath)
- oldname = file.collapse_path(oldname)
- newname = file.collapse_path(newname)
- local oldtime = lfs.attributes(oldname,'modification') or 0
- local newtime = lfs.attributes(newname,'modification') or 0
- if newtime == 0 or oldtime > newtime then
- if trace_conversion then
- report_graphics("converting '%s' from '%s' to '%s'",askedname,format,newformat)
+ if not file.is_writable(newpath) then
+ if trace_conversion then
+ report_graphics("[ath '%s'is not writable, forcing conversion path '.' ",newpath)
+ end
+ newpath = "."
end
- converter(oldname,newname,resolution or "")
- else
- if trace_conversion then
- report_graphics("no need to convert '%s' from '%s' to '%s'",askedname,format,newformat)
+ local subpath = specification.subpath or figures.cachepaths.subpath
+ if subpath and subpath ~= "" and subpath ~= "." then
+ newpath = newpath .. "/" .. subpath
+ end
+ local prefix = specification.prefix or figures.cachepaths.prefix
+ if prefix and prefix ~= "" then
+ newbase = prefix .. newbase
+ end
+ if resolution and resolution ~= "" then -- the order might change
+ newbase = newbase .. "_" .. resolution
+ end
+ local newbase = file.addsuffix(newbase,newformat)
+ local newname = file.join(newpath,newbase)
+ dir.makedirs(newpath)
+ oldname = file.collapsepath(oldname)
+ newname = file.collapsepath(newname)
+ local oldtime = lfs.attributes(oldname,'modification') or 0
+ local newtime = lfs.attributes(newname,'modification') or 0
+ if newtime == 0 or oldtime > newtime then
+ if trace_conversion then
+ report_graphics("converting '%s' from '%s' to '%s'",askedname,format,newformat)
+ end
+ converter(oldname,newname,resolution or "")
+ else
+ if trace_conversion then
+ report_graphics("no need to convert '%s' from '%s' to '%s'",askedname,format,newformat)
+ end
+ end
+ if io.exists(newname) then
+ specification.foundname = oldname
+ specification.fullname = newname
+ specification.prefix = prefix
+ specification.subpath = subpath
+ specification.converted = true
+ format = newformat
+ elseif io.exists(oldname) then
+ specification.fullname = newname
+ specification.converted = false
end
end
- if io.exists(newname) then
- specification.foundname = oldname
- specification.fullname = newname
- specification.prefix = prefix
- specification.subpath = subpath
- specification.converted = true
- format = newformat
- elseif io.exists(oldname) then
- specification.fullname = newname
- specification.converted = false
- end
- end
- end
- local found = figures.suffixes[format] -- validtypes[format]
- if not found then
- specification.found = false
- if trace_figures then
- commands.writestatus("figures","format not supported: %s",format)
end
- else
- specification.found = true
- if trace_figures then
- if validtypes[format] then
- commands.writestatus("figures","format natively supported by backend: %s",format)
- else
- commands.writestatus("figures","format supported by output file format: %s",format)
+ local found = figures.suffixes[format] -- validtypes[format]
+ if not found then
+ specification.found = false
+ if trace_figures then
+ commands.writestatus("figures","format not supported: %s",format)
+ end
+ else
+ specification.found = true
+ if trace_figures then
+ if validtypes[format] then
+ commands.writestatus("figures","format natively supported by backend: %s",format)
+ else
+ commands.writestatus("figures","format supported by output file format: %s",format)
+ end
end
end
end
diff --git a/tex/context/base/grph-inc.mkiv b/tex/context/base/grph-inc.mkiv
index 730fe1ee5..80a9c3187 100644
--- a/tex/context/base/grph-inc.mkiv
+++ b/tex/context/base/grph-inc.mkiv
@@ -218,7 +218,7 @@
{\global\setbox\foundexternalfigure\vbox{\cldprocessfile{#1}}}
\def\docheckfigurebuffer #1{\doprocesstexlikefigure{\getbuffer[#1]}}
-\def\docheckfiguretex #1{\doprocesstexlikefigure{\input#1\relax}}
+\def\docheckfiguretex #1{\doprocesstexlikefigure{\input{#1}}}
\def\docheckfigurecld #1{\doprocesscldlikefigure{#1}} % we can always add cldrun
\def\docheckfiguremps #1{\doprocessmpslikefigure{#1}}
\def\docheckfiguremprun #1#2{\doprocesstexlikefigure{\useMPrun{#1}{#2}}}
diff --git a/tex/context/base/l-boolean.lua b/tex/context/base/l-boolean.lua
index cf92d2f41..3fff7c126 100644
--- a/tex/context/base/l-boolean.lua
+++ b/tex/context/base/l-boolean.lua
@@ -11,8 +11,12 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
+-- function boolean.tonumber(b)
+-- return b and 1 or 0 -- test and test and return or return
+-- end
+
function boolean.tonumber(b)
- if b then return 1 else return 0 end
+ if b then return 1 else return 0 end -- test and return or return
end
function toboolean(str,tolerant)
@@ -36,6 +40,8 @@ function toboolean(str,tolerant)
end
end
+string.toboolean = toboolean
+
function string.is_boolean(str,default)
if type(str) == "string" then
if str == "true" or str == "yes" or str == "on" or str == "t" then
@@ -46,11 +52,3 @@ function string.is_boolean(str,default)
end
return default
end
-
-function boolean.alwaystrue()
- return true
-end
-
-function boolean.falsetrue()
- return false
-end
diff --git a/tex/context/base/l-dimen.lua b/tex/context/base/l-dimen.lua
index 35fca56da..cb97e35f6 100644
--- a/tex/context/base/l-dimen.lua
+++ b/tex/context/base/l-dimen.lua
@@ -81,9 +81,7 @@ local dimenfactors = {
format (string) is implemented using this table.</p>
--ldx]]--
--- was:
-
-local function todimen(n,unit,fmt)
+local function numbertodimen(n,unit,fmt)
if type(n) == 'string' then
return n
else
@@ -102,21 +100,21 @@ end
--ldx]]--
number.maxdimen = 1073741823
-number.todimen = todimen
+number.todimen = numbertodimen
number.dimenfactors = dimenfactors
-function number.topoints (n) return todimen(n,"pt") end
-function number.toinches (n) return todimen(n,"in") end
-function number.tocentimeters (n) return todimen(n,"cm") end
-function number.tomillimeters (n) return todimen(n,"mm") end
-function number.toscaledpoints(n) return todimen(n,"sp") end
-function number.toscaledpoints(n) return n .. "sp" end
-function number.tobasepoints (n) return todimen(n,"bp") end
-function number.topicas (n) return todimen(n "pc") end
-function number.todidots (n) return todimen(n,"dd") end
-function number.tociceros (n) return todimen(n,"cc") end
-function number.tonewdidots (n) return todimen(n,"nd") end
-function number.tonewciceros (n) return todimen(n,"nc") end
+function number.topoints (n) return numbertodimen(n,"pt") end
+function number.toinches (n) return numbertodimen(n,"in") end
+function number.tocentimeters (n) return numbertodimen(n,"cm") end
+function number.tomillimeters (n) return numbertodimen(n,"mm") end
+function number.toscaledpoints(n) return numbertodimen(n,"sp") end
+function number.toscaledpoints(n) return n .. "sp" end
+function number.tobasepoints (n) return numbertodimen(n,"bp") end
+function number.topicas (n) return numbertodimen(n "pc") end
+function number.todidots (n) return numbertodimen(n,"dd") end
+function number.tociceros (n) return numbertodimen(n,"cc") end
+function number.tonewdidots (n) return numbertodimen(n,"nd") end
+function number.tonewciceros (n) return numbertodimen(n,"nc") end
--[[ldx--
<p>More interesting it to implement a (sort of) dimen datatype, one
@@ -146,14 +144,24 @@ mt.__index = function(t,s)
return false
end
-function string:todimen()
- if type(self) == "number" then
- return self
- else
- local value, unit = lpegmatch(dimenpair,self)
- return value/unit
- end
-end
+
+--[[ldx--
+<p>We redefine the following function later on, so we comment it
+here (which saves us bytecodes.</p>
+--ldx]]--
+
+-- function string.todimen(str)
+-- if type(str) == "number" then
+-- return str
+-- else
+-- local value, unit = lpegmatch(dimenpair,str)
+-- return value/unit
+-- end
+-- end
+--
+-- local stringtodimen = string.todimen
+
+local stringtodimen -- assigned later (commenting saves bytecode)
local amount = S("+-")^0 * R("09")^0 * S(".,")^0 * R("09")^0
local unit = P("pt") + P("cm") + P("mm") + P("sp") + P("bp") + P("in") +
@@ -175,12 +183,6 @@ string.todimen("10pt")
string.todimen("10.0pt")
</typing>
-<p>And of course the often more efficient:</p>
-
-<typing>
-somestring:todimen("12.3cm")
-</typing>
-
<p>With this in place, we can now implement a proper datatype for dimensions, one
that permits us to do this:</p>
@@ -198,28 +200,28 @@ local dimensions = { }
<p>The main (and globally) visible representation of a dimen is defined next: it is
a one-element table. The unit that is returned from the match is normally a number
(one of the previously defined factors) but we also accept functions. Later we will
-see why.</p>
+see why. This function is redefined later.</p>
--ldx]]--
-function dimen(a)
- if a then
- local ta= type(a)
- if ta == "string" then
- local value, unit = lpegmatch(pattern,a)
- if type(unit) == "function" then
- k = value/unit()
- else
- k = value/unit
- end
- a = k
- elseif ta == "table" then
- a = a[1]
- end
- return setmetatable({ a }, dimensions)
- else
- return setmetatable({ 0 }, dimensions)
- end
-end
+-- function dimen(a)
+-- if a then
+-- local ta= type(a)
+-- if ta == "string" then
+-- local value, unit = lpegmatch(pattern,a)
+-- if type(unit) == "function" then
+-- k = value/unit()
+-- else
+-- k = value/unit
+-- end
+-- a = k
+-- elseif ta == "table" then
+-- a = a[1]
+-- end
+-- return setmetatable({ a }, dimensions)
+-- else
+-- return setmetatable({ 0 }, dimensions)
+-- end
+-- end
--[[ldx--
<p>This function return a small hash with a metatable attached. It is
@@ -229,35 +231,35 @@ shared some of the code but for reasons of speed we don't.</p>
function dimensions.__add(a, b)
local ta, tb = type(a), type(b)
- if ta == "string" then a = a:todimen() elseif ta == "table" then a = a[1] end
- if tb == "string" then b = b:todimen() elseif tb == "table" then b = b[1] end
+ 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 = a:todimen() elseif ta == "table" then a = a[1] end
- if tb == "string" then b = b:todimen() elseif tb == "table" then b = b[1] end
+ 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 = a:todimen() elseif ta == "table" then a = a[1] end
- if tb == "string" then b = b:todimen() elseif tb == "table" then b = b[1] end
+ 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 = a:todimen() elseif ta == "table" then a = a[1] end
- if tb == "string" then b = b:todimen() elseif tb == "table" then b = b[1] end
+ 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 = a:todimen() elseif ta == "table" then a = a[1] end
+ if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end
return setmetatable({ - a }, dimensions)
end
@@ -390,25 +392,27 @@ function dimen(a)
end
end
-function string:todimen()
- if type(self) == "number" then
- return self
+function string.todimen(str)
+ if type(str) == "number" then
+ return str
else
- local k = known[self]
+ local k = known[str]
if not k then
- local value, unit = lpegmatch(dimenpair,self)
+ local value, unit = lpegmatch(dimenpair,str)
if value and unit then
k = value/unit
else
k = 0
end
- -- print(self,value,unit)
- known[self] = k
+ -- print(str,value,unit)
+ known[str] = k
end
return k
end
end
+stringtodimen = string.todimen -- local variable defined earlier
+
function number.toscaled(d)
return format("%0.5f",d/2^16)
end
@@ -425,7 +429,7 @@ probably use a hash instead of a one-element table.</p>
function number.percent(n) -- will be cleaned up once luatex 0.30 is out
local hsize = tex.hsize
if type(hsize) == "string" then
- hsize = hsize:todimen()
+ hsize = stringtodimen(hsize)
end
return (n/100) * hsize
end
diff --git a/tex/context/base/l-dir.lua b/tex/context/base/l-dir.lua
index 455f71b53..be21fb985 100644
--- a/tex/context/base/l-dir.lua
+++ b/tex/context/base/l-dir.lua
@@ -131,9 +131,12 @@ local function glob(str,t)
end
return t
elseif isfile(str) then
- local t = t or { }
- t[#t+1] = str
- return t
+ if t then
+ t[#t+1] = str
+ return t
+ else
+ return { str }
+ end
else
local split = lpegmatch(pattern,str)
if split then
@@ -166,6 +169,7 @@ local function globfiles(path,recurse,func,files) -- func == pattern or function
func = function(name) return find(name,s) end
end
files = files or { }
+ local noffiles = #files
for name in walkdir(path) do
if find(name,"^%.") then
--- skip
@@ -176,12 +180,9 @@ local function globfiles(path,recurse,func,files) -- func == pattern or function
globfiles(path .. "/" .. name,recurse,func,files)
end
elseif mode == "file" then
- if func then
- if func(name) then
- files[#files+1] = path .. "/" .. name
- end
- else
- files[#files+1] = path .. "/" .. name
+ if not func or func(name) then
+ noffiles = noffiles + 1
+ files[noffiles] = path .. "/" .. name
end
end
end
diff --git a/tex/context/base/l-file.lua b/tex/context/base/l-file.lua
index edf3f8a06..7c5b9c67f 100644
--- a/tex/context/base/l-file.lua
+++ b/tex/context/base/l-file.lua
@@ -159,7 +159,7 @@ end
file.isreadable = file.is_readable -- depricated
file.iswritable = file.is_writable -- depricated
--- todo: lpeg
+-- todo: lpeg \\ / .. does not save much
local checkedsplit = string.checkedsplit
@@ -174,7 +174,7 @@ end
-- we can hash them weakly
---~ function file.old_collapse_path(str) -- fails on b.c/..
+--~ function file.collapsepath(str) -- fails on b.c/..
--~ str = gsub(str,"\\","/")
--~ if find(str,"/") then
--~ str = gsub(str,"^%./",(gsub(getcurrentdir(),"\\","/")) .. "/") -- ./xx in qualified
@@ -198,7 +198,7 @@ end
--~ Of course there are some optimizations too. Finally we had to deal with
--~ windows drive prefixes and thinsg like sys://.
-function file.collapse_path(str,anchor)
+function file.collapsepath(str,anchor)
if anchor and not find(str,"^/") and not find(str,"^%a:") then
str = getcurrentdir() .. "/" .. str
end
@@ -253,8 +253,10 @@ function file.collapse_path(str,anchor)
end
end
+file.collapse_path = file.collapsepath
+
--~ local function test(str)
---~ print(string.format("%-20s %-15s %-15s",str,file.collapse_path(str),file.collapse_path(str,true)))
+--~ print(string.format("%-20s %-15s %-15s",str,file.collapsepath(str),file.collapsepath(str,true)))
--~ end
--~ test("a/b.c/d") test("b.c/d") test("b.c/..")
--~ test("/") test("c:/..") test("sys://..")
diff --git a/tex/context/base/l-lpeg.lua b/tex/context/base/l-lpeg.lua
index 0a4ee0ba3..5c53fe710 100644
--- a/tex/context/base/l-lpeg.lua
+++ b/tex/context/base/l-lpeg.lua
@@ -14,15 +14,29 @@ local patterns = lpeg.patterns
local P, R, S, Ct, C, Cs, Cc, V = lpeg.P, lpeg.R, lpeg.S, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.V
local match = lpeg.match
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
local digit, sign = R('09'), S('+-')
local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local utf8byte = R("\128\191")
+local utf8next = R("\128\191")
+local escaped = P("\\") * P(1)
+local squote = P("'")
+local dquote = P('"')
-patterns.utf8byte = utf8byte
patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8byte
-patterns.utf8three = R("\224\239") * utf8byte * utf8byte
-patterns.utf8four = R("\240\244") * utf8byte * utf8byte * utf8byte
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = P('\000\000\254\255') + P('\255\254\000\000') + P('\255\254') + P('\254\255') + P('\239\187\191')
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * P(-1) * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
patterns.digit = digit
patterns.sign = sign
@@ -49,17 +63,28 @@ patterns.nonspace = 1 - patterns.space
patterns.nonspacer = 1 - patterns.spacer
patterns.whitespace = patterns.eol + patterns.spacer
patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.utf8 = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-patterns.utfbom = P('\000\000\254\255') + P('\255\254\000\000') + P('\255\254') + P('\254\255') + P('\239\187\191')
-patterns.validutf8 = patterns.utf8^0 * P(-1) * Cc(true) + Cc(false)
patterns.comma = P(",")
patterns.commaspacer = P(",") * patterns.spacer^0
patterns.period = P(".")
-
-patterns.undouble = P('"')/"" * (1-P('"'))^0 * P('"')/""
-patterns.unsingle = P("'")/"" * (1-P("'"))^0 * P("'")/""
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.undouble = (dquote/"") * ((escaped + (1-dquote))^0) * (dquote/"")
+patterns.unsingle = (squote/"") * ((escaped + (1-squote))^0) * (squote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
patterns.unspacer = ((patterns.spacer^1)/"")^0
+local unquoted = Cs(patterns.unquoted * P(-1)) -- not C
+
+function string.unquoted(str)
+ return match(unquoted,str) or str
+end
+
+--~ print(string.unquoted("test"))
+--~ print(string.unquoted([["t\"est"]]))
+--~ print(string.unquoted([["t\"est"x]]))
+--~ print(string.unquoted("\'test\'"))
+
function lpeg.anywhere(pattern) --slightly adapted from website
return P { P(pattern) + 1 * V(1) } -- why so complex?
end
@@ -75,8 +100,8 @@ local content = (empty + nonempty)^1
local capture = Ct(content^0)
-function string:splitlines()
- return match(capture,self)
+function string.splitlines(str)
+ return match(capture,str)
end
patterns.textline = content
@@ -92,12 +117,12 @@ 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 other, any = C((1 - separator)^0), P(1)
+ local any = P(1)
splitter = other * (separator * C(any^0) + "") -- ?
splitters_s[separator] = splitter
else
- local other = C((1 - separator)^0)
splitter = other * (separator * other)^0
splitters_m[separator] = splitter
end
@@ -118,16 +143,16 @@ function lpeg.split(separator,str)
return match(c,str)
end
-function string:split(separator)
+function string.split(str,separator)
local c = cache[separator]
if not c then
c = Ct(splitat(separator))
cache[separator] = c
end
- return match(c,self)
+ return match(c,str)
end
-lpeg.splitters = cache
+--~ lpeg.splitters = cache -- no longer public
local cache = { }
@@ -135,22 +160,22 @@ function lpeg.checkedsplit(separator,str)
local c = cache[separator]
if not c then
separator = P(separator)
- local other = C((1 - separator)^0)
+ local other = C((1 - separator)^1)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
return match(c,str)
end
-function string:checkedsplit(separator)
+function string.checkedsplit(str,separator)
local c = cache[separator]
if not c then
separator = P(separator)
- local other = C((1 - separator)^0)
+ local other = C((1 - separator)^1)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
- return match(c,self)
+ return match(c,str)
end
--~ function lpeg.append(list,pp)
@@ -173,7 +198,9 @@ local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2
local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-patterns.utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
--~ local str = " a b c d "
@@ -212,22 +239,25 @@ function lpeg.keeper(str)
end
end
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
function lpeg.replacer(t)
if #t > 0 then
local p
for i=1,#t do
local ti= t[i]
local pp = P(ti[1]) / ti[2]
- p = (p and p + pp ) or pp
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
end
return Cs((p + 1)^0)
end
end
---~ print(utf.check(""))
---~ print(utf.check("abcde"))
---~ print(utf.check("abcde\255\123"))
-
local splitters_f, splitters_s = { }, { }
function lpeg.firstofsplit(separator) -- always return value
@@ -251,6 +281,7 @@ function lpeg.secondofsplit(separator) -- nil if not split
end
function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
return P { left * ((1 - left - right) + V(1))^0 * right }
end
@@ -262,3 +293,176 @@ end
--~ print(6,match(lpeg.secondofsplit(":",""),"bc"))
--~ print(7,match(lpeg.secondofsplit(":"),"bc"))
--~ print(9,match(lpeg.secondofsplit(":","123"),"bc"))
+
+--~ -- slower:
+--~
+--~ function lpeg.counter(pattern)
+--~ local n, pattern = 0, (lpeg.P(pattern)/function() n = n + 1 end + lpeg.P(1))^0
+--~ return function(str) n = 0 ; lpegmatch(pattern,str) ; return n end
+--~ end
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + P(1))^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + P(1))^0)
+
+function string.escapedpattern(str,simple)
+ if simple then
+ return match(s,str)
+ else
+ return match(p,str)
+ end
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+--~ lpeg.print(lpeg.R("ab","cd","gh"))
+--~ lpeg.print(lpeg.P("a","b","c"))
+--~ lpeg.print(lpeg.S("a","b","c"))
+
+--~ print(lpeg.count("äáàa",lpeg.P("á") + lpeg.P("à")))
+--~ print(lpeg.count("äáàa",lpeg.UP("áà")))
+--~ print(lpeg.count("äáàa",lpeg.US("àá")))
+--~ print(lpeg.count("äáàa",lpeg.UR("aá")))
+--~ print(lpeg.count("äáàa",lpeg.UR("àá")))
+--~ print(lpeg.count("äáàa",lpeg.UR(0x0000,0xFFFF)))
diff --git a/tex/context/base/l-number.lua b/tex/context/base/l-number.lua
index 08acb6040..e4eae3d72 100644
--- a/tex/context/base/l-number.lua
+++ b/tex/context/base/l-number.lua
@@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['l-number'] = {
license = "see context related readme files"
}
+-- this module will be replaced when we have the bit library
+
local tostring = tostring
local format, floor, insert, match = string.format, math.floor, string.match
local concat, insert = table.concat, table.insert
diff --git a/tex/context/base/l-os.lua b/tex/context/base/l-os.lua
index c58983cfc..c2e229834 100644
--- a/tex/context/base/l-os.lua
+++ b/tex/context/base/l-os.lua
@@ -160,7 +160,7 @@ end
-- no need for function anymore as we have more clever code and helpers now
-- this metatable trickery might as well disappear
-os.resolvers = os.resolvers or { }
+os.resolvers = os.resolvers or { } -- will become private
local resolvers = os.resolvers
diff --git a/tex/context/base/l-set.lua b/tex/context/base/l-set.lua
index e78b67876..2370f0139 100644
--- a/tex/context/base/l-set.lua
+++ b/tex/context/base/l-set.lua
@@ -51,10 +51,11 @@ function set.tolist(n)
if n == 0 or not tabs[n] then
return ""
else
- local t = { }
+ local t, n = { }, 0
for k, v in next, tabs[n] do
if v then
- t[#t+1] = k
+ n = n + 1
+ t[n] = k
end
end
return concat(t," ")
diff --git a/tex/context/base/l-string.lua b/tex/context/base/l-string.lua
index d0f58b37d..1e55f6bac 100644
--- a/tex/context/base/l-string.lua
+++ b/tex/context/base/l-string.lua
@@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['l-string'] = {
local string = string
local sub, gsub, find, match, gmatch, format, char, byte, rep, lower = string.sub, string.gsub, string.find, string.match, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
-local lpegmatch = lpeg.match
+local lpegmatch, S, C, Ct = lpeg.match, lpeg.S, lpeg.C, lpeg.Ct
-- some functions may disappear as they are not used anywhere
@@ -16,157 +16,75 @@ if not string.split then
-- this will be overloaded by a faster lpeg variant
- function string:split(pattern)
- if #self > 0 then
- local t = { }
- for s in gmatch(self..pattern,"(.-)"..pattern) do
- t[#t+1] = s
+ function string.split(str,pattern)
+ local t = { }
+ if #str > 0 then
+ local n = 1
+ for s in gmatch(str..pattern,"(.-)"..pattern) do
+ t[n] = s
+ n = n + 1
end
- return t
- else
- return { }
end
+ return t
end
end
-string.patterns = { }
-
-local escapes = {
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["^"] = "%^", ["$"] = "%$",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%(", [")"] = "%)",
- ["{"] = "%{", ["}"] = "%}"
-}
-
-string.patterns.escapes = escapes
-
-function string:esc() -- variant 2
- return (gsub(self,"(.)",escapes))
-end
-
-function string:unquote()
- return (gsub(self,"^([\"\'])(.*)%1$","%2"))
+function string.unquoted(str)
+ return (gsub(str,"^([\"\'])(.*)%1$","%2"))
end
---~ function string:unquote()
---~ if find(self,"^[\'\"]") then
---~ return sub(self,2,-2)
+--~ function stringunquoted(str)
+--~ if find(str,"^[\'\"]") then
+--~ return sub(str,2,-2)
--~ else
---~ return self
+--~ return str
--~ end
--~ end
-function string:quote() -- we could use format("%q")
- return format("%q",self)
+function string.quoted(str)
+ return format("%q",str) -- always "
end
-function string:count(pattern) -- variant 3
+function string.count(str,pattern) -- variant 3
local n = 0
- for _ in gmatch(self,pattern) do
+ for _ in gmatch(str,pattern) do -- not for utf
n = n + 1
end
return n
end
-function string:limit(n,sentinel)
- if #self > n then
+function string.limit(str,n,sentinel)
+ if #str > n then
sentinel = sentinel or " ..."
- return sub(self,1,(n-#sentinel)) .. sentinel
+ return sub(str,1,(n-#sentinel)) .. sentinel
else
- return self
- end
-end
-
---~ function string:strip() -- the .- is quite efficient
---~ -- return match(self,"^%s*(.-)%s*$") or ""
---~ -- return match(self,'^%s*(.*%S)') or '' -- posted on lua list
---~ return find(s,'^%s*$') and '' or match(s,'^%s*(.*%S)')
---~ end
-
-do -- roberto's variant:
- local space = lpeg.S(" \t\v\n")
- local nospace = 1 - space
- local stripper = space^0 * lpeg.C((space^0 * nospace^1)^0)
- function string.strip(str)
- return lpegmatch(stripper,str) or ""
- end
-end
-
-function string:is_empty()
- return not find(self,"%S")
-end
-
-function string:enhance(pattern,action)
- local ok, n = true, 0
- while ok do
- ok = false
- self = gsub(self,pattern, function(...)
- ok, n = true, n + 1
- return action(...)
- end)
+ return str
end
- return self, n
end
-if not string.characters then
-
- local function nextchar(str, index)
- index = index + 1
- return (index <= #str) and index or nil, sub(str,index,index)
- end
- function string:characters()
- return nextchar, self, 0
- end
- local function nextbyte(str, index)
- index = index + 1
- return (index <= #str) and index or nil, byte(sub(str,index,index))
- end
- function string:bytes()
- return nextbyte, self, 0
- end
-
-end
+local space = S(" \t\v\n")
+local nospace = 1 - space
+local stripper = space^0 * C((space^0 * nospace^1)^0) -- roberto's code
-function string:rpadd(n,chr)
- local m = n-#self
- if m > 0 then
- return self .. rep(chr or " ",m)
- else
- return self
- end
+function string.strip(str)
+ return lpegmatch(stripper,str) or ""
end
-function string:lpadd(n,chr)
- local m = n-#self
- if m > 0 then
- return rep(chr or " ",m) .. self
- else
- return self
- end
+function string.is_empty(str)
+ return not find(str,"%S")
end
-string.padd = string.rpadd
-
local patterns_escapes = {
- ["-"] = "%-",
- ["."] = "%.",
- ["+"] = "%+",
- ["*"] = "%*",
["%"] = "%%",
- ["("] = "%)",
- [")"] = "%)",
- ["["] = "%[",
- ["]"] = "%]",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
}
-function string:escapedpattern()
- return (gsub(self,".",patterns_escapes))
-end
-
local simple_escapes = {
["-"] = "%-",
["."] = "%.",
@@ -174,22 +92,28 @@ local simple_escapes = {
["*"] = ".*",
}
-function string:partialescapedpattern()
- return (gsub(self,".",simple_escapes))
-end
-
-function string:tohash()
- local t = { }
- for s in gmatch(self,"([^, ]+)") do -- lpeg
- t[s] = true
+function string.escapedpattern(str,simple)
+ if simple then
+ return (gsub(str,".",simple_escapes))
+ else
+ return (gsub(str,".",patterns_escapes))
end
- return t
end
-local pattern = lpeg.Ct(lpeg.C(1)^0)
-
-function string:totable()
- return lpegmatch(pattern,self)
+function string.topattern(str,lowercase,strict)
+ if str == "" then
+ return ".*"
+ else
+ str = gsub(str,".",simple_escapes)
+ if lowercase then
+ str = lower(str)
+ end
+ if strict then
+ return "^" .. str .. "$"
+ else
+ return str
+ end
+ end
end
--~ local t = {
@@ -205,6 +129,8 @@ end
--~ print(string.tabtospace(t[k]))
--~ end
+-- The following functions might end up in another namespace.
+
function string.tabtospace(str,tab)
-- we don't handle embedded newlines
while true do
@@ -224,27 +150,19 @@ function string.tabtospace(str,tab)
return str
end
-function string:compactlong() -- strips newlines and leading spaces
- self = gsub(self,"[\n\r]+ *","")
- self = gsub(self,"^ *","")
- return self
-end
+--~ local template = string.striplong([[
+--~ aaaa
+--~ bb
+--~ cccccc
+--~ ]])
-function string:striplong() -- strips newlines and leading spaces
- self = gsub(self,"^%s*","")
- self = gsub(self,"[\n\r]+ *","\n")
- return self
+function string.striplong(str) -- strips all leading spaces
+ str = gsub(str,"^%s*","")
+ str = gsub(str,"[\n\r]+ *","\n")
+ return str
end
-function string:topattern(lowercase,strict)
- if lowercase then
- self = lower(self)
- end
- self = gsub(self,".",simple_escapes)
- if self == "" then
- self = ".*"
- elseif strict then
- self = "^" .. self .. "$"
- end
- return self
-end
+-- obsolete names:
+
+string.quote = string.quoted
+string.unquote = string.unquoted
diff --git a/tex/context/base/l-table.lua b/tex/context/base/l-table.lua
index 70c04e69c..abaaa62ba 100644
--- a/tex/context/base/l-table.lua
+++ b/tex/context/base/l-table.lua
@@ -61,24 +61,26 @@ end
-- extra functions, some might go (when not used)
function table.strip(tab)
- local lst = { }
+ local lst, l = { }, 0
for i=1,#tab do
local s = gsub(tab[i],"^%s*(.-)%s*$","%1")
if s == "" then
-- skip this one
else
- lst[#lst+1] = s
+ l = l + 1
+ lst[l] = s
end
end
return lst
end
function table.keys(t)
- local k = { }
+ local keys, k = { }, 0
for key, _ in next, t do
- k[#k+1] = key
+ k = k + 1
+ keys[k] = key
end
- return k
+ return keys
end
local function compare(a,b)
@@ -91,9 +93,10 @@ local function compare(a,b)
end
local function sortedkeys(tab)
- local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed
+ local srt, kind, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
for key,_ in next, tab do
- srt[#srt+1] = key
+ s = s + 1
+ srt[s] = key
if kind == 3 then
-- no further check
else
@@ -116,10 +119,11 @@ local function sortedkeys(tab)
end
local function sortedhashkeys(tab) -- fast one
- local srt = { }
+ local srt, s = { }, 0
for key,_ in next, tab do
if key then
- srt[#srt+1] = key
+ s= s + 1
+ srt[s] = key
end
end
sort(srt)
@@ -133,8 +137,7 @@ local function nothing() end
local function sortedhash(t)
if t then
- local s = sortedhashkeys(t) -- maybe just sortedkeys
- local n = 0
+ local n, s = 0, sortedkeys(t) -- the robust one
local function kv(s)
n = n + 1
local k = s[n]
@@ -150,20 +153,30 @@ table.sortedhash = sortedhash
table.sortedpairs = sortedhash
function table.append(t, list)
- for _,v in next, list do
- insert(t,v)
+ local n = #t
+ for i=1,#list do
+ n = n + 1
+ t[n] = list[i]
end
+ return t
end
function table.prepend(t, list)
- for k,v in next, list do
- insert(t,k,v)
+ 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, ...) -- first one is target
t = t or { }
- local lst = {...}
+ local lst = { ... }
for i=1,#lst do
for k, v in next, lst[i] do
t[k] = v
@@ -173,7 +186,7 @@ function table.merge(t, ...) -- first one is target
end
function table.merged(...)
- local tmp, lst = { }, {...}
+ local tmp, lst = { }, { ... }
for i=1,#lst do
for k, v in next, lst[i] do
tmp[k] = v
@@ -183,22 +196,24 @@ function table.merged(...)
end
function table.imerge(t, ...)
- local lst = {...}
+ local lst, nt = { ... }, #t
for i=1,#lst do
local nst = lst[i]
for j=1,#nst do
- t[#t+1] = nst[j]
+ nt = nt + 1
+ t[nt] = nst[j]
end
end
return t
end
function table.imerged(...)
- local tmp, lst = { }, {...}
+ local tmp, ntmp, lst = { }, 0, {...}
for i=1,#lst do
local nst = lst[i]
for j=1,#nst do
- tmp[#tmp+1] = nst[j]
+ ntmp = ntmp + 1
+ tmp[ntmp] = nst[j]
end
end
return tmp
@@ -274,11 +289,14 @@ function table.tohash(t,value)
end
function table.fromhash(t)
- local h = { }
+ local hsh, h = { }, 0
for k, v in next, t do -- no ipairs here
- if v then h[#h+1] = k end
+ if v then
+ h = h + 1
+ hsh[h] = k
+ end
end
- return h
+ return hsh
end
table.serialize_functions = true
@@ -299,20 +317,23 @@ local function simple_table(t)
n = n + 1
end
if n == #t then
- local tt = { }
+ local tt, nt = { }, 0
for i=1,#t do
local v = t[i]
local tv = type(v)
if tv == "number" then
+ nt = nt + 1
if hexify then
- tt[#tt+1] = format("0x%04X",v)
+ tt[nt] = format("0x%04X",v)
else
- tt[#tt+1] = tostring(v) -- tostring not needed
+ tt[nt] = tostring(v) -- tostring not needed
end
elseif tv == "boolean" then
- tt[#tt+1] = tostring(v)
+ nt = nt + 1
+ tt[nt] = tostring(v)
elseif tv == "string" then
- tt[#tt+1] = format("%q",v)
+ nt = nt + 1
+ tt[nt] = format("%q",v)
else
tt = nil
break
@@ -618,10 +639,11 @@ end
--~ 'return' : return { }
--~ number : [number] = { }
-function table.serialize(root,name,reduce,noquotes,hexify)
- local t = { }
+function table.serialize(root,name,reduce,noquotes,hexify) -- can be faster if flush == false and t as argument
+ local t, n = { }, 0
local function flush(s)
- t[#t+1] = s
+ n = n + 1
+ t[n] = s
end
serialize(root,name,flush,reduce,noquotes,hexify)
return concat(t,"\n")
@@ -647,12 +669,13 @@ function table.tofile(filename,root,name,reduce,noquotes,hexify)
if f then
local maxtab = table.tofile_maxtab
if maxtab > 1 then
- local t = { }
+ local t, n = { }, 0
local function flush(s)
- t[#t+1] = s
- if #t > maxtab then
+ n = n + 1
+ t[n] = s
+ if n > maxtab then
f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
- t = { }
+ t, n = { }, 0 -- we could recycle t if needed
end
end
serialize(root,name,flush,reduce,noquotes,hexify)
@@ -668,52 +691,72 @@ function table.tofile(filename,root,name,reduce,noquotes,hexify)
end
end
-local function flatten(t,f,complete) -- is this used? meybe a variant with next, ...
- for i=1,#t do
- local v = t[i]
- if type(v) == "table" then
- if complete or type(v[1]) == "table" then
- flatten(v,f,complete)
+local function flattened(t,f,depth)
+ if f == nil then
+ f = { }
+ depth = 0xFFFF
+ elseif tonumber(f) then
+ -- assume then only two arguments are given
+ 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
+ f[k] = v
end
+ end
+ end
+ local n = #f
+ for k=1,#t do
+ local v = t[k]
+ if depth > 0 and type(v) == "table" then
+ flattened(v,f,depth-1)
+ n = #f
else
- f[#f+1] = v
+ n = n + 1
+ f[n] = v
end
end
-end
-
-function table.flatten(t)
- local f = { }
- flatten(t,f,true)
- return f
-end
-
-function table.unnest(t) -- bad name
- local f = { }
- flatten(t,f,false)
return f
end
-table.flattenonelevel = table.unnest
-
--- a better one:
+table.flattened = flattened
-local function flattened(t,f)
- if not f then
+local function unnest(t,f) -- only used in mk, for old times sake
+ if not f then -- and only relevant for token lists
f = { }
end
- for k, v in next, t do
+ for i=1,#t do
+ local v = t[i]
if type(v) == "table" then
- flattened(v,f)
+ if type(v[1]) == "table" then
+ unnest(v,f)
+ else
+ f[#f+1] = v
+ end
else
- f[k] = v
+ f[#f+1] = v
end
end
return f
end
-table.flattened = flattened
+function table.unnest(t) -- bad name
+ return unnest(t)
+end
+
+--~ function table.unnest(t) -- for old times sake, undocumented (only in mk)
+--~ return flattened(t,1)
+--~ end
+
+--~ function table.are_equal(a,b)
+--~ return table.serialize(a) == table.serialize(b)
+--~ end
local function are_equal(a,b,n,m) -- indexed
if a and b and #a == #b then
@@ -739,7 +782,7 @@ end
local function identical(a,b) -- assumes same structure
for ka, va in next, a do
- local vb = b[k]
+ local vb = b[ka]
if va == vb then
-- same
elseif type(va) == "table" and type(vb) == "table" then
@@ -753,8 +796,8 @@ local function identical(a,b) -- assumes same structure
return true
end
-table.are_equal = are_equal
table.identical = identical
+table.are_equal = are_equal
-- maybe also make a combined one
@@ -780,14 +823,14 @@ function table.contains(t, v)
end
function table.count(t)
- local n, e = 0, next(t)
- while e do
- n, e = n + 1, next(t,e)
+ local n = 0
+ for k, v in next, t do
+ n = n + 1
end
return n
end
-function table.swapped(t,s)
+function table.swapped(t,s) -- hash
local n = { }
if s then
--~ for i=1,#s do
@@ -809,55 +852,34 @@ function table.swapped(t,s)
return n
end
---~ function table.are_equal(a,b)
---~ return table.serialize(a) == table.serialize(b)
---~ end
-
-function table.clone(t,p) -- t is optional or nil or table
- if not p then
- t, p = { }, t or { }
- elseif not t then
- t = { }
- end
- setmetatable(t, { __index = function(_,key) return p[key] end }) -- why not __index = p ?
- return t
-end
-
-function table.hexed(t,seperator)
- local tt = { }
- for i=1,#t do tt[i] = format("0x%04X",t[i]) end
- return concat(tt,seperator or " ")
-end
-
-function table.swaphash(h) -- needs another name
- local r = { }
- for k,v in next, h do
- r[v] = lower(gsub(k," ",""))
- end
- return r
-end
-
-function table.reverse(t)
- local tt = { }
- if #t > 0 then
- for i=#t,1,-1 do
- tt[#tt+1] = t[i]
+function table.reversed(t)
+ if t then
+ local tt, tn = { }, #t
+ if tn > 0 then
+ local ttn = 0
+ for i=tn,1,-1 do
+ ttn = ttn + 1
+ tt[ttn] = t[i]
+ end
end
+ return tt
end
- return tt
end
function table.sequenced(t,sep,simple) -- hash only
- local s = { }
+ local s, n = { }, 0
for k, v in sortedhash(t) do
if simple then
if v == true then
- s[#s+1] = k
+ n = n + 1
+ s[n] = k
elseif v and v~= "" then
- s[#s+1] = k .. "=" .. tostring(v)
+ n = n + 1
+ s[n] = k .. "=" .. tostring(v)
end
else
- s[#s+1] = k .. "=" .. tostring(v)
+ n = n + 1
+ s[n] = k .. "=" .. tostring(v)
end
end
return concat(s, sep or " | ")
@@ -867,7 +889,7 @@ function table.print(...)
table.tohandle(print,...)
end
--- -- -- obsolete but we keep them for a while and will comment them later -- -- --
+-- -- -- obsolete but we keep them for a while and might comment them later -- -- --
-- roughly: copy-loop : unpack : sub == 0.9 : 0.4 : 0.45 (so in critical apps, use unpack)
@@ -882,12 +904,5 @@ function table.is_empty(t)
end
function table.has_one_entry(t)
- local n = next(t)
- return n and not next(t,n)
-end
-
-function table.replace(a,b)
- for k,v in next, b do
- a[k] = v
- end
+ return t and not next(t,next(t))
end
diff --git a/tex/context/base/l-unicode.lua b/tex/context/base/l-unicode.lua
index 10f21e325..a97f01d1e 100644
--- a/tex/context/base/l-unicode.lua
+++ b/tex/context/base/l-unicode.lua
@@ -81,30 +81,37 @@ function unicode.utftype(f)
end
function unicode.utf16_to_utf8(str, endian) -- maybe a gsub is faster or an lpeg
- local result, tmp, n, m, p = { }, { }, 0, 0, 0
+ local result, tmp, n, m, p, r, t = { }, { }, 0, 0, 0, 0, 0 -- we reuse tmp
-- lf | cr | crlf / (cr:13, lf:10)
local function doit()
if n == 10 then
if p ~= 13 then
- result[#result+1] = concat(tmp)
- tmp = { }
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
+ t = 0
+ end
p = 0
end
elseif n == 13 then
- result[#result+1] = concat(tmp)
- tmp = { }
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
+ t = 0
+ end
p = n
else
- tmp[#tmp+1] = utfchar(n)
+ t = t + 1
+ tmp[t] = utfchar(n)
p = 0
end
end
for l,r in bytepairs(str) do
if r then
if endian then
- n = l*256 + r
+ n = 256*l + r
else
- n = r*256 + l
+ n = 256*r + l
end
if m > 0 then
n = (m-0xD800)*0x400 + (n-0xDC00) + 0x10000
@@ -117,29 +124,36 @@ function unicode.utf16_to_utf8(str, endian) -- maybe a gsub is faster or an lpeg
end
end
end
- if #tmp > 0 then
- result[#result+1] = concat(tmp)
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
end
return result
end
function unicode.utf32_to_utf8(str, endian)
- local result = { }
- local tmp, n, m, p = { }, 0, -1, 0
+ local result, tmp, n, m, p, r, t = { }, { }, 0, -1, 0, 0, 0
-- lf | cr | crlf / (cr:13, lf:10)
local function doit()
if n == 10 then
if p ~= 13 then
- result[#result+1] = concat(tmp)
- tmp = { }
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
+ t = 0
+ end
p = 0
end
elseif n == 13 then
- result[#result+1] = concat(tmp)
- tmp = { }
+ if t > 0 then
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
+ t = 0
+ end
p = n
else
- tmp[#tmp+1] = utfchar(n)
+ t = t + 1
+ tmp[t] = utfchar(n)
p = 0
end
end
@@ -147,15 +161,15 @@ function unicode.utf32_to_utf8(str, endian)
if a and b then
if m < 0 then
if endian then
- m = a*256*256*256 + b*256*256
+ m = 256*256*256*a + 256*256*b
else
- m = b*256 + a
+ m = 256*b + a
end
else
if endian then
- n = m + a*256 + b
+ n = m + 256*a + b
else
- n = m + b*256*256*256 + a*256*256
+ n = m + 256*256*256*b + 256*256*a
end
m = -1
doit()
@@ -165,13 +179,14 @@ function unicode.utf32_to_utf8(str, endian)
end
end
if #tmp > 0 then
- result[#result+1] = concat(tmp)
+ r = r + 1
+ result[r] = concat(tmp,"",1,t)
end
return result
end
local function little(c)
- local b = byte(c) -- b = c:byte()
+ local b = byte(c)
if b < 0x10000 then
return char(b%256,b/256)
else
@@ -201,9 +216,10 @@ function unicode.utf8_to_utf16(str,littleendian)
end
function unicode.utfcodes(str)
- local t = { }
- for k,v in utfvalues(str) do
- t[#t+1] = format("0x%04X",k)
+ local t, n = { }, 0
+ for u in utfvalues(str) do
+ n = n + 1
+ t[n] = format("0x%04X",u)
end
return concat(t,separator or " ")
end
diff --git a/tex/context/base/lang-ini.lua b/tex/context/base/lang-ini.lua
index 7bbf42aa7..507d59a9a 100644
--- a/tex/context/base/lang-ini.lua
+++ b/tex/context/base/lang-ini.lua
@@ -292,16 +292,17 @@ end
languages.logger = languages.logger or { }
function languages.logger.report()
- local result = { }
+ local result, r = { }, 0
local sorted = table.sortedkeys(registered)
for i=1,#sorted do
local tag = sorted[i]
local l = registered[tag]
if l.loaded then
- result[#result+1] = format("%s:%s:%s", tag, l.parent, l.number)
+ r = r + 1
+ result[r] = format("%s:%s:%s", tag, l.parent, l.number)
end
end
- return (#result > 0 and concat(result," ")) or "none"
+ return (r > 0 and concat(result," ")) or "none"
end
-- must happen at the tex end
diff --git a/tex/context/base/lang-wrd.lua b/tex/context/base/lang-wrd.lua
index 7f7099c6d..d008ed341 100644
--- a/tex/context/base/lang-wrd.lua
+++ b/tex/context/base/lang-wrd.lua
@@ -8,6 +8,7 @@ if not modules then modules = { } end modules ['lang-ini'] = {
local utf = unicode.utf8
local lower, utfchar = string.lower, utf.char
+local concat = table.concat
local lpegmatch = lpeg.match
local P, S, Cs = lpeg.P, lpeg.S, lpeg.Cs
@@ -59,6 +60,7 @@ local loaded = { } -- we share lists
function words.load(tag,filename)
local fullname = resolvers.findfile(filename,'other text file') or ""
if fullname ~= "" then
+ report_languages("loading word file '%s'",fullname)
statistics.starttiming(languages)
local list = loaded[fullname]
if not list then
@@ -78,9 +80,13 @@ function words.found(id, str)
local tag = languages.numbers[id]
if tag then
local data = wordsdata[tag]
- return data and (data[str] or data[lower(str)])
- else
- return false
+ if data then
+ if data[str] then
+ return 1
+ elseif data[lower(str)] then
+ return 2
+ end
+ end
end
end
@@ -89,20 +95,86 @@ end
-- there is an n=1 problem somewhere in nested boxes
+--~ local function mark_words(head,whenfound) -- can be optimized and shared
+--~ local current, start, str, language, n, done = head, nil, "", nil, 0, false
+--~ local function action()
+--~ if #str > 0 then
+--~ local f = whenfound(language,str)
+--~ if f then
+--~ done = true
+--~ for i=1,n do
+--~ f(start)
+--~ start = start.next
+--~ end
+--~ end
+--~ end
+--~ str, start, n = "", nil, 0
+--~ end
+--~ while current do
+--~ local id = current.id
+--~ if id == glyph_code then
+--~ local a = current.lang
+--~ if a then
+--~ if a ~= language then
+--~ if start then
+--~ action()
+--~ end
+--~ language = a
+--~ end
+--~ elseif start then
+--~ action()
+--~ language = a
+--~ end
+--~ local components = current.components
+--~ if components then
+--~ start = start or current
+--~ n = n + 1
+--~ for g in traverse_nodes(components) do
+--~ str = str .. utfchar(g.char)
+--~ end
+--~ else
+--~ local code = current.char
+--~ local data = chardata[code]
+--~ if is_letter[data.category] then
+--~ start = start or current
+--~ n = n + 1
+--~ str = str .. utfchar(code) -- slow, maybe str should be a table (and given max)
+--~ elseif start then
+--~ action()
+--~ end
+--~ end
+--~ elseif id == disc_code then
+--~ if n > 0 then
+--~ n = n + 1
+--~ end
+--~ elseif id == kern_code and current.subtype == kerning_code and start then
+--~ -- ok
+--~ elseif start then
+--~ action()
+--~ end
+--~ current = current.next
+--~ end
+--~ if start then
+--~ action()
+--~ end
+--~ return head, done
+--~ end
+
local function mark_words(head,whenfound) -- can be optimized and shared
- local current, start, str, language, n, done = head, nil, "", nil, 0, false
+ local current, language, done = head, nil, nil, 0, false
+ local str, s, nds, n = { }, 0, { }, 0 -- n could also be a table, saves calls
local function action()
- if #str > 0 then
- local f = whenfound(language,str)
- if f then
+ if s > 0 then
+ local word = concat(str,"",1,s)
+ local mark = whenfound(language,word)
+ if mark then
done = true
for i=1,n do
- f(start)
- start = start.next
+ mark(nds[i])
end
end
end
- str, start, n = "", nil, 0
+ n, s = 0, 0
end
while current do
local id = current.id
@@ -110,46 +182,48 @@ local function mark_words(head,whenfound) -- can be optimized and shared
local a = current.lang
if a then
if a ~= language then
- if start then
+ if s > 0 then
action()
end
language = a
end
- elseif start then
+ elseif s > 0 then
action()
language = a
end
local components = current.components
if components then
- start = start or current
n = n + 1
+ nds[n] = current
for g in traverse_nodes(components) do
- str = str .. utfchar(g.char)
+ s = s + 1
+ str[s] = utfchar(g.char)
end
else
local code = current.char
local data = chardata[code]
- if data.uccode or data.lccode then
---~ if is_letter[code] then -- why does this fail
- start = start or current
+ if is_letter[data.category] then
n = n + 1
- str = str .. utfchar(code) -- slow, maybe str should be a table
- elseif start then
+ nds[n] = current
+ s = s + 1
+ str[s] = utfchar(code)
+ elseif s > 0 then
action()
end
end
- elseif id == disc_code then
+ elseif id == disc_code then -- take the replace
if n > 0 then
n = n + 1
+ nds[n] = current
end
- elseif id == kern_code and current.subtype == kerning_code and start then
+ elseif id == kern_code and current.subtype == kerning_code and s > 0 then
-- ok
- elseif start then
+ elseif s > 0 then
action()
end
current = current.next
end
- if start then
+ if s > 0 then
action()
end
return head, done
@@ -192,7 +266,9 @@ local cache = { } -- can also be done with method 1 -- frozen colors once used
setmetatable(cache, {
__index = function(t,k) -- k == language, numbers[k] == tag
local c
- if k < 0 then
+ if type(k) == "string" then
+ c = colist[k]
+ elseif k < 0 then
c = colist["word:unset"]
else
c = colist["word:" .. (numbers[k] or "unset")] or colist["word:unknown"]
diff --git a/tex/context/base/lang-wrd.mkiv b/tex/context/base/lang-wrd.mkiv
index ad353905f..22c234d0c 100644
--- a/tex/context/base/lang-wrd.mkiv
+++ b/tex/context/base/lang-wrd.mkiv
@@ -60,10 +60,10 @@
\c!method=1,
\c!list=]
-\definecolor[word:yes] [darkgreen]
-\definecolor[word:no] [darkred]
+\definecolor[word:yes] [g=.75]
+\definecolor[word:no] [r=.75]
-%definecolor[word:unset] [darkgray]
+%definecolor[word:unset] [s=.75]
\definecolor[word:en] [b=.75]
\definecolor[word:de] [r=.75]
\definecolor[word:nl] [g=.75]
diff --git a/tex/context/base/lpdf-col.lua b/tex/context/base/lpdf-col.lua
index f5612a32b..a8e35dc74 100644
--- a/tex/context/base/lpdf-col.lua
+++ b/tex/context/base/lpdf-col.lua
@@ -25,7 +25,7 @@ local forcedmodel = colors.forcedmodel
-- This module assumes that some functions are defined in the colors namespace
-- which most likely will be loaded later.
-function lpdf.color(model,ca,default) -- todo: use gray when no color
+local function lpdfcolor(model,ca,default) -- todo: use gray when no color
if colors.supported then
local cv = colorsvalue(ca)
if cv then
@@ -57,6 +57,12 @@ function lpdf.color(model,ca,default) -- todo: use gray when no color
end
end
+lpdf.color = lpdfcolor
+
+function lpdf.pdfcolor(attribute) -- bonus, for pgf and friends
+ context(lpdfcolor(1,attribute))
+end
+
function lpdf.transparency(ct,default) -- kind of overlaps with transparencycode
-- beware, we need this hack because normally transparencies are not
-- yet registered and therefore the number is not not known ... we
diff --git a/tex/context/base/lpdf-epa.lua b/tex/context/base/lpdf-epa.lua
index 5709ced3f..58bbcf821 100644
--- a/tex/context/base/lpdf-epa.lua
+++ b/tex/context/base/lpdf-epa.lua
@@ -21,26 +21,36 @@ local backends, lpdf = backends, lpdf
local variables = interfaces.variables
local codeinjections = backends.pdf.codeinjections
+local layerspec = { -- predefining saves time
+ "epdflinks"
+}
+
+local locationspec = { -- predefining saves time
+ x = "",
+ y = "",
+ preset = "leftbottom",
+}
+
+local buttonspec = { -- predefining saves time
+ width = "",
+ height = "",
+ offset = variables.overlay,
+ frame = trace_links and variables.on or variables.off,
+}
+
local function add_link(x,y,w,h,destination,what)
if trace_links then
report_link("dx: %04i, dy: %04i, wd: %04i, ht: %04i, destination: %s, type: %s",x,y,w,h,destination,what)
end
+ locationspec.x = x .. "bp"
+ locationspec.y = y .. "bp"
+ buttonspec.width = w .. "bp"
+ buttonspec.height = h .. "bp"
context.setlayer (
- { "epdflinks" },
- { x = x .. "bp", y = y .. "bp", preset = "leftbottom" },
- function()
- -- context.blackrule { width = w.."bp", height = h.."bp", depth = "0bp" }
- context.button (
- {
- width = w.."bp",
- height = h.."bp",
- offset = variables.overlay,
- frame = trace_links and variables.on or variables.off,
- },
- "",
- { destination }
- )
- end
+ layerspec,
+ locationspec,
+ function() context.button ( buttonspec, "", { destination } ) end
+ -- context.nested.button(buttonspec, "", { destination }) -- time this
)
end
@@ -136,7 +146,8 @@ function codeinjections.mergereferences(specification)
end
end
context.flushlayer { "epdflinks" }
- context("\\gdef\\figurereference{%s}",reference) -- global
+ -- context("\\gdef\\figurereference{%s}",reference) -- global
+ context.setgvalue("figurereference",reference) -- global
specification.reference = reference
return namespace
end
diff --git a/tex/context/base/lpdf-epd.lua b/tex/context/base/lpdf-epd.lua
index 8a17aeb6b..ae84a29c7 100644
--- a/tex/context/base/lpdf-epd.lua
+++ b/tex/context/base/lpdf-epd.lua
@@ -61,9 +61,8 @@ local dictionary_access = {
checked_access = function(tab,key,v)
local n = v:getTypeName()
---~ print("!!!!!!!!!!!!!!",n)
if n == "array" then
- local t = { __data__ = v, size = v:arrayGetLength() }
+ local t = { __data__ = v, size = v:arrayGetLength() or 0 }
setmetatable(t,array_access)
if cache_lookups then rawset(tab,key,t) end
return t
@@ -130,7 +129,7 @@ local page_access = {
local annots = d:getAnnots()
local a = {
__data__ = annots,
- size = annots:arrayGetLength()
+ size = annots:arrayGetLength() or 0
}
setmetatable(a,basic_annots_access)
rawset(t,k,a)
diff --git a/tex/context/base/lpdf-ini.lua b/tex/context/base/lpdf-ini.lua
index a39040d7f..4b7972abe 100644
--- a/tex/context/base/lpdf-ini.lua
+++ b/tex/context/base/lpdf-ini.lua
@@ -45,15 +45,17 @@ local function tosixteen(str)
if not str or str == "" then
return "()"
else
- local r = { "<feff" }
+ local r, n = { "<feff" }, 1
for b in utfvalues(str) do
+ n = n + 1
if b < 0x10000 then
- r[#r+1] = format("%04x",b)
+ r[n] = format("%04x",b)
else
- r[#r+1] = format("%04x%04x",b/1024+0xD800,b%1024+0xDC00)
+ r[n] = format("%04x%04x",b/1024+0xD800,b%1024+0xDC00)
end
end
- r[#r+1] = ">"
+ n = n + 1
+ r[n] = ">"
return concat(r)
end
end
@@ -115,24 +117,25 @@ tostring_d = function(t,contentonly,key)
return "<< >>"
end
else
- local r = { }
+ local r, rn = { }, 0
for k, v in next, t do
+ rn = rn + 1
local tv = type(v)
if tv == "string" then
- r[#r+1] = format("/%s %s",k,toeight(v))
+ r[rn] = format("/%s %s",k,toeight(v))
elseif tv == "unicode" then
- r[#r+1] = format("/%s %s",k,tosixteen(v))
+ r[rn] = format("/%s %s",k,tosixteen(v))
elseif tv == "table" then
local mv = getmetatable(v)
if mv and mv.__lpdftype then
- r[#r+1] = format("/%s %s",k,tostring(v))
+ r[rn] = format("/%s %s",k,tostring(v))
elseif v[1] then
- r[#r+1] = format("/%s %s",k,tostring_a(v))
+ r[rn] = format("/%s %s",k,tostring_a(v))
else
- r[#r+1] = format("/%s %s",k,tostring_d(v))
+ r[rn] = format("/%s %s",k,tostring_d(v))
end
else
- r[#r+1] = format("/%s %s",k,tostring(v))
+ r[rn] = format("/%s %s",k,tostring(v))
end
end
if contentonly then
@@ -146,7 +149,8 @@ tostring_d = function(t,contentonly,key)
end
tostring_a = function(t,contentonly,key)
- if #t == 0 then
+ local tn = #t
+ if tn == 0 then
if contentonly then
return ""
else
@@ -154,24 +158,25 @@ tostring_a = function(t,contentonly,key)
end
else
local r = { }
- for k, v in next, t do
+ for k=1,tn do
+ local v = t[k]
local tv = type(v)
if tv == "string" then
- r[#r+1] = toeight(v)
+ r[k] = toeight(v)
elseif tv == "unicode" then
- r[#r+1] = tosixteen(v)
+ r[k] = tosixteen(v)
elseif tv == "table" then
local mv = getmetatable(v)
local mt = mv and mv.__lpdftype
if mt then
- r[#r+1] = tostring(v)
+ r[k] = tostring(v)
elseif v[1] then
- r[#r+1] = tostring_a(v)
+ r[k] = tostring_a(v)
else
- r[#r+1] = tostring_d(v)
+ r[k] = tostring_d(v)
end
else
- r[#r+1] = tostring(v)
+ r[k] = tostring(v)
end
end
if contentonly then
diff --git a/tex/context/base/lpdf-tag.lua b/tex/context/base/lpdf-tag.lua
index d05e3e22f..00ddef025 100644
--- a/tex/context/base/lpdf-tag.lua
+++ b/tex/context/base/lpdf-tag.lua
@@ -74,10 +74,10 @@ local add_ids = false -- true
local function finishstructure()
if #structure_kids > 0 then
- local nums = pdfarray()
+ local nums, n = pdfarray(), 0
for i=1,#tree do
- nums[#nums+1] = i-1
- nums[#nums+1] = pdfreference(pdfflushobject(tree[i]))
+ n = n + 1 ; nums[n] = i-1
+ n = n + 1 ; nums[n] = pdfreference(pdfflushobject(tree[i]))
end
local parenttree = pdfdictionary {
Nums = nums
diff --git a/tex/context/base/luat-cbk.lua b/tex/context/base/luat-cbk.lua
index a21976372..93538c6bb 100644
--- a/tex/context/base/luat-cbk.lua
+++ b/tex/context/base/luat-cbk.lua
@@ -124,7 +124,7 @@ end
function callbacks.freeze(name,freeze)
freeze = type(freeze) == "string" and freeze
if find(name,"%*") then
- local pattern = name -- string.partialescapedpattern(name)
+ local pattern = name
for name, _ in next, list do
if find(name,pattern) then
frozen[name] = freeze or frozen[name] or "frozen"
diff --git a/tex/context/base/luat-cnf.lua b/tex/context/base/luat-cnf.lua
index 8b52a269c..2ab97e71d 100644
--- a/tex/context/base/luat-cnf.lua
+++ b/tex/context/base/luat-cnf.lua
@@ -28,9 +28,6 @@ local variablenames = allocate { -- most of this becomes obsolete
'max_in_open', -- 15
'max_print_line', -- 79
'max_strings', -- 15000
- 'ocp_stack_size', -- 1000
- 'ocp_list_size', -- 1000
- 'ocp_buf_size', -- 1000
'param_size', -- 60
'pk_dpi', -- 72
'save_size', -- 4000
diff --git a/tex/context/base/luat-env.lua b/tex/context/base/luat-env.lua
index ed0884992..b8245afba 100644
--- a/tex/context/base/luat-env.lua
+++ b/tex/context/base/luat-env.lua
@@ -19,7 +19,7 @@ local report_resolvers = logs.new("resolvers")
local allocate, mark = utilities.storage.allocate, utilities.storage.mark
local format, sub, match, gsub, find = string.format, string.sub, string.match, string.gsub, string.find
-local unquote, quote = string.unquote, string.quote
+local unquoted, quoted = string.unquoted, string.quoted
local concat = table.concat
-- precautions
@@ -87,7 +87,7 @@ function environment.initializearguments(arg)
if index > 0 then
local flag, value = match(argument,"^%-+(.-)=(.-)$")
if flag then
- arguments[flag] = unquote(value or "")
+ arguments[flag] = unquoted(value or "")
else
flag = match(argument,"^%-+(.+)")
if flag then
@@ -152,19 +152,21 @@ end
function environment.reconstructcommandline(arg,noquote)
arg = arg or environment.originalarguments
if noquote and #arg == 1 then
+ -- we could just do: return unquoted(resolvers.resolve(arg[i]))
local a = arg[1]
a = resolvers.resolve(a)
- a = unquote(a)
+ a = unquoted(a)
return a
elseif #arg > 0 then
local result = { }
for i=1,#arg do
+ -- we could just do: result[#result+1] = format("%q",unquoted(resolvers.resolve(arg[i])))
local a = arg[i]
a = resolvers.resolve(a)
- a = unquote(a)
+ a = unquoted(a)
a = gsub(a,'"','\\"') -- tricky
if find(a," ") then
- result[#result+1] = quote(a)
+ result[#result+1] = quoted(a)
else
result[#result+1] = a
end
@@ -175,6 +177,23 @@ function environment.reconstructcommandline(arg,noquote)
end
end
+--~ -- to be tested:
+--~
+--~ function environment.reconstructcommandline(arg,noquote)
+--~ arg = arg or environment.originalarguments
+--~ if noquote and #arg == 1 then
+--~ return unquoted(resolvers.resolve(arg[1]))
+--~ elseif #arg > 0 then
+--~ local result = { }
+--~ for i=1,#arg do
+--~ result[#result+1] = format("%q",unquoted(resolvers.resolve(arg[i]))) -- always quote
+--~ end
+--~ return concat(result," ")
+--~ else
+--~ return ""
+--~ end
+--~ end
+
if arg then
-- new, reconstruct quoted snippets (maybe better just remove the " then and add them later)
diff --git a/tex/context/base/luat-fio.lua b/tex/context/base/luat-fio.lua
index db27e480d..5f65ead48 100644
--- a/tex/context/base/luat-fio.lua
+++ b/tex/context/base/luat-fio.lua
@@ -43,7 +43,6 @@ if not resolvers.instance then
register('find_format_file' , function(name) return findbinfile(name,"fmt") end, true)
register('find_image_file' , function(name) return findbinfile(name,"tex") end, true)
register('find_map_file' , function(name) return findbinfile(name,"map") end, true)
- register('find_ocp_file' , function(name) return findbinfile(name,"ocp") end, true)
register('find_opentype_file' , function(name) return findbinfile(name,"otf") end, true)
register('find_output_file' , function(name) return name end, true)
register('find_pk_file' , function(name) return findbinfile(name,"pk") end, true)
@@ -58,7 +57,6 @@ if not resolvers.instance then
-- format
-- image
register('read_map_file' , function(file) return loadbinfile(file,"map") end, true)
- register('read_ocp_file' , function(file) return loadbinfile(file,"ocp") end, true)
-- output
register('read_pk_file' , function(file) return loadbinfile(file,"pk") end, true) -- 600dpi/manfnt.720pk
register('read_sfd_file' , function(file) return loadbinfile(file,"sfd") end, true)
diff --git a/tex/context/base/luat-fmt.lua b/tex/context/base/luat-fmt.lua
index 42f75a1ba..2be205d8c 100644
--- a/tex/context/base/luat-fmt.lua
+++ b/tex/context/base/luat-fmt.lua
@@ -11,17 +11,17 @@ local format = string.format
-- helper for mtxrun
-local quote = string.quote
+local quoted = string.quoted
local function primaryflags()
local trackers = environment.argument("trackers")
local directives = environment.argument("directives")
local flags = ""
if trackers and trackers ~= "" then
- flags = flags .. "--trackers=" .. quote(trackers)
+ flags = flags .. "--trackers=" .. quoted(trackers)
end
if directives and directives ~= "" then
- flags = flags .. "--directives=" .. quote(directives)
+ flags = flags .. "--directives=" .. quoted(directives)
end
return flags
end
@@ -86,7 +86,7 @@ function environment.make_format(name)
return
end
-- generate format
- local command = format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quote(usedluastub),quote(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
+ local command = format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
logs.simple("running command: %s\n",command)
os.spawn(command)
-- remove related mem files
@@ -124,8 +124,7 @@ function environment.run_format(name,data,more)
logs.simple("using format name: %s",fmtname)
logs.simple("no luc/lua with name: %s",barename)
else
- local q = string.quote
- local command = format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quote(barename),quote(luaname),quote(data),more ~= "" and quote(more) or "")
+ local command = format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quoted(barename),quoted(luaname),quoted(data),more ~= "" and quoted(more) or "")
logs.simple("running command: %s",command)
os.spawn(command)
end
diff --git a/tex/context/base/luat-ini.lua b/tex/context/base/luat-ini.lua
index b57962c2d..40a49defa 100644
--- a/tex/context/base/luat-ini.lua
+++ b/tex/context/base/luat-ini.lua
@@ -95,6 +95,8 @@ local protected = {
userdata, thirddata = nil, nil
+-- we could have a metatable that automaticaly creates a top level namespace
+
if not setfenv then
texio.write_nl("warning: we need to fix setfenv by using 'load in' or '_ENV'")
end
diff --git a/tex/context/base/luat-lib.mkiv b/tex/context/base/luat-lib.mkiv
index 02bafa4cc..81d371cc4 100644
--- a/tex/context/base/luat-lib.mkiv
+++ b/tex/context/base/luat-lib.mkiv
@@ -13,12 +13,12 @@
\writestatus{loading}{ConTeXt Lua Macros / Libraries}
+\registerctxluafile{util-tab}{1.001}
\registerctxluafile{util-pck}{1.001}
\registerctxluafile{util-seq}{1.001}
%registerctxluafile{util-mrg}{1.001} % not needed in context itself, only mtxrun
\registerctxluafile{util-lua}{1.001}
\registerctxluafile{util-prs}{1.001}
-\registerctxluafile{util-tab}{1.001}
\registerctxluafile{util-fmt}{1.001}
\registerctxluafile{util-deb}{1.001} % could also be done in trac-deb.mkiv
\registerctxluafile{util-sto}{1.001} % could also be done in trac-deb.mkiv
diff --git a/tex/context/base/luat-run.lua b/tex/context/base/luat-run.lua
index f22470f5f..580137d8a 100644
--- a/tex/context/base/luat-run.lua
+++ b/tex/context/base/luat-run.lua
@@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['luat-run'] = {
license = "see context related readme files"
}
-local format, rpadd = string.format, string.rpadd
+local format = string.format
local insert = table.insert
local trace_lua_dump = false trackers.register("system.dump", function(v) trace_lua_dump = v end)
diff --git a/tex/context/base/lxml-aux.lua b/tex/context/base/lxml-aux.lua
index 7392afabb..088d82881 100644
--- a/tex/context/base/lxml-aux.lua
+++ b/tex/context/base/lxml-aux.lua
@@ -128,16 +128,17 @@ end
function xml.collect_tags(root, pattern, nonamespace)
local collected = xmlapplylpath(root,pattern)
if collected then
- local t = { }
+ local t, n = { }, 0
for c=1,#collected do
local e = collected[c]
local ns, tg = e.ns, e.tg
+ n = n + 1
if nonamespace then
- t[#t+1] = tg
+ t[n] = tg
elseif ns == "" then
- t[#t+1] = tg
+ t[n] = tg
else
- t[#t+1] = ns .. ":" .. tg
+ t[n] = ns .. ":" .. tg
end
end
return t
@@ -250,8 +251,10 @@ local function inject_element(root,pattern,whatever,prepend)
else
be, af = edt, cp
end
+ local bn = #be
for i=1,#af do
- be[#be+1] = af[i]
+ bn = bn + 1
+ be[bn] = af[i]
end
if rri then
r.dt[rri].dt = be
@@ -339,11 +342,12 @@ local function stripelement(e,nolines,anywhere)
local edt = e.dt
if edt then
if anywhere then
- local t = { }
+ local t, n = { }, 0
for e=1,#edt do
local str = edt[e]
if type(str) ~= "string" then
- t[#t+1] = str
+ n = n + 1
+ t[n] = str
elseif str ~= "" then
-- todo: lpeg for each case
if nolines then
@@ -351,7 +355,8 @@ local function stripelement(e,nolines,anywhere)
end
str = gsub(str,"^%s*(.-)%s*$","%1")
if str ~= "" then
- t[#t+1] = str
+ n = n + 1
+ t[n] = str
end
end
end
@@ -378,9 +383,10 @@ local function stripelement(e,nolines,anywhere)
end
end
end
- if #edt > 0 then
+ local nedt = #nedt
+ if nedt > 0 then
-- strip end
- local str = edt[#edt]
+ local str = edt[nedt]
if type(str) ~= "string" then
-- nothing
elseif str == "" then
@@ -393,7 +399,7 @@ local function stripelement(e,nolines,anywhere)
if str == "" then
remove(edt)
else
- edt[#edt] = str
+ edt[nedt] = str
end
end
end
diff --git a/tex/context/base/lxml-lpt.lua b/tex/context/base/lxml-lpt.lua
index ef9a1175b..274601d83 100644
--- a/tex/context/base/lxml-lpt.lua
+++ b/tex/context/base/lxml-lpt.lua
@@ -134,7 +134,7 @@ apply_axis['root'] = function(list)
rt = ll
end
end
- collected[#collected+1] = rt
+ collected[l] = rt
end
return collected
end
@@ -142,14 +142,14 @@ end
apply_axis['self'] = function(list)
--~ local collected = { }
--~ for l=1,#list do
---~ collected[#collected+1] = list[l]
+--~ collected[l] = list[l]
--~ end
--~ return collected
return list
end
apply_axis['child'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
local dt = ll.dt
@@ -158,7 +158,8 @@ apply_axis['child'] = function(list)
for k=1,#dt do
local dk = dt[k]
if dk.tg then
- collected[#collected+1] = dk
+ c = c + 1
+ collected[c] = dk
dk.ni = k -- refresh
en = en + 1
dk.ei = en
@@ -170,68 +171,74 @@ apply_axis['child'] = function(list)
return collected
end
-local function collect(list,collected)
+local function collect(list,collected,c)
local dt = list.dt
if dt then
local en = 0
for k=1,#dt do
local dk = dt[k]
if dk.tg then
- collected[#collected+1] = dk
+ c = c + 1
+ collected[c] = dk
dk.ni = k -- refresh
en = en + 1
dk.ei = en
- collect(dk,collected)
+ c = collect(dk,collected,c)
end
end
list.en = en
end
+ return c
end
apply_axis['descendant'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
- collect(list[l],collected)
+ c = collect(list[l],collected,c)
end
return collected
end
-local function collect(list,collected)
+local function collect(list,collected,c)
local dt = list.dt
if dt then
local en = 0
for k=1,#dt do
local dk = dt[k]
if dk.tg then
- collected[#collected+1] = dk
+ c = c + 1
+ collected[c] = dk
dk.ni = k -- refresh
en = en + 1
dk.ei = en
- collect(dk,collected)
+ c = collect(dk,collected,c)
end
end
list.en = en
end
+ return c
end
apply_axis['descendant-or-self'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
if ll.special ~= true then -- catch double root
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
end
- collect(ll,collected)
+ c = collect(ll,collected,c)
end
return collected
end
apply_axis['ancestor'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
while ll do
ll = ll.__p__
if ll then
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
end
end
end
@@ -239,14 +246,16 @@ apply_axis['ancestor'] = function(list)
end
apply_axis['ancestor-or-self'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
while ll do
ll = ll.__p__
if ll then
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
end
end
end
@@ -254,11 +263,12 @@ apply_axis['ancestor-or-self'] = function(list)
end
apply_axis['parent'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local pl = list[l].__p__
if pl then
- collected[#collected+1] = pl
+ c = c + 1
+ collected[c] = pl
end
end
return collected
@@ -273,7 +283,7 @@ apply_axis['namespace'] = function(list)
end
apply_axis['following'] = function(list) -- incomplete
---~ local collected = { }
+--~ local collected, c = { }, 0
--~ for l=1,#list do
--~ local ll = list[l]
--~ local p = ll.__p__
@@ -281,7 +291,8 @@ apply_axis['following'] = function(list) -- incomplete
--~ for i=ll.ni+1,#d do
--~ local di = d[i]
--~ if type(di) == "table" then
---~ collected[#collected+1] = di
+--~ c = c + 1
+--~ collected[c] = di
--~ break
--~ end
--~ end
@@ -291,7 +302,7 @@ apply_axis['following'] = function(list) -- incomplete
end
apply_axis['preceding'] = function(list) -- incomplete
---~ local collected = { }
+--~ local collected, c = { }, 0
--~ for l=1,#list do
--~ local ll = list[l]
--~ local p = ll.__p__
@@ -299,7 +310,8 @@ apply_axis['preceding'] = function(list) -- incomplete
--~ for i=ll.ni-1,1,-1 do
--~ local di = d[i]
--~ if type(di) == "table" then
---~ collected[#collected+1] = di
+--~ c = c + 1
+--~ collected[c] = di
--~ break
--~ end
--~ end
@@ -309,7 +321,7 @@ apply_axis['preceding'] = function(list) -- incomplete
end
apply_axis['following-sibling'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
local p = ll.__p__
@@ -317,7 +329,8 @@ apply_axis['following-sibling'] = function(list)
for i=ll.ni+1,#d do
local di = d[i]
if type(di) == "table" then
- collected[#collected+1] = di
+ c = c + 1
+ collected[c] = di
end
end
end
@@ -325,7 +338,7 @@ apply_axis['following-sibling'] = function(list)
end
apply_axis['preceding-sibling'] = function(list)
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
local p = ll.__p__
@@ -333,7 +346,8 @@ apply_axis['preceding-sibling'] = function(list)
for i=1,ll.ni-1 do
local di = d[i]
if type(di) == "table" then
- collected[#collected+1] = di
+ c = c + 1
+ collected[c] = di
end
end
end
@@ -341,7 +355,7 @@ apply_axis['preceding-sibling'] = function(list)
end
apply_axis['reverse-sibling'] = function(list) -- reverse preceding
- local collected = { }
+ local collected, c = { }, 0
for l=1,#list do
local ll = list[l]
local p = ll.__p__
@@ -349,7 +363,8 @@ apply_axis['reverse-sibling'] = function(list) -- reverse preceding
for i=ll.ni-1,1,-1 do
local di = d[i]
if type(di) == "table" then
- collected[#collected+1] = di
+ c = c + 1
+ collected[c] = di
end
end
end
@@ -375,7 +390,7 @@ local function apply_nodes(list,directive,nodes)
return { }
end
else
- local collected, m, p = { }, 0, nil
+ local collected, c, m, p = { }, 0, 0, nil
if not nns then -- only check tag
for l=1,#list do
local ll = list[l]
@@ -384,11 +399,13 @@ local function apply_nodes(list,directive,nodes)
if directive then
if ntg == ltg then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
elseif ntg ~= ltg then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
end
end
@@ -400,11 +417,13 @@ local function apply_nodes(list,directive,nodes)
if directive then
if lns == nns then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
elseif lns ~= nns then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
end
end
@@ -418,11 +437,13 @@ local function apply_nodes(list,directive,nodes)
if directive then
if ok then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
elseif not ok then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
end
end
@@ -430,7 +451,7 @@ local function apply_nodes(list,directive,nodes)
return collected
end
else
- local collected, m, p = { }, 0, nil
+ local collected, c, m, p = { }, 0, 0, nil
for l=1,#list do
local ll = list[l]
local ltg = ll.tg
@@ -447,11 +468,13 @@ local function apply_nodes(list,directive,nodes)
if directive then
if ok then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
elseif not ok then
local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- collected[#collected+1], ll.mi = ll, m
+ c = c + 1
+ collected[c], ll.mi = ll, m
end
end
end
@@ -462,12 +485,13 @@ end
local quit_expression = false
local function apply_expression(list,expression,order)
- local collected = { }
+ local collected, c = { }, 0
quit_expression = false
for l=1,#list do
local ll = list[l]
if expression(list,ll,l,order) then -- nasty, order alleen valid als n=1
- collected[#collected+1] = ll
+ c = c + 1
+ collected[c] = ll
end
if quit_expression then
break
@@ -765,7 +789,7 @@ local function nodesettostring(set,nodetest)
if not ns or ns == "" then ns = "*" end
if not tg or tg == "" then tg = "*" end
tg = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
- t[#t+1] = (directive and tg) or format("not(%s)",tg)
+ t[i] = (directive and tg) or format("not(%s)",tg)
end
if nodetest == false then
return format("not(%s)",concat(t,"|"))
@@ -784,7 +808,7 @@ local function tagstostring(list)
local ns, tg = li.ns, li.tg
if not ns or ns == "" then ns = "*" end
if not tg or tg == "" then tg = "*" end
- t[#t+1] = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
+ t[i] = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
end
return concat(t," ")
end
diff --git a/tex/context/base/lxml-tex.lua b/tex/context/base/lxml-tex.lua
index 0bf488342..bfa64fe65 100644
--- a/tex/context/base/lxml-tex.lua
+++ b/tex/context/base/lxml-tex.lua
@@ -31,6 +31,8 @@ local xmlapplylpath = xml.applylpath
local variables = (interfaces and interfaces.variables) or { }
+local insertbeforevalue, insertaftervalue = utilities.tables.insertbeforevalue, utilities.tables.insertaftervalue
+
local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming
local trace_setups = false trackers.register("lxml.setups", function(v) trace_setups = v end)
@@ -696,12 +698,12 @@ function lxml.installsetup(what,document,setup,where)
if trace_loading then
commands.writestatus("lxml","inserting setup %s for %s before %s",setup,document,where)
end
- table.insertbeforevalue(sd,setup,where)
+ insertbeforevalue(sd,setup,where)
elseif what == 4 then
if trace_loading then
commands.writestatus("lxml","inserting setup %s for %s after %s",setup,document,where)
end
- table.insertaftervalue(sd,setup,where)
+ insertaftervalue(sd,setup,where)
end
end
@@ -1450,9 +1452,10 @@ function lxml.toparameters(id)
if e then
local a = e.at
if a and next(a) then
- local setups = { }
+ local setups, s = { }, 0
for k, v in next, a do
- setups[#setups+1] = k .. "=" .. v
+ s = s + 1
+ setups[s] = k .. "=" .. v
end
setups = concat(setups,",")
-- tracing
diff --git a/tex/context/base/lxml-xml.lua b/tex/context/base/lxml-xml.lua
index 2a6d56800..2053d2353 100644
--- a/tex/context/base/lxml-xml.lua
+++ b/tex/context/base/lxml-xml.lua
@@ -26,15 +26,18 @@ local function all(collected)
return collected
end
-local function reverse(collected)
- if collected then
- local reversed = { }
- for c=#collected,1,-1 do
- reversed[#reversed+1] = collected[c]
- end
- return reversed
- end
-end
+--~ local function reverse(collected)
+--~ if collected then
+--~ local reversed, r = { }, 0
+--~ for c=#collected,1,-1 do
+--~ r = r + 1
+--~ reversed[r] = collected[c]
+--~ end
+--~ return reversed
+--~ end
+--~ end
+
+local reverse = table.reversed
local function attribute(collected,name)
if collected and #collected > 0 then
@@ -125,11 +128,12 @@ end
local function texts(collected)
if collected then
- local t = { }
+ local t, n = { }, 0
for c=1,#collected do
local e = collection[c]
if e and e.dt then
- t[#t+1] = e.dt
+ n = n + 1
+ t[n] = e.dt
end
end
return t
@@ -172,14 +176,15 @@ end
local function tags(collected,nonamespace)
if collected then
- local t = { }
+ local t, n = { }, 0
for c=1,#collected do
local e = collected[c]
local ns, tg = e.ns, e.tg
+ n = n + 1
if nonamespace or ns == "" then
- t[#t+1] = tg
+ t[n] = tg
else
- t[#t+1] = ns .. ":" .. tg
+ t[n] = ns .. ":" .. tg
end
end
return t
diff --git a/tex/context/base/m-database.lua b/tex/context/base/m-database.lua
index 810c8ba39..ffaafa2f3 100644
--- a/tex/context/base/m-database.lua
+++ b/tex/context/base/m-database.lua
@@ -65,7 +65,7 @@ end
for i=1,#data do
local line = data[i]
if line ~= "" and (not checker or not lpegmatch(checker,line)) then
- local result = { } -- we collect as this is nicer in tracing
+ local result, r = { }, 0 -- we collect as this is nicer in tracing
local list = lpegmatch(splitter,line)
if not found then
local setups = settings.setups or ""
@@ -77,20 +77,20 @@ end
sprint(ctxcatcodes,before)
found = true
end
- result[#result+1] = first
+ r = r + 1 ; result[r] = first
for j=1,#list do
result[#result+1] = left
if command == "" then
- result[#result+1] = list[j]
+ r = r + 1 ; result[r] = list[j]
else
- result[#result+1] = command
- result[#result+1] = "{"
- result[#result+1] = list[j]
- result[#result+1] = "}"
+ r = r + 1 ; result[r] = command
+ r = r + 1 ; result[r] = "{"
+ r = r + 1 ; result[r] = list[j]
+ r = r + 1 ; result[r] = "}"
end
- result[#result+1] = right
+ r = r + 1 ; result[r] = right
end
- result[#result+1] = last
+ r = r + 1 ; result[r] = last
sprint(ctxcatcodes,result)
end
end
diff --git a/tex/context/base/meta-pdf.lua b/tex/context/base/meta-pdf.lua
index 0c77469a8..ad4bcca81 100644
--- a/tex/context/base/meta-pdf.lua
+++ b/tex/context/base/meta-pdf.lua
@@ -94,11 +94,11 @@ local function flushpath(cmd)
local px, py = v[3], v[4] ; v[3], v[4] = (sy*(px-tx)-ry*(py-ty))/d, (sx*(py-ty)-rx*(px-tx))/d -- mpconcat(v[3],v[4])
local px, py = v[5], v[6] ; v[5], v[6] = (sy*(px-tx)-ry*(py-ty))/d, (sx*(py-ty)-rx*(px-tx))/d -- mpconcat(v[5],v[6])
end
- path[#path+1] = concat(v," ")
+ path[k] = concat(v," ")
end
else
for k=1,#m_stack_path do
- path[#path+1] = concat(m_stack_path[k]," ")
+ path[k] = concat(m_stack_path[k]," ")
end
end
flushconcat()
@@ -146,10 +146,13 @@ end
function mps.rlineto(x,y)
local dx, dy = 0, 0
- if #m_stack_path > 0 then
- dx, dy = m_stack_path[#m_stack_path][1], m_stack_path[#m_stack_path][2]
+ local topofstack = #m_stack_path
+ if topofstack > 0 then
+ local msp = m_stack_path[topofstack]
+ dx = msp[1]
+ dy = msp[2]
end
- m_stack_path[#m_stack_path+1] = {dx,dy,"l"}
+ m_stack_path[topofstack+1] = {dx,dy,"l"}
end
function mps.translate(tx,ty)
diff --git a/tex/context/base/mlib-pdf.lua b/tex/context/base/mlib-pdf.lua
index 47c93513a..30db3f52c 100644
--- a/tex/context/base/mlib-pdf.lua
+++ b/tex/context/base/mlib-pdf.lua
@@ -162,64 +162,81 @@ local function curved(ith,pth)
end
local function flushnormalpath(path, t, open)
- t = t or { }
- local pth, ith
+ local pth, ith, nt
+ if t then
+ nt = #t
+ else
+ t = { }
+ nt = 0
+ end
for i=1,#path do
+ nt = nt + 1
pth = path[i]
if not ith then
- t[#t+1] = format("%f %f m",pth.x_coord,pth.y_coord)
+ t[nt] = format("%f %f m",pth.x_coord,pth.y_coord)
elseif curved(ith,pth) then
- t[#t+1] = format("%f %f %f %f %f %f c",ith.right_x,ith.right_y,pth.left_x,pth.left_y,pth.x_coord,pth.y_coord)
+ t[nt] = format("%f %f %f %f %f %f c",ith.right_x,ith.right_y,pth.left_x,pth.left_y,pth.x_coord,pth.y_coord)
else
- t[#t+1] = format("%f %f l",pth.x_coord,pth.y_coord)
+ t[nt] = format("%f %f l",pth.x_coord,pth.y_coord)
end
ith = pth
end
if not open then
+ nt = nt + 1
local one = path[1]
if curved(pth,one) then
- t[#t+1] = format("%f %f %f %f %f %f c",pth.right_x,pth.right_y,one.left_x,one.left_y,one.x_coord,one.y_coord )
+ t[nt] = format("%f %f %f %f %f %f c",pth.right_x,pth.right_y,one.left_x,one.left_y,one.x_coord,one.y_coord )
else
- t[#t+1] = format("%f %f l",one.x_coord,one.y_coord)
+ t[nt] = format("%f %f l",one.x_coord,one.y_coord)
end
elseif #path == 1 then
-- special case .. draw point
local one = path[1]
- t[#t+1] = format("%f %f l",one.x_coord,one.y_coord)
+ nt = nt + 1
+ t[nt] = format("%f %f l",one.x_coord,one.y_coord)
end
return t
end
local function flushconcatpath(path, t, open)
- t = t or { }
- t[#t+1] = format("%f %f %f %f %f %f cm", sx, rx, ry, sy, tx ,ty)
- local pth, ith
+ local pth, ith, nt
+ if t then
+ nt = #t
+ else
+ t = { }
+ nt = 0
+ end
+ nt = nt + 1
+ t[nt] = format("%f %f %f %f %f %f cm", sx, rx, ry, sy, tx ,ty)
for i=1,#path do
+ nt = nt + 1
pth = path[i]
if not ith then
- t[#t+1] = format("%f %f m",mpconcat(pth.x_coord,pth.y_coord))
+ t[nt] = format("%f %f m",mpconcat(pth.x_coord,pth.y_coord))
elseif curved(ith,pth) then
local a, b = mpconcat(ith.right_x,ith.right_y)
local c, d = mpconcat(pth.left_x,pth.left_y)
- t[#t+1] = format("%f %f %f %f %f %f c",a,b,c,d,mpconcat(pth.x_coord,pth.y_coord))
+ t[nt] = format("%f %f %f %f %f %f c",a,b,c,d,mpconcat(pth.x_coord,pth.y_coord))
else
- t[#t+1] = format("%f %f l",mpconcat(pth.x_coord, pth.y_coord))
+ t[nt] = format("%f %f l",mpconcat(pth.x_coord, pth.y_coord))
end
ith = pth
end
if not open then
+ nt = nt + 1
local one = path[1]
if curved(pth,one) then
local a, b = mpconcat(pth.right_x,pth.right_y)
local c, d = mpconcat(one.left_x,one.left_y)
- t[#t+1] = format("%f %f %f %f %f %f c",a,b,c,d,mpconcat(one.x_coord, one.y_coord))
+ t[nt] = format("%f %f %f %f %f %f c",a,b,c,d,mpconcat(one.x_coord, one.y_coord))
else
- t[#t+1] = format("%f %f l",mpconcat(one.x_coord,one.y_coord))
+ t[nt] = format("%f %f l",mpconcat(one.x_coord,one.y_coord))
end
elseif #path == 1 then
-- special case .. draw point
+ nt = nt + 1
local one = path[1]
- t[#t+1] = format("%f %f l",mpconcat(one.x_coord,one.y_coord))
+ t[nt] = format("%f %f l",mpconcat(one.x_coord,one.y_coord))
end
return t
end
@@ -475,8 +492,10 @@ local flusher = {
context.startnointerference()
end,
flushfigure = function(literals)
+ local n = #t
for i=1, #literals do
- t[#t+1] = literals[i]
+ n = n + 1
+ t[n] = literals[i]
end
end,
stopfigure = function()
@@ -504,7 +523,7 @@ function metapost.totable(result)
local field = fields[f]
tt[field] = object[field]
end
- t[#t+1] = tt
+ t[o] = tt
end
local b = figure:boundingbox()
return {
diff --git a/tex/context/base/mlib-pps.lua b/tex/context/base/mlib-pps.lua
index e0592ca02..6fae400fc 100644
--- a/tex/context/base/mlib-pps.lua
+++ b/tex/context/base/mlib-pps.lua
@@ -109,9 +109,10 @@ function specials.register(str) -- only colors
local size, content, n, class = match(str,"^%%%%MetaPostSpecial: (%d+) (.*) (%d+) (%d+)$")
if class then
-- use lpeg splitter
- local data = { }
+ local data , d = { }, 0
for s in gmatch(content,"[^ ]+") do
- data[#data+1] = s
+ d = d + 1
+ data[d] = s
end
class, n = tonumber(class), tonumber(n)
if class == 3 or class == 4 or class == 5 then
@@ -682,14 +683,15 @@ local do_end_fig = "; endfig ;"
local do_safeguard = ";"
function metapost.texttextsdata()
- local t, n = { }, 0
+ local t, nt, n = { }, 0, 0
for n, box in next, textexts do
if box then
local wd, ht, dp = box.width/factor, box.height/factor, box.depth/factor
if trace_textexts then
report_mplib("passed textext data %s: (%0.4f,%0.4f,%0.4f)",n,wd,ht,dp)
end
- t[#t+1] = format(text_data_template,n,wd,n,ht,n,dp)
+ nt = nt + 1
+ t[nt] = format(text_data_template,n,wd,n,ht,n,dp)
else
break
end
@@ -782,11 +784,12 @@ function makempy.processgraphics(graphics)
if io.exists(pdffile) then
command = format("pstoedit -ssp -dt -f mpost %s %s", pdffile, mpyfile)
os.execute(command)
- local result = { }
+ local result, r = { }, 0
if io.exists(mpyfile) then
local data = io.loaddata(mpyfile)
for figure in gmatch(data,"beginfig(.-)endfig") do
- result[#result+1] = format("begingraphictextfig%sendgraphictextfig ;\n", figure)
+ r = r + 1
+ result[r] = format("begingraphictextfig%sendgraphictextfig ;\n", figure)
end
io.savedata(mpyfile,concat(result,""))
end
diff --git a/tex/context/base/mlib-run.lua b/tex/context/base/mlib-run.lua
index 7d670b77d..3d87c817e 100644
--- a/tex/context/base/mlib-run.lua
+++ b/tex/context/base/mlib-run.lua
@@ -323,7 +323,7 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass,
if not metapost.reporterror(result) then
if metapost.showlog then
local str = (result.term ~= "" and result.term) or "no terminal output"
- if not str:is_empty() then
+ if not string.is_empty(str) then
metapost.lastlog = metapost.lastlog .. "\n" .. str
report_mplib("mp log: %s",str)
end
diff --git a/tex/context/base/mult-cld.lua b/tex/context/base/mult-cld.lua
index f4c501423..a200625bb 100644
--- a/tex/context/base/mult-cld.lua
+++ b/tex/context/base/mult-cld.lua
@@ -268,9 +268,10 @@ end)
local tracedwriter = function(...)
nofwriters = nofwriters + 1
- local t, f = { "w : " }, flush
+ local t, f, n = { "w : " }, flush, 0
flush = function(...)
- t[#t+1] = concat({...},"",2)
+ n = n + 1
+ t[n] = concat({...},"",2)
normalflush(...)
end
normalwriter(...)
@@ -411,9 +412,10 @@ local nested = { } context.nested = nested
local function indexer(t,k)
local f = function(...)
- local t, savedflush = { }, flush
+ local t, savedflush, n = { }, flush, 0
flush = function(c,f,s,...) -- catcodes are ignored
- t[#t+1] = s and concat{f,s,...} or f -- optimized for #args == 1
+ n = n + 1
+ t[n] = s and concat{f,s,...} or f -- optimized for #args == 1
end
context[k](...)
flush = savedflush
@@ -424,9 +426,10 @@ local function indexer(t,k)
end
local function caller(t,...)
- local t, savedflush = { }, flush
+ local t, savedflush, n = { }, flush, 0
flush = function(c,f,s,...) -- catcodes are ignored
- t[#t+1] = s and concat{f,s,...} or f -- optimized for #args == 1
+ n = n + 1
+ t[n] = s and concat{f,s,...} or f -- optimized for #args == 1
end
context(...)
flush = savedflush
diff --git a/tex/context/base/mult-clm.lua b/tex/context/base/mult-clm.lua
index 044e31d2b..e2fff18dc 100644
--- a/tex/context/base/mult-clm.lua
+++ b/tex/context/base/mult-clm.lua
@@ -126,9 +126,11 @@ function mkiv.tolist(t)
for i=1,#t do
r[i] = t[i]
end
+ local n = #r
for k,v in table.sortedhash(t) do
if type(k) ~= "number" then
- r[#r+1] = k .. "=" .. v
+ n = n + 1
+ r[n] = k .. "=" .. v
end
end
return concat(r,", ")
diff --git a/tex/context/base/node-fin.lua b/tex/context/base/node-fin.lua
index af2ba0421..f7668415d 100644
--- a/tex/context/base/node-fin.lua
+++ b/tex/context/base/node-fin.lua
@@ -178,10 +178,15 @@ local nsdata, nsnone, nslistwise, nsforced, nsselector, nstrigger
local current, current_selector, done = 0, 0, false -- nb, stack has a local current !
function states.initialize(namespace,attribute,head)
- nsdata, nsnone = namespace.data, namespace.none
- nsforced, nsselector, nslistwise = namespace.forced, namespace.selector, namespace.listwise
- nstrigger = triggering and namespace.triggering and trigger
- current, current_selector, done = 0, 0, false -- todo: done cleanup
+ nsdata = namespace.data
+ nsnone = namespace.none
+ nsforced = namespace.forced
+ nsselector = namespace.selector
+ nslistwise = namespace.listwise
+ nstrigger = triggering and namespace.triggering and trigger
+ current = 0
+ current_selector = 0
+ done = false -- todo: done cleanup
end
function states.finalize(namespace,attribute,head) -- is this one ok?
@@ -213,11 +218,13 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr
if default and c == inheritance then
if current ~= default then
head = insert_node_before(head,stack,copy_node(nsdata[default]))
- current, done = default, true
+ current = default
+ done = true
end
elseif current ~= c then
head = insert_node_before(head,stack,copy_node(nsdata[c]))
- current, done = c, true
+ current = c
+ done = true
end
-- here ? compare selective
if id == glue_code then --leader
@@ -250,11 +257,13 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr
elseif default and inheritance then
if current ~= default then
head = insert_node_before(head,stack,copy_node(nsdata[default]))
- current, done = default, true
+ current = default
+ done = true
end
elseif current > 0 then
head = insert_node_before(head,stack,copy_node(nsnone))
- current, done = 0, true
+ current = 0
+ done = true
end
elseif id == hlist_code or id == vlist_code then
local content = stack.list
@@ -300,21 +309,25 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
if current ~= default then
local data = nsdata[default]
head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector]))
- current, done = default, true
+ current = default
+ done = true
end
else
local s = has_attribute(stack,nsselector)
if current ~= c or current_selector ~= s then
local data = nsdata[c]
head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector]))
- current, current_selector, done = c, s, true
+ current = c
+ current_selector = s
+ done = true
end
end
elseif default and inheritance then
if current ~= default then
local data = nsdata[default]
head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector]))
- current, done = default, true
+ current = default
+ done = true
end
elseif current > 0 then
head = insert_node_before(head,stack,copy_node(nsnone))
diff --git a/tex/context/base/node-fnt.lua b/tex/context/base/node-fnt.lua
index 7e8fa3694..399cd8642 100644
--- a/tex/context/base/node-fnt.lua
+++ b/tex/context/base/node-fnt.lua
@@ -107,7 +107,8 @@ function handlers.characters(head)
end
end
end
- prevfont, prevattr = font, attr
+ prevfont = font
+ prevattr = attr
end
end
if trace_fontrun then
@@ -122,11 +123,13 @@ function handlers.characters(head)
local n = #processors
if n > 0 then
local h, d = processors[1](head,font,0)
- head, done = h or head, done or d
+ head = h or head
+ done = done or d
if n > 1 then
for i=2,n do
local h, d = processors[i](head,font,0)
- head, done = h or head, done or d
+ head = h or head
+ done = done or d
end
end
end
@@ -134,11 +137,13 @@ function handlers.characters(head)
for font, processors in next, usedfonts do
local n = #processors
local h, d = processors[1](head,font,0)
- head, done = h or head, done or d
+ head = h or head
+ done = done or d
if n > 1 then
for i=2,n do
local h, d = processors[i](head,font,0)
- head, done = h or head, done or d
+ head = h or head
+ done = done or d
end
end
end
@@ -148,11 +153,13 @@ function handlers.characters(head)
for attribute, processors in next, dynamics do -- attr can switch in between
local n = #processors
local h, d = processors[1](head,font,attribute)
- head, done = h or head, done or d
+ head = h or head
+ done = done or d
if n > 1 then
for i=2,n do
local h, d = processors[i](head,font,attribute)
- head, done = h or head, done or d
+ head = h or head
+ done = done or d
end
end
end
@@ -161,11 +168,13 @@ function handlers.characters(head)
for attribute, processors in next, dynamics do -- attr can switch in between
local n = #processors
local h, d = processors[1](head,font,attribute)
- head, done = h or head, done or d
+ head = h or head
+ done = done or d
if n > 1 then
for i=2,n do
local h, d = processors[i](head,font,attribute)
- head, done = h or head, done or d
+ head = h or head
+ done = done or d
end
end
end
diff --git a/tex/context/base/node-ini.lua b/tex/context/base/node-ini.lua
index 6c48ba21d..f0b9b83fa 100644
--- a/tex/context/base/node-ini.lua
+++ b/tex/context/base/node-ini.lua
@@ -232,7 +232,8 @@ local function remove(head, current, free_too)
free_node(t)
t = nil
else
- t.next, t.prev = nil, nil
+ t.next = nil
+ t.prev = nil
end
end
return head, current, t
@@ -295,10 +296,12 @@ function nodes.replace(head,current,new) -- no head returned if false
end
local prev, next = current.prev, current.next
if next then
- new.next, next.prev = next, new
+ new.next = next
+ next.prev = new
end
if prev then
- new.prev, prev.next = prev, new
+ new.prev = prev
+ prev.next = new
end
if head then
if head == current then
diff --git a/tex/context/base/node-inj.lua b/tex/context/base/node-inj.lua
index f576c7ee2..e4380a4ea 100644
--- a/tex/context/base/node-inj.lua
+++ b/tex/context/base/node-inj.lua
@@ -188,12 +188,13 @@ function injections.handler(head,where,keep)
trace(head)
end
-- in the future variant we will not copy items but refs to tables
- local done, ky, rl, valid, cx, wx, mk = false, { }, { }, { }, { }, { }, { }
+ local done, ky, rl, valid, cx, wx, mk, nofvalid = false, { }, { }, { }, { }, { }, { }, 0
if has_kerns then -- move outside loop
local nf, tm = nil, nil
for n in traverse_id(glyph_code,head) do
if n.subtype < 256 then
- valid[#valid+1] = n
+ nofvalid = nofvalid + 1
+ valid[nofvalid] = n
if n.font ~= nf then
nf = n.font
tm = fontdata[nf].marks
@@ -221,7 +222,8 @@ function injections.handler(head,where,keep)
local nf, tm = nil, nil
for n in traverse_id(glyph_code,head) do
if n.subtype < 256 then
- valid[#valid+1] = n
+ nofvalid = nofvalid + 1
+ valid[nofvalid] = n
if n.font ~= nf then
nf = n.font
tm = fontdata[nf].marks
@@ -230,7 +232,7 @@ function injections.handler(head,where,keep)
end
end
end
- if #valid > 0 then
+ if nofvalid > 0 then
-- we can assume done == true because we have cursives and marks
local cx = { }
if has_kerns and next(ky) then
@@ -243,7 +245,7 @@ function injections.handler(head,where,keep)
local p_cursbase, p = nil, nil
-- since we need valid[n+1] we can also use a "while true do"
local t, d, maxt = { }, { }, 0
- for i=1,#valid do -- valid == glyphs
+ for i=1,nofvalid do -- valid == glyphs
local n = valid[i]
if not mk[n] then
local n_cursbase = has_attribute(n,cursbase)
@@ -307,7 +309,7 @@ function injections.handler(head,where,keep)
end
end
if has_marks then
- for i=1,#valid do
+ for i=1,nofvalid do
local p = valid[i]
local p_markbase = has_attribute(p,markbase)
if p_markbase then
diff --git a/tex/context/base/node-pro.lua b/tex/context/base/node-pro.lua
index 01dfc3352..9eb431d6b 100644
--- a/tex/context/base/node-pro.lua
+++ b/tex/context/base/node-pro.lua
@@ -33,15 +33,15 @@ local actions = tasks.actions("processors",4)
local n = 0
-local function reconstruct(head)
- local t = { }
- local h = head
+local function reconstruct(head) -- we probably have a better one
+ local t, n, h = { }, 0, head
while h do
+ n = n + 1
local id = h.id
- if id == glyph_code then
- t[#t+1] = utfchar(h.char)
+ if id == glyph_code then -- todo: disc etc
+ t[n] = utfchar(h.char)
else
- t[#t+1] = "[]"
+ t[n] = "[]"
end
h = h.next
end
diff --git a/tex/context/base/node-res.lua b/tex/context/base/node-res.lua
index 1487faa66..0a0cd0dc1 100644
--- a/tex/context/base/node-res.lua
+++ b/tex/context/base/node-res.lua
@@ -31,10 +31,11 @@ local nodecodes = nodes.nodecodes
local glyph_code = nodecodes.glyph
-local reserved = { }
+local reserved, nofreserved = { }, 0
local function register_node(n)
- reserved[#reserved+1] = n
+ nofreserved = nofreserved + 1
+ reserved[nofreserved] = n
return n
end
@@ -42,8 +43,8 @@ pool.register = register_node
function pool.cleanup(nofboxes) -- todo
nodes.tracers.steppers.reset() -- todo: make a registration subsystem
- local nr, nl = #reserved, 0
- for i=1,nr do
+ local nl, nr = 0, nofreserved
+ for i=1,nofreserved do
local ri = reserved[i]
-- if not (ri.id == glue_spec and not ri.is_writable) then
free_node(reserved[i])
@@ -60,6 +61,7 @@ function pool.cleanup(nofboxes) -- todo
end
end
reserved = { }
+ nofreserved = 0
return nr, nl, nofboxes -- can be nil
end
diff --git a/tex/context/base/node-rul.lua b/tex/context/base/node-rul.lua
index a0a18590b..51a7b4d3a 100644
--- a/tex/context/base/node-rul.lua
+++ b/tex/context/base/node-rul.lua
@@ -121,6 +121,8 @@ local checkdir = true
-- omkeren class en level -> scheelt functie call in analyze
+-- todo: switching inside math
+
local function processwords(attribute,data,flush,head,parent) -- we have hlistdir and local dir
local n = head
if n then
diff --git a/tex/context/base/node-ser.lua b/tex/context/base/node-ser.lua
index fd211b2c8..f90741aac 100644
--- a/tex/context/base/node-ser.lua
+++ b/tex/context/base/node-ser.lua
@@ -125,9 +125,10 @@ local function totable(n,flat,verbose)
end
if n then
if flat then
- local t = { }
+ local t, tn = { }, 0
while n do
- t[#t+1] = to_table(n,flat,verbise)
+ tn = tn + 1
+ t[tn] = to_table(n,flat,verbose)
n = n.next
end
return t
@@ -219,9 +220,10 @@ local function serialize(root,name,handle,depth,m)
end
function nodes.serialize(root,name)
- local t = { }
+ local t, n = { }, 0
local function flush(s)
- t[#t+1] = s
+ n = n + 1
+ t[n] = s
end
serialize(root, name, flush, nil, 0)
return concat(t,"\n")
diff --git a/tex/context/base/node-spl.lua b/tex/context/base/node-spl.lua
index 8d8c297bd..a942d3cdb 100644
--- a/tex/context/base/node-spl.lua
+++ b/tex/context/base/node-spl.lua
@@ -114,7 +114,7 @@ end
local contextsetups = fonts.definers.specifiers.contextsetups
local function convert(featuresets,name,set,what)
- local list, numbers = set[what], { }
+ local list, numbers, nofnumbers = set[what], { }, 0
if list then
for i=1,#list do
local feature = list[i]
@@ -126,7 +126,8 @@ local function convert(featuresets,name,set,what)
fn = fs and fs.number
end
if fn then
- numbers[#numbers+1] = fn
+ nofnumbers = nofnumbers + 1
+ numbers[nofnumbers] = fn
if trace_goodies or trace_optimize then
report_fonts("solution %s of '%s' uses feature '%s' with number %s",i,name,feature,fn)
end
@@ -134,7 +135,7 @@ local function convert(featuresets,name,set,what)
report_fonts("solution %s has an invalid feature reference '%s'",i,name,tostring(feature))
end
end
- return #numbers > 0 and numbers
+ return nofnumbers > 0 and numbers
end
end
@@ -179,18 +180,22 @@ function splitters.define(name,parameters)
end
else
if l then
+ local n = #less_set
for i=1,#l do
local ss = contextsetups[l[i]]
if ss then
- less_set[#less_set+1] = ss.number
+ n = n + 1
+ less_set[n] = ss.number
end
end
end
if m then
+ local n = #more_set
for i=1,#m do
local ss = contextsetups[m[i]]
if ss then
- more_set[#more_set+1] = ss.number
+ n = n + 1
+ more_set[n] = ss.number
end
end
end
@@ -198,14 +203,14 @@ function splitters.define(name,parameters)
if trace_optimize then
report_fonts("defining solutions '%s', less: '%s', more: '%s'",name,concat(less_set or {}," "),concat(more_set or {}," "))
end
- solutions[#solutions+1] = {
+ local nofsolutions = #solutions + 1
+ solutions[nofsolutions] = {
solution = solution,
less = less_set or { },
more = more_set or { },
settings = settings, -- for tracing
}
---~ print(table.serialize(solutions[#solutions]))
- tex.write(#solutions)
+ tex.write(nofsolutions)
end
local nofwords, noftries, nofadapted, nofkept, nofparagraphs = 0, 0, 0, 0, 0
@@ -287,13 +292,14 @@ function splitters.split(head)
end
local function collect_words(list)
- local words, word = { }, nil
+ local words, w, word = { }, 0, nil
for current in traverse_ids(whatsit_code,list) do
if current.subtype == userdefined_code then
local user_id = current.user_id
if user_id == 1 then
word = { current.value, current, current }
- words[#words+1] = word
+ w = w + 1
+ words[w] = word
elseif user_id == 2 then
word[3] = current
end
diff --git a/tex/context/base/node-tra.lua b/tex/context/base/node-tra.lua
index 78042cf44..d41089e6c 100644
--- a/tex/context/base/node-tra.lua
+++ b/tex/context/base/node-tra.lua
@@ -515,7 +515,7 @@ end
--~ else
--~ t[#t+1] = format("[%s]",node_type(last_id) or "?")
--~ end
---~ return table.concat(table.reverse(t)," ")
+--~ return table.concat(table.reversed(t)," ")
--~ end
@@ -631,7 +631,7 @@ end
-- might move elsewhere
local factor = number.dimenfactors.pt
-local stripper = lpeg.patterns.strip_zeros
+local stripper = lpeg.patterns.stripzeros
local points = function(n)
return lpegmatch(stripper,format("%.5fpt",n*factor))
diff --git a/tex/context/base/page-lin.lua b/tex/context/base/page-lin.lua
index 186989839..d31785329 100644
--- a/tex/context/base/page-lin.lua
+++ b/tex/context/base/page-lin.lua
@@ -257,9 +257,10 @@ end
function boxed.stage_two(n,m)
if #current_list > 0 then
m = m or lines.scratchbox
- local t, i = { }, 0
+ local t, tn = { }, 0
for l in traverse_id(hlist_code,texbox[m].list) do
- t[#t+1] = copy_node(l)
+ tn = tn + 1
+ t[tn] = copy_node(l)
end
for i=1,#current_list do
local li = current_list[i]
diff --git a/tex/context/base/s-fnt-10.tex b/tex/context/base/s-fnt-10.tex
index 8214946c6..56f2decb4 100644
--- a/tex/context/base/s-fnt-10.tex
+++ b/tex/context/base/s-fnt-10.tex
@@ -148,7 +148,7 @@ end
\page
\egroup}
-\endinput
+% \endinput
\starttext
@@ -171,6 +171,6 @@ end
% \ShowCompleteFont{name:palatinosansinformalcombold}{20pt}{2}
% \ShowCompleteFont{name:palatinonovaregular}{11pt}{2}
-% \ShowCompleteFont{name:optimanovaltregular}{11pt}{2}
+\ShowCompleteFont{pirat.ttf}{12pt}{1}
\stoptext
diff --git a/tex/context/base/scrn-int.mkiv b/tex/context/base/scrn-int.mkiv
index 83263d1df..dc919a8aa 100644
--- a/tex/context/base/scrn-int.mkiv
+++ b/tex/context/base/scrn-int.mkiv
@@ -247,6 +247,7 @@
\def\doinsertcomment#1%
{\begingroup
+ \doifelse\@@ccoption\v!max{\let\@@ccopen\s!true}{\let\@@ccopen\s!false}%
\ctxlua{backends.codeinjections.presetsymbollist("\@@ccsymbol")}%
% in between predefined symbols are dealt with
\ctxlua{backends.codeinjections.registercomment {
@@ -273,7 +274,6 @@
\def\dostartcomment[#1][#2][#3]%
{\bgroup
\doifassignmentelse{#1}{\getparameters[\??cc][#1]}{\getparameters[\??cc][\c!title=#1,#2]}%
- \doifelse\@@ccoption\v!max{\let\@@ccopen\s!true}{\let\@@ccopen\s!false}%
\setcurrentbuffer{\v!comment\v!buffer}%
\dostartbuffer[\v!comment\v!buffer][\v!comment\v!buffer][\e!start\v!comment][\e!stop\v!comment]}
diff --git a/tex/context/base/sort-ini.lua b/tex/context/base/sort-ini.lua
index 6511cd427..fb40c81a5 100644
--- a/tex/context/base/sort-ini.lua
+++ b/tex/context/base/sort-ini.lua
@@ -43,7 +43,7 @@ with any demand so nothign here is frozen.</p>
local utf = unicode.utf8
local gsub, rep, sub, sort, concat = string.gsub, string.rep, string.sub, table.sort, table.concat
local utfbyte, utfchar = utf.byte, utf.char
-local utfcharacters, utfvalues, strcharacters = string.utfcharacters, string.utfvalues, string.characters
+local utfcharacters = string.utfcharacters
local next, type, tonumber, rawget, rawset = next, type, tonumber, rawget, rawset
local allocate = utilities.storage.allocate
@@ -140,7 +140,7 @@ local function preparetables(data)
end
local mtm = {
__index = function(t,k)
- local n
+ local n, nn
if k then
if trace_tests then
report_sorters("simplifing character 0x%04x %s",utfbyte(k),k)
@@ -153,8 +153,10 @@ local function preparetables(data)
local ml = rawget(t,l)
if ml then
n = { }
+ nn = 0
for i=1,#ml do
- n[#n+1] = ml[i] + (t.__delta or 0)
+ nn = nn + 1
+ n[nn] = ml[i] + (t.__delta or 0)
end
if trace_tests then
report_sorters(" 2 order: %s",concat(n," "))
@@ -168,6 +170,7 @@ local function preparetables(data)
report_sorters(" 3 shape: %s",s)
end
n = { }
+ nn = 0
for l in utfcharacters(s) do
local ml = rawget(t,l)
if ml then
@@ -176,7 +179,8 @@ local function preparetables(data)
end
if ml then
for i=1,#ml do
- n[#n+1] = ml[i]
+ nn = nn + 1
+ n[nn] = ml[i]
end
end
else
@@ -188,7 +192,8 @@ local function preparetables(data)
local ml = rawget(t,l)
if ml then
for i=1,#ml do
- n[#n+1] = ml[i] + (t.__delta or 0)
+ nn = nn + 1
+ n[nn] = ml[i] + (t.__delta or 0)
end
end
end
@@ -200,6 +205,7 @@ local function preparetables(data)
end
if not n then
n = { 0 }
+ -- nn = 1
if trace_tests then
report_sorters(" 7 order: 0")
end
@@ -207,6 +213,7 @@ local function preparetables(data)
end
else
n = { 0 }
+ -- nn = 1
if trace_tests then
report_sorters(" 8 order: 0")
end
@@ -266,10 +273,12 @@ local function setlanguage(l,m,d)
--
local seq = utilities.parsers.settings_to_array(method or "") -- check the list
sequence = { }
+ local nofsequence = 0
for i=1,#seq do
local s = seq[i]
if validmethods[s] then
- sequence[#sequence+1] = s
+ nofsequence = nofsequence + 1
+ sequence[nofsequence] = s
else
report_sorters("invalid sorter method '%s' in '%s'",s,method)
end
@@ -434,6 +443,7 @@ function splitters.utf(str) -- we could append m and u but this is cleaner, s is
end
local m_case, z_case, p_case, m_mapping, z_mapping, p_mapping, char, byte, n = { }, { }, { }, { }, { }, { }, { }, { }, 0
+ local nm, nz, np = 0, 0, 0
for sc in utfcharacters(str) do
local b = utfbyte(sc)
if b >= digitsoffset then
@@ -456,9 +466,12 @@ function splitters.utf(str) -- we could append m and u but this is cleaner, s is
p_case[n] = b
char[n] = sc
byte[n] = b
- m_mapping[#m_mapping+1] = b
- z_mapping[#z_mapping+1] = b
- p_mapping[#p_mapping+1] = b
+ nm = nm + 1
+ nz = nz + 1
+ np = np + 1
+ m_mapping[nm] = b
+ z_mapping[nz] = b
+ p_mapping[np] = b
else
local l = lower[sc]
n = n + 1
@@ -474,15 +487,18 @@ function splitters.utf(str) -- we could append m and u but this is cleaner, s is
char[n], byte[n] = sc, b
local msc = m_mappings[sc]
for i=1,#msc do
- m_mapping[#m_mapping+1] = msc[i]
+ nm = nm + 1
+ m_mapping[nm] = msc[i]
end
local zsc = z_mappings[sc]
for i=1,#zsc do
- z_mapping[#z_mapping+1] = zsc[i]
+ nz = nz + 1
+ z_mapping[nz] = zsc[i]
end
local psc = p_mappings[sc]
for i=1,#psc do
- p_mapping[#p_mapping+1] = psc[i]
+ np = np + 1
+ p_mapping[np] = psc[i]
end
end
end
@@ -503,15 +519,6 @@ function splitters.utf(str) -- we could append m and u but this is cleaner, s is
return t
end
-
-function table.remap(t)
- local tt = { }
- for k,v in next, t do
- tt[v] = k
- end
- return tt
-end
-
local function pack(entry)
local t = { }
local split = entry.split
diff --git a/tex/context/base/spac-ver.lua b/tex/context/base/spac-ver.lua
index d58eaa329..9e29398cc 100644
--- a/tex/context/base/spac-ver.lua
+++ b/tex/context/base/spac-ver.lua
@@ -624,18 +624,20 @@ end
local trace_list, tracing_info, before, after = { }, false, "", ""
+local stripzeros, topoints = utilities.formatters.stripzeros, number.topoints
+
local function glue_to_string(glue)
local spec = glue.spec
local t = { points(spec.width) }
if spec.stretch_order and spec.stretch_order ~= 0 then
t[#t+1] = format("plus %s%s",spec.stretch/65536,fillcodes[spec.stretch_order])
elseif spec.stretch and spec.stretch ~= 0 then
- t[#t+1] = format("plus %s",utilities.formatters.strip_zeros(number.topoints(spec.stretch)))
+ t[#t+1] = format("plus %s",stripzeros(topoints(spec.stretch)))
end
if spec.shrink_order and spec.shrink_order ~= 0 then
t[#t+1] = format("minus %s%s",spec.shrink/65536,fillcodes[spec.shrink_order])
elseif spec.shrink and spec.shrink ~= 0 then
- t[#t+1] = format("minus %s",utilities.formatters.strip_zeros(number.topoints(spec.shrink)))
+ t[#t+1] = format("minus %s",stripzeros(topoints(spec.shrink)))
end
return concat(t," ")
end
@@ -648,9 +650,9 @@ local function nodes_to_string(head)
if id == penalty_code then
t[#t+1] = format("%s:%s",ty,current.penalty)
elseif id == glue_code then
- t[#t+1] = format("%s:%s",ty,utilities.formatters.strip_zeros(number.topoints(current.spec.width)))
+ t[#t+1] = format("%s:%s",ty,stripzeros(topoints(current.spec.width)))
elseif id == kern_code then
- t[#t+1] = format("%s:%s",ty,utilities.formatters.strip_zeros(number.topoints(current.kern)))
+ t[#t+1] = format("%s:%s",ty,stripzeros(topoints(current.kern)))
else
t[#t+1] = ty
end
diff --git a/tex/context/base/strc-bkm.lua b/tex/context/base/strc-bkm.lua
index 87327618c..08f26c88f 100644
--- a/tex/context/base/strc-bkm.lua
+++ b/tex/context/base/strc-bkm.lua
@@ -105,7 +105,7 @@ function bookmarks.place()
if next(names) then
local list = lists.filtercollected(names,"all",nil,lists.collected,forced)
if #list > 0 then
- local levels, lastlevel = { }, 1
+ local levels, noflevels, lastlevel = { }, 0, 1
for i=1,#list do
local li = list[i]
local metadata = li.metadata
@@ -133,7 +133,8 @@ function bookmarks.place()
title = concat(sections.typesetnumber(sectiondata,"direct",numberspec,sectiondata)) .. " " .. title
end
end
- levels[#levels+1] = {
+ noflevels = noflevels + 1
+ levels[noflevels] = {
lastlevel,
stripped(title), -- can be replaced by converter
li.references, -- has internal and realpage
@@ -142,7 +143,6 @@ function bookmarks.place()
end
end
end
---~ print(table.serialize(levels))
bookmarks.finalize(levels)
end
function bookmarks.place() end -- prevent second run
diff --git a/tex/context/base/strc-des.mkiv b/tex/context/base/strc-des.mkiv
index 06e4c2534..68e3ba155 100644
--- a/tex/context/base/strc-des.mkiv
+++ b/tex/context/base/strc-des.mkiv
@@ -676,18 +676,32 @@
\def\@@doenumerationtext
{\ifconditional\enumerationnumberenabled
\iftrialtypesetting
- \doenumerationfullnumber\showdntext
+ \doenumerationfullnumberyes
\doenumerationcouplingsymbol
\else
\doenumerationregistercoupling
- \doenumerationfullnumber\showdntext
+ \doenumerationfullnumberyes
\doenumerationcouplingsymbol
\fi
\else
- \doenumerationfullnumber\showdnpuretext
+ \doenumerationfullnumbernop
\fi}
-\def\doenumerationfullnumber#1% text, title
+\def\doenumerationfullnumberyes % text, title
+ {\begingroup
+ \dosetdescriptionattributes\c!headstyle\c!headcolor
+ \the\everyenumeration
+ \descriptionparameter\c!command{\strut\showdntext\doenumerationnumber\doenumerationextratext}%
+ \endgroup}
+
+\def\doenumerationfullnumbernop % text, title
+ {\begingroup
+ \dosetdescriptionattributes\c!headstyle\c!headcolor
+ \the\everyenumeration
+ \descriptionparameter\c!command{\strut\showdnpuretext\doenumerationextratext}%
+ \endgroup}
+
+\def\doenumerationfullnumber#1% text, title (used in notes) .. todo
{\begingroup
\dosetdescriptionattributes\c!headstyle\c!headcolor
\the\everyenumeration
@@ -696,14 +710,15 @@
\def\doenumerationextratext
{\doif{\descriptionparameter\c!title}\v!yes
- {\begingroup
- \dosetdescriptionattributes\c!titlestyle\c!titlecolor
- \hskip\descriptionparameter\c!titledistance
- \descriptionparameter\c!titlecommand
- {\descriptionparameter\c!titleleft
- \begstrut\@@dodoenumerationtext\endstrut
- \descriptionparameter\c!titleright}%
- \endgroup}}
+ {\doifsomething\@@dodoenumerationtext
+ {\begingroup
+ \dosetdescriptionattributes\c!titlestyle\c!titlecolor
+ \hskip\descriptionparameter\c!titledistance
+ \descriptionparameter\c!titlecommand
+ {\descriptionparameter\c!titleleft
+ \begstrut\@@dodoenumerationtext\endstrut
+ \descriptionparameter\c!titleright}%
+ \endgroup}}}
\def\doenumerationsavecounter {\savestructurecounter[\currentdescriptionnumber]}
\def\doenumerationrestorecounter {\restorestructurecounter[\currentdescriptionnumber]}
diff --git a/tex/context/base/strc-doc.lua b/tex/context/base/strc-doc.lua
index 322322e2a..1b8dfeb6f 100644
--- a/tex/context/base/strc-doc.lua
+++ b/tex/context/base/strc-doc.lua
@@ -725,57 +725,7 @@ function sections.fullnumber(depth,what)
end
end
---~ function sections.directnumber(depth,what)
---~ local sectiondata = sections.findnumber(depth,what)
---~ return sectiondata and sections.typesetnumber(sectiondata,'direct',sectiondata) or ""
---~ end
-
function sections.getnumber(depth,what) -- redefined here
local sectiondata = sections.findnumber(depth,what)
texwrite((sectiondata and sectiondata.numbers[depth]) or 0)
end
-
---~ local done, preceding = false, false
---~ local function process(index,result) -- move to outer
---~ -- todo: too much (100 steps)
---~ local number = numbers and (numbers[index] or 0)
---~ local ownnumber = ownnumbers and ownnumbers[index] or ""
---~ if number > criterium or (ownnumber ~= "") then
---~ local block = (entry.block ~= "" and entry.block) or sections.currentblock() -- added
---~ if preceding then
---~ local separator = sets.get("structure:separators",block,separatorset,preceding,".")
---~ if separator then
---~ if result then
---~ result[#result+1] = ignoreprocessor(separator)
---~ else
---~ sprintprocessor(ctxcatcodes,separator)
---~ end
---~ end
---~ preceding = false
---~ end
---~ if result then
---~ if ownnumber ~= "" then
---~ result[#result+1] = ownnumber
---~ elseif conversion and conversion ~= "" then -- traditional (e.g. used in itemgroups)
---~ result[#result+1] = converters.convert(conversion,number,true)
---~ else
---~ local theconversion = sets.get("structure:conversions",block,conversionset,index,"numbers")
---~ result[#result+1] = converters.convert(theconversion,number,true)
---~ end
---~ else
---~ if ownnumber ~= "" then
---~ sprintprocessor(ctxcatcodes,ownnumber)
---~ elseif conversion and conversion ~= "" then -- traditional (e.g. used in itemgroups)
---~ context.convertnumber(conversion,number)
---~ else
---~ local theconversion = sets.get("structure:conversions",block,conversionset,index,"numbers")
---~ sprintprocessor(ctxcatcodes,theconversion,function(str)
---~ return format("\\convertnumber{%s}{%s}",str or "numbers",number)
---~ end)
---~ end
---~ end
---~ preceding, done = index, true
---~ else
---~ preceding = preceding or false
---~ end
---~ end
diff --git a/tex/context/base/strc-lst.lua b/tex/context/base/strc-lst.lua
index 9709e7180..7b6448aca 100644
--- a/tex/context/base/strc-lst.lua
+++ b/tex/context/base/strc-lst.lua
@@ -55,7 +55,7 @@ local matchingtilldepth, numberatdepth = sections.matchingtilldepth, sections.nu
-- -- -- -- -- --
-function table.zerostrippedconcat(t,separator)
+local function zerostrippedconcat(t,separator) -- for the moment not public
local f, l = 1, #t
for i=f,l do
if t[i] == 0 then
@@ -198,7 +198,7 @@ local splitter = lpeg.splitat(":")
local function filtercollected(names, criterium, number, collected, forced, nested) -- names is hash or string
local numbers, depth = documents.data.numbers, documents.data.depth
- local result, detail = { }, nil
+ local result, nofresult, detail = { }, 0, nil
local block = false -- all
criterium = gsub(criterium or ""," ","") -- not needed
-- new, will be applied stepwise
@@ -230,7 +230,8 @@ local function filtercollected(names, criterium, number, collected, forced, nest
local v = collected[i]
local r = v.references
if r and r.section == 0 then
- result[#result+1] = v
+ nofresult = nofresult + 1
+ result[nofresult] = v
end
end
elseif all or criterium == variables.all or criterium == variables.text then
@@ -243,7 +244,8 @@ local function filtercollected(names, criterium, number, collected, forced, nest
local name = metadata.name or false
local sectionnumber = (r.section == 0) or sections.collected[r.section]
if forced[name] or (sectionnumber and not metadata.nolist and (all or names[name])) then -- and not sectionnumber.hidenumber then
- result[#result+1] = v
+ nofresult = nofresult + 1
+ result[nofresult] = v
end
end
end
@@ -271,7 +273,8 @@ local function filtercollected(names, criterium, number, collected, forced, nest
end
end
if ok then
- result[#result+1] = v
+ nofresult = nofresult + 1
+ result[nofresult] = v
end
end
end
@@ -304,7 +307,8 @@ local function filtercollected(names, criterium, number, collected, forced, nest
end
end
if ok then
- result[#result+1] = v
+ nofresult = nofresult + 1
+ result[nofresult] = v
end
end
end
@@ -335,7 +339,8 @@ local function filtercollected(names, criterium, number, collected, forced, nest
end
end
if ok then
- result[#result+1] = v
+ nofresult = nofresult + 1
+ result[nofresult] = v
end
end
end
@@ -372,7 +377,8 @@ local function filtercollected(names, criterium, number, collected, forced, nest
local cnumbers = sectionnumber.numbers
if cnumbers then
if (all or names[metadata.name or false]) and #cnumbers >= depth and matchingtilldepth(depth,cnumbers,parent) then
- result[#result+1] = v
+ nofresult = nofresult + 1
+ result[nofresult] = v
end
end
end
@@ -405,7 +411,7 @@ function lists.process(specification)
for i=1,#lists.result do
local r = lists.result[i]
local m = r.metadata
- local s = specials and r.numberdata and specials[table.zerostrippedconcat(r.numberdata.numbers,".")] or ""
+ local s = specials and r.numberdata and specials[zerostrippedconcat(r.numberdata.numbers,".")] or ""
context.processlistofstructure(m.name,m.kind,i,s)
end
end
@@ -441,17 +447,6 @@ function lists.location(n)
texsprint(l.references.internal or n)
end
---~ function lists.stamp(n)
---~ local l = lists.result[n]
---~ local numberdata = l.numberdata
---~ if numberdata then
---~ local numbers = numberdata.numbers
---~ if numbers then
---~ tex.sprint(table.zerostrippedconcat(numbers,"."))
---~ end
---~ end
---~ end
-
function lists.sectionnumber(name,n,spec)
local data = lists.result[n]
local sectiondata = sections.collected[data.references.section]
diff --git a/tex/context/base/strc-lst.mkiv b/tex/context/base/strc-lst.mkiv
index 4a88da083..f752051d7 100644
--- a/tex/context/base/strc-lst.mkiv
+++ b/tex/context/base/strc-lst.mkiv
@@ -264,7 +264,8 @@
\setuplistalternative[b][\c!distance=5em,\c!width=2em,\c!stretch=10em,\c!command=\hfill]
\setuplistalternative[c][\c!distance=5em,\c!width=0pt,\c!stretch=10em,\c!command=\hskip.5em\listdots\hskip.5em\relax]
-\def\listdots{\leaders\hbox to .5em{\hss.\hss}\hfill}
+%def\listdots{\leaders \hbox to .5em{\hss.\hss}\hfill}
+\def\listdots{\gleaders\hbox to .5em{\hss.\hss}\hfill}
% \setvalue{\??li\c!alternative}{\getvalue{\??li\c!alternative b}} % ?
% \getvalue{\??li\c!alternative} % ?
diff --git a/tex/context/base/strc-not.mkiv b/tex/context/base/strc-not.mkiv
index 97cf2c7d1..183ef65a1 100644
--- a/tex/context/base/strc-not.mkiv
+++ b/tex/context/base/strc-not.mkiv
@@ -183,7 +183,7 @@
\c!width=\defaultnotewidth,
\c!height=\textheight,
\c!numbercommand=\high,
- \c!command=\noteparameter\c!numbercommand, % downward compatible
+ \c!command=, % \noteparameter\c!numbercommand, % (command in enumeration) too messy, called twice
\c!separator=,% \@@koseparator,
\c!textcommand=\high,
\c!textstyle=\tx,
diff --git a/tex/context/base/strc-ref.lua b/tex/context/base/strc-ref.lua
index 459cbb9bb..3dddc6bc5 100644
--- a/tex/context/base/strc-ref.lua
+++ b/tex/context/base/strc-ref.lua
@@ -552,11 +552,12 @@ function exporters.lists.generic(data)
end
if numberdata then
local numbers = numberdata.numbers
- local t = { }
+ local t, tn = { }, 0
for i=1,#numbers do
local n = numbers[i]
if n ~= 0 then
- t[#t+1] = n
+ tn = tn + 1
+ t[tn] = n
end
end
useddata.number = concat(t,".")
@@ -1162,21 +1163,23 @@ function references.setinternalreference(prefix,tag,internal,view)
if innermethod == "page" then
return unsetvalue
else
- local t = { } -- maybe add to current
+ local t, tn = { }, 0 -- maybe add to current
if tag then
if prefix and prefix ~= "" then
prefix = prefix .. ":"
for ref in gmatch(tag,"[^,]+") do
- t[#t+1] = prefix .. ref
+ tn = tn + 1
+ t[tn] = prefix .. ref
end
else
for ref in gmatch(tag,"[^,]+") do
- t[#t+1] = ref
+ tn = tn + 1
+ t[tn] = ref
end
end
end
if internal and innermethod == "names" then -- mixed or page
- t[#t+1] = "aut:" .. internal
+ t[tn] = "aut:" .. internal
end
local destination = references.mark(t,nil,nil,view) -- returns an attribute
texcount.lastdestinationattribute = destination
diff --git a/tex/context/base/strc-reg.lua b/tex/context/base/strc-reg.lua
index abab0959a..7e392ba72 100644
--- a/tex/context/base/strc-reg.lua
+++ b/tex/context/base/strc-reg.lua
@@ -8,7 +8,8 @@ if not modules then modules = { } end modules ['strc-reg'] = {
local next, type = next, type
local texwrite, texcount = tex.write, tex.count
-local format, gmatch, concat, remove = string.format, string.gmatch, table.concat, table.remove
+local format, gmatch = string.format, string.gmatch
+local equal, concat, remove = table.are_equal, table.concat, table.remove
local utfchar = utf.char
local lpegmatch = lpeg.match
local allocate, mark = utilities.storage.allocate, utilities.storage.mark
@@ -44,7 +45,7 @@ local function filtercollected(names,criterium,number,collected,prevmode)
if not criterium or criterium == "" then criterium = variables.all end
local data = documents.data
local numbers, depth = data.numbers, data.depth
- local hash, result, all, detail = { }, { }, not names or names == "" or names == variables.all, nil
+ local hash, result, nofresult, all, detail = { }, { }, 0, not names or names == "" or names == variables.all, nil
if not all then
for s in gmatch(names,"[^, ]+") do
hash[s] = true
@@ -54,11 +55,13 @@ local function filtercollected(names,criterium,number,collected,prevmode)
for i=1,#collected do
local v = collected[i]
if all then
- result[#result+1] = v
+ nofresult = nofresult + 1
+ result[nofresult] = v
else
local vmn = v.metadata and v.metadata.name
if hash[vmn] then
- result[#result+1] = v
+ nofresult = nofresult + 1
+ result[nofresult] = v
end
end
end
@@ -78,7 +81,8 @@ local function filtercollected(names,criterium,number,collected,prevmode)
end
end
if ok then
- result[#result+1] = v
+ nofresult = nofresult + 1
+ result[nofresult] = v
end
end
else
@@ -92,7 +96,8 @@ local function filtercollected(names,criterium,number,collected,prevmode)
end
end
if ok then
- result[#result+1] = v
+ nofresult = nofresult + 1
+ result[nofresult] = v
end
end
end
@@ -123,7 +128,8 @@ local function filtercollected(names,criterium,number,collected,prevmode)
end
end
if ok then
- result[#result+1] = v
+ nofresult = nofresult + 1
+ result[nofresult] = v
end
end
end
@@ -152,7 +158,8 @@ local function filtercollected(names,criterium,number,collected,prevmode)
local cnumbers = sectionnumber.numbers
if cnumbers then
if (all or hash[metadata.name or false]) and #cnumbers >= depth and matchingtilldepth(depth,cnumbers) then
- result[#result+1] = v
+ nofresult = nofresult + 1
+ result[nofresult] = v
end
end
end
@@ -394,13 +401,15 @@ local function crosslinkseewords(result) -- all words
local seeparent = seeparents[text]
if seeparent then
local seeindex = seewords[text]
- local s, d, w, l = { }, data.split, seeparent.split, data.list
+ local s, ns, d, w, l = { }, 0, data.split, seeparent.split, data.list
-- trick: we influence sorting by adding fake subentries
for i=1,#d do
- s[#s+1] = d[i] -- parent
+ ns = ns + 1
+ s[ns] = d[i] -- parent
end
for i=1,#w do
- s[#s+1] = w[i] -- see
+ ns = ns + 1
+ s[ns] = w[i] -- see
end
data.split = s
-- we also register a fake extra list entry so that the
@@ -416,7 +425,6 @@ local function crosslinkseewords(result) -- all words
end
end
-
local function removeemptyentries(result)
local i, n, m = 1, #result, 0
while i <= n do
@@ -465,53 +473,61 @@ function registers.sort(data,options)
end
function registers.unique(data,options)
- local result, prev, equal = { }, nil, table.are_equal
+ local result, nofresult, prev = { }, 0, nil
local dataresult = data.result
for k=1,#dataresult do
local v = dataresult[k]
- if not prev then
- result[#result+1], prev = v, v
- else
+ if prev then
local pr, vr = prev.references, v.references
if not equal(prev.list,v.list) then
- result[#result+1], prev = v, v
+ -- ok
elseif pr.realpage ~= vr.realpage then
- result[#result+1], prev = v, v
+ -- ok
else
local pl, vl = pr.lastrealpage, vr.lastrealpage
if pl or vl then
if not vl then
- result[#result+1], prev = v, v
+ -- ok
elseif not pl then
- result[#result+1], prev = v, v
+ -- ok
elseif pl ~= vl then
- result[#result+1], prev = v, v
+ -- ok
+ else
+ v = nil
end
+ else
+ v = nil
end
end
end
+ if v then
+ nofresult = nofresult + 1
+ result[nofresult] = v
+ prev = v
+ end
end
data.result = result
end
-function registers.finalize(data,options)
+function registers.finalize(data,options) -- maps character to index (order)
local result = data.result
data.metadata.nofsorted = #result
- local split, lasttag, s, d = { }, nil, nil, nil
- -- maps character to index (order)
+ local split, nofsplit, lasttag, done, nofdone = { }, 0, nil, nil, 0
+ local firstofsplit = sorters.firstofsplit
for k=1,#result do
local v = result[k]
- local entry, tag = sorters.firstofsplit(v)
+ local entry, tag = firstofsplit(v)
if tag ~= lasttag then
if trace_registers then
report_registers("splitting at %s",tag)
end
- d = { }
- s = { tag = tag, data = d }
- split[#split+1] = s
+ done, nofdone = { }, 0
+ nofsplit = nofsplit + 1
+ split[nofsplit] = { tag = tag, data = done }
lasttag = tag
end
- d[#d+1] = v
+ nofdone = nofdone + 1
+ done[nofdone] = v
end
data.result = split
end
@@ -576,19 +592,6 @@ local function pagenumber(entry,prefixspec,pagespec)
)
end
--- local usedtags = { }
--- for i=1,#result do
--- usedtags[#usedtags+1] = result[i].tag
--- end
--- context.setvalue("usedregistertags",concat(usedtags,",")) -- todo: { } and escape special chars
-
---~ local function remove(pages,i) -- todo: use table.remove(pages,i)
---~ for j=i,#pages-1 do
---~ pages[j] = pages[j+1]
---~ end
---~ pages[#pages] = nil
---~ end
-
local function collapsedpage(pages)
for i=2,#pages do
local first, second = pages[i-1], pages[i]
@@ -649,10 +652,10 @@ end
function collapsepages(pages)
while collapsedpage(pages) do end
+ return #pages
end
function registers.flush(data,options,prefixspec,pagespec)
- local equal = table.are_equal
local collapse_singles = options.compress == variables.yes
local collapse_ranges = options.compress == variables.all
local result = data.result
@@ -716,7 +719,7 @@ function registers.flush(data,options,prefixspec,pagespec)
if collapse_singles or collapse_ranges then
-- we collapse ranges and keep existing ranges as they are
-- so we get prebuilt as well as built ranges
- local first, last, prev, pages, dd = entry, nil, entry, { }, d
+ local first, last, prev, pages, dd, nofpages = entry, nil, entry, { }, d, 0
while dd < #data do
dd = dd + 1
local next = data[dd]
@@ -730,28 +733,32 @@ function registers.flush(data,options,prefixspec,pagespec)
--~ first = nil
break
elseif next.references.lastrealpage then
- pages[#pages+1] = first and { first, last or first } or { entry, entry }
- pages[#pages+1] = { next, next }
+ nofpages = nofpages + 1
+ pages[nofpages] = first and { first, last or first } or { entry, entry }
+ nofpages = nofpages + 1
+ pages[nofpages] = { next, next }
first, last, prev = nil, nil, nil
elseif not first then
first, prev = next, next
elseif next.references.realpage - prev.references.realpage == 1 then -- 1 ?
last, prev = next, next
else
- pages[#pages+1] = { first, last or first }
+ nofpages = nofpages + 1
+ pages[nofpages] = { first, last or first }
first, last, prev = next, nil, next
end
end
end
if first then
- pages[#pages+1] = { first, last or first }
+ nofpages = nofpages + 1
+ pages[nofpages] = { first, last or first }
end
- if collapse_ranges and #pages > 1 then
- collapsepages(pages)
+ if collapse_ranges and nofpages > 1 then
+ nofpages = collapsepages(pages)
end
- if #pages > 0 then -- or 0
+ if nofpages > 0 then -- or 0
d = dd
- for p=1,#pages do
+ for p=1,nofpages do
local first, last = pages[p][1], pages[p][2]
if first == last then
if first.references.lastrealpage then
@@ -793,9 +800,10 @@ function registers.flush(data,options,prefixspec,pagespec)
end
context.stopregisterpages()
elseif kind == 'see' then
- local t = { }
+ local t, nt = { }, 0
while true do
- t[#t+1] = entry
+ nt = nt + 1
+ t[nt] = entry
if d == #data then
break
else
@@ -810,8 +818,7 @@ function registers.flush(data,options,prefixspec,pagespec)
end
end
context.startregisterseewords()
- local n = #t
- for i=1,n do
+ for i=1,nt do
local entry = t[i]
local processor = entry.processors and entry.processors[1] or ""
local seeindex = entry.references.seeindex or ""
diff --git a/tex/context/base/supp-fil.lua b/tex/context/base/supp-fil.lua
index 62252bf06..b95d72d7f 100644
--- a/tex/context/base/supp-fil.lua
+++ b/tex/context/base/supp-fil.lua
@@ -264,18 +264,20 @@ end
statistics.register("loaded tex modules", function()
if next(modstatus) then
- local t, f = { }, { }
+ local t, f, nt, nf = { }, { }, 0, 0
for k, v in table.sortedhash(modstatus) do
k = file.basename(k)
if v == 0 then
- f[#f+1] = k
+ nf = nf + 1
+ f[nf] = k
else
- t[#t+1] = k
+ nt = nt + 1
+ t[nt] = k
end
end
- local ts = (#t>0 and format(" (%s)",concat(t," "))) or ""
- local fs = (#f>0 and format(" (%s)",concat(f," "))) or ""
- return format("%s requested, %s found%s, %s missing%s",#t+#f,#t,ts,#f,fs)
+ local ts = (nt>0 and format(" (%s)",concat(t," "))) or ""
+ local fs = (nf>0 and format(" (%s)",concat(f," "))) or ""
+ return format("%s requested, %s found%s, %s missing%s",nt+nf,nt,ts,nf,fs)
else
return nil
end
diff --git a/tex/context/base/supp-fil.mkiv b/tex/context/base/supp-fil.mkiv
index 55b8528ae..aa2891689 100644
--- a/tex/context/base/supp-fil.mkiv
+++ b/tex/context/base/supp-fil.mkiv
@@ -39,11 +39,8 @@
\def\f!parentpath {..}
\fi
-% \def\openinputfile #1#2{\immediate\openin #1="#2"\relax} \def\closeinputfile #1{\immediate\closein #1}
-% \def\openoutputfile#1#2{\immediate\openout#1="#2"\relax} \def\closeoutputfile#1{\immediate\closeout#1}
-
-\def\openinputfile #1#2{\immediate\openin #1=#2\relax} \def\closeinputfile #1{\immediate\closein #1}
-\def\openoutputfile#1#2{\immediate\openout#1=#2\relax} \def\closeoutputfile#1{\immediate\closeout#1}
+\def\openinputfile #1#2{\immediate\openin #1={#2}} \def\closeinputfile #1{\immediate\closein #1}
+\def\openoutputfile#1#2{\immediate\openout#1={#2}} \def\closeoutputfile#1{\immediate\closeout#1}
%D \macros
%D {pushendofline,popendofline}
@@ -191,7 +188,7 @@
\unexpanded\def\input{\normalinput}
-\def\inputgivenfile#1{\normalinput"#1"\relax}
+\def\inputgivenfile#1{\normalinput{#1}}
%D \macros
%D {readfile,ReadFile}
diff --git a/tex/context/base/toks-ini.lua b/tex/context/base/toks-ini.lua
index 7a4c221a4..f8b5b9439 100644
--- a/tex/context/base/toks-ini.lua
+++ b/tex/context/base/toks-ini.lua
@@ -57,9 +57,10 @@ tokens.letter = function(chr) return createtoken(utfbyte(chr), 11) end
tokens.other = function(chr) return createtoken(utfbyte(chr), 12) end
tokens.letters = function(str)
- local t = { }
+ local t, n = { }, 0
for chr in string.utfvalues(str) do
- t[#t+1] = createtoken(chr, 11)
+ n = n + 1
+ t[n] = createtoken(chr, 11)
end
return t
end
@@ -99,7 +100,7 @@ local letter = command_id("letter")
local other = command_id("other_char")
function collectors.install(tag,end_cs)
- local data = { }
+ local data, d = { }, 0
collectordata[tag] = data
local endcs = csname_id(end_cs)
while true do
@@ -111,7 +112,8 @@ function collectors.install(tag,end_cs)
elseif a == call and registered[b] then
expand()
else
- data[#data+1] = t
+ d = d + 1
+ data[d] = t
end
end
end
@@ -135,31 +137,38 @@ function collectors.show(tag, method)
end
function collectors.defaultwords(t,str)
- t[#t+1] = tokens.bgroup
- t[#t+1] = createtoken("red")
+ local n = #t
+ n = n + 1
+ t[n] = tokens.bgroup
+ n = n + 1
+ t[n] = createtoken("red")
for i=1,#str do
- t[#t+1] = tokens.other('*')
+ n = n + 1
+ t[n] = tokens.other('*')
end
- t[#t+1] = tokens.egroup
+ n = n + 1
+ t[n] = tokens.egroup
end
function collectors.dowithwords(tag,handle)
- local t, w = { }, { }
+ local t, w, tn, wn = { }, { }, 0, 0
handle = handle or collectors.defaultwords
local tagdata = collectordata[tag]
for k=1,#tagdata do
local v = tagdata[k]
if v[1] == letter then
- w[#w+1] = v[2]
+ wn = wn + 1
+ w[wn] = v[2]
else
- if #w > 0 then
+ if wn > 0 then
handle(t,w)
- w = { }
+ wn = 0
end
- t[#t+1] = v
+ tn = tn + 1
+ t[tn] = v
end
end
- if #w > 0 then
+ if wn > 0 then
handle(t,w)
end
collectordata[tag] = t
@@ -297,35 +306,35 @@ function remapper.convert(tag,toks)
local skipping = 0
-- todo: math
if data then
- local t = { }
+ local t, n = { }, 0
for s=1,#toks do
local tok = toks[s]
local one, two = tok[1], tok[2]
if one == 11 or one == 12 then
if two == leftbracket then
skipping = skipping + 1
- t[#t+1] = tok
+ n = n + 1 ; t[n] = tok
elseif two == rightbracket then
skipping = skipping - 1
- t[#t+1] = tok
+ n = n + 1 ; t[n] = tok
elseif skipping == 0 then
local new = data[two]
if new then
if #new > 1 then
for n=1,#new do
- t[#t+1] = new[n]
+ n = n + 1 ; t[n] = new[n]
end
else
- t[#t+1] = new[1]
+ n = n + 1 ; t[n] = new[1]
end
else
- t[#t+1] = tok
+ n = n + 1 ; t[n] = tok
end
else
- t[#t+1] = tok
+ n = n + 1 ; t[n] = tok
end
else
- t[#t+1] = tok
+ n = n + 1 ; t[n] = tok
end
end
return t
diff --git a/tex/context/base/trac-inf.lua b/tex/context/base/trac-inf.lua
index 7bd7a7ca4..aa224cf38 100644
--- a/tex/context/base/trac-inf.lua
+++ b/tex/context/base/trac-inf.lua
@@ -13,6 +13,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
local format = string.format
local clock = os.gettimeofday or os.clock -- should go in environment
+local write_nl = texio.write_nl
statistics = statistics or { }
local statistics = statistics
@@ -108,7 +109,7 @@ end
function statistics.show(reporter)
if statistics.enable then
- if not reporter then reporter = function(tag,data,n) texio.write_nl(tag .. " " .. data) end end
+ if not reporter then reporter = function(tag,data,n) write_nl(tag .. " " .. data) end end
-- this code will move
local register = statistics.register
register("luatex banner", function()
@@ -131,18 +132,24 @@ function statistics.show(reporter)
reporter(s[1],r,n)
end
end
- texio.write_nl("") -- final newline
+ write_nl("") -- final newline
statistics.enable = false
end
end
+
+local template, nn = nil, 0 -- we only calcute it once
+
function statistics.showjobstat(tag,data,n)
if type(data) == "table" then
for i=1,#data do
statistics.showjobstat(tag,data[i],n)
end
else
- texio.write_nl(format("%-15s: %s - %s","mkiv lua stats",tag:rpadd(n," "),data))
+ if not template or n > nn then
+ template, n = format("%%-%ss: %%-%ss - %%s",15,n), nn
+ end
+ write_nl(format(template,"mkiv lua stats",tag,data))
end
end
diff --git a/tex/context/base/trac-set.lua b/tex/context/base/trac-set.lua
index 9ae215817..f4e152b14 100644
--- a/tex/context/base/trac-set.lua
+++ b/tex/context/base/trac-set.lua
@@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['trac-set'] = { -- might become u
local type, next, tostring = type, next, tostring
local concat = table.concat
-local format, find, lower, gsub, partialescapedpattern = string.format, string.find, string.lower, string.gsub, string.partialescapedpattern
+local format, find, lower, gsub, escapedpattern = string.format, string.find, string.lower, string.gsub, string.escapedpattern
local is_boolean = string.is_boolean
local settings_to_hash = utilities.parsers.settings_to_hash
local allocate = utilities.storage.allocate
@@ -88,7 +88,7 @@ local function set(t,what,newvalue)
for name, functions in next, data do
if done[name] then
-- prevent recursion due to wildcards
- elseif find(name,partialescapedpattern(w)) then
+ elseif find(name,escapedpattern(w,true)) then
done[name] = true
for i=1,#functions do
functions[i](value)
diff --git a/tex/context/base/typo-krn.lua b/tex/context/base/typo-krn.lua
index 83f2e9102..91849db85 100644
--- a/tex/context/base/typo-krn.lua
+++ b/tex/context/base/typo-krn.lua
@@ -230,7 +230,7 @@ function kerns.set(factor)
tasks.enableaction("processors","typesetters.kerns.handler")
enabled = true
end
- if factor > 0 then
+ if factor ~= 0 then
local a = factors[factor]
if not a then
a = #mapping + 1
diff --git a/tex/context/base/typo-spa.lua b/tex/context/base/typo-spa.lua
index c375b9fb5..e351cc9f7 100644
--- a/tex/context/base/typo-spa.lua
+++ b/tex/context/base/typo-spa.lua
@@ -65,7 +65,9 @@ local function process(namespace,attribute,head)
map = map[start.char]
unset_attribute(start,attribute) -- needed?
if map then
- local left, right, alternative = map.left, map.right, map.alternative
+ local left = map.left
+ local right = map.right
+ local alternative = map.alternative
local quad = quaddata[start.font]
local prev = start.prev
if left and left ~= 0 and prev then
diff --git a/tex/context/base/util-fmt.lua b/tex/context/base/util-fmt.lua
index e94782c32..e049d0b94 100644
--- a/tex/context/base/util-fmt.lua
+++ b/tex/context/base/util-fmt.lua
@@ -35,9 +35,9 @@ local stripper = Cs((number + 1)^0)
--~ lpegmatch(stripper,str)
--~ print(#str, os.clock()-ts, lpegmatch(stripper,sample))
-lpeg.patterns.strip_zeros = stripper
+lpeg.patterns.stripzeros = stripper
-function formatters.strip_zeros(str)
+function formatters.stripzeros(str)
return lpegmatch(stripper,str)
end
diff --git a/tex/context/base/util-lua.lua b/tex/context/base/util-lua.lua
index 3aecbfa26..6ad325fcf 100644
--- a/tex/context/base/util-lua.lua
+++ b/tex/context/base/util-lua.lua
@@ -13,7 +13,7 @@ utilities.report = utilities.report or print
function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
- local command = "-o " .. string.quote(lucfile) .. " " .. string.quote(luafile)
+ local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
@@ -24,3 +24,25 @@ function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: clean
end
return done
end
+
+--~ local getmetatable, type = getmetatable, type
+
+--~ local types = { }
+
+--~ function utilities.lua.registerdatatype(d,name)
+--~ types[getmetatable(d)] = name
+--~ end
+
+--~ function utilities.lua.datatype(d)
+--~ local t = type(d)
+--~ if t == "userdata" then
+--~ local m = getmetatable(d)
+--~ return m and types[m] or "userdata"
+--~ else
+--~ return t
+--~ end
+--~ end
+
+--~ utilities.lua.registerdatatype(lpeg.P("!"),"lpeg")
+
+--~ print(utilities.lua.datatype(lpeg.P("oeps")))
diff --git a/tex/context/base/util-pck.lua b/tex/context/base/util-pck.lua
index cd1fc510e..c802a09ed 100644
--- a/tex/context/base/util-pck.lua
+++ b/tex/context/base/util-pck.lua
@@ -17,12 +17,13 @@ local packers = utilities.packers
packers.version = 1.00
local function hashed(t)
- local s = { }
+ local s, ns = { }, 0
for k, v in next, t do
+ ns = ns + 1
if type(v) == "table" then
- s[#s+1] = k .. "={" .. hashed(v) .. "}"
+ s[ns] = k .. "={" .. hashed(v) .. "}"
else
- s[#s+1] = k .. "=" .. tostring(v)
+ s[ns] = k .. "=" .. tostring(v)
end
end
sort(s)
@@ -30,9 +31,10 @@ local function hashed(t)
end
local function simplehashed(t)
- local s = { }
+ local s, ns = { }, 0
for k, v in next, t do
- s[#s+1] = k.. "=" .. v
+ ns = ns + 1
+ s[ns] = k .. "=" .. v
end
sort(s)
return concat(s,",")
diff --git a/tex/context/base/util-prs.lua b/tex/context/base/util-prs.lua
index e1a2ebbed..08fe2f686 100644
--- a/tex/context/base/util-prs.lua
+++ b/tex/context/base/util-prs.lua
@@ -14,7 +14,7 @@ parsers.patterns = parsers.patterns or { }
local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
local lpegmatch = lpeg.match
local concat, format, gmatch = table.concat, string.format, string.gmatch
-local tostring, type, next = tostring, type, next
+local tostring, type, next, setmetatable = tostring, type, next, setmetatable
local sortedhash = table.sortedhash
local escape, left, right = P("\\"), P('{'), P('}')
@@ -133,7 +133,7 @@ end
function parsers.hash_to_string(h,separator,yes,no,strict,omit)
if h then
- local t, s = { }, table.sortedkeys(h)
+ local t, tn, s = { }, 0, table.sortedkeys(h)
omit = omit and table.tohash(omit)
for i=1,#s do
local key = s[i]
@@ -142,15 +142,19 @@ function parsers.hash_to_string(h,separator,yes,no,strict,omit)
if type(value) == "boolean" then
if yes and no then
if value then
- t[#t+1] = key .. '=' .. yes
+ tn = tn + 1
+ t[tn] = key .. '=' .. yes
elseif not strict then
- t[#t+1] = key .. '=' .. no
+ tn = tn + 1
+ t[tn] = key .. '=' .. no
end
elseif value or not strict then
- t[#t+1] = key .. '=' .. tostring(value)
+ tn = tn + 1
+ t[tn] = key .. '=' .. tostring(value)
end
else
- t[#t+1] = key .. '=' .. value
+ tn = tn + 1
+ t[tn] = key .. '=' .. value
end
end
end
@@ -177,10 +181,11 @@ function parsers.settings_to_set(str,t) -- tohash? -- todo: lpeg -- duplicate an
end
function parsers.simple_hash_to_string(h, separator)
- local t = { }
+ local t, tn = { }, 0
for k, v in sortedhash(h) do
if v then
- t[#t+1] = k
+ tn = tn + 1
+ t[tn] = k
end
end
return concat(t,separator or ",")
@@ -198,8 +203,16 @@ end
function parsers.getparameters(self,class,parentclass,settings)
local sc = self[class]
if not sc then
- sc = table.clone(self[parent])
+ sc = { }
self[class] = sc
+ if parentclass then
+ local sp = self[parentclass]
+ if not sp then
+ sp = { }
+ self[parentclass] = sp
+ end
+ setmetatable(sc, { __index = sp })
+ end
end
parsers.settings_to_hash(settings,sc)
end
diff --git a/tex/context/base/util-seq.lua b/tex/context/base/util-seq.lua
index 415918a44..14c425dfc 100644
--- a/tex/context/base/util-seq.lua
+++ b/tex/context/base/util-seq.lua
@@ -19,8 +19,12 @@ local format, gsub, concat, gmatch = string.format, string.gsub, table.concat, s
local type, loadstring = type, loadstring
utilities = utilities or { }
-utilities.sequencers = utilities.sequencers or { }
-local sequencers = utilities.sequencers
+local tables = utilities.tables
+
+local sequencers = { }
+utilities.sequencers = sequencers
+
+local removevalue, insertaftervalue, insertbeforevalue = tables.removevalue, tables.insertaftervalue, tables.insertbeforevalue
local function validaction(action)
local g = _G
@@ -45,23 +49,23 @@ end
function sequencers.prependgroup(t,group,where)
local list, order = t.list, t.order
- table.removevalue(order,group)
- table.insertbeforevalue(order,where,group)
+ removevalue(order,group)
+ insertbeforevalue(order,where,group)
list[group] = { }
end
function sequencers.appendgroup(t,group,where)
local list, order = t.list, t.order
- table.removevalue(order,group)
- table.insertaftervalue(order,where,group)
+ removevalue(order,group)
+ insertaftervalue(order,where,group)
list[group] = { }
end
function sequencers.prependaction(t,group,action,where,kind,force)
local g = t.list[group]
if g and (force or validaction(action)) then
- table.removevalue(g,action)
- table.insertbeforevalue(g,where,action)
+ removevalue(g,action)
+ insertbeforevalue(g,where,action)
t.kind[action] = kind
end
end
@@ -69,8 +73,8 @@ end
function sequencers.appendaction(t,group,action,where,kind,force)
local g = t.list[group]
if g and (force or validaction(action)) then
- table.removevalue(g,action)
- table.insertaftervalue(g,where,action)
+ removevalue(g,action)
+ insertaftervalue(g,where,action)
t.kind[action] = kind
end
end
@@ -87,7 +91,7 @@ end
function sequencers.removeaction(t,group,action,force)
local g = t.list[group]
if g and (force or validaction(action)) then
- table.removevalue(g,action)
+ removevalue(g,action)
end
end
@@ -114,7 +118,7 @@ end]]
function sequencers.tostring(t)
local list, order, kind, gskip, askip = t.list, t.order, t.kind, t.gskip, t.askip
- local vars, calls, args = { }, { }, nil
+ local vars, calls, args, n = { }, { }, nil, 0
for i=1,#order do
local group = order[i]
if not gskip[group] then
@@ -123,8 +127,9 @@ function sequencers.tostring(t)
local action = actions[i]
if not askip[action] then
local localized = localize(action)
- vars [#vars +1] = format("local %s = %s", localized, action)
- calls[#calls+1] = format(" %s(...) -- %s %i", localized, group, i)
+ n = n + 1
+ vars [n] = format("local %s = %s", localized, action)
+ calls[n] = format(" %s(...) -- %s %i", localized, group, i)
end
end
end
@@ -148,7 +153,7 @@ end]]
function sequencers.nodeprocessor(t,n)
local list, order, kind, gskip, askip = t.list, t.order, t.kind, t.gskip, t.askip
- local vars, calls, args = { }, { }, nil
+ local vars, calls, args, n = { }, { }, nil, 0
if n == 0 then
args = ""
elseif n == 1 then
@@ -172,11 +177,12 @@ function sequencers.nodeprocessor(t,n)
local action = actions[i]
if not askip[action] then
local localized = localize(action)
- vars[#vars+1] = format("local %s = %s",localized,action)
+ n = n + 1
+ vars[n] = format("local %s = %s",localized,action)
if kind[action] == "nohead" then
- calls[#calls+1] = format(" ok = %s(head%s) done = done or ok -- %s %i",localized,args,group,i)
+ calls[n] = format(" ok = %s(head%s) done = done or ok -- %s %i",localized,args,group,i)
else
- calls[#calls+1] = format(" head, ok = %s(head%s) done = done or ok -- %s %i",localized,args,group,i)
+ calls[n] = format(" head, ok = %s(head%s) done = done or ok -- %s %i",localized,args,group,i)
end
end
end
diff --git a/tex/context/base/util-sto.lua b/tex/context/base/util-sto.lua
index 34787be9b..19b8093c9 100644
--- a/tex/context/base/util-sto.lua
+++ b/tex/context/base/util-sto.lua
@@ -98,3 +98,14 @@ function storage.setinitializer(data,initialize)
end
setmetatable(data, m)
end
+
+local keyisvalue = { __index = function(t,k)
+ t[k] = k
+ return k
+end }
+
+function storage.sparse(t)
+ t = t or { }
+ setmetatable(t,keyisvalue)
+ return t
+end
diff --git a/tex/context/base/util-tab.lua b/tex/context/base/util-tab.lua
index 6c0ae8970..ea440e736 100644
--- a/tex/context/base/util-tab.lua
+++ b/tex/context/base/util-tab.lua
@@ -15,14 +15,15 @@ local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable = setmetatable
function tables.definetable(target) -- defines undefined tables
- local composed, t = nil, { }
+ local composed, t, n = nil, { }, 0
for name in gmatch(target,"([^%.]+)") do
+ n = n + 1
if composed then
composed = composed .. "." .. name
else
composed = name
end
- t[#t+1] = format("%s = %s or { }",composed,composed)
+ t[n] = format("%s = %s or { }",composed,composed)
end
return concat(t,"\n")
end
@@ -35,7 +36,7 @@ function tables.accesstable(target)
return t
end
-function table.removevalue(t,value) -- todo: n
+function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
if t[i] == value then
@@ -46,7 +47,7 @@ function table.removevalue(t,value) -- todo: n
end
end
-function table.insertbeforevalue(t,value,extra)
+function tables.insertbeforevalue(t,value,extra)
for i=1,#t do
if t[i] == extra then
remove(t,i)
@@ -61,7 +62,7 @@ function table.insertbeforevalue(t,value,extra)
insert(t,1,extra)
end
-function table.insertaftervalue(t,value,extra)
+function tables.insertaftervalue(t,value,extra)
for i=1,#t do
if t[i] == extra then
remove(t,i)
diff --git a/tex/context/base/x-mathml.lua b/tex/context/base/x-mathml.lua
index 9ea128ef3..209f575e1 100644
--- a/tex/context/base/x-mathml.lua
+++ b/tex/context/base/x-mathml.lua
@@ -450,17 +450,6 @@ function lxml.mml.stripped(str)
tex.sprint(ctxcatcodes,str:strip())
end
-function table.keys_as_string(t)
- local k = { }
- for k,_ in next, t do
- k[#k+1] = k
- end
- return concat(k,"")
-end
-
---~ local leftdelimiters = "[" .. table.keys_as_string(l_replacements) .. "]"
---~ local rightdelimiters = "[" .. table.keys_as_string(r_replacements) .. "]"
-
function characters.remapentity(chr,slot)
texsprint(format("{\\catcode%s=13\\xdef%s{\\string%s}}",slot,utfchar(slot),chr))
end
diff --git a/tex/generic/context/luatex-fonts-merged.lua b/tex/generic/context/luatex-fonts-merged.lua
index fdf07d31c..0cdeaeba6 100644
--- a/tex/generic/context/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
-- merged file : luatex-fonts-merged.lua
-- parent file : luatex-fonts.lua
--- merge date : 10/22/10 16:46:39
+-- merge date : 10/29/10 11:35:59
do -- begin closure to overcome local limits and interference
@@ -14,7 +14,7 @@ if not modules then modules = { } end modules ['l-string'] = {
local string = string
local sub, gsub, find, match, gmatch, format, char, byte, rep, lower = string.sub, string.gsub, string.find, string.match, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
-local lpegmatch = lpeg.match
+local lpegmatch, S, C, Ct = lpeg.match, lpeg.S, lpeg.C, lpeg.Ct
-- some functions may disappear as they are not used anywhere
@@ -22,157 +22,75 @@ if not string.split then
-- this will be overloaded by a faster lpeg variant
- function string:split(pattern)
- if #self > 0 then
- local t = { }
- for s in gmatch(self..pattern,"(.-)"..pattern) do
- t[#t+1] = s
+ function string.split(str,pattern)
+ local t = { }
+ if #str > 0 then
+ local n = 1
+ for s in gmatch(str..pattern,"(.-)"..pattern) do
+ t[n] = s
+ n = n + 1
end
- return t
- else
- return { }
end
+ return t
end
end
-string.patterns = { }
-
-local escapes = {
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["^"] = "%^", ["$"] = "%$",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%(", [")"] = "%)",
- ["{"] = "%{", ["}"] = "%}"
-}
-
-string.patterns.escapes = escapes
-
-function string:esc() -- variant 2
- return (gsub(self,"(.)",escapes))
-end
-
-function string:unquote()
- return (gsub(self,"^([\"\'])(.*)%1$","%2"))
+function string.unquoted(str)
+ return (gsub(str,"^([\"\'])(.*)%1$","%2"))
end
---~ function string:unquote()
---~ if find(self,"^[\'\"]") then
---~ return sub(self,2,-2)
+--~ function stringunquoted(str)
+--~ if find(str,"^[\'\"]") then
+--~ return sub(str,2,-2)
--~ else
---~ return self
+--~ return str
--~ end
--~ end
-function string:quote() -- we could use format("%q")
- return format("%q",self)
+function string.quoted(str)
+ return format("%q",str) -- always "
end
-function string:count(pattern) -- variant 3
+function string.count(str,pattern) -- variant 3
local n = 0
- for _ in gmatch(self,pattern) do
+ for _ in gmatch(str,pattern) do -- not for utf
n = n + 1
end
return n
end
-function string:limit(n,sentinel)
- if #self > n then
+function string.limit(str,n,sentinel)
+ if #str > n then
sentinel = sentinel or " ..."
- return sub(self,1,(n-#sentinel)) .. sentinel
+ return sub(str,1,(n-#sentinel)) .. sentinel
else
- return self
- end
-end
-
---~ function string:strip() -- the .- is quite efficient
---~ -- return match(self,"^%s*(.-)%s*$") or ""
---~ -- return match(self,'^%s*(.*%S)') or '' -- posted on lua list
---~ return find(s,'^%s*$') and '' or match(s,'^%s*(.*%S)')
---~ end
-
-do -- roberto's variant:
- local space = lpeg.S(" \t\v\n")
- local nospace = 1 - space
- local stripper = space^0 * lpeg.C((space^0 * nospace^1)^0)
- function string.strip(str)
- return lpegmatch(stripper,str) or ""
- end
-end
-
-function string:is_empty()
- return not find(self,"%S")
-end
-
-function string:enhance(pattern,action)
- local ok, n = true, 0
- while ok do
- ok = false
- self = gsub(self,pattern, function(...)
- ok, n = true, n + 1
- return action(...)
- end)
+ return str
end
- return self, n
end
-if not string.characters then
-
- local function nextchar(str, index)
- index = index + 1
- return (index <= #str) and index or nil, sub(str,index,index)
- end
- function string:characters()
- return nextchar, self, 0
- end
- local function nextbyte(str, index)
- index = index + 1
- return (index <= #str) and index or nil, byte(sub(str,index,index))
- end
- function string:bytes()
- return nextbyte, self, 0
- end
-
-end
+local space = S(" \t\v\n")
+local nospace = 1 - space
+local stripper = space^0 * C((space^0 * nospace^1)^0) -- roberto's code
-function string:rpadd(n,chr)
- local m = n-#self
- if m > 0 then
- return self .. rep(chr or " ",m)
- else
- return self
- end
+function string.strip(str)
+ return lpegmatch(stripper,str) or ""
end
-function string:lpadd(n,chr)
- local m = n-#self
- if m > 0 then
- return rep(chr or " ",m) .. self
- else
- return self
- end
+function string.is_empty(str)
+ return not find(str,"%S")
end
-string.padd = string.rpadd
-
local patterns_escapes = {
- ["-"] = "%-",
- ["."] = "%.",
- ["+"] = "%+",
- ["*"] = "%*",
["%"] = "%%",
- ["("] = "%)",
- [")"] = "%)",
- ["["] = "%[",
- ["]"] = "%]",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
}
-function string:escapedpattern()
- return (gsub(self,".",patterns_escapes))
-end
-
local simple_escapes = {
["-"] = "%-",
["."] = "%.",
@@ -180,22 +98,28 @@ local simple_escapes = {
["*"] = ".*",
}
-function string:partialescapedpattern()
- return (gsub(self,".",simple_escapes))
-end
-
-function string:tohash()
- local t = { }
- for s in gmatch(self,"([^, ]+)") do -- lpeg
- t[s] = true
+function string.escapedpattern(str,simple)
+ if simple then
+ return (gsub(str,".",simple_escapes))
+ else
+ return (gsub(str,".",patterns_escapes))
end
- return t
end
-local pattern = lpeg.Ct(lpeg.C(1)^0)
-
-function string:totable()
- return lpegmatch(pattern,self)
+function string.topattern(str,lowercase,strict)
+ if str == "" then
+ return ".*"
+ else
+ str = gsub(str,".",simple_escapes)
+ if lowercase then
+ str = lower(str)
+ end
+ if strict then
+ return "^" .. str .. "$"
+ else
+ return str
+ end
+ end
end
--~ local t = {
@@ -211,6 +135,8 @@ end
--~ print(string.tabtospace(t[k]))
--~ end
+-- The following functions might end up in another namespace.
+
function string.tabtospace(str,tab)
-- we don't handle embedded newlines
while true do
@@ -230,30 +156,22 @@ function string.tabtospace(str,tab)
return str
end
-function string:compactlong() -- strips newlines and leading spaces
- self = gsub(self,"[\n\r]+ *","")
- self = gsub(self,"^ *","")
- return self
-end
+--~ local template = string.striplong([[
+--~ aaaa
+--~ bb
+--~ cccccc
+--~ ]])
-function string:striplong() -- strips newlines and leading spaces
- self = gsub(self,"^%s*","")
- self = gsub(self,"[\n\r]+ *","\n")
- return self
+function string.striplong(str) -- strips all leading spaces
+ str = gsub(str,"^%s*","")
+ str = gsub(str,"[\n\r]+ *","\n")
+ return str
end
-function string:topattern(lowercase,strict)
- if lowercase then
- self = lower(self)
- end
- self = gsub(self,".",simple_escapes)
- if self == "" then
- self = ".*"
- elseif strict then
- self = "^" .. self .. "$"
- end
- return self
-end
+-- obsolete names:
+
+string.quote = string.quoted
+string.unquote = string.unquoted
end -- closure
@@ -275,15 +193,29 @@ local patterns = lpeg.patterns
local P, R, S, Ct, C, Cs, Cc, V = lpeg.P, lpeg.R, lpeg.S, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.V
local match = lpeg.match
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
local digit, sign = R('09'), S('+-')
local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local utf8byte = R("\128\191")
+local utf8next = R("\128\191")
+local escaped = P("\\") * P(1)
+local squote = P("'")
+local dquote = P('"')
-patterns.utf8byte = utf8byte
patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8byte
-patterns.utf8three = R("\224\239") * utf8byte * utf8byte
-patterns.utf8four = R("\240\244") * utf8byte * utf8byte * utf8byte
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = P('\000\000\254\255') + P('\255\254\000\000') + P('\255\254') + P('\254\255') + P('\239\187\191')
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * P(-1) * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
patterns.digit = digit
patterns.sign = sign
@@ -310,17 +242,28 @@ patterns.nonspace = 1 - patterns.space
patterns.nonspacer = 1 - patterns.spacer
patterns.whitespace = patterns.eol + patterns.spacer
patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.utf8 = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-patterns.utfbom = P('\000\000\254\255') + P('\255\254\000\000') + P('\255\254') + P('\254\255') + P('\239\187\191')
-patterns.validutf8 = patterns.utf8^0 * P(-1) * Cc(true) + Cc(false)
patterns.comma = P(",")
patterns.commaspacer = P(",") * patterns.spacer^0
patterns.period = P(".")
-
-patterns.undouble = P('"')/"" * (1-P('"'))^0 * P('"')/""
-patterns.unsingle = P("'")/"" * (1-P("'"))^0 * P("'")/""
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.undouble = (dquote/"") * ((escaped + (1-dquote))^0) * (dquote/"")
+patterns.unsingle = (squote/"") * ((escaped + (1-squote))^0) * (squote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
patterns.unspacer = ((patterns.spacer^1)/"")^0
+local unquoted = Cs(patterns.unquoted * P(-1)) -- not C
+
+function string.unquoted(str)
+ return match(unquoted,str) or str
+end
+
+--~ print(string.unquoted("test"))
+--~ print(string.unquoted([["t\"est"]]))
+--~ print(string.unquoted([["t\"est"x]]))
+--~ print(string.unquoted("\'test\'"))
+
function lpeg.anywhere(pattern) --slightly adapted from website
return P { P(pattern) + 1 * V(1) } -- why so complex?
end
@@ -336,8 +279,8 @@ local content = (empty + nonempty)^1
local capture = Ct(content^0)
-function string:splitlines()
- return match(capture,self)
+function string.splitlines(str)
+ return match(capture,str)
end
patterns.textline = content
@@ -353,12 +296,12 @@ 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 other, any = C((1 - separator)^0), P(1)
+ local any = P(1)
splitter = other * (separator * C(any^0) + "") -- ?
splitters_s[separator] = splitter
else
- local other = C((1 - separator)^0)
splitter = other * (separator * other)^0
splitters_m[separator] = splitter
end
@@ -379,16 +322,16 @@ function lpeg.split(separator,str)
return match(c,str)
end
-function string:split(separator)
+function string.split(str,separator)
local c = cache[separator]
if not c then
c = Ct(splitat(separator))
cache[separator] = c
end
- return match(c,self)
+ return match(c,str)
end
-lpeg.splitters = cache
+--~ lpeg.splitters = cache -- no longer public
local cache = { }
@@ -396,22 +339,22 @@ function lpeg.checkedsplit(separator,str)
local c = cache[separator]
if not c then
separator = P(separator)
- local other = C((1 - separator)^0)
+ local other = C((1 - separator)^1)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
return match(c,str)
end
-function string:checkedsplit(separator)
+function string.checkedsplit(str,separator)
local c = cache[separator]
if not c then
separator = P(separator)
- local other = C((1 - separator)^0)
+ local other = C((1 - separator)^1)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
- return match(c,self)
+ return match(c,str)
end
--~ function lpeg.append(list,pp)
@@ -434,7 +377,9 @@ local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2
local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-patterns.utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
--~ local str = " a b c d "
@@ -473,22 +418,25 @@ function lpeg.keeper(str)
end
end
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
function lpeg.replacer(t)
if #t > 0 then
local p
for i=1,#t do
local ti= t[i]
local pp = P(ti[1]) / ti[2]
- p = (p and p + pp ) or pp
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
end
return Cs((p + 1)^0)
end
end
---~ print(utf.check(""))
---~ print(utf.check("abcde"))
---~ print(utf.check("abcde\255\123"))
-
local splitters_f, splitters_s = { }, { }
function lpeg.firstofsplit(separator) -- always return value
@@ -512,6 +460,7 @@ function lpeg.secondofsplit(separator) -- nil if not split
end
function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
return P { left * ((1 - left - right) + V(1))^0 * right }
end
@@ -524,6 +473,179 @@ end
--~ print(7,match(lpeg.secondofsplit(":"),"bc"))
--~ print(9,match(lpeg.secondofsplit(":","123"),"bc"))
+--~ -- slower:
+--~
+--~ function lpeg.counter(pattern)
+--~ local n, pattern = 0, (lpeg.P(pattern)/function() n = n + 1 end + lpeg.P(1))^0
+--~ return function(str) n = 0 ; lpegmatch(pattern,str) ; return n end
+--~ end
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + P(1))^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + P(1))^0)
+
+function string.escapedpattern(str,simple)
+ if simple then
+ return match(s,str)
+ else
+ return match(p,str)
+ end
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+--~ lpeg.print(lpeg.R("ab","cd","gh"))
+--~ lpeg.print(lpeg.P("a","b","c"))
+--~ lpeg.print(lpeg.S("a","b","c"))
+
+--~ print(lpeg.count("äáàa",lpeg.P("á") + lpeg.P("à")))
+--~ print(lpeg.count("äáàa",lpeg.UP("áà")))
+--~ print(lpeg.count("äáàa",lpeg.US("àá")))
+--~ print(lpeg.count("äáàa",lpeg.UR("aá")))
+--~ print(lpeg.count("äáàa",lpeg.UR("àá")))
+--~ print(lpeg.count("äáàa",lpeg.UR(0x0000,0xFFFF)))
+
end -- closure
do -- begin closure to overcome local limits and interference
@@ -541,8 +663,12 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
+-- function boolean.tonumber(b)
+-- return b and 1 or 0 -- test and test and return or return
+-- end
+
function boolean.tonumber(b)
- if b then return 1 else return 0 end
+ if b then return 1 else return 0 end -- test and return or return
end
function toboolean(str,tolerant)
@@ -566,6 +692,8 @@ function toboolean(str,tolerant)
end
end
+string.toboolean = toboolean
+
function string.is_boolean(str,default)
if type(str) == "string" then
if str == "true" or str == "yes" or str == "on" or str == "t" then
@@ -577,14 +705,6 @@ function string.is_boolean(str,default)
return default
end
-function boolean.alwaystrue()
- return true
-end
-
-function boolean.falsetrue()
- return false
-end
-
end -- closure
do -- begin closure to overcome local limits and interference
@@ -698,24 +818,26 @@ end
-- extra functions, some might go (when not used)
function table.strip(tab)
- local lst = { }
+ local lst, l = { }, 0
for i=1,#tab do
local s = gsub(tab[i],"^%s*(.-)%s*$","%1")
if s == "" then
-- skip this one
else
- lst[#lst+1] = s
+ l = l + 1
+ lst[l] = s
end
end
return lst
end
function table.keys(t)
- local k = { }
+ local keys, k = { }, 0
for key, _ in next, t do
- k[#k+1] = key
+ k = k + 1
+ keys[k] = key
end
- return k
+ return keys
end
local function compare(a,b)
@@ -728,9 +850,10 @@ local function compare(a,b)
end
local function sortedkeys(tab)
- local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed
+ local srt, kind, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
for key,_ in next, tab do
- srt[#srt+1] = key
+ s = s + 1
+ srt[s] = key
if kind == 3 then
-- no further check
else
@@ -753,10 +876,11 @@ local function sortedkeys(tab)
end
local function sortedhashkeys(tab) -- fast one
- local srt = { }
+ local srt, s = { }, 0
for key,_ in next, tab do
if key then
- srt[#srt+1] = key
+ s= s + 1
+ srt[s] = key
end
end
sort(srt)
@@ -770,8 +894,7 @@ local function nothing() end
local function sortedhash(t)
if t then
- local s = sortedhashkeys(t) -- maybe just sortedkeys
- local n = 0
+ local n, s = 0, sortedkeys(t) -- the robust one
local function kv(s)
n = n + 1
local k = s[n]
@@ -787,20 +910,30 @@ table.sortedhash = sortedhash
table.sortedpairs = sortedhash
function table.append(t, list)
- for _,v in next, list do
- insert(t,v)
+ local n = #t
+ for i=1,#list do
+ n = n + 1
+ t[n] = list[i]
end
+ return t
end
function table.prepend(t, list)
- for k,v in next, list do
- insert(t,k,v)
+ 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, ...) -- first one is target
t = t or { }
- local lst = {...}
+ local lst = { ... }
for i=1,#lst do
for k, v in next, lst[i] do
t[k] = v
@@ -810,7 +943,7 @@ function table.merge(t, ...) -- first one is target
end
function table.merged(...)
- local tmp, lst = { }, {...}
+ local tmp, lst = { }, { ... }
for i=1,#lst do
for k, v in next, lst[i] do
tmp[k] = v
@@ -820,22 +953,24 @@ function table.merged(...)
end
function table.imerge(t, ...)
- local lst = {...}
+ local lst, nt = { ... }, #t
for i=1,#lst do
local nst = lst[i]
for j=1,#nst do
- t[#t+1] = nst[j]
+ nt = nt + 1
+ t[nt] = nst[j]
end
end
return t
end
function table.imerged(...)
- local tmp, lst = { }, {...}
+ local tmp, ntmp, lst = { }, 0, {...}
for i=1,#lst do
local nst = lst[i]
for j=1,#nst do
- tmp[#tmp+1] = nst[j]
+ ntmp = ntmp + 1
+ tmp[ntmp] = nst[j]
end
end
return tmp
@@ -911,11 +1046,14 @@ function table.tohash(t,value)
end
function table.fromhash(t)
- local h = { }
+ local hsh, h = { }, 0
for k, v in next, t do -- no ipairs here
- if v then h[#h+1] = k end
+ if v then
+ h = h + 1
+ hsh[h] = k
+ end
end
- return h
+ return hsh
end
table.serialize_functions = true
@@ -936,20 +1074,23 @@ local function simple_table(t)
n = n + 1
end
if n == #t then
- local tt = { }
+ local tt, nt = { }, 0
for i=1,#t do
local v = t[i]
local tv = type(v)
if tv == "number" then
+ nt = nt + 1
if hexify then
- tt[#tt+1] = format("0x%04X",v)
+ tt[nt] = format("0x%04X",v)
else
- tt[#tt+1] = tostring(v) -- tostring not needed
+ tt[nt] = tostring(v) -- tostring not needed
end
elseif tv == "boolean" then
- tt[#tt+1] = tostring(v)
+ nt = nt + 1
+ tt[nt] = tostring(v)
elseif tv == "string" then
- tt[#tt+1] = format("%q",v)
+ nt = nt + 1
+ tt[nt] = format("%q",v)
else
tt = nil
break
@@ -1255,10 +1396,11 @@ end
--~ 'return' : return { }
--~ number : [number] = { }
-function table.serialize(root,name,reduce,noquotes,hexify)
- local t = { }
+function table.serialize(root,name,reduce,noquotes,hexify) -- can be faster if flush == false and t as argument
+ local t, n = { }, 0
local function flush(s)
- t[#t+1] = s
+ n = n + 1
+ t[n] = s
end
serialize(root,name,flush,reduce,noquotes,hexify)
return concat(t,"\n")
@@ -1284,12 +1426,13 @@ function table.tofile(filename,root,name,reduce,noquotes,hexify)
if f then
local maxtab = table.tofile_maxtab
if maxtab > 1 then
- local t = { }
+ local t, n = { }, 0
local function flush(s)
- t[#t+1] = s
- if #t > maxtab then
+ n = n + 1
+ t[n] = s
+ if n > maxtab then
f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
- t = { }
+ t, n = { }, 0 -- we could recycle t if needed
end
end
serialize(root,name,flush,reduce,noquotes,hexify)
@@ -1305,52 +1448,72 @@ function table.tofile(filename,root,name,reduce,noquotes,hexify)
end
end
-local function flatten(t,f,complete) -- is this used? meybe a variant with next, ...
- for i=1,#t do
- local v = t[i]
- if type(v) == "table" then
- if complete or type(v[1]) == "table" then
- flatten(v,f,complete)
+local function flattened(t,f,depth)
+ if f == nil then
+ f = { }
+ depth = 0xFFFF
+ elseif tonumber(f) then
+ -- assume then only two arguments are given
+ 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
+ f[k] = v
end
+ end
+ end
+ local n = #f
+ for k=1,#t do
+ local v = t[k]
+ if depth > 0 and type(v) == "table" then
+ flattened(v,f,depth-1)
+ n = #f
else
- f[#f+1] = v
+ n = n + 1
+ f[n] = v
end
end
-end
-
-function table.flatten(t)
- local f = { }
- flatten(t,f,true)
return f
end
-function table.unnest(t) -- bad name
- local f = { }
- flatten(t,f,false)
- return f
-end
-
-table.flattenonelevel = table.unnest
-
--- a better one:
+table.flattened = flattened
-local function flattened(t,f)
- if not f then
+local function unnest(t,f) -- only used in mk, for old times sake
+ if not f then -- and only relevant for token lists
f = { }
end
- for k, v in next, t do
+ for i=1,#t do
+ local v = t[i]
if type(v) == "table" then
- flattened(v,f)
+ if type(v[1]) == "table" then
+ unnest(v,f)
+ else
+ f[#f+1] = v
+ end
else
- f[k] = v
+ f[#f+1] = v
end
end
return f
end
-table.flattened = flattened
+function table.unnest(t) -- bad name
+ return unnest(t)
+end
+
+--~ function table.unnest(t) -- for old times sake, undocumented (only in mk)
+--~ return flattened(t,1)
+--~ end
+
+--~ function table.are_equal(a,b)
+--~ return table.serialize(a) == table.serialize(b)
+--~ end
local function are_equal(a,b,n,m) -- indexed
if a and b and #a == #b then
@@ -1376,7 +1539,7 @@ end
local function identical(a,b) -- assumes same structure
for ka, va in next, a do
- local vb = b[k]
+ local vb = b[ka]
if va == vb then
-- same
elseif type(va) == "table" and type(vb) == "table" then
@@ -1390,8 +1553,8 @@ local function identical(a,b) -- assumes same structure
return true
end
-table.are_equal = are_equal
table.identical = identical
+table.are_equal = are_equal
-- maybe also make a combined one
@@ -1417,14 +1580,14 @@ function table.contains(t, v)
end
function table.count(t)
- local n, e = 0, next(t)
- while e do
- n, e = n + 1, next(t,e)
+ local n = 0
+ for k, v in next, t do
+ n = n + 1
end
return n
end
-function table.swapped(t,s)
+function table.swapped(t,s) -- hash
local n = { }
if s then
--~ for i=1,#s do
@@ -1446,55 +1609,34 @@ function table.swapped(t,s)
return n
end
---~ function table.are_equal(a,b)
---~ return table.serialize(a) == table.serialize(b)
---~ end
-
-function table.clone(t,p) -- t is optional or nil or table
- if not p then
- t, p = { }, t or { }
- elseif not t then
- t = { }
- end
- setmetatable(t, { __index = function(_,key) return p[key] end }) -- why not __index = p ?
- return t
-end
-
-function table.hexed(t,seperator)
- local tt = { }
- for i=1,#t do tt[i] = format("0x%04X",t[i]) end
- return concat(tt,seperator or " ")
-end
-
-function table.swaphash(h) -- needs another name
- local r = { }
- for k,v in next, h do
- r[v] = lower(gsub(k," ",""))
- end
- return r
-end
-
-function table.reverse(t)
- local tt = { }
- if #t > 0 then
- for i=#t,1,-1 do
- tt[#tt+1] = t[i]
+function table.reversed(t)
+ if t then
+ local tt, tn = { }, #t
+ if tn > 0 then
+ local ttn = 0
+ for i=tn,1,-1 do
+ ttn = ttn + 1
+ tt[ttn] = t[i]
+ end
end
+ return tt
end
- return tt
end
function table.sequenced(t,sep,simple) -- hash only
- local s = { }
+ local s, n = { }, 0
for k, v in sortedhash(t) do
if simple then
if v == true then
- s[#s+1] = k
+ n = n + 1
+ s[n] = k
elseif v and v~= "" then
- s[#s+1] = k .. "=" .. tostring(v)
+ n = n + 1
+ s[n] = k .. "=" .. tostring(v)
end
else
- s[#s+1] = k .. "=" .. tostring(v)
+ n = n + 1
+ s[n] = k .. "=" .. tostring(v)
end
end
return concat(s, sep or " | ")
@@ -1504,7 +1646,7 @@ function table.print(...)
table.tohandle(print,...)
end
--- -- -- obsolete but we keep them for a while and will comment them later -- -- --
+-- -- -- obsolete but we keep them for a while and might comment them later -- -- --
-- roughly: copy-loop : unpack : sub == 0.9 : 0.4 : 0.45 (so in critical apps, use unpack)
@@ -1519,14 +1661,7 @@ function table.is_empty(t)
end
function table.has_one_entry(t)
- local n = next(t)
- return n and not next(t,n)
-end
-
-function table.replace(a,b)
- for k,v in next, b do
- a[k] = v
- end
+ return t and not next(t,next(t))
end
end -- closure
@@ -1694,7 +1829,7 @@ end
file.isreadable = file.is_readable -- depricated
file.iswritable = file.is_writable -- depricated
--- todo: lpeg
+-- todo: lpeg \\ / .. does not save much
local checkedsplit = string.checkedsplit
@@ -1709,7 +1844,7 @@ end
-- we can hash them weakly
---~ function file.old_collapse_path(str) -- fails on b.c/..
+--~ function file.collapsepath(str) -- fails on b.c/..
--~ str = gsub(str,"\\","/")
--~ if find(str,"/") then
--~ str = gsub(str,"^%./",(gsub(getcurrentdir(),"\\","/")) .. "/") -- ./xx in qualified
@@ -1733,7 +1868,7 @@ end
--~ Of course there are some optimizations too. Finally we had to deal with
--~ windows drive prefixes and thinsg like sys://.
-function file.collapse_path(str,anchor)
+function file.collapsepath(str,anchor)
if anchor and not find(str,"^/") and not find(str,"^%a:") then
str = getcurrentdir() .. "/" .. str
end
@@ -1788,8 +1923,10 @@ function file.collapse_path(str,anchor)
end
end
+file.collapse_path = file.collapsepath
+
--~ local function test(str)
---~ print(string.format("%-20s %-15s %-15s",str,file.collapse_path(str),file.collapse_path(str,true)))
+--~ print(string.format("%-20s %-15s %-15s",str,file.collapsepath(str),file.collapsepath(str,true)))
--~ end
--~ test("a/b.c/d") test("b.c/d") test("b.c/..")
--~ test("/") test("c:/..") test("sys://..")
@@ -2847,12 +2984,13 @@ function injections.handler(head,where,keep)
trace(head)
end
-- in the future variant we will not copy items but refs to tables
- local done, ky, rl, valid, cx, wx, mk = false, { }, { }, { }, { }, { }, { }
+ local done, ky, rl, valid, cx, wx, mk, nofvalid = false, { }, { }, { }, { }, { }, { }, 0
if has_kerns then -- move outside loop
local nf, tm = nil, nil
for n in traverse_id(glyph_code,head) do
if n.subtype < 256 then
- valid[#valid+1] = n
+ nofvalid = nofvalid + 1
+ valid[nofvalid] = n
if n.font ~= nf then
nf = n.font
tm = fontdata[nf].marks
@@ -2880,7 +3018,8 @@ function injections.handler(head,where,keep)
local nf, tm = nil, nil
for n in traverse_id(glyph_code,head) do
if n.subtype < 256 then
- valid[#valid+1] = n
+ nofvalid = nofvalid + 1
+ valid[nofvalid] = n
if n.font ~= nf then
nf = n.font
tm = fontdata[nf].marks
@@ -2889,7 +3028,7 @@ function injections.handler(head,where,keep)
end
end
end
- if #valid > 0 then
+ if nofvalid > 0 then
-- we can assume done == true because we have cursives and marks
local cx = { }
if has_kerns and next(ky) then
@@ -2902,7 +3041,7 @@ function injections.handler(head,where,keep)
local p_cursbase, p = nil, nil
-- since we need valid[n+1] we can also use a "while true do"
local t, d, maxt = { }, { }, 0
- for i=1,#valid do -- valid == glyphs
+ for i=1,nofvalid do -- valid == glyphs
local n = valid[i]
if not mk[n] then
local n_cursbase = has_attribute(n,cursbase)
@@ -2966,7 +3105,7 @@ function injections.handler(head,where,keep)
end
end
if has_marks then
- for i=1,#valid do
+ for i=1,nofvalid do
local p = valid[i]
local p_markbase = has_attribute(p,markbase)
if p_markbase then
@@ -3795,13 +3934,13 @@ function tfm.scale(tfmtable, scaledpoints, relativeid)
local ivc = vc[i]
local key = ivc[1]
if key == "right" then
- tt[#tt+1] = { key, ivc[2]*hdelta }
+ tt[i] = { key, ivc[2]*hdelta }
elseif key == "down" then
- tt[#tt+1] = { key, ivc[2]*vdelta }
+ tt[i] = { key, ivc[2]*vdelta }
elseif key == "rule" then
- tt[#tt+1] = { key, ivc[2]*vdelta, ivc[3]*hdelta }
+ tt[i] = { key, ivc[2]*vdelta, ivc[3]*hdelta }
else -- not comment
- tt[#tt+1] = ivc -- shared since in cache and untouched
+ tt[i] = ivc -- shared since in cache and untouched
end
end
chr.commands = tt
@@ -4783,9 +4922,18 @@ local baselines = allocate {
['romn'] = 'Roman baseline'
}
-local verbosescripts = allocate(table.swaphash(scripts ))
-local verboselanguages = allocate(table.swaphash(languages))
-local verbosefeatures = allocate(table.swaphash(features ))
+
+local function swap(h) -- can be a tables.swap when we get a better name
+ local r = { }
+ for k, v in next, h do
+ r[v] = lower(gsub(k," ",""))
+ end
+ return r
+end
+
+local verbosescripts = allocate(swap(scripts ))
+local verboselanguages = allocate(swap(languages))
+local verbosefeatures = allocate(swap(features ))
tables.scripts = scripts
tables.languages = languages
@@ -4806,12 +4954,6 @@ for k, v in next, verbosefeatures do
verbosefeatures[lower(k)] = v
end
--- can be sped up by local tables
-
-function tables.totag(id) -- not used
- return format("%4s",lower(id))
-end
-
local function resolve(tab,id)
if tab and id then
id = lower(id)
@@ -5325,21 +5467,23 @@ fonts.map.addtounicode = function(data,filename)
originals[index], tounicode[index], ns = unicode, tounicode16(unicode), ns + 1
end
else
- local t = { }
+ local t, n = { }, 0
for l=1,nplit do
local base = split[l]
local u = unicodes[base] or (aglmap and aglmap[base])
if not u then
break
elseif type(u) == "table" then
- t[#t+1] = u[1]
+ n = n + 1
+ t[n] = u[1]
else
- t[#t+1] = u
+ n = n + 1
+ t[n] = u
end
end
- if #t == 0 then -- done then
+ if n == 0 then -- done then
-- nothing
- elseif #t == 1 then
+ elseif n == 1 then
originals[index], tounicode[index], nl, unicode = t[1], tounicode16(t[1]), nl + 1, true
else
originals[index], tounicode[index], nl, unicode = t, tounicode16sequence(t), nl + 1, true
@@ -5499,13 +5643,13 @@ if not modules then modules = { } end modules ['font-otf'] = {
local utf = unicode.utf8
-local concat, utfbyte = table.concat, utf.byte
+local utfbyte = utf.byte
local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
local type, next, tonumber, tostring = type, next, tonumber, tostring
local abs = math.abs
local getn = table.getn
local lpegmatch = lpeg.match
-local reverse = table.reverse
+local reversed, concat = table.reversed, table.concat
local ioflush = io.flush
local allocate = utilities.storage.allocate
@@ -5543,7 +5687,7 @@ local definers = fonts.definers
otf.glists = { "gsub", "gpos" }
-otf.version = 2.705 -- beware: also sync font-mis.lua
+otf.version = 2.706 -- beware: also sync font-mis.lua
otf.cache = containers.define("fonts", "otf", otf.version, true)
local loadmethod = "table" -- table, mixed, sparse
@@ -6454,6 +6598,7 @@ actions["prepare unicodes"] = function(data,filename,raw)
local luatex = data.luatex
local indices, unicodes, multiples, internals = { }, { }, { }, { }
local mapmap = data.map or raw.map
+ local mapenc = nil -- will go away
if not mapmap then
report_otf("no map in %s",filename)
mapmap = { }
@@ -6463,6 +6608,7 @@ actions["prepare unicodes"] = function(data,filename,raw)
mapmap = { }
data.map.map = mapmap
else
+ mapenc = mapmap.enc -- will go away
mapmap = mapmap.map
end
local criterium = fonts.privateoffset
@@ -6486,41 +6632,53 @@ actions["prepare unicodes"] = function(data,filename,raw)
indices[unicode] = index
unicodes[name] = unicode
end
+ -- maybe deal with altuni here in the future but first we need
+ -- to encounter a proper font that sets them
else
-- message that something is wrong
end
end
end
-- beware: the indices table is used to initialize the tfm table
- for unicode, index in next, mapmap do
- if not internals[index] then
- local name = glyphs[index].name
- if name then
- local un = unicodes[name]
- if not un then
- unicodes[name] = unicode -- or 0
- elseif type(un) == "number" then -- tonumber(un)
- if un ~= unicode then
- multiples[#multiples+1] = name
- unicodes[name] = { un, unicode }
- indices[unicode] = index
- end
- else
- local ok = false
- for u=1,#un do
- if un[u] == unicode then
- ok = true
- break
+ local encname = lower(data.enc_name or (mapenc and mapenc[1] and mapenc[1].enc_name) or "") -- mapenc will go away
+ -- will become: local encname = lower(data.enc_name or "")
+ if encname == "" or encname == "unicodebmp" or encname == "unicodefull" then -- maybe find(encname,"unicode")
+ if trace_loading then
+ report_otf("using extra unicode map")
+ end
+ -- ok -- we can also consider using the altuni
+ for unicode, index in next, mapmap do
+ if not internals[index] then
+ local name = glyphs[index].name
+ if name then
+ local un = unicodes[name]
+ if not un then
+ unicodes[name] = unicode -- or 0
+ elseif type(un) == "number" then -- tonumber(un)
+ if un ~= unicode then
+ multiples[#multiples+1] = name
+ unicodes[name] = { un, unicode }
+ indices[unicode] = index
+ end
+ else
+ local ok = false
+ for u=1,#un do
+ if un[u] == unicode then
+ ok = true
+ break
+ end
+ end
+ if not ok then
+ multiples[#multiples+1] = name
+ un[#un+1] = unicode
+ indices[unicode] = index
end
- end
- if not ok then
- multiples[#multiples+1] = name
- un[#un+1] = unicode
- indices[unicode] = index
end
end
end
end
+ else
+ report_otf("warning: non unicode map '%s', only using glyph unicode data",encname or "whatever")
end
if trace_loading then
if #multiples > 0 then
@@ -6549,7 +6707,7 @@ actions["reorganize lookups"] = function(data,filename,raw)
for _, vv in next, v.rules do
local c = vv.coverage
if c and c.before then
- c.before = reverse(c.before)
+ c.before = reversed(c.before)
end
end
end
@@ -7068,8 +7226,8 @@ local function copytotfm(data,cache_id) -- we can save a copy when we reorder th
local glyphs, pfminfo, metadata = data.glyphs or { }, data.pfminfo or { }, data.metadata or { }
local luatex = data.luatex
local unicodes = luatex.unicodes -- names to unicodes
- local indices = luatex.indices local mode = data.mode or "base"
-
+ local indices = luatex.indices
+ local mode = data.mode or "base"
local characters, parameters, math_parameters, descriptions = { }, { }, { }, { }
local designsize = metadata.designsize or metadata.design_size or 100
if designsize == 0 then
@@ -8099,7 +8257,7 @@ local zwj = 0x200D
local wildcard = "*"
local default = "dflt"
-local split_at_space = lpeg.splitters[" "] or lpeg.Ct(lpeg.splitat(" ")) -- no trailing or multiple spaces anyway
+local split_at_space = lpeg.Ct(lpeg.splitat(" ")) -- no trailing or multiple spaces anyway
local nodecodes = nodes.nodecodes
local whatcodes = nodes.whatcodes
@@ -8205,9 +8363,9 @@ local function gref(n)
local num, nam = { }, { }
for i=1,#n do
local ni = n[i]
- num[#num+1] = format("U+%04X",ni)
- local dni = descriptions[ni]
- nam[#num] = (dni and dni.name) or "?"
+ local di = descriptions[ni]
+ num[i] = format("U+%04X",ni)
+ nam[i] = di and di.name or "?"
end
return format("%s (%s)",concat(num," "), concat(nam," "))
end
@@ -10177,13 +10335,14 @@ otf.features.prepare = { }
local function split(replacement,original,cache,unicodes)
-- we can cache this too, but not the same (although unicode is a unique enough hash)
- local o, t, n = { }, { }, 0
+ local o, t, n, no = { }, { }, 0, 0
for s in gmatch(original,"[^ ]+") do
local us = unicodes[s]
+ no = no + 1
if type(us) == "number" then -- tonumber(us)
- o[#o+1] = us
+ o[no] = us
else
- o[#o+1] = us[1]
+ o[no] = us[1]
end
end
for s in gmatch(replacement,"[^ ]+") do
@@ -10200,9 +10359,11 @@ end
local function uncover(covers,result,cache,unicodes)
-- lpeg hardly faster (.005 sec on mk)
+ local nofresults = #result
for n=1,#covers do
local c = covers[n]
local cc = cache[c]
+ nofresults = nofresults + 1
if not cc then
local t = { }
for s in gmatch(c,"[^ ]+") do
@@ -10216,9 +10377,9 @@ local function uncover(covers,result,cache,unicodes)
end
end
cache[c] = t
- result[#result+1] = t
+ result[nofresults] = t
else
- result[#result+1] = cc
+ result[nofresults] = cc
end
end
end
@@ -10260,16 +10421,17 @@ local function prepare_lookups(tfmdata)
--~ end
end,
multiple = function (p,lookup,glyph,unicode)
- local old, new = unicode, { }
+ local old, new, nnew = unicode, { }, 0
local m = multiple[lookup]
if not m then m = { } multiple[lookup] = m end
m[old] = new
for pc in gmatch(p[2],"[^ ]+") do
local upc = unicodes[pc]
+ nnew = nnew + 1
if type(upc) == "number" then
- new[#new+1] = upc
+ new[nnew] = upc
else
- new[#new+1] = upc[1]
+ new[nnew] = upc[1]
end
end
--~ if trace_lookups then
@@ -10277,16 +10439,17 @@ local function prepare_lookups(tfmdata)
--~ end
end,
alternate = function(p,lookup,glyph,unicode)
- local old, new = unicode, { }
+ local old, new, nnew = unicode, { }, 0
local a = alternate[lookup]
if not a then a = { } alternate[lookup] = a end
a[old] = new
for pc in gmatch(p[2],"[^ ]+") do
local upc = unicodes[pc]
+ nnew = nnew + 1
if type(upc) == "number" then
- new[#new+1] = upc
+ new[nnew] = upc
else
- new[#new+1] = upc[1]
+ new[nnew] = upc[1]
end
end
--~ if trace_lookups then
@@ -10480,7 +10643,7 @@ local function prepare_contextchains(tfmdata)
contexts = { }
contextchain[lookupname] = contexts
end
- local t = { }
+ local t, nt = { }, 0
for nofrules=1,#rules do -- does #rules>1 happen often?
local rule = rules[nofrules]
local coverage = rule.coverage
@@ -10496,7 +10659,8 @@ local function prepare_contextchains(tfmdata)
uncover(after,sequence,cache,unicodes)
end
if sequence[1] then
- t[#t+1] = { nofrules, lookuptype, sequence, start, stop, rule.lookups }
+ nt = nt + 1
+ t[nt] = { nofrules, lookuptype, sequence, start, stop, rule.lookups }
for unic, _ in next, sequence[start] do
local cu = contexts[unic]
if not cu then
@@ -10516,7 +10680,7 @@ local function prepare_contextchains(tfmdata)
contexts = { }
reversecontextchain[lookupname] = contexts
end
- local t = { }
+ local t, nt = { }, 0
for nofrules=1,#rules do
local rule = rules[nofrules]
local reversecoverage = rule.reversecoverage
@@ -10536,7 +10700,8 @@ local function prepare_contextchains(tfmdata)
end
if sequence[1] then
-- this is different from normal coverage, we assume only replacements
- t[#t+1] = { nofrules, lookuptype, sequence, start, stop, rule.lookups, replacements }
+ nt = nt + 1
+ t[nt] = { nofrules, lookuptype, sequence, start, stop, rule.lookups, replacements }
for unic, _ in next, sequence[start] do
local cu = contexts[unic]
if not cu then
@@ -10556,7 +10721,7 @@ local function prepare_contextchains(tfmdata)
contexts = { }
contextchain[lookupname] = contexts
end
- local t = { }
+ local t, nt = { }, 0
for nofrules=1,#rules do
-- nearly the same as coverage so we could as well rename it
local rule = rules[nofrules]
@@ -10576,7 +10741,8 @@ local function prepare_contextchains(tfmdata)
uncover(back,sequence,cache,unicodes)
end
if sequence[1] then
- t[#t+1] = { nofrules, lookuptype, sequence, start, stop, rule.lookups }
+ nt = nt + 1
+ t[nt] = { nofrules, lookuptype, sequence, start, stop, rule.lookups }
for unic, _ in next, sequence[start] do
local cu = contexts[unic]
if not cu then
@@ -15035,14 +15201,15 @@ local sortedhashkeys = table.sortedhashkeys
function tfm.hashfeatures(specification)
local features = specification.features
if features then
- local t = { }
+ local t, tn = { }, 0
local normal = features.normal
if normal and next(normal) then
local f = sortedhashkeys(normal)
for i=1,#f do
local v = f[i]
if v ~= "number" and v ~= "features" then -- i need to figure this out, features
- t[#t+1] = v .. '=' .. tostring(normal[v])
+ tn = tn + 1
+ t[tn] = v .. '=' .. tostring(normal[v])
end
end
end
@@ -15051,13 +15218,15 @@ function tfm.hashfeatures(specification)
local f = sortedhashkeys(vtf)
for i=1,#f do
local v = f[i]
- t[#t+1] = v .. '=' .. tostring(vtf[v])
+ tn = tn + 1
+ t[tn] = v .. '=' .. tostring(vtf[v])
end
end
---~ if specification.mathsize then
---~ t[#t+1] = "mathsize=" .. specification.mathsize
---~ end
- if #t > 0 then
+ --~ if specification.mathsize then
+ --~ tn = tn + 1
+ --~ t[tn] = "mathsize=" .. specification.mathsize
+ --~ end
+ if tn > 0 then
return concat(t,"+")
end
end
@@ -15642,7 +15811,7 @@ local function colonized(specification) -- xetex mode
list = { }
lpegmatch(pattern,specification.specification)
-- for k, v in next, list do
- -- list[k] = v:is_boolean()
+ -- list[k] = is_boolean(v)
-- if type(list[a]) == "nil" then
-- list[k] = v
-- end