diff options
author | Hans Hagen <pragma@wxs.nl> | 2009-08-14 10:48:00 +0200 |
---|---|---|
committer | Hans Hagen <pragma@wxs.nl> | 2009-08-14 10:48:00 +0200 |
commit | 923d32d477730ca7b7634853c0c9e63c25f65088 (patch) | |
tree | e15e6bd06147f795cbd5372ab43ba4a9149a6512 | |
parent | 1ba28aeb4ea244e4b82a024c107472b216293689 (diff) | |
download | context-923d32d477730ca7b7634853c0c9e63c25f65088.tar.gz |
beta 2009.08.14 10:48
-rw-r--r-- | scripts/context/lua/luatools.lua | 380 | ||||
-rw-r--r-- | scripts/context/lua/mtxrun.lua | 332 | ||||
-rw-r--r-- | scripts/context/stubs/mswin/luatools.lua | 380 | ||||
-rw-r--r-- | scripts/context/stubs/mswin/mtxrun.lua | 332 | ||||
-rwxr-xr-x | scripts/context/stubs/unix/luatools | 380 | ||||
-rwxr-xr-x | scripts/context/stubs/unix/mtxrun | 332 | ||||
-rw-r--r-- | tex/context/base/cont-new.tex | 2 | ||||
-rw-r--r-- | tex/context/base/context.tex | 2 | ||||
-rw-r--r-- | tex/context/base/core-sys.mkiv | 76 | ||||
-rw-r--r-- | tex/context/base/data-res.lua | 6 | ||||
-rw-r--r-- | tex/context/base/font-syn.lua | 11 | ||||
-rw-r--r-- | tex/context/base/lpdf-mis.lua | 26 | ||||
-rw-r--r-- | tex/context/base/node-ref.lua | 39 | ||||
-rw-r--r-- | tex/generic/context/luatex-fonts-merged.lua | 2 |
14 files changed, 2038 insertions, 262 deletions
diff --git a/scripts/context/lua/luatools.lua b/scripts/context/lua/luatools.lua index f0fcd517d..433d1b8dc 100644 --- a/scripts/context/lua/luatools.lua +++ b/scripts/context/lua/luatools.lua @@ -265,6 +265,11 @@ 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 end -- of closure @@ -407,6 +412,10 @@ function table.strip(tab) return lst end +local function compare(a,b) + return (tostring(a) < tostring(b)) +end + local function sortedkeys(tab) local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed for key,_ in next, tab do @@ -427,7 +436,7 @@ local function sortedkeys(tab) end end if kind == 0 or kind == 3 then - sort(srt,function(a,b) return (tostring(a) < tostring(b)) end) + sort(srt,compare) else sort(srt) end @@ -1058,7 +1067,7 @@ function table.insert_after_value(t,value,str) end local function are_equal(a,b,n,m) -- indexed - if #a == #b then + if a and b and #a == #b then n = n or 1 m = m or #a for i=n,m do @@ -1215,6 +1224,7 @@ end function io.loaddata(filename,textmode) local f = io.open(filename,(textmode and 'r') or 'rb') if f then + -- collectgarbage("step") -- sometimes makes a big difference in mem consumption local data = f:read('*all') -- garbagecollector.check(data) f:close() @@ -1451,6 +1461,7 @@ set = set or { } local nums = { } local tabs = { } local concat = table.concat +local next, type = next, type set.create = table.tohash @@ -1458,17 +1469,19 @@ function set.tonumber(t) if next(t) then local s = "" -- we could save mem by sorting, but it slows down - for k, v in pairs(t) do + for k, v in next, t do if v then -- why bother about the leading space s = s .. " " .. k end end - if not nums[s] then - tabs[#tabs+1] = t - nums[s] = #tabs + local n = nums[s] + if not n then + n = #tabs + 1 + tabs[n] = t + nums[s] = n end - return nums[s] + return n else return 0 end @@ -1482,6 +1495,20 @@ function set.totable(n) end end +function set.tolist(n) + if n == 0 or not tabs[n] then + return "" + else + local t = { } + for k, v in next, tabs[n] do + if v then + t[#t+1] = k + end + end + return concat(t," ") + end +end + function set.contains(n,s) if type(n) == "table" then return n[s] @@ -1678,8 +1705,8 @@ function file.replacesuffix(filename, suffix) return (gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix end -function file.dirname(name) - return match(name,"^(.+)[/\\].-$") or "" +function file.dirname(name,default) + return match(name,"^(.+)[/\\].-$") or (default or "") end function file.basename(name) @@ -1717,15 +1744,8 @@ function file.join(...) end function file.iswritable(name) - local a = lfs.attributes(name) - if a and a.permissions:sub(2,2) == "w" then - return true - else - name = file.dirname(name) or "." - if name == "" then name = "." end - a = lfs.attributes(name) - return a and a.permissions:sub(2,2) == "w" - end + local a = lfs.attributes(name) or lfs.attributes(file.dirname(name,".")) + return a and a.permissions:sub(2,2) == "w" end function file.isreadable(name) @@ -1893,6 +1913,26 @@ function file.is_rootbased_path(filename) return rootbased:match(filename) end +local slash = lpeg.S("\\/") +local period = lpeg.P(".") +local drive = lpeg.C(lpeg.R("az","AZ")) * lpeg.P(":") +local path = lpeg.C(((1-slash)^0 * slash)^0) +local suffix = period * lpeg.C(lpeg.P(1-period)^0 * lpeg.P(-1)) +local base = lpeg.C((1-suffix)^0) + +local pattern = (drive + lpeg.Cc("")) * (path + lpeg.Cc("")) * (base + lpeg.Cc("")) * (suffix + lpeg.Cc("")) + +function file.splitname(str) -- returns drive, path, base, suffix + return pattern:match(str) +end + +-- function test(t) for k, v in pairs(t) do print(v, "=>", file.splitname(v)) end end +-- +-- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" } +-- test { "c:", "c:aa", "c:aa/bb", "c:aa/bb/cc", "c:aa/bb/cc.dd", "c:aa/bb/cc.dd.ee" } +-- test { "/aa", "/aa/bb", "/aa/bb/cc", "/aa/bb/cc.dd", "/aa/bb/cc.dd.ee" } +-- test { "aa", "aa/bb", "aa/bb/cc", "aa/bb/cc.dd", "aa/bb/cc.dd.ee" } + end -- of closure @@ -1948,7 +1988,7 @@ function file.checksum(name) if md5 then local data = io.loaddata(name) if data then - return md5.HEXsum(data) + return md5.HEX(data) end end return nil @@ -2862,6 +2902,235 @@ end -- of closure do -- create closure to overcome 200 locals limit +if not modules then modules = { } end modules ['l-aux'] = { + version = 1.001, + comment = "companion to luat-lib.tex", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +aux = aux or { } + +local concat, format, gmatch = table.concat, string.format, string.gmatch +local tostring, type = tostring, type + +local space = lpeg.P(' ') +local equal = lpeg.P("=") +local comma = lpeg.P(",") +local lbrace = lpeg.P("{") +local rbrace = lpeg.P("}") +local nobrace = 1 - (lbrace+rbrace) +local nested = lpeg.P{ lbrace * (nobrace + lpeg.V(1))^0 * rbrace } +local spaces = space^0 + +local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0) + +local key = lpeg.C((1-equal-comma)^1) +local pattern_a = (space+comma)^0 * (key * equal * value + key * lpeg.C("")) +local pattern_c = (space+comma)^0 * (key * equal * value) + +local key = lpeg.C((1-space-equal-comma)^1) +local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + lpeg.C(""))) + +-- "a=1, b=2, c=3, d={a{b,c}d}, e=12345, f=xx{a{b,c}d}xx, g={}" : outer {} removes, leading spaces ignored + +local hash = { } + +local function set(key,value) -- using Carg is slower here + hash[key] = value +end + +local pattern_a_s = (pattern_a/set)^1 +local pattern_b_s = (pattern_b/set)^1 +local pattern_c_s = (pattern_c/set)^1 + +aux.settings_to_hash_pattern_a = pattern_a_s +aux.settings_to_hash_pattern_b = pattern_b_s +aux.settings_to_hash_pattern_c = pattern_c_s + +function aux.make_settings_to_hash_pattern(set,how) + if how == "strict" then + return (pattern_c/set)^1 + elseif how == "tolerant" then + return (pattern_b/set)^1 + else + return (pattern_a/set)^1 + end +end + +function aux.settings_to_hash(str) + if str and str ~= "" then + hash = { } + if moretolerant then + pattern_b_s:match(str) + else + pattern_a_s:match(str) + end + return hash + else + return { } + end +end + +function aux.settings_to_hash_tolerant(str) + if str and str ~= "" then + hash = { } + pattern_b_s:match(str) + return hash + else + return { } + end +end + +function aux.settings_to_hash_strict(str) + if str and str ~= "" then + hash = { } + pattern_c_s:match(str) + return next(hash) and hash + else + return nil + end +end + +local seperator = comma * space^0 +local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0) +local pattern = lpeg.Ct(value*(seperator*value)^0) + +-- "aap, {noot}, mies" : outer {} removes, leading spaces ignored + +aux.settings_to_array_pattern = pattern + +function aux.settings_to_array(str) + if not str or str == "" then + return { } + else + return pattern:match(str) + end +end + +local function set(t,v) + t[#t+1] = v +end + +local value = lpeg.P(lpeg.Carg(1)*value) / set +local pattern = value*(seperator*value)^0 * lpeg.Carg(1) + +function aux.add_settings_to_array(t,str) + return pattern:match(str, nil, t) +end + +function aux.hash_to_string(h,separator,yes,no,strict,omit) + if h then + local t, s = { }, table.sortedkeys(h) + omit = omit and table.tohash(omit) + for i=1,#s do + local key = s[i] + if not omit or not omit[key] then + local value = h[key] + if type(value) == "boolean" then + if yes and no then + if value then + t[#t+1] = key .. '=' .. yes + elseif not strict then + t[#t+1] = key .. '=' .. no + end + elseif value or not strict then + t[#t+1] = key .. '=' .. tostring(value) + end + else + t[#t+1] = key .. '=' .. value + end + end + end + return concat(t,separator or ",") + else + return "" + end +end + +function aux.array_to_string(a,separator) + if a then + return concat(a,separator or ",") + else + return "" + end +end + +function aux.settings_to_set(str,t) + t = t or { } + for s in gmatch(str,"%s*([^,]+)") do + t[s] = true + end + return t +end + +-- temporary here + +function aux.getparameters(self,class,parentclass,settings) + local sc = self[class] + if not sc then + sc = table.clone(self[parent]) + self[class] = sc + end + aux.add_settings_to_array(sc, settings) +end + +-- temporary here + +local digit = lpeg.R("09") +local period = lpeg.P(".") +local zero = lpeg.P("0") + +--~ local finish = lpeg.P(-1) +--~ local nodigit = (1-digit) + finish +--~ local case_1 = (period * zero^1 * #nodigit)/"" -- .000 +--~ local case_2 = (period * (1-(zero^0/"") * #nodigit)^1 * (zero^0/"") * nodigit) -- .010 .10 .100100 + +local trailingzeros = zero^0 * -digit -- suggested by Roberto R +local case_1 = period * trailingzeros / "" +local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "") + +local number = digit^1 * (case_1 + case_2) +local stripper = lpeg.Cs((number + 1)^0) + +--~ local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100" +--~ collectgarbage("collect") +--~ str = string.rep(sample,10000) +--~ local ts = os.clock() +--~ stripper:match(str) +--~ print(#str, os.clock()-ts, stripper:match(sample)) + +function aux.strip_zeros(str) + return stripper:match(str) +end + +function aux.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 aux.accesstable(target) + local t = _G + for name in gmatch(target,"([^%.]+)") do + t = t[name] + end + return t +end + + +end -- of closure + +do -- create closure to overcome 200 locals limit + if not modules then modules = { } end modules ['trac-tra'] = { version = 1.001, comment = "companion to luat-lib.tex", @@ -3012,7 +3281,11 @@ trackers = trackers or { } local data, done = { }, { } local function set(what,value) - for w in gmatch(lower(what),"[^, ]+") do + if type(what) == "string" then + what = aux.settings_to_array(what) + end + for i=1,#what do + local w = what[i] for d, f in next, data do if done[d] then -- prevent recursion due to wildcards @@ -3391,27 +3664,34 @@ statistics.threshold = 0.05 local clock = os.gettimeofday or os.clock +local notimer + function statistics.hastimer(instance) return instance and instance.starttime end function statistics.starttiming(instance) - if instance then - local it = instance.timing - if not it then - it = 0 - end - if it == 0 then - instance.starttime = clock() - if not instance.loadtime then - instance.loadtime = 0 - end + if not instance then + notimer = { } + instance = notimer + end + local it = instance.timing + if not it then + it = 0 + end + if it == 0 then + instance.starttime = clock() + if not instance.loadtime then + instance.loadtime = 0 end - instance.timing = it + 1 end + instance.timing = it + 1 end function statistics.stoptiming(instance, report) + if not instance then + instance = notimer + end if instance then local it = instance.timing if it > 1 then @@ -3435,10 +3715,16 @@ function statistics.stoptiming(instance, report) end function statistics.elapsedtime(instance) + if not instance then + instance = notimer + end return format("%0.3f",(instance and instance.loadtime) or 0) end function statistics.elapsedindeed(instance) + if not instance then + instance = notimer + end local t = (instance and instance.loadtime) or 0 return t > statistics.threshold end @@ -3479,6 +3765,7 @@ function statistics.show(reporter) reporter(s[1],r,n) end end + texio.write_nl("") -- final newline statistics.enable = false end end @@ -3536,6 +3823,7 @@ if not modules then modules = { } end modules ['luat-log'] = { -- this is old code that needs an overhaul local write_nl, write, format = texio.write_nl or print, texio.write or io.write, string.format +local texcount = tex and tex.count if texlua then write_nl = print @@ -3615,10 +3903,8 @@ function logs.tex.line(fmt,...) -- new end end -local texcount = tex and tex.count - function logs.tex.start_page_number() - local real, user, sub = texcount[0], texcount[1], texcount[2] + local real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno if real > 0 then if user > 0 then if sub > 0 then @@ -3673,7 +3959,7 @@ function logs.xml.stop_run() end function logs.xml.start_page_number() - write_nl(format("<p real='%s' page='%s' sub='%s'", texcount[0], texcount[1], texcount[2])) + write_nl(format("<p real='%s' page='%s' sub='%s'", texcount.realpageno, texcount.userpageno, texcount.subpageno)) end function logs.xml.stop_page_number() @@ -3908,7 +4194,7 @@ formats['ovf'] = 'OVFFONTS' suffixes['ovf'] = { 'ovf', 'vf' } formats['ovp'] = 'OVPFONTS' suffixes['ovp'] = { 'ovp' } formats['tex'] = 'TEXINPUTS' suffixes['tex'] = { 'tex' } formats['tfm'] = 'TFMFONTS' suffixes['tfm'] = { 'tfm' } -formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc' } +formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc', 'dfont' } formats['pfb'] = 'T1FONTS' suffixes['pfb'] = { 'pfb', 'pfa' } formats['vf'] = 'VFFONTS' suffixes['vf'] = { 'vf' } @@ -3930,6 +4216,7 @@ alternatives['fea files'] = 'fea' alternatives['opentype fonts'] = 'otf' alternatives['truetype fonts'] = 'ttf' alternatives['truetype collections'] = 'ttc' +alternatives['truetype dictionary'] = 'dfont' alternatives['type1 fonts'] = 'pfb' -- obscure ones @@ -4046,12 +4333,12 @@ local function reset_hashes() end local function check_configuration() -- not yet ok, no time for debugging now - local ie = instance.environment + local ie, iv = instance.environment, instance.variables local function fix(varname,default) local proname = varname .. "." .. instance.progname or "crap" - local p, v = ie[proname], ie[varname] + local p, v = ie[proname], ie[varname] or iv[varname] if not ((p and p ~= "") or (v and v ~= "")) then - instance.variables[varname] = default -- or environment? + iv[varname] = default -- or environment? end end local name = os.name @@ -5890,10 +6177,6 @@ caches.paths = caches.paths or nil caches.force = false caches.defaults = { "TEXMFCACHE", "TMPDIR", "TEMPDIR", "TMP", "TEMP", "HOME", "HOMEPATH" } -function caches.cleanname(name) - return (gsub(lower(name),"[^%w%d]+","-")) -end - function caches.temp() local cachepath = nil local function check(list,isenv) @@ -5990,7 +6273,9 @@ function caches.loaddata(path,name) local tmaname, tmcname = caches.setluanames(path,name) local loader = loadfile(tmcname) or loadfile(tmaname) if loader then - return loader() + loader = loader() + collectgarbage("step") + return loader else return false end @@ -6132,7 +6417,7 @@ function containers.define(category, subcategory, version, enabled) enabled = enabled, version = version or 1.000, trace = false, - path = caches and caches.setpath(category,subcategory), + path = caches and caches.setpath and caches.setpath(category,subcategory), } c[subcategory] = s end @@ -6191,6 +6476,10 @@ function containers.content(container,name) return container.storage[name] end +function containers.cleanname(name) + return (gsub(lower(name),"[^%w%d]+","-")) +end + end -- of closure @@ -6585,6 +6874,7 @@ own.libs = { -- todo: check which ones are really needed 'l-unicode.lua', 'l-math.lua', 'l-utils.lua', + 'l-aux.lua', 'trac-tra.lua', 'luat-env.lua', 'trac-inf.lua', diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua index aba22a16e..82d1edecb 100644 --- a/scripts/context/lua/mtxrun.lua +++ b/scripts/context/lua/mtxrun.lua @@ -421,6 +421,10 @@ function table.strip(tab) return lst end +local function compare(a,b) + return (tostring(a) < tostring(b)) +end + local function sortedkeys(tab) local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed for key,_ in next, tab do @@ -441,7 +445,7 @@ local function sortedkeys(tab) end end if kind == 0 or kind == 3 then - sort(srt,function(a,b) return (tostring(a) < tostring(b)) end) + sort(srt,compare) else sort(srt) end @@ -1072,7 +1076,7 @@ function table.insert_after_value(t,value,str) end local function are_equal(a,b,n,m) -- indexed - if #a == #b then + if a and b and #a == #b then n = n or 1 m = m or #a for i=n,m do @@ -1229,6 +1233,7 @@ end function io.loaddata(filename,textmode) local f = io.open(filename,(textmode and 'r') or 'rb') if f then + -- collectgarbage("step") -- sometimes makes a big difference in mem consumption local data = f:read('*all') -- garbagecollector.check(data) f:close() @@ -1465,6 +1470,7 @@ set = set or { } local nums = { } local tabs = { } local concat = table.concat +local next, type = next, type set.create = table.tohash @@ -1472,17 +1478,19 @@ function set.tonumber(t) if next(t) then local s = "" -- we could save mem by sorting, but it slows down - for k, v in pairs(t) do + for k, v in next, t do if v then -- why bother about the leading space s = s .. " " .. k end end - if not nums[s] then - tabs[#tabs+1] = t - nums[s] = #tabs + local n = nums[s] + if not n then + n = #tabs + 1 + tabs[n] = t + nums[s] = n end - return nums[s] + return n else return 0 end @@ -1496,6 +1504,20 @@ function set.totable(n) end end +function set.tolist(n) + if n == 0 or not tabs[n] then + return "" + else + local t = { } + for k, v in next, tabs[n] do + if v then + t[#t+1] = k + end + end + return concat(t," ") + end +end + function set.contains(n,s) if type(n) == "table" then return n[s] @@ -2600,6 +2622,235 @@ end -- of closure do -- create closure to overcome 200 locals limit +if not modules then modules = { } end modules ['l-aux'] = { + version = 1.001, + comment = "companion to luat-lib.tex", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +aux = aux or { } + +local concat, format, gmatch = table.concat, string.format, string.gmatch +local tostring, type = tostring, type + +local space = lpeg.P(' ') +local equal = lpeg.P("=") +local comma = lpeg.P(",") +local lbrace = lpeg.P("{") +local rbrace = lpeg.P("}") +local nobrace = 1 - (lbrace+rbrace) +local nested = lpeg.P{ lbrace * (nobrace + lpeg.V(1))^0 * rbrace } +local spaces = space^0 + +local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0) + +local key = lpeg.C((1-equal-comma)^1) +local pattern_a = (space+comma)^0 * (key * equal * value + key * lpeg.C("")) +local pattern_c = (space+comma)^0 * (key * equal * value) + +local key = lpeg.C((1-space-equal-comma)^1) +local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + lpeg.C(""))) + +-- "a=1, b=2, c=3, d={a{b,c}d}, e=12345, f=xx{a{b,c}d}xx, g={}" : outer {} removes, leading spaces ignored + +local hash = { } + +local function set(key,value) -- using Carg is slower here + hash[key] = value +end + +local pattern_a_s = (pattern_a/set)^1 +local pattern_b_s = (pattern_b/set)^1 +local pattern_c_s = (pattern_c/set)^1 + +aux.settings_to_hash_pattern_a = pattern_a_s +aux.settings_to_hash_pattern_b = pattern_b_s +aux.settings_to_hash_pattern_c = pattern_c_s + +function aux.make_settings_to_hash_pattern(set,how) + if how == "strict" then + return (pattern_c/set)^1 + elseif how == "tolerant" then + return (pattern_b/set)^1 + else + return (pattern_a/set)^1 + end +end + +function aux.settings_to_hash(str) + if str and str ~= "" then + hash = { } + if moretolerant then + pattern_b_s:match(str) + else + pattern_a_s:match(str) + end + return hash + else + return { } + end +end + +function aux.settings_to_hash_tolerant(str) + if str and str ~= "" then + hash = { } + pattern_b_s:match(str) + return hash + else + return { } + end +end + +function aux.settings_to_hash_strict(str) + if str and str ~= "" then + hash = { } + pattern_c_s:match(str) + return next(hash) and hash + else + return nil + end +end + +local seperator = comma * space^0 +local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0) +local pattern = lpeg.Ct(value*(seperator*value)^0) + +-- "aap, {noot}, mies" : outer {} removes, leading spaces ignored + +aux.settings_to_array_pattern = pattern + +function aux.settings_to_array(str) + if not str or str == "" then + return { } + else + return pattern:match(str) + end +end + +local function set(t,v) + t[#t+1] = v +end + +local value = lpeg.P(lpeg.Carg(1)*value) / set +local pattern = value*(seperator*value)^0 * lpeg.Carg(1) + +function aux.add_settings_to_array(t,str) + return pattern:match(str, nil, t) +end + +function aux.hash_to_string(h,separator,yes,no,strict,omit) + if h then + local t, s = { }, table.sortedkeys(h) + omit = omit and table.tohash(omit) + for i=1,#s do + local key = s[i] + if not omit or not omit[key] then + local value = h[key] + if type(value) == "boolean" then + if yes and no then + if value then + t[#t+1] = key .. '=' .. yes + elseif not strict then + t[#t+1] = key .. '=' .. no + end + elseif value or not strict then + t[#t+1] = key .. '=' .. tostring(value) + end + else + t[#t+1] = key .. '=' .. value + end + end + end + return concat(t,separator or ",") + else + return "" + end +end + +function aux.array_to_string(a,separator) + if a then + return concat(a,separator or ",") + else + return "" + end +end + +function aux.settings_to_set(str,t) + t = t or { } + for s in gmatch(str,"%s*([^,]+)") do + t[s] = true + end + return t +end + +-- temporary here + +function aux.getparameters(self,class,parentclass,settings) + local sc = self[class] + if not sc then + sc = table.clone(self[parent]) + self[class] = sc + end + aux.add_settings_to_array(sc, settings) +end + +-- temporary here + +local digit = lpeg.R("09") +local period = lpeg.P(".") +local zero = lpeg.P("0") + +--~ local finish = lpeg.P(-1) +--~ local nodigit = (1-digit) + finish +--~ local case_1 = (period * zero^1 * #nodigit)/"" -- .000 +--~ local case_2 = (period * (1-(zero^0/"") * #nodigit)^1 * (zero^0/"") * nodigit) -- .010 .10 .100100 + +local trailingzeros = zero^0 * -digit -- suggested by Roberto R +local case_1 = period * trailingzeros / "" +local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "") + +local number = digit^1 * (case_1 + case_2) +local stripper = lpeg.Cs((number + 1)^0) + +--~ local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100" +--~ collectgarbage("collect") +--~ str = string.rep(sample,10000) +--~ local ts = os.clock() +--~ stripper:match(str) +--~ print(#str, os.clock()-ts, stripper:match(sample)) + +function aux.strip_zeros(str) + return stripper:match(str) +end + +function aux.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 aux.accesstable(target) + local t = _G + for name in gmatch(target,"([^%.]+)") do + t = t[name] + end + return t +end + + +end -- of closure + +do -- create closure to overcome 200 locals limit + if not modules then modules = { } end modules ['lxml-tab'] = { version = 1.001, comment = "this module is the basis for the lxml-* ones", @@ -3047,7 +3298,7 @@ generic table copier. Since we know what we're dealing with we can speed up things a bit. The second argument is not to be used!</p> --ldx]]-- -function copy(old,tables) +local function copy(old,tables) if old then tables = tables or { } local new = { } @@ -3270,7 +3521,7 @@ function xml.tostring(root) -- 25% overhead due to collecting return root elseif next(root) then -- next is faster than type (and >0 test) local result = { } - serialize(root,function(s) result[#result+1] = s end) + serialize(root,function(s) result[#result+1] = s end) -- brrr, slow (direct printing is faster) return concat(result,"") end end @@ -5333,7 +5584,11 @@ trackers = trackers or { } local data, done = { }, { } local function set(what,value) - for w in gmatch(lower(what),"[^, ]+") do + if type(what) == "string" then + what = aux.settings_to_array(what) + end + for i=1,#what do + local w = what[i] for d, f in next, data do if done[d] then -- prevent recursion due to wildcards @@ -5712,27 +5967,34 @@ statistics.threshold = 0.05 local clock = os.gettimeofday or os.clock +local notimer + function statistics.hastimer(instance) return instance and instance.starttime end function statistics.starttiming(instance) - if instance then - local it = instance.timing - if not it then - it = 0 - end - if it == 0 then - instance.starttime = clock() - if not instance.loadtime then - instance.loadtime = 0 - end + if not instance then + notimer = { } + instance = notimer + end + local it = instance.timing + if not it then + it = 0 + end + if it == 0 then + instance.starttime = clock() + if not instance.loadtime then + instance.loadtime = 0 end - instance.timing = it + 1 end + instance.timing = it + 1 end function statistics.stoptiming(instance, report) + if not instance then + instance = notimer + end if instance then local it = instance.timing if it > 1 then @@ -5756,10 +6018,16 @@ function statistics.stoptiming(instance, report) end function statistics.elapsedtime(instance) + if not instance then + instance = notimer + end return format("%0.3f",(instance and instance.loadtime) or 0) end function statistics.elapsedindeed(instance) + if not instance then + instance = notimer + end local t = (instance and instance.loadtime) or 0 return t > statistics.threshold end @@ -5800,6 +6068,7 @@ function statistics.show(reporter) reporter(s[1],r,n) end end + texio.write_nl("") -- final newline statistics.enable = false end end @@ -5857,6 +6126,7 @@ if not modules then modules = { } end modules ['luat-log'] = { -- this is old code that needs an overhaul local write_nl, write, format = texio.write_nl or print, texio.write or io.write, string.format +local texcount = tex and tex.count if texlua then write_nl = print @@ -5936,10 +6206,8 @@ function logs.tex.line(fmt,...) -- new end end -local texcount = tex and tex.count - function logs.tex.start_page_number() - local real, user, sub = texcount[0], texcount[1], texcount[2] + local real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno if real > 0 then if user > 0 then if sub > 0 then @@ -5994,7 +6262,7 @@ function logs.xml.stop_run() end function logs.xml.start_page_number() - write_nl(format("<p real='%s' page='%s' sub='%s'", texcount[0], texcount[1], texcount[2])) + write_nl(format("<p real='%s' page='%s' sub='%s'", texcount.realpageno, texcount.userpageno, texcount.subpageno)) end function logs.xml.stop_page_number() @@ -6229,7 +6497,7 @@ formats['ovf'] = 'OVFFONTS' suffixes['ovf'] = { 'ovf', 'vf' } formats['ovp'] = 'OVPFONTS' suffixes['ovp'] = { 'ovp' } formats['tex'] = 'TEXINPUTS' suffixes['tex'] = { 'tex' } formats['tfm'] = 'TFMFONTS' suffixes['tfm'] = { 'tfm' } -formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc' } +formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc', 'dfont' } formats['pfb'] = 'T1FONTS' suffixes['pfb'] = { 'pfb', 'pfa' } formats['vf'] = 'VFFONTS' suffixes['vf'] = { 'vf' } @@ -6251,6 +6519,7 @@ alternatives['fea files'] = 'fea' alternatives['opentype fonts'] = 'otf' alternatives['truetype fonts'] = 'ttf' alternatives['truetype collections'] = 'ttc' +alternatives['truetype dictionary'] = 'dfont' alternatives['type1 fonts'] = 'pfb' -- obscure ones @@ -6367,12 +6636,12 @@ local function reset_hashes() end local function check_configuration() -- not yet ok, no time for debugging now - local ie = instance.environment + local ie, iv = instance.environment, instance.variables local function fix(varname,default) local proname = varname .. "." .. instance.progname or "crap" - local p, v = ie[proname], ie[varname] + local p, v = ie[proname], ie[varname] or iv[varname] if not ((p and p ~= "") or (v and v ~= "")) then - instance.variables[varname] = default -- or environment? + iv[varname] = default -- or environment? end end local name = os.name @@ -8307,7 +8576,9 @@ function caches.loaddata(path,name) local tmaname, tmcname = caches.setluanames(path,name) local loader = loadfile(tmcname) or loadfile(tmaname) if loader then - return loader() + loader = loader() + collectgarbage("step") + return loader else return false end @@ -9517,6 +9788,7 @@ own.libs = { -- todo: check which ones are really needed -- 'l-unicode.lua', -- 'l-tex.lua', 'l-utils.lua', + 'l-aux.lua', -- 'l-xml.lua', 'lxml-tab.lua', 'lxml-pth.lua', diff --git a/scripts/context/stubs/mswin/luatools.lua b/scripts/context/stubs/mswin/luatools.lua index f0fcd517d..433d1b8dc 100644 --- a/scripts/context/stubs/mswin/luatools.lua +++ b/scripts/context/stubs/mswin/luatools.lua @@ -265,6 +265,11 @@ 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 end -- of closure @@ -407,6 +412,10 @@ function table.strip(tab) return lst end +local function compare(a,b) + return (tostring(a) < tostring(b)) +end + local function sortedkeys(tab) local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed for key,_ in next, tab do @@ -427,7 +436,7 @@ local function sortedkeys(tab) end end if kind == 0 or kind == 3 then - sort(srt,function(a,b) return (tostring(a) < tostring(b)) end) + sort(srt,compare) else sort(srt) end @@ -1058,7 +1067,7 @@ function table.insert_after_value(t,value,str) end local function are_equal(a,b,n,m) -- indexed - if #a == #b then + if a and b and #a == #b then n = n or 1 m = m or #a for i=n,m do @@ -1215,6 +1224,7 @@ end function io.loaddata(filename,textmode) local f = io.open(filename,(textmode and 'r') or 'rb') if f then + -- collectgarbage("step") -- sometimes makes a big difference in mem consumption local data = f:read('*all') -- garbagecollector.check(data) f:close() @@ -1451,6 +1461,7 @@ set = set or { } local nums = { } local tabs = { } local concat = table.concat +local next, type = next, type set.create = table.tohash @@ -1458,17 +1469,19 @@ function set.tonumber(t) if next(t) then local s = "" -- we could save mem by sorting, but it slows down - for k, v in pairs(t) do + for k, v in next, t do if v then -- why bother about the leading space s = s .. " " .. k end end - if not nums[s] then - tabs[#tabs+1] = t - nums[s] = #tabs + local n = nums[s] + if not n then + n = #tabs + 1 + tabs[n] = t + nums[s] = n end - return nums[s] + return n else return 0 end @@ -1482,6 +1495,20 @@ function set.totable(n) end end +function set.tolist(n) + if n == 0 or not tabs[n] then + return "" + else + local t = { } + for k, v in next, tabs[n] do + if v then + t[#t+1] = k + end + end + return concat(t," ") + end +end + function set.contains(n,s) if type(n) == "table" then return n[s] @@ -1678,8 +1705,8 @@ function file.replacesuffix(filename, suffix) return (gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix end -function file.dirname(name) - return match(name,"^(.+)[/\\].-$") or "" +function file.dirname(name,default) + return match(name,"^(.+)[/\\].-$") or (default or "") end function file.basename(name) @@ -1717,15 +1744,8 @@ function file.join(...) end function file.iswritable(name) - local a = lfs.attributes(name) - if a and a.permissions:sub(2,2) == "w" then - return true - else - name = file.dirname(name) or "." - if name == "" then name = "." end - a = lfs.attributes(name) - return a and a.permissions:sub(2,2) == "w" - end + local a = lfs.attributes(name) or lfs.attributes(file.dirname(name,".")) + return a and a.permissions:sub(2,2) == "w" end function file.isreadable(name) @@ -1893,6 +1913,26 @@ function file.is_rootbased_path(filename) return rootbased:match(filename) end +local slash = lpeg.S("\\/") +local period = lpeg.P(".") +local drive = lpeg.C(lpeg.R("az","AZ")) * lpeg.P(":") +local path = lpeg.C(((1-slash)^0 * slash)^0) +local suffix = period * lpeg.C(lpeg.P(1-period)^0 * lpeg.P(-1)) +local base = lpeg.C((1-suffix)^0) + +local pattern = (drive + lpeg.Cc("")) * (path + lpeg.Cc("")) * (base + lpeg.Cc("")) * (suffix + lpeg.Cc("")) + +function file.splitname(str) -- returns drive, path, base, suffix + return pattern:match(str) +end + +-- function test(t) for k, v in pairs(t) do print(v, "=>", file.splitname(v)) end end +-- +-- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" } +-- test { "c:", "c:aa", "c:aa/bb", "c:aa/bb/cc", "c:aa/bb/cc.dd", "c:aa/bb/cc.dd.ee" } +-- test { "/aa", "/aa/bb", "/aa/bb/cc", "/aa/bb/cc.dd", "/aa/bb/cc.dd.ee" } +-- test { "aa", "aa/bb", "aa/bb/cc", "aa/bb/cc.dd", "aa/bb/cc.dd.ee" } + end -- of closure @@ -1948,7 +1988,7 @@ function file.checksum(name) if md5 then local data = io.loaddata(name) if data then - return md5.HEXsum(data) + return md5.HEX(data) end end return nil @@ -2862,6 +2902,235 @@ end -- of closure do -- create closure to overcome 200 locals limit +if not modules then modules = { } end modules ['l-aux'] = { + version = 1.001, + comment = "companion to luat-lib.tex", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +aux = aux or { } + +local concat, format, gmatch = table.concat, string.format, string.gmatch +local tostring, type = tostring, type + +local space = lpeg.P(' ') +local equal = lpeg.P("=") +local comma = lpeg.P(",") +local lbrace = lpeg.P("{") +local rbrace = lpeg.P("}") +local nobrace = 1 - (lbrace+rbrace) +local nested = lpeg.P{ lbrace * (nobrace + lpeg.V(1))^0 * rbrace } +local spaces = space^0 + +local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0) + +local key = lpeg.C((1-equal-comma)^1) +local pattern_a = (space+comma)^0 * (key * equal * value + key * lpeg.C("")) +local pattern_c = (space+comma)^0 * (key * equal * value) + +local key = lpeg.C((1-space-equal-comma)^1) +local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + lpeg.C(""))) + +-- "a=1, b=2, c=3, d={a{b,c}d}, e=12345, f=xx{a{b,c}d}xx, g={}" : outer {} removes, leading spaces ignored + +local hash = { } + +local function set(key,value) -- using Carg is slower here + hash[key] = value +end + +local pattern_a_s = (pattern_a/set)^1 +local pattern_b_s = (pattern_b/set)^1 +local pattern_c_s = (pattern_c/set)^1 + +aux.settings_to_hash_pattern_a = pattern_a_s +aux.settings_to_hash_pattern_b = pattern_b_s +aux.settings_to_hash_pattern_c = pattern_c_s + +function aux.make_settings_to_hash_pattern(set,how) + if how == "strict" then + return (pattern_c/set)^1 + elseif how == "tolerant" then + return (pattern_b/set)^1 + else + return (pattern_a/set)^1 + end +end + +function aux.settings_to_hash(str) + if str and str ~= "" then + hash = { } + if moretolerant then + pattern_b_s:match(str) + else + pattern_a_s:match(str) + end + return hash + else + return { } + end +end + +function aux.settings_to_hash_tolerant(str) + if str and str ~= "" then + hash = { } + pattern_b_s:match(str) + return hash + else + return { } + end +end + +function aux.settings_to_hash_strict(str) + if str and str ~= "" then + hash = { } + pattern_c_s:match(str) + return next(hash) and hash + else + return nil + end +end + +local seperator = comma * space^0 +local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0) +local pattern = lpeg.Ct(value*(seperator*value)^0) + +-- "aap, {noot}, mies" : outer {} removes, leading spaces ignored + +aux.settings_to_array_pattern = pattern + +function aux.settings_to_array(str) + if not str or str == "" then + return { } + else + return pattern:match(str) + end +end + +local function set(t,v) + t[#t+1] = v +end + +local value = lpeg.P(lpeg.Carg(1)*value) / set +local pattern = value*(seperator*value)^0 * lpeg.Carg(1) + +function aux.add_settings_to_array(t,str) + return pattern:match(str, nil, t) +end + +function aux.hash_to_string(h,separator,yes,no,strict,omit) + if h then + local t, s = { }, table.sortedkeys(h) + omit = omit and table.tohash(omit) + for i=1,#s do + local key = s[i] + if not omit or not omit[key] then + local value = h[key] + if type(value) == "boolean" then + if yes and no then + if value then + t[#t+1] = key .. '=' .. yes + elseif not strict then + t[#t+1] = key .. '=' .. no + end + elseif value or not strict then + t[#t+1] = key .. '=' .. tostring(value) + end + else + t[#t+1] = key .. '=' .. value + end + end + end + return concat(t,separator or ",") + else + return "" + end +end + +function aux.array_to_string(a,separator) + if a then + return concat(a,separator or ",") + else + return "" + end +end + +function aux.settings_to_set(str,t) + t = t or { } + for s in gmatch(str,"%s*([^,]+)") do + t[s] = true + end + return t +end + +-- temporary here + +function aux.getparameters(self,class,parentclass,settings) + local sc = self[class] + if not sc then + sc = table.clone(self[parent]) + self[class] = sc + end + aux.add_settings_to_array(sc, settings) +end + +-- temporary here + +local digit = lpeg.R("09") +local period = lpeg.P(".") +local zero = lpeg.P("0") + +--~ local finish = lpeg.P(-1) +--~ local nodigit = (1-digit) + finish +--~ local case_1 = (period * zero^1 * #nodigit)/"" -- .000 +--~ local case_2 = (period * (1-(zero^0/"") * #nodigit)^1 * (zero^0/"") * nodigit) -- .010 .10 .100100 + +local trailingzeros = zero^0 * -digit -- suggested by Roberto R +local case_1 = period * trailingzeros / "" +local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "") + +local number = digit^1 * (case_1 + case_2) +local stripper = lpeg.Cs((number + 1)^0) + +--~ local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100" +--~ collectgarbage("collect") +--~ str = string.rep(sample,10000) +--~ local ts = os.clock() +--~ stripper:match(str) +--~ print(#str, os.clock()-ts, stripper:match(sample)) + +function aux.strip_zeros(str) + return stripper:match(str) +end + +function aux.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 aux.accesstable(target) + local t = _G + for name in gmatch(target,"([^%.]+)") do + t = t[name] + end + return t +end + + +end -- of closure + +do -- create closure to overcome 200 locals limit + if not modules then modules = { } end modules ['trac-tra'] = { version = 1.001, comment = "companion to luat-lib.tex", @@ -3012,7 +3281,11 @@ trackers = trackers or { } local data, done = { }, { } local function set(what,value) - for w in gmatch(lower(what),"[^, ]+") do + if type(what) == "string" then + what = aux.settings_to_array(what) + end + for i=1,#what do + local w = what[i] for d, f in next, data do if done[d] then -- prevent recursion due to wildcards @@ -3391,27 +3664,34 @@ statistics.threshold = 0.05 local clock = os.gettimeofday or os.clock +local notimer + function statistics.hastimer(instance) return instance and instance.starttime end function statistics.starttiming(instance) - if instance then - local it = instance.timing - if not it then - it = 0 - end - if it == 0 then - instance.starttime = clock() - if not instance.loadtime then - instance.loadtime = 0 - end + if not instance then + notimer = { } + instance = notimer + end + local it = instance.timing + if not it then + it = 0 + end + if it == 0 then + instance.starttime = clock() + if not instance.loadtime then + instance.loadtime = 0 end - instance.timing = it + 1 end + instance.timing = it + 1 end function statistics.stoptiming(instance, report) + if not instance then + instance = notimer + end if instance then local it = instance.timing if it > 1 then @@ -3435,10 +3715,16 @@ function statistics.stoptiming(instance, report) end function statistics.elapsedtime(instance) + if not instance then + instance = notimer + end return format("%0.3f",(instance and instance.loadtime) or 0) end function statistics.elapsedindeed(instance) + if not instance then + instance = notimer + end local t = (instance and instance.loadtime) or 0 return t > statistics.threshold end @@ -3479,6 +3765,7 @@ function statistics.show(reporter) reporter(s[1],r,n) end end + texio.write_nl("") -- final newline statistics.enable = false end end @@ -3536,6 +3823,7 @@ if not modules then modules = { } end modules ['luat-log'] = { -- this is old code that needs an overhaul local write_nl, write, format = texio.write_nl or print, texio.write or io.write, string.format +local texcount = tex and tex.count if texlua then write_nl = print @@ -3615,10 +3903,8 @@ function logs.tex.line(fmt,...) -- new end end -local texcount = tex and tex.count - function logs.tex.start_page_number() - local real, user, sub = texcount[0], texcount[1], texcount[2] + local real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno if real > 0 then if user > 0 then if sub > 0 then @@ -3673,7 +3959,7 @@ function logs.xml.stop_run() end function logs.xml.start_page_number() - write_nl(format("<p real='%s' page='%s' sub='%s'", texcount[0], texcount[1], texcount[2])) + write_nl(format("<p real='%s' page='%s' sub='%s'", texcount.realpageno, texcount.userpageno, texcount.subpageno)) end function logs.xml.stop_page_number() @@ -3908,7 +4194,7 @@ formats['ovf'] = 'OVFFONTS' suffixes['ovf'] = { 'ovf', 'vf' } formats['ovp'] = 'OVPFONTS' suffixes['ovp'] = { 'ovp' } formats['tex'] = 'TEXINPUTS' suffixes['tex'] = { 'tex' } formats['tfm'] = 'TFMFONTS' suffixes['tfm'] = { 'tfm' } -formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc' } +formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc', 'dfont' } formats['pfb'] = 'T1FONTS' suffixes['pfb'] = { 'pfb', 'pfa' } formats['vf'] = 'VFFONTS' suffixes['vf'] = { 'vf' } @@ -3930,6 +4216,7 @@ alternatives['fea files'] = 'fea' alternatives['opentype fonts'] = 'otf' alternatives['truetype fonts'] = 'ttf' alternatives['truetype collections'] = 'ttc' +alternatives['truetype dictionary'] = 'dfont' alternatives['type1 fonts'] = 'pfb' -- obscure ones @@ -4046,12 +4333,12 @@ local function reset_hashes() end local function check_configuration() -- not yet ok, no time for debugging now - local ie = instance.environment + local ie, iv = instance.environment, instance.variables local function fix(varname,default) local proname = varname .. "." .. instance.progname or "crap" - local p, v = ie[proname], ie[varname] + local p, v = ie[proname], ie[varname] or iv[varname] if not ((p and p ~= "") or (v and v ~= "")) then - instance.variables[varname] = default -- or environment? + iv[varname] = default -- or environment? end end local name = os.name @@ -5890,10 +6177,6 @@ caches.paths = caches.paths or nil caches.force = false caches.defaults = { "TEXMFCACHE", "TMPDIR", "TEMPDIR", "TMP", "TEMP", "HOME", "HOMEPATH" } -function caches.cleanname(name) - return (gsub(lower(name),"[^%w%d]+","-")) -end - function caches.temp() local cachepath = nil local function check(list,isenv) @@ -5990,7 +6273,9 @@ function caches.loaddata(path,name) local tmaname, tmcname = caches.setluanames(path,name) local loader = loadfile(tmcname) or loadfile(tmaname) if loader then - return loader() + loader = loader() + collectgarbage("step") + return loader else return false end @@ -6132,7 +6417,7 @@ function containers.define(category, subcategory, version, enabled) enabled = enabled, version = version or 1.000, trace = false, - path = caches and caches.setpath(category,subcategory), + path = caches and caches.setpath and caches.setpath(category,subcategory), } c[subcategory] = s end @@ -6191,6 +6476,10 @@ function containers.content(container,name) return container.storage[name] end +function containers.cleanname(name) + return (gsub(lower(name),"[^%w%d]+","-")) +end + end -- of closure @@ -6585,6 +6874,7 @@ own.libs = { -- todo: check which ones are really needed 'l-unicode.lua', 'l-math.lua', 'l-utils.lua', + 'l-aux.lua', 'trac-tra.lua', 'luat-env.lua', 'trac-inf.lua', diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua index aba22a16e..82d1edecb 100644 --- a/scripts/context/stubs/mswin/mtxrun.lua +++ b/scripts/context/stubs/mswin/mtxrun.lua @@ -421,6 +421,10 @@ function table.strip(tab) return lst end +local function compare(a,b) + return (tostring(a) < tostring(b)) +end + local function sortedkeys(tab) local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed for key,_ in next, tab do @@ -441,7 +445,7 @@ local function sortedkeys(tab) end end if kind == 0 or kind == 3 then - sort(srt,function(a,b) return (tostring(a) < tostring(b)) end) + sort(srt,compare) else sort(srt) end @@ -1072,7 +1076,7 @@ function table.insert_after_value(t,value,str) end local function are_equal(a,b,n,m) -- indexed - if #a == #b then + if a and b and #a == #b then n = n or 1 m = m or #a for i=n,m do @@ -1229,6 +1233,7 @@ end function io.loaddata(filename,textmode) local f = io.open(filename,(textmode and 'r') or 'rb') if f then + -- collectgarbage("step") -- sometimes makes a big difference in mem consumption local data = f:read('*all') -- garbagecollector.check(data) f:close() @@ -1465,6 +1470,7 @@ set = set or { } local nums = { } local tabs = { } local concat = table.concat +local next, type = next, type set.create = table.tohash @@ -1472,17 +1478,19 @@ function set.tonumber(t) if next(t) then local s = "" -- we could save mem by sorting, but it slows down - for k, v in pairs(t) do + for k, v in next, t do if v then -- why bother about the leading space s = s .. " " .. k end end - if not nums[s] then - tabs[#tabs+1] = t - nums[s] = #tabs + local n = nums[s] + if not n then + n = #tabs + 1 + tabs[n] = t + nums[s] = n end - return nums[s] + return n else return 0 end @@ -1496,6 +1504,20 @@ function set.totable(n) end end +function set.tolist(n) + if n == 0 or not tabs[n] then + return "" + else + local t = { } + for k, v in next, tabs[n] do + if v then + t[#t+1] = k + end + end + return concat(t," ") + end +end + function set.contains(n,s) if type(n) == "table" then return n[s] @@ -2600,6 +2622,235 @@ end -- of closure do -- create closure to overcome 200 locals limit +if not modules then modules = { } end modules ['l-aux'] = { + version = 1.001, + comment = "companion to luat-lib.tex", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +aux = aux or { } + +local concat, format, gmatch = table.concat, string.format, string.gmatch +local tostring, type = tostring, type + +local space = lpeg.P(' ') +local equal = lpeg.P("=") +local comma = lpeg.P(",") +local lbrace = lpeg.P("{") +local rbrace = lpeg.P("}") +local nobrace = 1 - (lbrace+rbrace) +local nested = lpeg.P{ lbrace * (nobrace + lpeg.V(1))^0 * rbrace } +local spaces = space^0 + +local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0) + +local key = lpeg.C((1-equal-comma)^1) +local pattern_a = (space+comma)^0 * (key * equal * value + key * lpeg.C("")) +local pattern_c = (space+comma)^0 * (key * equal * value) + +local key = lpeg.C((1-space-equal-comma)^1) +local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + lpeg.C(""))) + +-- "a=1, b=2, c=3, d={a{b,c}d}, e=12345, f=xx{a{b,c}d}xx, g={}" : outer {} removes, leading spaces ignored + +local hash = { } + +local function set(key,value) -- using Carg is slower here + hash[key] = value +end + +local pattern_a_s = (pattern_a/set)^1 +local pattern_b_s = (pattern_b/set)^1 +local pattern_c_s = (pattern_c/set)^1 + +aux.settings_to_hash_pattern_a = pattern_a_s +aux.settings_to_hash_pattern_b = pattern_b_s +aux.settings_to_hash_pattern_c = pattern_c_s + +function aux.make_settings_to_hash_pattern(set,how) + if how == "strict" then + return (pattern_c/set)^1 + elseif how == "tolerant" then + return (pattern_b/set)^1 + else + return (pattern_a/set)^1 + end +end + +function aux.settings_to_hash(str) + if str and str ~= "" then + hash = { } + if moretolerant then + pattern_b_s:match(str) + else + pattern_a_s:match(str) + end + return hash + else + return { } + end +end + +function aux.settings_to_hash_tolerant(str) + if str and str ~= "" then + hash = { } + pattern_b_s:match(str) + return hash + else + return { } + end +end + +function aux.settings_to_hash_strict(str) + if str and str ~= "" then + hash = { } + pattern_c_s:match(str) + return next(hash) and hash + else + return nil + end +end + +local seperator = comma * space^0 +local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0) +local pattern = lpeg.Ct(value*(seperator*value)^0) + +-- "aap, {noot}, mies" : outer {} removes, leading spaces ignored + +aux.settings_to_array_pattern = pattern + +function aux.settings_to_array(str) + if not str or str == "" then + return { } + else + return pattern:match(str) + end +end + +local function set(t,v) + t[#t+1] = v +end + +local value = lpeg.P(lpeg.Carg(1)*value) / set +local pattern = value*(seperator*value)^0 * lpeg.Carg(1) + +function aux.add_settings_to_array(t,str) + return pattern:match(str, nil, t) +end + +function aux.hash_to_string(h,separator,yes,no,strict,omit) + if h then + local t, s = { }, table.sortedkeys(h) + omit = omit and table.tohash(omit) + for i=1,#s do + local key = s[i] + if not omit or not omit[key] then + local value = h[key] + if type(value) == "boolean" then + if yes and no then + if value then + t[#t+1] = key .. '=' .. yes + elseif not strict then + t[#t+1] = key .. '=' .. no + end + elseif value or not strict then + t[#t+1] = key .. '=' .. tostring(value) + end + else + t[#t+1] = key .. '=' .. value + end + end + end + return concat(t,separator or ",") + else + return "" + end +end + +function aux.array_to_string(a,separator) + if a then + return concat(a,separator or ",") + else + return "" + end +end + +function aux.settings_to_set(str,t) + t = t or { } + for s in gmatch(str,"%s*([^,]+)") do + t[s] = true + end + return t +end + +-- temporary here + +function aux.getparameters(self,class,parentclass,settings) + local sc = self[class] + if not sc then + sc = table.clone(self[parent]) + self[class] = sc + end + aux.add_settings_to_array(sc, settings) +end + +-- temporary here + +local digit = lpeg.R("09") +local period = lpeg.P(".") +local zero = lpeg.P("0") + +--~ local finish = lpeg.P(-1) +--~ local nodigit = (1-digit) + finish +--~ local case_1 = (period * zero^1 * #nodigit)/"" -- .000 +--~ local case_2 = (period * (1-(zero^0/"") * #nodigit)^1 * (zero^0/"") * nodigit) -- .010 .10 .100100 + +local trailingzeros = zero^0 * -digit -- suggested by Roberto R +local case_1 = period * trailingzeros / "" +local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "") + +local number = digit^1 * (case_1 + case_2) +local stripper = lpeg.Cs((number + 1)^0) + +--~ local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100" +--~ collectgarbage("collect") +--~ str = string.rep(sample,10000) +--~ local ts = os.clock() +--~ stripper:match(str) +--~ print(#str, os.clock()-ts, stripper:match(sample)) + +function aux.strip_zeros(str) + return stripper:match(str) +end + +function aux.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 aux.accesstable(target) + local t = _G + for name in gmatch(target,"([^%.]+)") do + t = t[name] + end + return t +end + + +end -- of closure + +do -- create closure to overcome 200 locals limit + if not modules then modules = { } end modules ['lxml-tab'] = { version = 1.001, comment = "this module is the basis for the lxml-* ones", @@ -3047,7 +3298,7 @@ generic table copier. Since we know what we're dealing with we can speed up things a bit. The second argument is not to be used!</p> --ldx]]-- -function copy(old,tables) +local function copy(old,tables) if old then tables = tables or { } local new = { } @@ -3270,7 +3521,7 @@ function xml.tostring(root) -- 25% overhead due to collecting return root elseif next(root) then -- next is faster than type (and >0 test) local result = { } - serialize(root,function(s) result[#result+1] = s end) + serialize(root,function(s) result[#result+1] = s end) -- brrr, slow (direct printing is faster) return concat(result,"") end end @@ -5333,7 +5584,11 @@ trackers = trackers or { } local data, done = { }, { } local function set(what,value) - for w in gmatch(lower(what),"[^, ]+") do + if type(what) == "string" then + what = aux.settings_to_array(what) + end + for i=1,#what do + local w = what[i] for d, f in next, data do if done[d] then -- prevent recursion due to wildcards @@ -5712,27 +5967,34 @@ statistics.threshold = 0.05 local clock = os.gettimeofday or os.clock +local notimer + function statistics.hastimer(instance) return instance and instance.starttime end function statistics.starttiming(instance) - if instance then - local it = instance.timing - if not it then - it = 0 - end - if it == 0 then - instance.starttime = clock() - if not instance.loadtime then - instance.loadtime = 0 - end + if not instance then + notimer = { } + instance = notimer + end + local it = instance.timing + if not it then + it = 0 + end + if it == 0 then + instance.starttime = clock() + if not instance.loadtime then + instance.loadtime = 0 end - instance.timing = it + 1 end + instance.timing = it + 1 end function statistics.stoptiming(instance, report) + if not instance then + instance = notimer + end if instance then local it = instance.timing if it > 1 then @@ -5756,10 +6018,16 @@ function statistics.stoptiming(instance, report) end function statistics.elapsedtime(instance) + if not instance then + instance = notimer + end return format("%0.3f",(instance and instance.loadtime) or 0) end function statistics.elapsedindeed(instance) + if not instance then + instance = notimer + end local t = (instance and instance.loadtime) or 0 return t > statistics.threshold end @@ -5800,6 +6068,7 @@ function statistics.show(reporter) reporter(s[1],r,n) end end + texio.write_nl("") -- final newline statistics.enable = false end end @@ -5857,6 +6126,7 @@ if not modules then modules = { } end modules ['luat-log'] = { -- this is old code that needs an overhaul local write_nl, write, format = texio.write_nl or print, texio.write or io.write, string.format +local texcount = tex and tex.count if texlua then write_nl = print @@ -5936,10 +6206,8 @@ function logs.tex.line(fmt,...) -- new end end -local texcount = tex and tex.count - function logs.tex.start_page_number() - local real, user, sub = texcount[0], texcount[1], texcount[2] + local real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno if real > 0 then if user > 0 then if sub > 0 then @@ -5994,7 +6262,7 @@ function logs.xml.stop_run() end function logs.xml.start_page_number() - write_nl(format("<p real='%s' page='%s' sub='%s'", texcount[0], texcount[1], texcount[2])) + write_nl(format("<p real='%s' page='%s' sub='%s'", texcount.realpageno, texcount.userpageno, texcount.subpageno)) end function logs.xml.stop_page_number() @@ -6229,7 +6497,7 @@ formats['ovf'] = 'OVFFONTS' suffixes['ovf'] = { 'ovf', 'vf' } formats['ovp'] = 'OVPFONTS' suffixes['ovp'] = { 'ovp' } formats['tex'] = 'TEXINPUTS' suffixes['tex'] = { 'tex' } formats['tfm'] = 'TFMFONTS' suffixes['tfm'] = { 'tfm' } -formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc' } +formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc', 'dfont' } formats['pfb'] = 'T1FONTS' suffixes['pfb'] = { 'pfb', 'pfa' } formats['vf'] = 'VFFONTS' suffixes['vf'] = { 'vf' } @@ -6251,6 +6519,7 @@ alternatives['fea files'] = 'fea' alternatives['opentype fonts'] = 'otf' alternatives['truetype fonts'] = 'ttf' alternatives['truetype collections'] = 'ttc' +alternatives['truetype dictionary'] = 'dfont' alternatives['type1 fonts'] = 'pfb' -- obscure ones @@ -6367,12 +6636,12 @@ local function reset_hashes() end local function check_configuration() -- not yet ok, no time for debugging now - local ie = instance.environment + local ie, iv = instance.environment, instance.variables local function fix(varname,default) local proname = varname .. "." .. instance.progname or "crap" - local p, v = ie[proname], ie[varname] + local p, v = ie[proname], ie[varname] or iv[varname] if not ((p and p ~= "") or (v and v ~= "")) then - instance.variables[varname] = default -- or environment? + iv[varname] = default -- or environment? end end local name = os.name @@ -8307,7 +8576,9 @@ function caches.loaddata(path,name) local tmaname, tmcname = caches.setluanames(path,name) local loader = loadfile(tmcname) or loadfile(tmaname) if loader then - return loader() + loader = loader() + collectgarbage("step") + return loader else return false end @@ -9517,6 +9788,7 @@ own.libs = { -- todo: check which ones are really needed -- 'l-unicode.lua', -- 'l-tex.lua', 'l-utils.lua', + 'l-aux.lua', -- 'l-xml.lua', 'lxml-tab.lua', 'lxml-pth.lua', diff --git a/scripts/context/stubs/unix/luatools b/scripts/context/stubs/unix/luatools index f0fcd517d..433d1b8dc 100755 --- a/scripts/context/stubs/unix/luatools +++ b/scripts/context/stubs/unix/luatools @@ -265,6 +265,11 @@ 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 end -- of closure @@ -407,6 +412,10 @@ function table.strip(tab) return lst end +local function compare(a,b) + return (tostring(a) < tostring(b)) +end + local function sortedkeys(tab) local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed for key,_ in next, tab do @@ -427,7 +436,7 @@ local function sortedkeys(tab) end end if kind == 0 or kind == 3 then - sort(srt,function(a,b) return (tostring(a) < tostring(b)) end) + sort(srt,compare) else sort(srt) end @@ -1058,7 +1067,7 @@ function table.insert_after_value(t,value,str) end local function are_equal(a,b,n,m) -- indexed - if #a == #b then + if a and b and #a == #b then n = n or 1 m = m or #a for i=n,m do @@ -1215,6 +1224,7 @@ end function io.loaddata(filename,textmode) local f = io.open(filename,(textmode and 'r') or 'rb') if f then + -- collectgarbage("step") -- sometimes makes a big difference in mem consumption local data = f:read('*all') -- garbagecollector.check(data) f:close() @@ -1451,6 +1461,7 @@ set = set or { } local nums = { } local tabs = { } local concat = table.concat +local next, type = next, type set.create = table.tohash @@ -1458,17 +1469,19 @@ function set.tonumber(t) if next(t) then local s = "" -- we could save mem by sorting, but it slows down - for k, v in pairs(t) do + for k, v in next, t do if v then -- why bother about the leading space s = s .. " " .. k end end - if not nums[s] then - tabs[#tabs+1] = t - nums[s] = #tabs + local n = nums[s] + if not n then + n = #tabs + 1 + tabs[n] = t + nums[s] = n end - return nums[s] + return n else return 0 end @@ -1482,6 +1495,20 @@ function set.totable(n) end end +function set.tolist(n) + if n == 0 or not tabs[n] then + return "" + else + local t = { } + for k, v in next, tabs[n] do + if v then + t[#t+1] = k + end + end + return concat(t," ") + end +end + function set.contains(n,s) if type(n) == "table" then return n[s] @@ -1678,8 +1705,8 @@ function file.replacesuffix(filename, suffix) return (gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix end -function file.dirname(name) - return match(name,"^(.+)[/\\].-$") or "" +function file.dirname(name,default) + return match(name,"^(.+)[/\\].-$") or (default or "") end function file.basename(name) @@ -1717,15 +1744,8 @@ function file.join(...) end function file.iswritable(name) - local a = lfs.attributes(name) - if a and a.permissions:sub(2,2) == "w" then - return true - else - name = file.dirname(name) or "." - if name == "" then name = "." end - a = lfs.attributes(name) - return a and a.permissions:sub(2,2) == "w" - end + local a = lfs.attributes(name) or lfs.attributes(file.dirname(name,".")) + return a and a.permissions:sub(2,2) == "w" end function file.isreadable(name) @@ -1893,6 +1913,26 @@ function file.is_rootbased_path(filename) return rootbased:match(filename) end +local slash = lpeg.S("\\/") +local period = lpeg.P(".") +local drive = lpeg.C(lpeg.R("az","AZ")) * lpeg.P(":") +local path = lpeg.C(((1-slash)^0 * slash)^0) +local suffix = period * lpeg.C(lpeg.P(1-period)^0 * lpeg.P(-1)) +local base = lpeg.C((1-suffix)^0) + +local pattern = (drive + lpeg.Cc("")) * (path + lpeg.Cc("")) * (base + lpeg.Cc("")) * (suffix + lpeg.Cc("")) + +function file.splitname(str) -- returns drive, path, base, suffix + return pattern:match(str) +end + +-- function test(t) for k, v in pairs(t) do print(v, "=>", file.splitname(v)) end end +-- +-- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" } +-- test { "c:", "c:aa", "c:aa/bb", "c:aa/bb/cc", "c:aa/bb/cc.dd", "c:aa/bb/cc.dd.ee" } +-- test { "/aa", "/aa/bb", "/aa/bb/cc", "/aa/bb/cc.dd", "/aa/bb/cc.dd.ee" } +-- test { "aa", "aa/bb", "aa/bb/cc", "aa/bb/cc.dd", "aa/bb/cc.dd.ee" } + end -- of closure @@ -1948,7 +1988,7 @@ function file.checksum(name) if md5 then local data = io.loaddata(name) if data then - return md5.HEXsum(data) + return md5.HEX(data) end end return nil @@ -2862,6 +2902,235 @@ end -- of closure do -- create closure to overcome 200 locals limit +if not modules then modules = { } end modules ['l-aux'] = { + version = 1.001, + comment = "companion to luat-lib.tex", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +aux = aux or { } + +local concat, format, gmatch = table.concat, string.format, string.gmatch +local tostring, type = tostring, type + +local space = lpeg.P(' ') +local equal = lpeg.P("=") +local comma = lpeg.P(",") +local lbrace = lpeg.P("{") +local rbrace = lpeg.P("}") +local nobrace = 1 - (lbrace+rbrace) +local nested = lpeg.P{ lbrace * (nobrace + lpeg.V(1))^0 * rbrace } +local spaces = space^0 + +local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0) + +local key = lpeg.C((1-equal-comma)^1) +local pattern_a = (space+comma)^0 * (key * equal * value + key * lpeg.C("")) +local pattern_c = (space+comma)^0 * (key * equal * value) + +local key = lpeg.C((1-space-equal-comma)^1) +local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + lpeg.C(""))) + +-- "a=1, b=2, c=3, d={a{b,c}d}, e=12345, f=xx{a{b,c}d}xx, g={}" : outer {} removes, leading spaces ignored + +local hash = { } + +local function set(key,value) -- using Carg is slower here + hash[key] = value +end + +local pattern_a_s = (pattern_a/set)^1 +local pattern_b_s = (pattern_b/set)^1 +local pattern_c_s = (pattern_c/set)^1 + +aux.settings_to_hash_pattern_a = pattern_a_s +aux.settings_to_hash_pattern_b = pattern_b_s +aux.settings_to_hash_pattern_c = pattern_c_s + +function aux.make_settings_to_hash_pattern(set,how) + if how == "strict" then + return (pattern_c/set)^1 + elseif how == "tolerant" then + return (pattern_b/set)^1 + else + return (pattern_a/set)^1 + end +end + +function aux.settings_to_hash(str) + if str and str ~= "" then + hash = { } + if moretolerant then + pattern_b_s:match(str) + else + pattern_a_s:match(str) + end + return hash + else + return { } + end +end + +function aux.settings_to_hash_tolerant(str) + if str and str ~= "" then + hash = { } + pattern_b_s:match(str) + return hash + else + return { } + end +end + +function aux.settings_to_hash_strict(str) + if str and str ~= "" then + hash = { } + pattern_c_s:match(str) + return next(hash) and hash + else + return nil + end +end + +local seperator = comma * space^0 +local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0) +local pattern = lpeg.Ct(value*(seperator*value)^0) + +-- "aap, {noot}, mies" : outer {} removes, leading spaces ignored + +aux.settings_to_array_pattern = pattern + +function aux.settings_to_array(str) + if not str or str == "" then + return { } + else + return pattern:match(str) + end +end + +local function set(t,v) + t[#t+1] = v +end + +local value = lpeg.P(lpeg.Carg(1)*value) / set +local pattern = value*(seperator*value)^0 * lpeg.Carg(1) + +function aux.add_settings_to_array(t,str) + return pattern:match(str, nil, t) +end + +function aux.hash_to_string(h,separator,yes,no,strict,omit) + if h then + local t, s = { }, table.sortedkeys(h) + omit = omit and table.tohash(omit) + for i=1,#s do + local key = s[i] + if not omit or not omit[key] then + local value = h[key] + if type(value) == "boolean" then + if yes and no then + if value then + t[#t+1] = key .. '=' .. yes + elseif not strict then + t[#t+1] = key .. '=' .. no + end + elseif value or not strict then + t[#t+1] = key .. '=' .. tostring(value) + end + else + t[#t+1] = key .. '=' .. value + end + end + end + return concat(t,separator or ",") + else + return "" + end +end + +function aux.array_to_string(a,separator) + if a then + return concat(a,separator or ",") + else + return "" + end +end + +function aux.settings_to_set(str,t) + t = t or { } + for s in gmatch(str,"%s*([^,]+)") do + t[s] = true + end + return t +end + +-- temporary here + +function aux.getparameters(self,class,parentclass,settings) + local sc = self[class] + if not sc then + sc = table.clone(self[parent]) + self[class] = sc + end + aux.add_settings_to_array(sc, settings) +end + +-- temporary here + +local digit = lpeg.R("09") +local period = lpeg.P(".") +local zero = lpeg.P("0") + +--~ local finish = lpeg.P(-1) +--~ local nodigit = (1-digit) + finish +--~ local case_1 = (period * zero^1 * #nodigit)/"" -- .000 +--~ local case_2 = (period * (1-(zero^0/"") * #nodigit)^1 * (zero^0/"") * nodigit) -- .010 .10 .100100 + +local trailingzeros = zero^0 * -digit -- suggested by Roberto R +local case_1 = period * trailingzeros / "" +local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "") + +local number = digit^1 * (case_1 + case_2) +local stripper = lpeg.Cs((number + 1)^0) + +--~ local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100" +--~ collectgarbage("collect") +--~ str = string.rep(sample,10000) +--~ local ts = os.clock() +--~ stripper:match(str) +--~ print(#str, os.clock()-ts, stripper:match(sample)) + +function aux.strip_zeros(str) + return stripper:match(str) +end + +function aux.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 aux.accesstable(target) + local t = _G + for name in gmatch(target,"([^%.]+)") do + t = t[name] + end + return t +end + + +end -- of closure + +do -- create closure to overcome 200 locals limit + if not modules then modules = { } end modules ['trac-tra'] = { version = 1.001, comment = "companion to luat-lib.tex", @@ -3012,7 +3281,11 @@ trackers = trackers or { } local data, done = { }, { } local function set(what,value) - for w in gmatch(lower(what),"[^, ]+") do + if type(what) == "string" then + what = aux.settings_to_array(what) + end + for i=1,#what do + local w = what[i] for d, f in next, data do if done[d] then -- prevent recursion due to wildcards @@ -3391,27 +3664,34 @@ statistics.threshold = 0.05 local clock = os.gettimeofday or os.clock +local notimer + function statistics.hastimer(instance) return instance and instance.starttime end function statistics.starttiming(instance) - if instance then - local it = instance.timing - if not it then - it = 0 - end - if it == 0 then - instance.starttime = clock() - if not instance.loadtime then - instance.loadtime = 0 - end + if not instance then + notimer = { } + instance = notimer + end + local it = instance.timing + if not it then + it = 0 + end + if it == 0 then + instance.starttime = clock() + if not instance.loadtime then + instance.loadtime = 0 end - instance.timing = it + 1 end + instance.timing = it + 1 end function statistics.stoptiming(instance, report) + if not instance then + instance = notimer + end if instance then local it = instance.timing if it > 1 then @@ -3435,10 +3715,16 @@ function statistics.stoptiming(instance, report) end function statistics.elapsedtime(instance) + if not instance then + instance = notimer + end return format("%0.3f",(instance and instance.loadtime) or 0) end function statistics.elapsedindeed(instance) + if not instance then + instance = notimer + end local t = (instance and instance.loadtime) or 0 return t > statistics.threshold end @@ -3479,6 +3765,7 @@ function statistics.show(reporter) reporter(s[1],r,n) end end + texio.write_nl("") -- final newline statistics.enable = false end end @@ -3536,6 +3823,7 @@ if not modules then modules = { } end modules ['luat-log'] = { -- this is old code that needs an overhaul local write_nl, write, format = texio.write_nl or print, texio.write or io.write, string.format +local texcount = tex and tex.count if texlua then write_nl = print @@ -3615,10 +3903,8 @@ function logs.tex.line(fmt,...) -- new end end -local texcount = tex and tex.count - function logs.tex.start_page_number() - local real, user, sub = texcount[0], texcount[1], texcount[2] + local real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno if real > 0 then if user > 0 then if sub > 0 then @@ -3673,7 +3959,7 @@ function logs.xml.stop_run() end function logs.xml.start_page_number() - write_nl(format("<p real='%s' page='%s' sub='%s'", texcount[0], texcount[1], texcount[2])) + write_nl(format("<p real='%s' page='%s' sub='%s'", texcount.realpageno, texcount.userpageno, texcount.subpageno)) end function logs.xml.stop_page_number() @@ -3908,7 +4194,7 @@ formats['ovf'] = 'OVFFONTS' suffixes['ovf'] = { 'ovf', 'vf' } formats['ovp'] = 'OVPFONTS' suffixes['ovp'] = { 'ovp' } formats['tex'] = 'TEXINPUTS' suffixes['tex'] = { 'tex' } formats['tfm'] = 'TFMFONTS' suffixes['tfm'] = { 'tfm' } -formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc' } +formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc', 'dfont' } formats['pfb'] = 'T1FONTS' suffixes['pfb'] = { 'pfb', 'pfa' } formats['vf'] = 'VFFONTS' suffixes['vf'] = { 'vf' } @@ -3930,6 +4216,7 @@ alternatives['fea files'] = 'fea' alternatives['opentype fonts'] = 'otf' alternatives['truetype fonts'] = 'ttf' alternatives['truetype collections'] = 'ttc' +alternatives['truetype dictionary'] = 'dfont' alternatives['type1 fonts'] = 'pfb' -- obscure ones @@ -4046,12 +4333,12 @@ local function reset_hashes() end local function check_configuration() -- not yet ok, no time for debugging now - local ie = instance.environment + local ie, iv = instance.environment, instance.variables local function fix(varname,default) local proname = varname .. "." .. instance.progname or "crap" - local p, v = ie[proname], ie[varname] + local p, v = ie[proname], ie[varname] or iv[varname] if not ((p and p ~= "") or (v and v ~= "")) then - instance.variables[varname] = default -- or environment? + iv[varname] = default -- or environment? end end local name = os.name @@ -5890,10 +6177,6 @@ caches.paths = caches.paths or nil caches.force = false caches.defaults = { "TEXMFCACHE", "TMPDIR", "TEMPDIR", "TMP", "TEMP", "HOME", "HOMEPATH" } -function caches.cleanname(name) - return (gsub(lower(name),"[^%w%d]+","-")) -end - function caches.temp() local cachepath = nil local function check(list,isenv) @@ -5990,7 +6273,9 @@ function caches.loaddata(path,name) local tmaname, tmcname = caches.setluanames(path,name) local loader = loadfile(tmcname) or loadfile(tmaname) if loader then - return loader() + loader = loader() + collectgarbage("step") + return loader else return false end @@ -6132,7 +6417,7 @@ function containers.define(category, subcategory, version, enabled) enabled = enabled, version = version or 1.000, trace = false, - path = caches and caches.setpath(category,subcategory), + path = caches and caches.setpath and caches.setpath(category,subcategory), } c[subcategory] = s end @@ -6191,6 +6476,10 @@ function containers.content(container,name) return container.storage[name] end +function containers.cleanname(name) + return (gsub(lower(name),"[^%w%d]+","-")) +end + end -- of closure @@ -6585,6 +6874,7 @@ own.libs = { -- todo: check which ones are really needed 'l-unicode.lua', 'l-math.lua', 'l-utils.lua', + 'l-aux.lua', 'trac-tra.lua', 'luat-env.lua', 'trac-inf.lua', diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun index aba22a16e..82d1edecb 100755 --- a/scripts/context/stubs/unix/mtxrun +++ b/scripts/context/stubs/unix/mtxrun @@ -421,6 +421,10 @@ function table.strip(tab) return lst end +local function compare(a,b) + return (tostring(a) < tostring(b)) +end + local function sortedkeys(tab) local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed for key,_ in next, tab do @@ -441,7 +445,7 @@ local function sortedkeys(tab) end end if kind == 0 or kind == 3 then - sort(srt,function(a,b) return (tostring(a) < tostring(b)) end) + sort(srt,compare) else sort(srt) end @@ -1072,7 +1076,7 @@ function table.insert_after_value(t,value,str) end local function are_equal(a,b,n,m) -- indexed - if #a == #b then + if a and b and #a == #b then n = n or 1 m = m or #a for i=n,m do @@ -1229,6 +1233,7 @@ end function io.loaddata(filename,textmode) local f = io.open(filename,(textmode and 'r') or 'rb') if f then + -- collectgarbage("step") -- sometimes makes a big difference in mem consumption local data = f:read('*all') -- garbagecollector.check(data) f:close() @@ -1465,6 +1470,7 @@ set = set or { } local nums = { } local tabs = { } local concat = table.concat +local next, type = next, type set.create = table.tohash @@ -1472,17 +1478,19 @@ function set.tonumber(t) if next(t) then local s = "" -- we could save mem by sorting, but it slows down - for k, v in pairs(t) do + for k, v in next, t do if v then -- why bother about the leading space s = s .. " " .. k end end - if not nums[s] then - tabs[#tabs+1] = t - nums[s] = #tabs + local n = nums[s] + if not n then + n = #tabs + 1 + tabs[n] = t + nums[s] = n end - return nums[s] + return n else return 0 end @@ -1496,6 +1504,20 @@ function set.totable(n) end end +function set.tolist(n) + if n == 0 or not tabs[n] then + return "" + else + local t = { } + for k, v in next, tabs[n] do + if v then + t[#t+1] = k + end + end + return concat(t," ") + end +end + function set.contains(n,s) if type(n) == "table" then return n[s] @@ -2600,6 +2622,235 @@ end -- of closure do -- create closure to overcome 200 locals limit +if not modules then modules = { } end modules ['l-aux'] = { + version = 1.001, + comment = "companion to luat-lib.tex", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +aux = aux or { } + +local concat, format, gmatch = table.concat, string.format, string.gmatch +local tostring, type = tostring, type + +local space = lpeg.P(' ') +local equal = lpeg.P("=") +local comma = lpeg.P(",") +local lbrace = lpeg.P("{") +local rbrace = lpeg.P("}") +local nobrace = 1 - (lbrace+rbrace) +local nested = lpeg.P{ lbrace * (nobrace + lpeg.V(1))^0 * rbrace } +local spaces = space^0 + +local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0) + +local key = lpeg.C((1-equal-comma)^1) +local pattern_a = (space+comma)^0 * (key * equal * value + key * lpeg.C("")) +local pattern_c = (space+comma)^0 * (key * equal * value) + +local key = lpeg.C((1-space-equal-comma)^1) +local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + lpeg.C(""))) + +-- "a=1, b=2, c=3, d={a{b,c}d}, e=12345, f=xx{a{b,c}d}xx, g={}" : outer {} removes, leading spaces ignored + +local hash = { } + +local function set(key,value) -- using Carg is slower here + hash[key] = value +end + +local pattern_a_s = (pattern_a/set)^1 +local pattern_b_s = (pattern_b/set)^1 +local pattern_c_s = (pattern_c/set)^1 + +aux.settings_to_hash_pattern_a = pattern_a_s +aux.settings_to_hash_pattern_b = pattern_b_s +aux.settings_to_hash_pattern_c = pattern_c_s + +function aux.make_settings_to_hash_pattern(set,how) + if how == "strict" then + return (pattern_c/set)^1 + elseif how == "tolerant" then + return (pattern_b/set)^1 + else + return (pattern_a/set)^1 + end +end + +function aux.settings_to_hash(str) + if str and str ~= "" then + hash = { } + if moretolerant then + pattern_b_s:match(str) + else + pattern_a_s:match(str) + end + return hash + else + return { } + end +end + +function aux.settings_to_hash_tolerant(str) + if str and str ~= "" then + hash = { } + pattern_b_s:match(str) + return hash + else + return { } + end +end + +function aux.settings_to_hash_strict(str) + if str and str ~= "" then + hash = { } + pattern_c_s:match(str) + return next(hash) and hash + else + return nil + end +end + +local seperator = comma * space^0 +local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0) +local pattern = lpeg.Ct(value*(seperator*value)^0) + +-- "aap, {noot}, mies" : outer {} removes, leading spaces ignored + +aux.settings_to_array_pattern = pattern + +function aux.settings_to_array(str) + if not str or str == "" then + return { } + else + return pattern:match(str) + end +end + +local function set(t,v) + t[#t+1] = v +end + +local value = lpeg.P(lpeg.Carg(1)*value) / set +local pattern = value*(seperator*value)^0 * lpeg.Carg(1) + +function aux.add_settings_to_array(t,str) + return pattern:match(str, nil, t) +end + +function aux.hash_to_string(h,separator,yes,no,strict,omit) + if h then + local t, s = { }, table.sortedkeys(h) + omit = omit and table.tohash(omit) + for i=1,#s do + local key = s[i] + if not omit or not omit[key] then + local value = h[key] + if type(value) == "boolean" then + if yes and no then + if value then + t[#t+1] = key .. '=' .. yes + elseif not strict then + t[#t+1] = key .. '=' .. no + end + elseif value or not strict then + t[#t+1] = key .. '=' .. tostring(value) + end + else + t[#t+1] = key .. '=' .. value + end + end + end + return concat(t,separator or ",") + else + return "" + end +end + +function aux.array_to_string(a,separator) + if a then + return concat(a,separator or ",") + else + return "" + end +end + +function aux.settings_to_set(str,t) + t = t or { } + for s in gmatch(str,"%s*([^,]+)") do + t[s] = true + end + return t +end + +-- temporary here + +function aux.getparameters(self,class,parentclass,settings) + local sc = self[class] + if not sc then + sc = table.clone(self[parent]) + self[class] = sc + end + aux.add_settings_to_array(sc, settings) +end + +-- temporary here + +local digit = lpeg.R("09") +local period = lpeg.P(".") +local zero = lpeg.P("0") + +--~ local finish = lpeg.P(-1) +--~ local nodigit = (1-digit) + finish +--~ local case_1 = (period * zero^1 * #nodigit)/"" -- .000 +--~ local case_2 = (period * (1-(zero^0/"") * #nodigit)^1 * (zero^0/"") * nodigit) -- .010 .10 .100100 + +local trailingzeros = zero^0 * -digit -- suggested by Roberto R +local case_1 = period * trailingzeros / "" +local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "") + +local number = digit^1 * (case_1 + case_2) +local stripper = lpeg.Cs((number + 1)^0) + +--~ local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100" +--~ collectgarbage("collect") +--~ str = string.rep(sample,10000) +--~ local ts = os.clock() +--~ stripper:match(str) +--~ print(#str, os.clock()-ts, stripper:match(sample)) + +function aux.strip_zeros(str) + return stripper:match(str) +end + +function aux.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 aux.accesstable(target) + local t = _G + for name in gmatch(target,"([^%.]+)") do + t = t[name] + end + return t +end + + +end -- of closure + +do -- create closure to overcome 200 locals limit + if not modules then modules = { } end modules ['lxml-tab'] = { version = 1.001, comment = "this module is the basis for the lxml-* ones", @@ -3047,7 +3298,7 @@ generic table copier. Since we know what we're dealing with we can speed up things a bit. The second argument is not to be used!</p> --ldx]]-- -function copy(old,tables) +local function copy(old,tables) if old then tables = tables or { } local new = { } @@ -3270,7 +3521,7 @@ function xml.tostring(root) -- 25% overhead due to collecting return root elseif next(root) then -- next is faster than type (and >0 test) local result = { } - serialize(root,function(s) result[#result+1] = s end) + serialize(root,function(s) result[#result+1] = s end) -- brrr, slow (direct printing is faster) return concat(result,"") end end @@ -5333,7 +5584,11 @@ trackers = trackers or { } local data, done = { }, { } local function set(what,value) - for w in gmatch(lower(what),"[^, ]+") do + if type(what) == "string" then + what = aux.settings_to_array(what) + end + for i=1,#what do + local w = what[i] for d, f in next, data do if done[d] then -- prevent recursion due to wildcards @@ -5712,27 +5967,34 @@ statistics.threshold = 0.05 local clock = os.gettimeofday or os.clock +local notimer + function statistics.hastimer(instance) return instance and instance.starttime end function statistics.starttiming(instance) - if instance then - local it = instance.timing - if not it then - it = 0 - end - if it == 0 then - instance.starttime = clock() - if not instance.loadtime then - instance.loadtime = 0 - end + if not instance then + notimer = { } + instance = notimer + end + local it = instance.timing + if not it then + it = 0 + end + if it == 0 then + instance.starttime = clock() + if not instance.loadtime then + instance.loadtime = 0 end - instance.timing = it + 1 end + instance.timing = it + 1 end function statistics.stoptiming(instance, report) + if not instance then + instance = notimer + end if instance then local it = instance.timing if it > 1 then @@ -5756,10 +6018,16 @@ function statistics.stoptiming(instance, report) end function statistics.elapsedtime(instance) + if not instance then + instance = notimer + end return format("%0.3f",(instance and instance.loadtime) or 0) end function statistics.elapsedindeed(instance) + if not instance then + instance = notimer + end local t = (instance and instance.loadtime) or 0 return t > statistics.threshold end @@ -5800,6 +6068,7 @@ function statistics.show(reporter) reporter(s[1],r,n) end end + texio.write_nl("") -- final newline statistics.enable = false end end @@ -5857,6 +6126,7 @@ if not modules then modules = { } end modules ['luat-log'] = { -- this is old code that needs an overhaul local write_nl, write, format = texio.write_nl or print, texio.write or io.write, string.format +local texcount = tex and tex.count if texlua then write_nl = print @@ -5936,10 +6206,8 @@ function logs.tex.line(fmt,...) -- new end end -local texcount = tex and tex.count - function logs.tex.start_page_number() - local real, user, sub = texcount[0], texcount[1], texcount[2] + local real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno if real > 0 then if user > 0 then if sub > 0 then @@ -5994,7 +6262,7 @@ function logs.xml.stop_run() end function logs.xml.start_page_number() - write_nl(format("<p real='%s' page='%s' sub='%s'", texcount[0], texcount[1], texcount[2])) + write_nl(format("<p real='%s' page='%s' sub='%s'", texcount.realpageno, texcount.userpageno, texcount.subpageno)) end function logs.xml.stop_page_number() @@ -6229,7 +6497,7 @@ formats['ovf'] = 'OVFFONTS' suffixes['ovf'] = { 'ovf', 'vf' } formats['ovp'] = 'OVPFONTS' suffixes['ovp'] = { 'ovp' } formats['tex'] = 'TEXINPUTS' suffixes['tex'] = { 'tex' } formats['tfm'] = 'TFMFONTS' suffixes['tfm'] = { 'tfm' } -formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc' } +formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc', 'dfont' } formats['pfb'] = 'T1FONTS' suffixes['pfb'] = { 'pfb', 'pfa' } formats['vf'] = 'VFFONTS' suffixes['vf'] = { 'vf' } @@ -6251,6 +6519,7 @@ alternatives['fea files'] = 'fea' alternatives['opentype fonts'] = 'otf' alternatives['truetype fonts'] = 'ttf' alternatives['truetype collections'] = 'ttc' +alternatives['truetype dictionary'] = 'dfont' alternatives['type1 fonts'] = 'pfb' -- obscure ones @@ -6367,12 +6636,12 @@ local function reset_hashes() end local function check_configuration() -- not yet ok, no time for debugging now - local ie = instance.environment + local ie, iv = instance.environment, instance.variables local function fix(varname,default) local proname = varname .. "." .. instance.progname or "crap" - local p, v = ie[proname], ie[varname] + local p, v = ie[proname], ie[varname] or iv[varname] if not ((p and p ~= "") or (v and v ~= "")) then - instance.variables[varname] = default -- or environment? + iv[varname] = default -- or environment? end end local name = os.name @@ -8307,7 +8576,9 @@ function caches.loaddata(path,name) local tmaname, tmcname = caches.setluanames(path,name) local loader = loadfile(tmcname) or loadfile(tmaname) if loader then - return loader() + loader = loader() + collectgarbage("step") + return loader else return false end @@ -9517,6 +9788,7 @@ own.libs = { -- todo: check which ones are really needed -- 'l-unicode.lua', -- 'l-tex.lua', 'l-utils.lua', + 'l-aux.lua', -- 'l-xml.lua', 'lxml-tab.lua', 'lxml-pth.lua', diff --git a/tex/context/base/cont-new.tex b/tex/context/base/cont-new.tex index 1b9d7d62e..26860f811 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{2009.08.13 13:13} +\newcontextversion{2009.08.14 10:48} %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 c7bf9cdd7..f3c5cdcc5 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{2009.08.13 13:13} +\edef\contextversion{2009.08.14 10:48} %D For those who want to use this: diff --git a/tex/context/base/core-sys.mkiv b/tex/context/base/core-sys.mkiv index 28ef1e520..f30c8a958 100644 --- a/tex/context/base/core-sys.mkiv +++ b/tex/context/base/core-sys.mkiv @@ -268,6 +268,82 @@ \definecomplexorsimpleempty\define +% \startluacode +% local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes +% local format, match, gmatch, rep = string.format, string.match, string.gmatch, string.rep +% local empty = { +% "single", +% "double", +% "triple", +% "quadruple", +% "quintuple", +% } +% local check = { +% "first", +% "second", +% "third", +% "fourth", +% "fifth", +% } +% function commands.define(str) +% -- we could store the defaults in lua and call lua instead but why bother +% local arg, cmd = match(str,"(.*)\\(.-)$") +% local a = { } +% for s in gmatch(arg,"%[(.-)%]") do +% a[#a+1] = s +% end +% local n = tonumber(a[#a]) +% if n then +% a[#a] = nil +% else +% n = 0 +% end +% texsprint(ctxcatcodes,format("\\unexpanded\\def\\%s",cmd)) +% if #a > 0 then +% texsprint(ctxcatcodes,format("{\\do%sempty\\do%s}",empty[#a],cmd)) +% texsprint(ctxcatcodes,format("\\def\\do%s",cmd)) +% for i=1,#a do +% texsprint(ctxcatcodes,"[#",i,"]") +% end +% texsprint(ctxcatcodes,"{") +% for i=#a,1,-1 do +% texsprint(ctxcatcodes,format("\\if%sargument",check[i])) +% texsprint(ctxcatcodes,format("\\def\\next{\\dodo%s",cmd)) +% for j=1,#a-i do +% texsprint(ctxcatcodes,format("[%s]",a[j])) +% end +% for j=1,i do +% texsprint(ctxcatcodes,format("[#%s]",j)) +% end +% texsprint(ctxcatcodes,"}") +% if i == 1 then +% texsprint(ctxcatcodes,rep("\\fi",#a)) +% else +% texsprint(ctxcatcodes,"\\else") +% end +% end +% texsprint(ctxcatcodes,"\\next}") +% texsprint(ctxcatcodes,format("\\def\\dodo%s",cmd)) +% for i=1,#a do +% texsprint(ctxcatcodes,"[#",i,"]") +% end +% end +% for i=1,n do +% texsprint(ctxcatcodes,"#",#a+i) +% end +% end +% \stopluacode +% +% \def\define#1#{\ctxlua{commands.define([[\detokenize{#1}]])}} +% +% \starttext +% \define[2]\whatevera{#1+#2} +% \whatevera{A}{B} +% \define[me][too][2]\whateverb{#1+#2+#3+#4} +% \whateverb[A]{B}{C} +% \whateverb[A][B]{C}{D} +% \stoptext + \unexpanded\def\macroname#1% brrr {\executeifdefined{#1}\empty} diff --git a/tex/context/base/data-res.lua b/tex/context/base/data-res.lua index da51dc64a..39e4aa208 100644 --- a/tex/context/base/data-res.lua +++ b/tex/context/base/data-res.lua @@ -229,12 +229,12 @@ local function reset_hashes() end local function check_configuration() -- not yet ok, no time for debugging now - local ie = instance.environment + local ie, iv = instance.environment, instance.variables local function fix(varname,default) local proname = varname .. "." .. instance.progname or "crap" - local p, v = ie[proname], ie[varname] + local p, v = ie[proname], ie[varname] or iv[varname] if not ((p and p ~= "") or (v and v ~= "")) then - instance.variables[varname] = default -- or environment? + iv[varname] = default -- or environment? end end local name = os.name diff --git a/tex/context/base/font-syn.lua b/tex/context/base/font-syn.lua index 84bf7f91c..828808ec5 100644 --- a/tex/context/base/font-syn.lua +++ b/tex/context/base/font-syn.lua @@ -49,6 +49,8 @@ filters.ttc = fontloader.info filters.dfont = fontloader.info function filters.afm(name) + -- we could parse the afm file as well, and then report an error but + -- it's not worth the trouble local pfbname = resolvers.find_file(file.removesuffix(name)..".pfb","pfb") or "" if pfbname == "" then pfbname = resolvers.find_file(file.removesuffix(file.basename(name))..".pfb","pfb") or "" @@ -70,7 +72,7 @@ function filters.afm(name) return hash end end - return nil + return nil, "no matching pfb file" end function filters.pfb(name) @@ -239,7 +241,7 @@ function names.identify(verbose) -- lsr is for kpse logs.report("fontnames","identifying %s font %s",suffix,completename) logs.push() end - local result = filters[lower(suffix)](completename) + local result, message = filters[lower(suffix)](completename) if trace then logs.pop() end @@ -251,6 +253,11 @@ function names.identify(verbose) -- lsr is for kpse check(result[r],storedname,suffix,true) -- was name end end + if message and message ~= "" then + logs.report("fontnames","warning when identifying %s font %s: %s",suffix,completename,message) + end + else + logs.report("fontnames","error when identifying %s font %s: %s",suffix,completename,message or "unknown") end done[name] = true end diff --git a/tex/context/base/lpdf-mis.lua b/tex/context/base/lpdf-mis.lua index e3ed8919d..e47da1c49 100644 --- a/tex/context/base/lpdf-mis.lua +++ b/tex/context/base/lpdf-mis.lua @@ -143,18 +143,20 @@ end local function flushjavascripts() local t = javascripts.flushpreambles() - local a = pdfarray() - local pdf_javascript = pdfconstant("JavaScript") - for i=1,#t do - local name, script = t[i][1], t[i][2] - local j = pdfdictionary { - S = pdf_javascript, - JS = pdfreference(pdfimmediateobj("stream",script)), - } - a[#a+1] = pdfstring(name) - a[#a+1] = pdfreference(pdfimmediateobj(tostring(j))) - end - lpdf.addtonames("JavaScript",pdfreference(pdfimmediateobj(tostring(pdfdictionary{ Names = a })))) + if #t > 0 then + local a = pdfarray() + local pdf_javascript = pdfconstant("JavaScript") + for i=1,#t do + local name, script = t[i][1], t[i][2] + local j = pdfdictionary { + S = pdf_javascript, + JS = pdfreference(pdfimmediateobj("stream",script)), + } + a[#a+1] = pdfstring(name) + a[#a+1] = pdfreference(pdfimmediateobj(tostring(j))) + end + lpdf.addtonames("JavaScript",pdfreference(pdfimmediateobj(tostring(pdfdictionary{ Names = a })))) + end end lpdf.registerdocumentfinalizer(flushjavascripts) diff --git a/tex/context/base/node-ref.lua b/tex/context/base/node-ref.lua index 873302d6b..85d7e869e 100644 --- a/tex/context/base/node-ref.lua +++ b/tex/context/base/node-ref.lua @@ -40,28 +40,33 @@ local traverse = node.traverse local find_node_tail = node.tail or node.slide local tosequence = nodes.tosequence ---~ local copy_list = node.copy_list ---~ local flush_list = node.flush_list ---~ ---~ local function dimensions(parent,start,stop) -- so we need parent for glue_set info ---~ local n = stop.next ---~ stop.next = nil ---~ local p = hpack_list(copy_list(start)) ---~ stop.next = n ---~ local w, h, d = p.width, p.height, p.depth ---~ flush_list(p) ---~ return w, h, d ---~ end - -local function dimensions(parent,start,stop) -- so we need parent for glue_set info +local function dimensions(parent,start,stop) stop = stop and stop.next - if stop then - return list_dimensions(start,stop) + if parent then + if stop then + return list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,start,stop) + else + return list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,start) + end else - return list_dimensions(start) + if stop then + return list_dimensions(start,stop) + else + return list_dimensions(start) + end end end +--~ more compact +--~ +--~ local function dimensions(parent,start,stop) +--~ if parent then +--~ return list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,start,stop and stop.next) +--~ else +--~ return list_dimensions(start,stop and stop.next) +--~ end +--~ end + local function inject_range(head,first,last,reference,make,stack,parent,pardir,txtdir) local width, height, depth = dimensions(parent,first,last) if pardir == "TRT" or txtdir == "+TRT" then diff --git a/tex/generic/context/luatex-fonts-merged.lua b/tex/generic/context/luatex-fonts-merged.lua index a17ea5411..6e2436369 100644 --- a/tex/generic/context/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/texmf/tex/generic/context/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/texmf/tex/generic/context/luatex-fonts.lua --- merge date : 08/13/09 13:15:16 +-- merge date : 08/14/09 10:50:13 do -- begin closure to overcome local limits and interference |