diff options
40 files changed, 1342 insertions, 539 deletions
diff --git a/scripts/context/lua/luatools.lua b/scripts/context/lua/luatools.lua index f9b855f74..1a579eb69 100644 --- a/scripts/context/lua/luatools.lua +++ b/scripts/context/lua/luatools.lua @@ -338,6 +338,8 @@ if not modules then modules = { } end modules ['l-lpeg'] = { lpeg = require("lpeg") +lpeg.patterns = lpeg.patterns or { } -- so that we can share + local P, R, S, Ct, C, Cs, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc local match = lpeg.match @@ -488,11 +490,9 @@ end --~ --~ local decode_pattern = lpeg.Ct(utf8^0) * -1 - local cont = R("\128\191") -- continuation byte -lpeg.utf8 = R("\0\127") + R("\194\223") * cont + R("\224\239") * cont * cont + R("\240\244") * cont * cont * cont - +lpeg.patterns.utf8 = R("\0\127") + R("\194\223") * cont + R("\224\239") * cont * cont + R("\240\244") * cont * cont * cont end -- of closure @@ -1868,6 +1868,7 @@ elseif os.type == "windows" then elseif name == "linux" then function os.resolvers.platform(t,k) + -- we sometims have HOSTTYPE set so let's check that first local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or "" if find(architecture,"x86_64") then platform = "linux-64" @@ -1881,17 +1882,28 @@ elseif name == "linux" then return platform end -elseif name == "macosx" then -- a rather inconsistent mess +elseif name == "macosx" then + + --[[ + Identifying the architecture of OSX is quite a mess and this + is the best we can come up with. For some reason $HOSTTYPE is + a kind of pseudo environment variable, not known to the current + environment. And yes, uname cannot be trusted either, so there + is a change that you end up with a 32 bit run on a 64 bit system. + Also, some proper 64 bit intel macs are too cheap (low-end) and + therefore not permitted to run the 64 bit kernel. + ]]-- function os.resolvers.platform(t,k) - local platform, architecture = "", os.resultof("uname -m") or "" + -- local platform, architecture = "", os.getenv("HOSTTYPE") or "" + -- if architecture == "" then + -- architecture = os.resultof("echo $HOSTTYPE") or "" + -- end + local platform, architecture = "", os.resultof("echo $HOSTTYPE") or "" if architecture == "" then - architecture = os.getenv("HOSTTYPE") or "" - end - if architecture == "" then - architecture = os.resultof("echo $HOSTTYPE") or "" - end - if find(architecture,"i386") then + -- print("\nI have no clue what kind of OSX you're running so let's assume an 32 bit intel.\n") + platform = "osx-intel" + elseif find(architecture,"i386") then platform = "osx-intel" elseif find(architecture,"x86_64") then platform = "osx-64" @@ -1931,6 +1943,21 @@ elseif name == "freebsd" then return platform end +elseif name == "kfreebsd" then + + function os.resolvers.platform(t,k) + -- we sometims have HOSTTYPE set so let's check that first + local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or "" + if find(architecture,"x86_64") then + platform = "kfreebsd-64" + else + platform = "kfreebsd-i386" + end + os.setenv("MTX_PLATFORM",platform) + os.platform = platform + return platform + end + else -- platform = "linux" @@ -1967,6 +1994,21 @@ function os.uuid() ) end +local d + +function os.timezone(delta) + d = d or tonumber(tonumber(os.date("%H")-os.date("!%H"))) + if delta then + if d > 0 then + return format("+%02i:00",d) + else + return format("-%02i:00",-d) + end + else + return 1 + end +end + end -- of closure @@ -1985,7 +2027,7 @@ if not modules then modules = { } end modules ['l-file'] = { file = file or { } local concat = table.concat -local find, gmatch, match, gsub, sub = string.find, string.gmatch, string.match, string.gsub, string.sub +local find, gmatch, match, gsub, sub, char = string.find, string.gmatch, string.match, string.gsub, string.sub, string.char local lpegmatch = lpeg.match function file.removesuffix(filename) @@ -2022,14 +2064,33 @@ end file.suffix = file.extname ---~ print(file.join("x/","/y")) ---~ print(file.join("http://","/y")) ---~ print(file.join("http://a","/y")) ---~ print(file.join("http:///a","/y")) ---~ print(file.join("//nas-1","/y")) +--~ function file.join(...) +--~ local pth = concat({...},"/") +--~ pth = gsub(pth,"\\","/") +--~ local a, b = match(pth,"^(.*://)(.*)$") +--~ if a and b then +--~ return a .. gsub(b,"//+","/") +--~ end +--~ a, b = match(pth,"^(//)(.*)$") +--~ if a and b then +--~ return a .. gsub(b,"//+","/") +--~ end +--~ return (gsub(pth,"//+","/")) +--~ end + +local trick_1 = char(1) +local trick_2 = "^" .. trick_1 .. "/+" function file.join(...) - local pth = concat({...},"/") + local lst = { ... } + local a, b = lst[1], lst[2] + if a == "" then + lst[1] = trick_1 + elseif b and find(a,"^/+$") and find(b,"^/") then + lst[1] = "" + lst[2] = gsub(b,"^/+","") + end + local pth = concat(lst,"/") pth = gsub(pth,"\\","/") local a, b = match(pth,"^(.*://)(.*)$") if a and b then @@ -2039,9 +2100,20 @@ function file.join(...) if a and b then return a .. gsub(b,"//+","/") end + pth = gsub(pth,trick_2,"") return (gsub(pth,"//+","/")) end +--~ print(file.join("//","/y")) +--~ print(file.join("/","/y")) +--~ print(file.join("","/y")) +--~ print(file.join("/x/","/y")) +--~ print(file.join("x/","/y")) +--~ print(file.join("http://","/y")) +--~ print(file.join("http://a","/y")) +--~ print(file.join("http:///a","/y")) +--~ print(file.join("//nas-1","/y")) + function file.iswritable(name) local a = lfs.attributes(name) or lfs.attributes(file.dirname(name,".")) return a and sub(a.permissions,2,2) == "w" @@ -2080,16 +2152,22 @@ function file.join_path(tab) return concat(tab,io.pathseparator) -- can have trailing // end +-- we can hash them weakly + function file.collapse_path(str) - str = gsub(str,"/%./","/") - local n, m = 1, 1 - while n > 0 or m > 0 do - str, n = gsub(str,"[^/%.]+/%.%.$","") - str, m = gsub(str,"[^/%.]+/%.%./","") - end - str = gsub(str,"([^/])/$","%1") - str = gsub(str,"^%./","") - str = gsub(str,"/%.$","") + str = gsub(str,"\\","/") + if find(str,"/") then + str = gsub(str,"^%./",(gsub(lfs.currentdir(),"\\","/")) .. "/") -- ./xx in qualified + str = gsub(str,"/%./","/") + local n, m = 1, 1 + while n > 0 or m > 0 do + str, n = gsub(str,"[^/%.]+/%.%.$","") + str, m = gsub(str,"[^/%.]+/%.%./","") + end + str = gsub(str,"([^/])/$","%1") + -- str = gsub(str,"^%./","") -- ./xx in qualified + str = gsub(str,"/%.$","") + end if str == "" then str = "." end return str end @@ -2391,7 +2469,7 @@ function url.hashed(str) end function url.hasscheme(str) - return not url.split(str).nosheme + return url.split(str)[1] ~= "" end function url.addscheme(str,scheme) @@ -2788,7 +2866,7 @@ else --~ print(dir.mkdirs("///a/b/c")) --~ print(dir.mkdirs("a/bbb//ccc/")) - function dir.expand_name(str) + function dir.expand_name(str) -- will be merged with cleanpath and collapsepath if not find(str,"^/") then str = lfs.currentdir() .. "/" .. str end @@ -3503,6 +3581,8 @@ local stripper = lpeg.Cs((number + 1)^0) --~ lpegmatch(stripper,str) --~ print(#str, os.clock()-ts, lpegmatch(stripper,sample)) +lpeg.patterns.strip_zeros = stripper + function aux.strip_zeros(str) return lpegmatch(stripper,str) end @@ -3789,14 +3869,14 @@ end function setters.enable(t,what) local e = t.enable t.enable, t.done = enable, { } - enable(t,string.simpleesc(what)) + enable(t,string.simpleesc(tostring(what))) t.enable, t.done = e, { } end function setters.disable(t,what) local e = t.disable t.disable, t.done = disable, { } - disable(t,string.simpleesc(what)) + disable(t,string.simpleesc(tostring(what))) t.disable, t.done = e, { } end @@ -3847,13 +3927,15 @@ function setters.new(name) return t end -trackers = setters.new("trackers") -directives = setters.new("directives") +trackers = setters.new("trackers") +directives = setters.new("directives") +experiments = setters.new("experiments") -- nice trick: we overload two of the directives related functions with variants that -- do tracing (itself using a tracker) .. proof of concept -local trace_directives = false local trace_directives = false trackers.register("system.directives", function(v) trace_directives = v end) +local trace_directives = false local trace_directives = false trackers.register("system.directives", function(v) trace_directives = v end) +local trace_experiments = false local trace_experiments = false trackers.register("system.experiments", function(v) trace_experiments = v end) local e = directives.enable local d = directives.disable @@ -3868,6 +3950,26 @@ function directives.disable(...) d(...) end +local e = experiments.enable +local d = experiments.disable + +function experiments.enable(...) + commands.writestatus("experiments","enabling: %s",concat({...}," ")) + e(...) +end + +function experiments.disable(...) + commands.writestatus("experiments","disabling: %s",concat({...}," ")) + d(...) +end + +-- a useful example + +directives.register("system.nostatistics", function(v) + statistics.enable = not v +end) + + end -- of closure @@ -4181,6 +4283,14 @@ function statistics.hastimer(instance) return instance and instance.starttime end +function statistics.resettiming(instance) + if not instance then + notimer = { timing = 0, loadtime = 0 } + else + instance.timing, instance.loadtime = 0, 0 + end +end + function statistics.starttiming(instance) if not instance then notimer = { } @@ -4240,6 +4350,12 @@ function statistics.elapsedindeed(instance) return t > statistics.threshold end +function statistics.elapsedseconds(instance,rest) -- returns nil if 0 seconds + if statistics.elapsedindeed(instance) then + return format("%s seconds %s", statistics.elapsedtime(instance),rest or "") + end +end + -- general function function statistics.register(tag,fnc) @@ -4318,6 +4434,23 @@ function statistics.timed(action,report) report("total runtime: %s",statistics.elapsedtime(timer)) end +-- where, not really the best spot for this: + +commands = commands or { } + +local timer + +function commands.resettimer() + statistics.resettiming(timer) + statistics.starttiming(timer) +end + +function commands.elapsedtime() + statistics.stoptiming(timer) + tex.sprint(statistics.elapsedtime(timer)) +end + +commands.resettimer() end -- of closure @@ -4755,8 +4888,8 @@ suffixes['lua'] = { 'lua', 'luc', 'tma', 'tmc' } alternatives['map files'] = 'map' alternatives['enc files'] = 'enc' -alternatives['cid files'] = 'cid' -alternatives['fea files'] = 'fea' +alternatives['cid maps'] = 'cid' -- great, why no cid files +alternatives['font feature files'] = 'fea' -- and fea files here alternatives['opentype fonts'] = 'otf' alternatives['truetype fonts'] = 'ttf' alternatives['truetype collections'] = 'ttc' @@ -4899,8 +5032,10 @@ local function check_configuration() -- not yet ok, no time for debugging now -- bad luck end fix("LUAINPUTS" , ".;$TEXINPUTS;$TEXMFSCRIPTS") -- no progname, hm - fix("FONTFEATURES", ".;$TEXMF/fonts/fea//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") - fix("FONTCIDMAPS" , ".;$TEXMF/fonts/cid//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + -- this will go away some day + fix("FONTFEATURES", ".;$TEXMF/fonts/{data,fea}//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + fix("FONTCIDMAPS" , ".;$TEXMF/fonts/{data,cid}//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + -- fix("LUATEXLIBS" , ".;$TEXMF/luatex/lua//") end @@ -5290,7 +5425,7 @@ function resolvers.load_cnf() else instance.rootpath = instance.cnffiles[1] for k,fname in ipairs(instance.cnffiles) do - instance.cnffiles[k] = file.collapse_path(gsub(fname,"\\",'/')) + instance.cnffiles[k] = file.collapse_path(fname) end for i=1,3 do instance.rootpath = file.dirname(instance.rootpath) @@ -5319,7 +5454,7 @@ function resolvers.load_lua() else instance.rootpath = instance.luafiles[1] for k,fname in ipairs(instance.luafiles) do - instance.luafiles[k] = file.collapse_path(gsub(fname,"\\",'/')) + instance.luafiles[k] = file.collapse_path(fname) end for i=1,3 do instance.rootpath = file.dirname(instance.rootpath) @@ -5444,7 +5579,7 @@ local weird = lpeg.P(".")^1 + lpeg.anywhere(lpeg.S("~`!#$%^&*()={}[]:;\"\'||<>,? --~ local l_forbidden = lpeg.S("~`!#$%^&*()={}[]:;\"\'||\\/<>,?\n\r\t") --~ local l_confusing = lpeg.P(" ") ---~ local l_character = lpeg.utf8 +--~ local l_character = lpeg.patterns.utf8 --~ local l_dangerous = lpeg.P(".") --~ local l_normal = (l_character - l_forbidden - l_confusing - l_dangerous) * (l_character - l_forbidden - l_confusing^2)^0 * lpeg.P(-1) @@ -6184,8 +6319,7 @@ end local function collect_instance_files(filename,collected) -- todo : plugin (scanners, checkers etc) local result = collected or { } local stamp = nil - filename = file.collapse_path(filename) -- elsewhere - filename = file.collapse_path(gsub(filename,"\\","/")) -- elsewhere + filename = file.collapse_path(filename) -- speed up / beware: format problem if instance.remember then stamp = filename .. "--" .. instance.engine .. "--" .. instance.progname .. "--" .. instance.format @@ -6666,12 +6800,13 @@ end function table.sequenced(t,sep) -- temp here local s = { } for k, v in pairs(t) do -- pairs? - s[#s+1] = k .. "=" .. v + s[#s+1] = k .. "=" .. tostring(v) end return concat(s, sep or " | ") end function resolvers.methodhandler(what, filename, filetype) -- ... + filename = file.collapse_path(filename) local specification = (type(filename) == "string" and resolvers.splitmethod(filename)) or filename -- no or { }, let it bomb local scheme = specification.scheme if resolvers[what][scheme] then diff --git a/scripts/context/lua/mtx-update.lua b/scripts/context/lua/mtx-update.lua index 09d3106b6..4f04b2245 100644 --- a/scripts/context/lua/mtx-update.lua +++ b/scripts/context/lua/mtx-update.lua @@ -383,7 +383,13 @@ function scripts.update.synchronize() end if not force then logs.report("update", "use --force to really update files") + else + -- update filename database for pdftex/xetex + scripts.update.run("mktexlsr") + -- update filename database for luatex + scripts.update.run("luatools --generate") end + logs.report("update","done") end @@ -408,10 +414,6 @@ function scripts.update.make() local formats = states.get('formats') resolvers.load_tree(texroot) - -- update filename database for pdftex/xetex - scripts.update.run("mktexlsr") - -- update filename database for luatex - scripts.update.run("luatools --generate") local askedformats = formats local texformats = table.tohash(scripts.update.texformats) local mpformats = table.tohash(scripts.update.mpformats) diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua index 8a2d7a123..ef7eda9b0 100644 --- a/scripts/context/lua/mtxrun.lua +++ b/scripts/context/lua/mtxrun.lua @@ -347,6 +347,8 @@ if not modules then modules = { } end modules ['l-lpeg'] = { lpeg = require("lpeg") +lpeg.patterns = lpeg.patterns or { } -- so that we can share + local P, R, S, Ct, C, Cs, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc local match = lpeg.match @@ -497,11 +499,9 @@ end --~ --~ local decode_pattern = lpeg.Ct(utf8^0) * -1 - local cont = R("\128\191") -- continuation byte -lpeg.utf8 = R("\0\127") + R("\194\223") * cont + R("\224\239") * cont * cont + R("\240\244") * cont * cont * cont - +lpeg.patterns.utf8 = R("\0\127") + R("\194\223") * cont + R("\224\239") * cont * cont + R("\240\244") * cont * cont * cont end -- of closure @@ -1952,6 +1952,21 @@ elseif name == "freebsd" then return platform end +elseif name == "kfreebsd" then + + function os.resolvers.platform(t,k) + -- we sometims have HOSTTYPE set so let's check that first + local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or "" + if find(architecture,"x86_64") then + platform = "kfreebsd-64" + else + platform = "kfreebsd-i386" + end + os.setenv("MTX_PLATFORM",platform) + os.platform = platform + return platform + end + else -- platform = "linux" @@ -2021,7 +2036,7 @@ if not modules then modules = { } end modules ['l-file'] = { file = file or { } local concat = table.concat -local find, gmatch, match, gsub, sub = string.find, string.gmatch, string.match, string.gsub, string.sub +local find, gmatch, match, gsub, sub, char = string.find, string.gmatch, string.match, string.gsub, string.sub, string.char local lpegmatch = lpeg.match function file.removesuffix(filename) @@ -2058,14 +2073,33 @@ end file.suffix = file.extname ---~ print(file.join("x/","/y")) ---~ print(file.join("http://","/y")) ---~ print(file.join("http://a","/y")) ---~ print(file.join("http:///a","/y")) ---~ print(file.join("//nas-1","/y")) +--~ function file.join(...) +--~ local pth = concat({...},"/") +--~ pth = gsub(pth,"\\","/") +--~ local a, b = match(pth,"^(.*://)(.*)$") +--~ if a and b then +--~ return a .. gsub(b,"//+","/") +--~ end +--~ a, b = match(pth,"^(//)(.*)$") +--~ if a and b then +--~ return a .. gsub(b,"//+","/") +--~ end +--~ return (gsub(pth,"//+","/")) +--~ end + +local trick_1 = char(1) +local trick_2 = "^" .. trick_1 .. "/+" function file.join(...) - local pth = concat({...},"/") + local lst = { ... } + local a, b = lst[1], lst[2] + if a == "" then + lst[1] = trick_1 + elseif b and find(a,"^/+$") and find(b,"^/") then + lst[1] = "" + lst[2] = gsub(b,"^/+","") + end + local pth = concat(lst,"/") pth = gsub(pth,"\\","/") local a, b = match(pth,"^(.*://)(.*)$") if a and b then @@ -2075,9 +2109,20 @@ function file.join(...) if a and b then return a .. gsub(b,"//+","/") end + pth = gsub(pth,trick_2,"") return (gsub(pth,"//+","/")) end +--~ print(file.join("//","/y")) +--~ print(file.join("/","/y")) +--~ print(file.join("","/y")) +--~ print(file.join("/x/","/y")) +--~ print(file.join("x/","/y")) +--~ print(file.join("http://","/y")) +--~ print(file.join("http://a","/y")) +--~ print(file.join("http:///a","/y")) +--~ print(file.join("//nas-1","/y")) + function file.iswritable(name) local a = lfs.attributes(name) or lfs.attributes(file.dirname(name,".")) return a and sub(a.permissions,2,2) == "w" @@ -2116,16 +2161,22 @@ function file.join_path(tab) return concat(tab,io.pathseparator) -- can have trailing // end +-- we can hash them weakly + function file.collapse_path(str) - str = gsub(str,"/%./","/") - local n, m = 1, 1 - while n > 0 or m > 0 do - str, n = gsub(str,"[^/%.]+/%.%.$","") - str, m = gsub(str,"[^/%.]+/%.%./","") - end - str = gsub(str,"([^/])/$","%1") - str = gsub(str,"^%./","") - str = gsub(str,"/%.$","") + str = gsub(str,"\\","/") + if find(str,"/") then + str = gsub(str,"^%./",(gsub(lfs.currentdir(),"\\","/")) .. "/") -- ./xx in qualified + str = gsub(str,"/%./","/") + local n, m = 1, 1 + while n > 0 or m > 0 do + str, n = gsub(str,"[^/%.]+/%.%.$","") + str, m = gsub(str,"[^/%.]+/%.%./","") + end + str = gsub(str,"([^/])/$","%1") + -- str = gsub(str,"^%./","") -- ./xx in qualified + str = gsub(str,"/%.$","") + end if str == "" then str = "." end return str end @@ -2824,7 +2875,7 @@ else --~ print(dir.mkdirs("///a/b/c")) --~ print(dir.mkdirs("a/bbb//ccc/")) - function dir.expand_name(str) + function dir.expand_name(str) -- will be merged with cleanpath and collapsepath if not find(str,"^/") then str = lfs.currentdir() .. "/" .. str end @@ -3340,6 +3391,8 @@ local stripper = lpeg.Cs((number + 1)^0) --~ lpegmatch(stripper,str) --~ print(#str, os.clock()-ts, lpegmatch(stripper,sample)) +lpeg.patterns.strip_zeros = stripper + function aux.strip_zeros(str) return lpegmatch(stripper,str) end @@ -3626,14 +3679,14 @@ end function setters.enable(t,what) local e = t.enable t.enable, t.done = enable, { } - enable(t,string.simpleesc(what)) + enable(t,string.simpleesc(tostring(what))) t.enable, t.done = e, { } end function setters.disable(t,what) local e = t.disable t.disable, t.done = disable, { } - disable(t,string.simpleesc(what)) + disable(t,string.simpleesc(tostring(what))) t.disable, t.done = e, { } end @@ -3720,6 +3773,13 @@ function experiments.disable(...) d(...) end +-- a useful example + +directives.register("system.nostatistics", function(v) + statistics.enable = not v +end) + + end -- of closure @@ -3995,9 +4055,9 @@ local function attribute_specification_error(str) return str end -function xml.unknown_dec_entity_format(str) return format("&%s;", str) end +function xml.unknown_dec_entity_format(str) return (str == "" and "&error;") or format("&%s;",str) end function xml.unknown_hex_entity_format(str) return format("&#x%s;",str) end -function xml.unknown_any_entity_format(str) return format("&%s;", str) end +function xml.unknown_any_entity_format(str) return format("&#x%s;",str) end local function handle_hex_entity(str) local h = hcache[str] @@ -4111,7 +4171,11 @@ local function handle_any_entity(str) if trace_entities then logs.report("xml","keeping entity &%s;",str) end - a = "&" .. str .. ";" + if str == "" then + a = "&error;" + else + a = "&" .. str .. ";" + end end end acache[str] = a @@ -4132,6 +4196,9 @@ local function handle_any_entity(str) if a then -- one of the predefined acache[str] = a + elseif str == "" then + a = "&error;" + acache[str] = a else a = "&" .. str .. ";" acache[str] = a @@ -4460,7 +4527,7 @@ function xml.checkbom(root) -- can be made faster local dt, found = root.dt, false for k=1,#dt do local v = dt[k] - if type(v) == "table" and v.special and v.tg == "@pi" and find(v.dt,"xml.*version=") then + if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then found = true break end @@ -4842,6 +4909,8 @@ function xml.assign(dt,k,root) end end +-- the following helpers may move + --[[ldx-- <p>The next helper assigns a tree (or string). Usage:</p> <typing> @@ -4860,6 +4929,22 @@ function xml.tocdata(e,wrapper) e.dt = { t } end +function xml.makestandalone(root) + if root.ri then + local dt = root.dt + for k=1,#dt do + local v = dt[k] + if type(v) == "table" and v.special and v.tg == "@pi@" then + local txt = v.dt[1] + if find(txt,"xml.*version=") then + v.dt[1] = txt .. " standalone='yes'" + break + end + end + end + end +end + end -- of closure @@ -5476,8 +5561,13 @@ local register_initial_child = { kind = "axis", axis = "initial-child" local register_all_nodes = { kind = "nodes", nodetest = true, nodes = { true, false, false } } +local skip = { } + local function errorrunner_e(str,cnv) - logs.report("lpath","error in expression: %s => %s",str,cnv) + if not skip[str] then + logs.report("lpath","error in expression: %s => %s",str,cnv) + skip[str] = cnv or str + end return false end local function errorrunner_f(str,arg) @@ -7287,6 +7377,14 @@ function statistics.hastimer(instance) return instance and instance.starttime end +function statistics.resettiming(instance) + if not instance then + notimer = { timing = 0, loadtime = 0 } + else + instance.timing, instance.loadtime = 0, 0 + end +end + function statistics.starttiming(instance) if not instance then notimer = { } @@ -7346,6 +7444,12 @@ function statistics.elapsedindeed(instance) return t > statistics.threshold end +function statistics.elapsedseconds(instance,rest) -- returns nil if 0 seconds + if statistics.elapsedindeed(instance) then + return format("%s seconds %s", statistics.elapsedtime(instance),rest or "") + end +end + -- general function function statistics.register(tag,fnc) @@ -7424,6 +7528,23 @@ function statistics.timed(action,report) report("total runtime: %s",statistics.elapsedtime(timer)) end +-- where, not really the best spot for this: + +commands = commands or { } + +local timer + +function commands.resettimer() + statistics.resettiming(timer) + statistics.starttiming(timer) +end + +function commands.elapsedtime() + statistics.stoptiming(timer) + tex.sprint(statistics.elapsedtime(timer)) +end + +commands.resettimer() end -- of closure @@ -7861,8 +7982,8 @@ suffixes['lua'] = { 'lua', 'luc', 'tma', 'tmc' } alternatives['map files'] = 'map' alternatives['enc files'] = 'enc' -alternatives['cid files'] = 'cid' -alternatives['fea files'] = 'fea' +alternatives['cid maps'] = 'cid' -- great, why no cid files +alternatives['font feature files'] = 'fea' -- and fea files here alternatives['opentype fonts'] = 'otf' alternatives['truetype fonts'] = 'ttf' alternatives['truetype collections'] = 'ttc' @@ -8005,8 +8126,10 @@ local function check_configuration() -- not yet ok, no time for debugging now -- bad luck end fix("LUAINPUTS" , ".;$TEXINPUTS;$TEXMFSCRIPTS") -- no progname, hm - fix("FONTFEATURES", ".;$TEXMF/fonts/fea//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") - fix("FONTCIDMAPS" , ".;$TEXMF/fonts/cid//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + -- this will go away some day + fix("FONTFEATURES", ".;$TEXMF/fonts/{data,fea}//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + fix("FONTCIDMAPS" , ".;$TEXMF/fonts/{data,cid}//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + -- fix("LUATEXLIBS" , ".;$TEXMF/luatex/lua//") end @@ -8396,7 +8519,7 @@ function resolvers.load_cnf() else instance.rootpath = instance.cnffiles[1] for k,fname in ipairs(instance.cnffiles) do - instance.cnffiles[k] = file.collapse_path(gsub(fname,"\\",'/')) + instance.cnffiles[k] = file.collapse_path(fname) end for i=1,3 do instance.rootpath = file.dirname(instance.rootpath) @@ -8425,7 +8548,7 @@ function resolvers.load_lua() else instance.rootpath = instance.luafiles[1] for k,fname in ipairs(instance.luafiles) do - instance.luafiles[k] = file.collapse_path(gsub(fname,"\\",'/')) + instance.luafiles[k] = file.collapse_path(fname) end for i=1,3 do instance.rootpath = file.dirname(instance.rootpath) @@ -8550,7 +8673,7 @@ local weird = lpeg.P(".")^1 + lpeg.anywhere(lpeg.S("~`!#$%^&*()={}[]:;\"\'||<>,? --~ local l_forbidden = lpeg.S("~`!#$%^&*()={}[]:;\"\'||\\/<>,?\n\r\t") --~ local l_confusing = lpeg.P(" ") ---~ local l_character = lpeg.utf8 +--~ local l_character = lpeg.patterns.utf8 --~ local l_dangerous = lpeg.P(".") --~ local l_normal = (l_character - l_forbidden - l_confusing - l_dangerous) * (l_character - l_forbidden - l_confusing^2)^0 * lpeg.P(-1) @@ -9290,8 +9413,7 @@ end local function collect_instance_files(filename,collected) -- todo : plugin (scanners, checkers etc) local result = collected or { } local stamp = nil - filename = file.collapse_path(filename) -- elsewhere - filename = file.collapse_path(gsub(filename,"\\","/")) -- elsewhere + filename = file.collapse_path(filename) -- speed up / beware: format problem if instance.remember then stamp = filename .. "--" .. instance.engine .. "--" .. instance.progname .. "--" .. instance.format @@ -9772,12 +9894,13 @@ end function table.sequenced(t,sep) -- temp here local s = { } for k, v in pairs(t) do -- pairs? - s[#s+1] = k .. "=" .. v + s[#s+1] = k .. "=" .. tostring(v) end return concat(s, sep or " | ") end function resolvers.methodhandler(what, filename, filetype) -- ... + filename = file.collapse_path(filename) local specification = (type(filename) == "string" and resolvers.splitmethod(filename)) or filename -- no or { }, let it bomb local scheme = specification.scheme if resolvers[what][scheme] then diff --git a/scripts/context/stubs/mswin/context.exe b/scripts/context/stubs/mswin/context.exe Binary files differindex 9a67fc133..2d45f2749 100755 --- a/scripts/context/stubs/mswin/context.exe +++ b/scripts/context/stubs/mswin/context.exe diff --git a/scripts/context/stubs/mswin/luatools.exe b/scripts/context/stubs/mswin/luatools.exe Binary files differindex 9a67fc133..2d45f2749 100755 --- a/scripts/context/stubs/mswin/luatools.exe +++ b/scripts/context/stubs/mswin/luatools.exe diff --git a/scripts/context/stubs/mswin/luatools.lua b/scripts/context/stubs/mswin/luatools.lua index f9b855f74..1a579eb69 100644 --- a/scripts/context/stubs/mswin/luatools.lua +++ b/scripts/context/stubs/mswin/luatools.lua @@ -338,6 +338,8 @@ if not modules then modules = { } end modules ['l-lpeg'] = { lpeg = require("lpeg") +lpeg.patterns = lpeg.patterns or { } -- so that we can share + local P, R, S, Ct, C, Cs, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc local match = lpeg.match @@ -488,11 +490,9 @@ end --~ --~ local decode_pattern = lpeg.Ct(utf8^0) * -1 - local cont = R("\128\191") -- continuation byte -lpeg.utf8 = R("\0\127") + R("\194\223") * cont + R("\224\239") * cont * cont + R("\240\244") * cont * cont * cont - +lpeg.patterns.utf8 = R("\0\127") + R("\194\223") * cont + R("\224\239") * cont * cont + R("\240\244") * cont * cont * cont end -- of closure @@ -1868,6 +1868,7 @@ elseif os.type == "windows" then elseif name == "linux" then function os.resolvers.platform(t,k) + -- we sometims have HOSTTYPE set so let's check that first local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or "" if find(architecture,"x86_64") then platform = "linux-64" @@ -1881,17 +1882,28 @@ elseif name == "linux" then return platform end -elseif name == "macosx" then -- a rather inconsistent mess +elseif name == "macosx" then + + --[[ + Identifying the architecture of OSX is quite a mess and this + is the best we can come up with. For some reason $HOSTTYPE is + a kind of pseudo environment variable, not known to the current + environment. And yes, uname cannot be trusted either, so there + is a change that you end up with a 32 bit run on a 64 bit system. + Also, some proper 64 bit intel macs are too cheap (low-end) and + therefore not permitted to run the 64 bit kernel. + ]]-- function os.resolvers.platform(t,k) - local platform, architecture = "", os.resultof("uname -m") or "" + -- local platform, architecture = "", os.getenv("HOSTTYPE") or "" + -- if architecture == "" then + -- architecture = os.resultof("echo $HOSTTYPE") or "" + -- end + local platform, architecture = "", os.resultof("echo $HOSTTYPE") or "" if architecture == "" then - architecture = os.getenv("HOSTTYPE") or "" - end - if architecture == "" then - architecture = os.resultof("echo $HOSTTYPE") or "" - end - if find(architecture,"i386") then + -- print("\nI have no clue what kind of OSX you're running so let's assume an 32 bit intel.\n") + platform = "osx-intel" + elseif find(architecture,"i386") then platform = "osx-intel" elseif find(architecture,"x86_64") then platform = "osx-64" @@ -1931,6 +1943,21 @@ elseif name == "freebsd" then return platform end +elseif name == "kfreebsd" then + + function os.resolvers.platform(t,k) + -- we sometims have HOSTTYPE set so let's check that first + local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or "" + if find(architecture,"x86_64") then + platform = "kfreebsd-64" + else + platform = "kfreebsd-i386" + end + os.setenv("MTX_PLATFORM",platform) + os.platform = platform + return platform + end + else -- platform = "linux" @@ -1967,6 +1994,21 @@ function os.uuid() ) end +local d + +function os.timezone(delta) + d = d or tonumber(tonumber(os.date("%H")-os.date("!%H"))) + if delta then + if d > 0 then + return format("+%02i:00",d) + else + return format("-%02i:00",-d) + end + else + return 1 + end +end + end -- of closure @@ -1985,7 +2027,7 @@ if not modules then modules = { } end modules ['l-file'] = { file = file or { } local concat = table.concat -local find, gmatch, match, gsub, sub = string.find, string.gmatch, string.match, string.gsub, string.sub +local find, gmatch, match, gsub, sub, char = string.find, string.gmatch, string.match, string.gsub, string.sub, string.char local lpegmatch = lpeg.match function file.removesuffix(filename) @@ -2022,14 +2064,33 @@ end file.suffix = file.extname ---~ print(file.join("x/","/y")) ---~ print(file.join("http://","/y")) ---~ print(file.join("http://a","/y")) ---~ print(file.join("http:///a","/y")) ---~ print(file.join("//nas-1","/y")) +--~ function file.join(...) +--~ local pth = concat({...},"/") +--~ pth = gsub(pth,"\\","/") +--~ local a, b = match(pth,"^(.*://)(.*)$") +--~ if a and b then +--~ return a .. gsub(b,"//+","/") +--~ end +--~ a, b = match(pth,"^(//)(.*)$") +--~ if a and b then +--~ return a .. gsub(b,"//+","/") +--~ end +--~ return (gsub(pth,"//+","/")) +--~ end + +local trick_1 = char(1) +local trick_2 = "^" .. trick_1 .. "/+" function file.join(...) - local pth = concat({...},"/") + local lst = { ... } + local a, b = lst[1], lst[2] + if a == "" then + lst[1] = trick_1 + elseif b and find(a,"^/+$") and find(b,"^/") then + lst[1] = "" + lst[2] = gsub(b,"^/+","") + end + local pth = concat(lst,"/") pth = gsub(pth,"\\","/") local a, b = match(pth,"^(.*://)(.*)$") if a and b then @@ -2039,9 +2100,20 @@ function file.join(...) if a and b then return a .. gsub(b,"//+","/") end + pth = gsub(pth,trick_2,"") return (gsub(pth,"//+","/")) end +--~ print(file.join("//","/y")) +--~ print(file.join("/","/y")) +--~ print(file.join("","/y")) +--~ print(file.join("/x/","/y")) +--~ print(file.join("x/","/y")) +--~ print(file.join("http://","/y")) +--~ print(file.join("http://a","/y")) +--~ print(file.join("http:///a","/y")) +--~ print(file.join("//nas-1","/y")) + function file.iswritable(name) local a = lfs.attributes(name) or lfs.attributes(file.dirname(name,".")) return a and sub(a.permissions,2,2) == "w" @@ -2080,16 +2152,22 @@ function file.join_path(tab) return concat(tab,io.pathseparator) -- can have trailing // end +-- we can hash them weakly + function file.collapse_path(str) - str = gsub(str,"/%./","/") - local n, m = 1, 1 - while n > 0 or m > 0 do - str, n = gsub(str,"[^/%.]+/%.%.$","") - str, m = gsub(str,"[^/%.]+/%.%./","") - end - str = gsub(str,"([^/])/$","%1") - str = gsub(str,"^%./","") - str = gsub(str,"/%.$","") + str = gsub(str,"\\","/") + if find(str,"/") then + str = gsub(str,"^%./",(gsub(lfs.currentdir(),"\\","/")) .. "/") -- ./xx in qualified + str = gsub(str,"/%./","/") + local n, m = 1, 1 + while n > 0 or m > 0 do + str, n = gsub(str,"[^/%.]+/%.%.$","") + str, m = gsub(str,"[^/%.]+/%.%./","") + end + str = gsub(str,"([^/])/$","%1") + -- str = gsub(str,"^%./","") -- ./xx in qualified + str = gsub(str,"/%.$","") + end if str == "" then str = "." end return str end @@ -2391,7 +2469,7 @@ function url.hashed(str) end function url.hasscheme(str) - return not url.split(str).nosheme + return url.split(str)[1] ~= "" end function url.addscheme(str,scheme) @@ -2788,7 +2866,7 @@ else --~ print(dir.mkdirs("///a/b/c")) --~ print(dir.mkdirs("a/bbb//ccc/")) - function dir.expand_name(str) + function dir.expand_name(str) -- will be merged with cleanpath and collapsepath if not find(str,"^/") then str = lfs.currentdir() .. "/" .. str end @@ -3503,6 +3581,8 @@ local stripper = lpeg.Cs((number + 1)^0) --~ lpegmatch(stripper,str) --~ print(#str, os.clock()-ts, lpegmatch(stripper,sample)) +lpeg.patterns.strip_zeros = stripper + function aux.strip_zeros(str) return lpegmatch(stripper,str) end @@ -3789,14 +3869,14 @@ end function setters.enable(t,what) local e = t.enable t.enable, t.done = enable, { } - enable(t,string.simpleesc(what)) + enable(t,string.simpleesc(tostring(what))) t.enable, t.done = e, { } end function setters.disable(t,what) local e = t.disable t.disable, t.done = disable, { } - disable(t,string.simpleesc(what)) + disable(t,string.simpleesc(tostring(what))) t.disable, t.done = e, { } end @@ -3847,13 +3927,15 @@ function setters.new(name) return t end -trackers = setters.new("trackers") -directives = setters.new("directives") +trackers = setters.new("trackers") +directives = setters.new("directives") +experiments = setters.new("experiments") -- nice trick: we overload two of the directives related functions with variants that -- do tracing (itself using a tracker) .. proof of concept -local trace_directives = false local trace_directives = false trackers.register("system.directives", function(v) trace_directives = v end) +local trace_directives = false local trace_directives = false trackers.register("system.directives", function(v) trace_directives = v end) +local trace_experiments = false local trace_experiments = false trackers.register("system.experiments", function(v) trace_experiments = v end) local e = directives.enable local d = directives.disable @@ -3868,6 +3950,26 @@ function directives.disable(...) d(...) end +local e = experiments.enable +local d = experiments.disable + +function experiments.enable(...) + commands.writestatus("experiments","enabling: %s",concat({...}," ")) + e(...) +end + +function experiments.disable(...) + commands.writestatus("experiments","disabling: %s",concat({...}," ")) + d(...) +end + +-- a useful example + +directives.register("system.nostatistics", function(v) + statistics.enable = not v +end) + + end -- of closure @@ -4181,6 +4283,14 @@ function statistics.hastimer(instance) return instance and instance.starttime end +function statistics.resettiming(instance) + if not instance then + notimer = { timing = 0, loadtime = 0 } + else + instance.timing, instance.loadtime = 0, 0 + end +end + function statistics.starttiming(instance) if not instance then notimer = { } @@ -4240,6 +4350,12 @@ function statistics.elapsedindeed(instance) return t > statistics.threshold end +function statistics.elapsedseconds(instance,rest) -- returns nil if 0 seconds + if statistics.elapsedindeed(instance) then + return format("%s seconds %s", statistics.elapsedtime(instance),rest or "") + end +end + -- general function function statistics.register(tag,fnc) @@ -4318,6 +4434,23 @@ function statistics.timed(action,report) report("total runtime: %s",statistics.elapsedtime(timer)) end +-- where, not really the best spot for this: + +commands = commands or { } + +local timer + +function commands.resettimer() + statistics.resettiming(timer) + statistics.starttiming(timer) +end + +function commands.elapsedtime() + statistics.stoptiming(timer) + tex.sprint(statistics.elapsedtime(timer)) +end + +commands.resettimer() end -- of closure @@ -4755,8 +4888,8 @@ suffixes['lua'] = { 'lua', 'luc', 'tma', 'tmc' } alternatives['map files'] = 'map' alternatives['enc files'] = 'enc' -alternatives['cid files'] = 'cid' -alternatives['fea files'] = 'fea' +alternatives['cid maps'] = 'cid' -- great, why no cid files +alternatives['font feature files'] = 'fea' -- and fea files here alternatives['opentype fonts'] = 'otf' alternatives['truetype fonts'] = 'ttf' alternatives['truetype collections'] = 'ttc' @@ -4899,8 +5032,10 @@ local function check_configuration() -- not yet ok, no time for debugging now -- bad luck end fix("LUAINPUTS" , ".;$TEXINPUTS;$TEXMFSCRIPTS") -- no progname, hm - fix("FONTFEATURES", ".;$TEXMF/fonts/fea//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") - fix("FONTCIDMAPS" , ".;$TEXMF/fonts/cid//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + -- this will go away some day + fix("FONTFEATURES", ".;$TEXMF/fonts/{data,fea}//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + fix("FONTCIDMAPS" , ".;$TEXMF/fonts/{data,cid}//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + -- fix("LUATEXLIBS" , ".;$TEXMF/luatex/lua//") end @@ -5290,7 +5425,7 @@ function resolvers.load_cnf() else instance.rootpath = instance.cnffiles[1] for k,fname in ipairs(instance.cnffiles) do - instance.cnffiles[k] = file.collapse_path(gsub(fname,"\\",'/')) + instance.cnffiles[k] = file.collapse_path(fname) end for i=1,3 do instance.rootpath = file.dirname(instance.rootpath) @@ -5319,7 +5454,7 @@ function resolvers.load_lua() else instance.rootpath = instance.luafiles[1] for k,fname in ipairs(instance.luafiles) do - instance.luafiles[k] = file.collapse_path(gsub(fname,"\\",'/')) + instance.luafiles[k] = file.collapse_path(fname) end for i=1,3 do instance.rootpath = file.dirname(instance.rootpath) @@ -5444,7 +5579,7 @@ local weird = lpeg.P(".")^1 + lpeg.anywhere(lpeg.S("~`!#$%^&*()={}[]:;\"\'||<>,? --~ local l_forbidden = lpeg.S("~`!#$%^&*()={}[]:;\"\'||\\/<>,?\n\r\t") --~ local l_confusing = lpeg.P(" ") ---~ local l_character = lpeg.utf8 +--~ local l_character = lpeg.patterns.utf8 --~ local l_dangerous = lpeg.P(".") --~ local l_normal = (l_character - l_forbidden - l_confusing - l_dangerous) * (l_character - l_forbidden - l_confusing^2)^0 * lpeg.P(-1) @@ -6184,8 +6319,7 @@ end local function collect_instance_files(filename,collected) -- todo : plugin (scanners, checkers etc) local result = collected or { } local stamp = nil - filename = file.collapse_path(filename) -- elsewhere - filename = file.collapse_path(gsub(filename,"\\","/")) -- elsewhere + filename = file.collapse_path(filename) -- speed up / beware: format problem if instance.remember then stamp = filename .. "--" .. instance.engine .. "--" .. instance.progname .. "--" .. instance.format @@ -6666,12 +6800,13 @@ end function table.sequenced(t,sep) -- temp here local s = { } for k, v in pairs(t) do -- pairs? - s[#s+1] = k .. "=" .. v + s[#s+1] = k .. "=" .. tostring(v) end return concat(s, sep or " | ") end function resolvers.methodhandler(what, filename, filetype) -- ... + filename = file.collapse_path(filename) local specification = (type(filename) == "string" and resolvers.splitmethod(filename)) or filename -- no or { }, let it bomb local scheme = specification.scheme if resolvers[what][scheme] then diff --git a/scripts/context/stubs/mswin/metatex.exe b/scripts/context/stubs/mswin/metatex.exe Binary files differindex 9a67fc133..2d45f2749 100755 --- a/scripts/context/stubs/mswin/metatex.exe +++ b/scripts/context/stubs/mswin/metatex.exe diff --git a/scripts/context/stubs/mswin/mtxrun.dll b/scripts/context/stubs/mswin/mtxrun.dll Binary files differindex 6af687abe..bb7af56ec 100644 --- a/scripts/context/stubs/mswin/mtxrun.dll +++ b/scripts/context/stubs/mswin/mtxrun.dll diff --git a/scripts/context/stubs/mswin/mtxrun.exe b/scripts/context/stubs/mswin/mtxrun.exe Binary files differindex 9a67fc133..2d45f2749 100755 --- a/scripts/context/stubs/mswin/mtxrun.exe +++ b/scripts/context/stubs/mswin/mtxrun.exe diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua index 8a2d7a123..ef7eda9b0 100644 --- a/scripts/context/stubs/mswin/mtxrun.lua +++ b/scripts/context/stubs/mswin/mtxrun.lua @@ -347,6 +347,8 @@ if not modules then modules = { } end modules ['l-lpeg'] = { lpeg = require("lpeg") +lpeg.patterns = lpeg.patterns or { } -- so that we can share + local P, R, S, Ct, C, Cs, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc local match = lpeg.match @@ -497,11 +499,9 @@ end --~ --~ local decode_pattern = lpeg.Ct(utf8^0) * -1 - local cont = R("\128\191") -- continuation byte -lpeg.utf8 = R("\0\127") + R("\194\223") * cont + R("\224\239") * cont * cont + R("\240\244") * cont * cont * cont - +lpeg.patterns.utf8 = R("\0\127") + R("\194\223") * cont + R("\224\239") * cont * cont + R("\240\244") * cont * cont * cont end -- of closure @@ -1952,6 +1952,21 @@ elseif name == "freebsd" then return platform end +elseif name == "kfreebsd" then + + function os.resolvers.platform(t,k) + -- we sometims have HOSTTYPE set so let's check that first + local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or "" + if find(architecture,"x86_64") then + platform = "kfreebsd-64" + else + platform = "kfreebsd-i386" + end + os.setenv("MTX_PLATFORM",platform) + os.platform = platform + return platform + end + else -- platform = "linux" @@ -2021,7 +2036,7 @@ if not modules then modules = { } end modules ['l-file'] = { file = file or { } local concat = table.concat -local find, gmatch, match, gsub, sub = string.find, string.gmatch, string.match, string.gsub, string.sub +local find, gmatch, match, gsub, sub, char = string.find, string.gmatch, string.match, string.gsub, string.sub, string.char local lpegmatch = lpeg.match function file.removesuffix(filename) @@ -2058,14 +2073,33 @@ end file.suffix = file.extname ---~ print(file.join("x/","/y")) ---~ print(file.join("http://","/y")) ---~ print(file.join("http://a","/y")) ---~ print(file.join("http:///a","/y")) ---~ print(file.join("//nas-1","/y")) +--~ function file.join(...) +--~ local pth = concat({...},"/") +--~ pth = gsub(pth,"\\","/") +--~ local a, b = match(pth,"^(.*://)(.*)$") +--~ if a and b then +--~ return a .. gsub(b,"//+","/") +--~ end +--~ a, b = match(pth,"^(//)(.*)$") +--~ if a and b then +--~ return a .. gsub(b,"//+","/") +--~ end +--~ return (gsub(pth,"//+","/")) +--~ end + +local trick_1 = char(1) +local trick_2 = "^" .. trick_1 .. "/+" function file.join(...) - local pth = concat({...},"/") + local lst = { ... } + local a, b = lst[1], lst[2] + if a == "" then + lst[1] = trick_1 + elseif b and find(a,"^/+$") and find(b,"^/") then + lst[1] = "" + lst[2] = gsub(b,"^/+","") + end + local pth = concat(lst,"/") pth = gsub(pth,"\\","/") local a, b = match(pth,"^(.*://)(.*)$") if a and b then @@ -2075,9 +2109,20 @@ function file.join(...) if a and b then return a .. gsub(b,"//+","/") end + pth = gsub(pth,trick_2,"") return (gsub(pth,"//+","/")) end +--~ print(file.join("//","/y")) +--~ print(file.join("/","/y")) +--~ print(file.join("","/y")) +--~ print(file.join("/x/","/y")) +--~ print(file.join("x/","/y")) +--~ print(file.join("http://","/y")) +--~ print(file.join("http://a","/y")) +--~ print(file.join("http:///a","/y")) +--~ print(file.join("//nas-1","/y")) + function file.iswritable(name) local a = lfs.attributes(name) or lfs.attributes(file.dirname(name,".")) return a and sub(a.permissions,2,2) == "w" @@ -2116,16 +2161,22 @@ function file.join_path(tab) return concat(tab,io.pathseparator) -- can have trailing // end +-- we can hash them weakly + function file.collapse_path(str) - str = gsub(str,"/%./","/") - local n, m = 1, 1 - while n > 0 or m > 0 do - str, n = gsub(str,"[^/%.]+/%.%.$","") - str, m = gsub(str,"[^/%.]+/%.%./","") - end - str = gsub(str,"([^/])/$","%1") - str = gsub(str,"^%./","") - str = gsub(str,"/%.$","") + str = gsub(str,"\\","/") + if find(str,"/") then + str = gsub(str,"^%./",(gsub(lfs.currentdir(),"\\","/")) .. "/") -- ./xx in qualified + str = gsub(str,"/%./","/") + local n, m = 1, 1 + while n > 0 or m > 0 do + str, n = gsub(str,"[^/%.]+/%.%.$","") + str, m = gsub(str,"[^/%.]+/%.%./","") + end + str = gsub(str,"([^/])/$","%1") + -- str = gsub(str,"^%./","") -- ./xx in qualified + str = gsub(str,"/%.$","") + end if str == "" then str = "." end return str end @@ -2824,7 +2875,7 @@ else --~ print(dir.mkdirs("///a/b/c")) --~ print(dir.mkdirs("a/bbb//ccc/")) - function dir.expand_name(str) + function dir.expand_name(str) -- will be merged with cleanpath and collapsepath if not find(str,"^/") then str = lfs.currentdir() .. "/" .. str end @@ -3340,6 +3391,8 @@ local stripper = lpeg.Cs((number + 1)^0) --~ lpegmatch(stripper,str) --~ print(#str, os.clock()-ts, lpegmatch(stripper,sample)) +lpeg.patterns.strip_zeros = stripper + function aux.strip_zeros(str) return lpegmatch(stripper,str) end @@ -3626,14 +3679,14 @@ end function setters.enable(t,what) local e = t.enable t.enable, t.done = enable, { } - enable(t,string.simpleesc(what)) + enable(t,string.simpleesc(tostring(what))) t.enable, t.done = e, { } end function setters.disable(t,what) local e = t.disable t.disable, t.done = disable, { } - disable(t,string.simpleesc(what)) + disable(t,string.simpleesc(tostring(what))) t.disable, t.done = e, { } end @@ -3720,6 +3773,13 @@ function experiments.disable(...) d(...) end +-- a useful example + +directives.register("system.nostatistics", function(v) + statistics.enable = not v +end) + + end -- of closure @@ -3995,9 +4055,9 @@ local function attribute_specification_error(str) return str end -function xml.unknown_dec_entity_format(str) return format("&%s;", str) end +function xml.unknown_dec_entity_format(str) return (str == "" and "&error;") or format("&%s;",str) end function xml.unknown_hex_entity_format(str) return format("&#x%s;",str) end -function xml.unknown_any_entity_format(str) return format("&%s;", str) end +function xml.unknown_any_entity_format(str) return format("&#x%s;",str) end local function handle_hex_entity(str) local h = hcache[str] @@ -4111,7 +4171,11 @@ local function handle_any_entity(str) if trace_entities then logs.report("xml","keeping entity &%s;",str) end - a = "&" .. str .. ";" + if str == "" then + a = "&error;" + else + a = "&" .. str .. ";" + end end end acache[str] = a @@ -4132,6 +4196,9 @@ local function handle_any_entity(str) if a then -- one of the predefined acache[str] = a + elseif str == "" then + a = "&error;" + acache[str] = a else a = "&" .. str .. ";" acache[str] = a @@ -4460,7 +4527,7 @@ function xml.checkbom(root) -- can be made faster local dt, found = root.dt, false for k=1,#dt do local v = dt[k] - if type(v) == "table" and v.special and v.tg == "@pi" and find(v.dt,"xml.*version=") then + if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then found = true break end @@ -4842,6 +4909,8 @@ function xml.assign(dt,k,root) end end +-- the following helpers may move + --[[ldx-- <p>The next helper assigns a tree (or string). Usage:</p> <typing> @@ -4860,6 +4929,22 @@ function xml.tocdata(e,wrapper) e.dt = { t } end +function xml.makestandalone(root) + if root.ri then + local dt = root.dt + for k=1,#dt do + local v = dt[k] + if type(v) == "table" and v.special and v.tg == "@pi@" then + local txt = v.dt[1] + if find(txt,"xml.*version=") then + v.dt[1] = txt .. " standalone='yes'" + break + end + end + end + end +end + end -- of closure @@ -5476,8 +5561,13 @@ local register_initial_child = { kind = "axis", axis = "initial-child" local register_all_nodes = { kind = "nodes", nodetest = true, nodes = { true, false, false } } +local skip = { } + local function errorrunner_e(str,cnv) - logs.report("lpath","error in expression: %s => %s",str,cnv) + if not skip[str] then + logs.report("lpath","error in expression: %s => %s",str,cnv) + skip[str] = cnv or str + end return false end local function errorrunner_f(str,arg) @@ -7287,6 +7377,14 @@ function statistics.hastimer(instance) return instance and instance.starttime end +function statistics.resettiming(instance) + if not instance then + notimer = { timing = 0, loadtime = 0 } + else + instance.timing, instance.loadtime = 0, 0 + end +end + function statistics.starttiming(instance) if not instance then notimer = { } @@ -7346,6 +7444,12 @@ function statistics.elapsedindeed(instance) return t > statistics.threshold end +function statistics.elapsedseconds(instance,rest) -- returns nil if 0 seconds + if statistics.elapsedindeed(instance) then + return format("%s seconds %s", statistics.elapsedtime(instance),rest or "") + end +end + -- general function function statistics.register(tag,fnc) @@ -7424,6 +7528,23 @@ function statistics.timed(action,report) report("total runtime: %s",statistics.elapsedtime(timer)) end +-- where, not really the best spot for this: + +commands = commands or { } + +local timer + +function commands.resettimer() + statistics.resettiming(timer) + statistics.starttiming(timer) +end + +function commands.elapsedtime() + statistics.stoptiming(timer) + tex.sprint(statistics.elapsedtime(timer)) +end + +commands.resettimer() end -- of closure @@ -7861,8 +7982,8 @@ suffixes['lua'] = { 'lua', 'luc', 'tma', 'tmc' } alternatives['map files'] = 'map' alternatives['enc files'] = 'enc' -alternatives['cid files'] = 'cid' -alternatives['fea files'] = 'fea' +alternatives['cid maps'] = 'cid' -- great, why no cid files +alternatives['font feature files'] = 'fea' -- and fea files here alternatives['opentype fonts'] = 'otf' alternatives['truetype fonts'] = 'ttf' alternatives['truetype collections'] = 'ttc' @@ -8005,8 +8126,10 @@ local function check_configuration() -- not yet ok, no time for debugging now -- bad luck end fix("LUAINPUTS" , ".;$TEXINPUTS;$TEXMFSCRIPTS") -- no progname, hm - fix("FONTFEATURES", ".;$TEXMF/fonts/fea//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") - fix("FONTCIDMAPS" , ".;$TEXMF/fonts/cid//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + -- this will go away some day + fix("FONTFEATURES", ".;$TEXMF/fonts/{data,fea}//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + fix("FONTCIDMAPS" , ".;$TEXMF/fonts/{data,cid}//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + -- fix("LUATEXLIBS" , ".;$TEXMF/luatex/lua//") end @@ -8396,7 +8519,7 @@ function resolvers.load_cnf() else instance.rootpath = instance.cnffiles[1] for k,fname in ipairs(instance.cnffiles) do - instance.cnffiles[k] = file.collapse_path(gsub(fname,"\\",'/')) + instance.cnffiles[k] = file.collapse_path(fname) end for i=1,3 do instance.rootpath = file.dirname(instance.rootpath) @@ -8425,7 +8548,7 @@ function resolvers.load_lua() else instance.rootpath = instance.luafiles[1] for k,fname in ipairs(instance.luafiles) do - instance.luafiles[k] = file.collapse_path(gsub(fname,"\\",'/')) + instance.luafiles[k] = file.collapse_path(fname) end for i=1,3 do instance.rootpath = file.dirname(instance.rootpath) @@ -8550,7 +8673,7 @@ local weird = lpeg.P(".")^1 + lpeg.anywhere(lpeg.S("~`!#$%^&*()={}[]:;\"\'||<>,? --~ local l_forbidden = lpeg.S("~`!#$%^&*()={}[]:;\"\'||\\/<>,?\n\r\t") --~ local l_confusing = lpeg.P(" ") ---~ local l_character = lpeg.utf8 +--~ local l_character = lpeg.patterns.utf8 --~ local l_dangerous = lpeg.P(".") --~ local l_normal = (l_character - l_forbidden - l_confusing - l_dangerous) * (l_character - l_forbidden - l_confusing^2)^0 * lpeg.P(-1) @@ -9290,8 +9413,7 @@ end local function collect_instance_files(filename,collected) -- todo : plugin (scanners, checkers etc) local result = collected or { } local stamp = nil - filename = file.collapse_path(filename) -- elsewhere - filename = file.collapse_path(gsub(filename,"\\","/")) -- elsewhere + filename = file.collapse_path(filename) -- speed up / beware: format problem if instance.remember then stamp = filename .. "--" .. instance.engine .. "--" .. instance.progname .. "--" .. instance.format @@ -9772,12 +9894,13 @@ end function table.sequenced(t,sep) -- temp here local s = { } for k, v in pairs(t) do -- pairs? - s[#s+1] = k .. "=" .. v + s[#s+1] = k .. "=" .. tostring(v) end return concat(s, sep or " | ") end function resolvers.methodhandler(what, filename, filetype) -- ... + filename = file.collapse_path(filename) local specification = (type(filename) == "string" and resolvers.splitmethod(filename)) or filename -- no or { }, let it bomb local scheme = specification.scheme if resolvers[what][scheme] then diff --git a/scripts/context/stubs/mswin/texexec.exe b/scripts/context/stubs/mswin/texexec.exe Binary files differindex 9a67fc133..2d45f2749 100755 --- a/scripts/context/stubs/mswin/texexec.exe +++ b/scripts/context/stubs/mswin/texexec.exe diff --git a/scripts/context/stubs/mswin/texmfstart.exe b/scripts/context/stubs/mswin/texmfstart.exe Binary files differindex 9a67fc133..2d45f2749 100755 --- a/scripts/context/stubs/mswin/texmfstart.exe +++ b/scripts/context/stubs/mswin/texmfstart.exe diff --git a/scripts/context/stubs/source/mtxrun_dll.c b/scripts/context/stubs/source/mtxrun_dll.c index 6cac18c9b..9836c2ac5 100644 --- a/scripts/context/stubs/source/mtxrun_dll.c +++ b/scripts/context/stubs/source/mtxrun_dll.c @@ -1,214 +1,207 @@ -/* +/************************************************************************ -Copyright: + Copyright: -The originally 'runscript' program was written by in 2009 by -T.M.Trzeciak and is public domain. This derived mtxrun program -is an adapted version by Hans Hagen. + Public Domain + Originally written in 2010 by Tomasz M. Trzeciak and Hans Hagen -Comment: + This program is derived from the 'runscript' program originally + written in 2009 by T.M. Trzeciak. It has been adapted for use in + ConTeXt MkIV. -In ConTeXt MkIV we have two core scripts: luatools.lua and -mtxrun.lua where the second one is used to launch other scripts. -Normally a user will use a call like: + Comment: -mtxrun --script font --reload + In ConTeXt MkIV we have two core scripts: luatools.lua and + mtxrun.lua where the second one is used to launch other scripts. + Normally a user will use a call like: -Here mtxrun is a lua script. In order to avoid the usage of a cmd -file on windows this runner will start texlua directly. In TeXlive -a runner is added for each cmd file but we don't want that overhead -(and extra files). By using an exe we can call these scripts in -batch files without the need for using call. + mtxrun --script font --reload -We also don't want to use other runners, like those that use kpse -to locate the script as this is exactly what mtxrun itself is doing -already. Therefore the runscript program is adapted to a more direct -approach suitable for mtxrun. + Here mtxrun is a lua script. In order to avoid the usage of a cmd + file on windows this runner will start texlua directly. If the + shared library luatex.dll is available, texlua will be started in + the same process avoiding thus any additional overhead. Otherwise + it will be spawned in a new proces. -Compilation: + We also don't want to use other runners, like those that use kpse + to locate the script as this is exactly what mtxrun itself is doing + already. Therefore the runscript program is adapted to a more direct + approach suitable for mtxrun. -with gcc (size optimized): + Compilation: -gcc -Os -s -shared -o mtxrun.dll mtxrun_dll.c -gcc -Os -s -o mtxrun.exe mtxrun_exe.c -L./ -lmtxrun + with gcc (size optimized): -with tcc (ver. 0.9.24), extra small size + gcc -Os -s -shared -o mtxrun.dll mtxrun_dll.c + gcc -Os -s -o mtxrun.exe mtxrun_exe.c -tcc -shared -o runscript.dll runscript_dll.c -tcc -o runscript.exe runscript_exe.c runscript.def + with tcc (extra small size): -*/ + tcc -shared -o mtxrun.dll mtxrun_dll.c + tcc -o mtxrun.exe mtxrun_exe.c mtxrun.def + +************************************************************************/ -#include <windows.h> #include <stdio.h> +#include <stdlib.h> +#include <windows.h> +//#define STATIC #define IS_WHITESPACE(c) ((c == ' ') || (c == '\t')) #define MAX_CMD 32768 -//~ #define DRYRUN +#define DIE(...) { \ + fprintf( stderr, "mtxrun: " ); \ + fprintf( stderr, __VA_ARGS__ ); \ + return 1; \ +} -static char dirname [MAX_PATH]; -static char basename[MAX_PATH]; +char texlua_name[] = "texlua"; // just a bare name, luatex strips the rest anyway +static char cmdline[MAX_CMD]; +static char dirpath[MAX_PATH]; static char progname[MAX_PATH]; -static char cmdline [MAX_CMD]; - -__declspec(dllexport) int dllrunscript( int argc, char *argv[] ) { - - int i; - - static char path[MAX_PATH]; - - // get file name of this executable and split it into parts - - DWORD nchars = GetModuleFileNameA(NULL, path, MAX_PATH); - if ( !nchars || (nchars == MAX_PATH) ) { - fprintf(stderr, "mtxrun: unable to determine a valid own name\n"); - return -1; - } - - // file extension part - - i = strlen(path); - - while ( i && (path[i] != '.') && (path[i] != '\\') ) i--; - - strcpy(basename, path); - - if ( basename[i] == '.' ) basename[i] = '\0'; //remove file extension - - // file name part - - while ( i && (path[i] != '\\') ) i--; - - if ( path[i] != '\\' ) { - fprintf(stderr, "mtxrun: the runner has no directory part in its name: %s\n", path); - return -1; - } - - strcpy(dirname, path); - dirname[i+1] = '\0'; //remove file name, leave trailing backslash - strcpy(progname, &basename[i+1]); - - // find program to execute - - if ( (strlen(basename)+100 >= MAX_PATH) ) { - fprintf(stderr, "mtxrun: the runners path is too long: %s\n", path); - return -1; - } - - // check .lua - - strcpy(path, dirname); - strcat(path, "mtxrun.lua"); - - if ( GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES ) { - goto PROGRAM_FOUND; - } else { - fprintf(stderr, "mtxrun: the mtxrun.lua file is not in the same path\n"); - return -1; - } - -PROGRAM_FOUND: - - strcpy(cmdline,"texlua.exe "); - - if ( ( strcmp(progname,"mtxrun") == 0 ) || ( strcmp(progname,"luatools") == 0 ) ) { - strcat(cmdline, dirname); - strcat(cmdline,progname); - strcat(cmdline, ".lua"); - } else if ( ( strcmp(progname,"texmfstart") == 0 ) ) { - strcat(cmdline, dirname); - strcat(cmdline,"mtxrun.lua"); - } else { - strcat(cmdline, dirname); - strcat(cmdline, "mtxrun.lua --script "); - strcat(cmdline,progname); - } - - // get the command line for this process - - char *argstr; - argstr = GetCommandLineA(); - if ( argstr == NULL ) { - fprintf(stderr, "mtxrun: fetching the command line string fails\n"); - return -1; +static char scriptpath[MAX_PATH]; +HMODULE dllluatex = NULL; +typedef int ( *mainlikeproc )( int, char ** ); + +#ifdef STATIC +int main( int argc, char *argv[] ) +#else +__declspec(dllexport) int dllrunscript( int argc, char *argv[] ) +#endif +{ + char *s, *argstr, **lua_argv; + int k, quoted, lua_argc; + int passprogname = 0; + + // directory of this module/executable + + HMODULE module_handle = GetModuleHandle( "mtxrun.dll" ); + // if ( module_handle == NULL ) exe path will be used, which is OK too + k = (int) GetModuleFileName( module_handle, dirpath, MAX_PATH ); + if ( !k || ( k == MAX_PATH ) ) + DIE( "unable to determine a valid module name\n" ); + s = strrchr(dirpath, '\\'); + if ( s == NULL ) DIE( "no directory part in module path: %s\n", dirpath ); + *(++s) = '\0'; //remove file name, leave trailing backslash + + // program name + + k = strlen(argv[0]); + while ( k && (argv[0][k] != '/') && (argv[0][k] != '\\') ) k--; + strcpy(progname, &argv[0][k]); + s = progname; + if ( s = strrchr(s, '.') ) *s = '\0'; // remove file extension part + + // script path + + strcpy( scriptpath, dirpath ); + k = strlen(progname); + if ( k < 6 ) k = 6; // in case the program name is shorter than "mtxrun" + if ( strlen(dirpath) + k + 4 >= MAX_PATH ) + DIE( "path too long: %s%s\n", dirpath, progname ); + if ( ( strcmpi(progname,"mtxrun") == 0 ) || ( strcmpi(progname,"luatools") == 0 ) ) { + strcat( scriptpath, progname ); + strcat( scriptpath, ".lua" ); + } else { + strcat( scriptpath, "mtxrun.lua" ); + if ( strcmpi(progname,"texmfstart") != 0 ) passprogname = 1; + } + if ( GetFileAttributes(scriptpath) == INVALID_FILE_ATTRIBUTES ) + DIE( "file not found: %s\n", scriptpath ); + + // link with luatex.dll if available + + if ( dllluatex = LoadLibrary("luatex.dll") ) + { + mainlikeproc dllluatexmain = (mainlikeproc) GetProcAddress( dllluatex, "dllluatexmain" ); + if ( dllluatexmain == NULL ) + DIE( "unable to locate dllluatexmain procedure in luatex.dll" ); + + // set up argument list for texlua script + + lua_argv = (char **)malloc( (argc + 4) * sizeof(char *) ); + if ( lua_argv == NULL ) DIE( "out of memory\n" ); + lua_argv[lua_argc=0] = texlua_name; + lua_argv[++lua_argc] = scriptpath; // script to execute + if (passprogname) { + lua_argv[++lua_argc] = "--script"; + lua_argv[++lua_argc] = progname; } + for ( k = 1; k < argc; k++ ) lua_argv[++lua_argc] = argv[k]; + lua_argv[++lua_argc] = NULL; - // skip over argv[0] (it can contain embedded double quotes if launched from cmd.exe!) + // call texlua interpreter + // dllluatexmain never returns, but we pretend that it does - int argstrlen = strlen(argstr); - int quoted = 0; - for ( i = 0; ( i < argstrlen) && ( !IS_WHITESPACE(argstr[i]) || quoted ); i++ ) + k = dllluatexmain( lua_argc, lua_argv ); + if (lua_argv) free( lua_argv ); + return k; + } - if (argstr[i] == '"') quoted = !quoted; + // we are still here, so no luatex.dll; spawn texlua.exe instead - // while ( IS_WHITESPACE(argstr[i]) ) i++; // arguments leading whitespace + strcpy( cmdline, "\"" ); +// strcat( cmdline, dirpath ); + strcat( cmdline, "texlua.exe\" \"" ); + strcat( cmdline, scriptpath ); + strcat( cmdline, "\"" ); + if (passprogname) { + strcat( cmdline, " --script " ); + strcat( cmdline, progname ); + } - argstr = &argstr[i]; + argstr = GetCommandLine(); // get the command line of this process + if ( argstr == NULL ) DIE( "unable to retrieve the command line string\n" ); - if ( strlen(cmdline) + strlen(argstr) >= MAX_CMD ) { - fprintf(stderr, "mtxrun: the command line string is too long:\n%s%s\n", cmdline, argstr); - return -1; - } + // skip over argv[0] in the argument string + // (it can contain embedded double quotes if launched from cmd.exe!) - // pass through all the arguments + for ( quoted = 0; (*argstr) && ( !IS_WHITESPACE(*argstr) || quoted ); argstr++ ) + if (*argstr == '"') quoted = !quoted; - strcat(cmdline, argstr); + // pass through all the arguments -#ifdef DRYRUN - printf("progname : %s\n", progname); - printf("dirname : %s\n", dirname); - printf("arguments : %s\n", &argstr[-i]); - for (i = 0; i < argc; i++) { - printf("argv[%d] : %s\n", i, argv[i]); - } - printf("commandline : %s\n", cmdline); - return; -#endif + if ( strlen(cmdline) + strlen(argstr) >= MAX_CMD ) + DIE( "command line string too long:\n%s%s\n", cmdline, argstr ); + strcat( cmdline, argstr ); - // create child process + // create child process - STARTUPINFOA si; // ANSI variant - PROCESS_INFORMATION pi; - ZeroMemory( &si, sizeof(si) ); - si.cb = sizeof(si); + STARTUPINFO si; + PROCESS_INFORMATION pi; + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES;// | STARTF_USESHOWWINDOW; - //si.dwFlags = STARTF_USESHOWWINDOW; //si.wShowWindow = SW_HIDE ; // can be used to hide console window (requires STARTF_USESHOWWINDOW flag) - - si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); - si.hStdError = GetStdHandle(STD_ERROR_HANDLE); - - ZeroMemory( &pi, sizeof(pi) ); - if( !CreateProcessA( - NULL, // module name (uses command line if NULL) - cmdline, // command line - NULL, // process security attributes - NULL, // thread security attributes - TRUE, // handle inheritance - 0, // creation flags, e.g. CREATE_NEW_CONSOLE, CREATE_NO_WINDOW, DETACHED_PROCESS - NULL, // pointer to environment block (uses parent if NULL) - NULL, // starting directory (uses parent if NULL) - &si, // STARTUPINFO structure - &pi ) // PROCESS_INFORMATION structure - ) { - fprintf(stderr, "mtxrun: unable to create a process for: %s\n", cmdline); - return -1; - } - CloseHandle( pi.hThread ); // thread handle is not needed - DWORD ret = 0; - if ( WaitForSingleObject( pi.hProcess, INFINITE ) == WAIT_OBJECT_0 ) { - if ( !GetExitCodeProcess( pi.hProcess, &ret) ) { - fprintf(stderr, "mtxrun: unable to fetch the exit code for process: %s\n", cmdline); - return -1; - } - } else { - fprintf(stderr, "mtxrun: the script has been terminated unexpectedly: %s\n", cmdline); - return -1; - } - CloseHandle( pi.hProcess ); - - return ret; + si.hStdInput = GetStdHandle( STD_INPUT_HANDLE ); + si.hStdOutput = GetStdHandle( STD_OUTPUT_HANDLE ); + si.hStdError = GetStdHandle( STD_ERROR_HANDLE ); + ZeroMemory( &pi, sizeof(pi) ); + + if( !CreateProcess( + NULL, // module name (uses command line if NULL) + cmdline, // command line + NULL, // process security atrributes + NULL, // thread security atrributes + TRUE, // handle inheritance + 0, // creation flags, e.g. CREATE_NEW_CONSOLE, CREATE_NO_WINDOW, DETACHED_PROCESS + NULL, // pointer to environment block (uses parent if NULL) + NULL, // starting directory (uses parent if NULL) + &si, // STARTUPINFO structure + &pi ) // PROCESS_INFORMATION structure + ) DIE( "command execution failed: %s\n", cmdline ); + + DWORD ret = 0; + CloseHandle( pi.hThread ); // thread handle is not needed + if ( WaitForSingleObject( pi.hProcess, INFINITE ) == WAIT_OBJECT_0 ) { + if ( !GetExitCodeProcess( pi.hProcess, &ret) ) + DIE( "unable to retrieve process exit code: %s\n", cmdline ); + } else DIE( "failed to wait for process termination: %s\n", cmdline ); + CloseHandle( pi.hProcess ); + + // propagate exit code from the child process + + return ret; } diff --git a/scripts/context/stubs/unix/luatools b/scripts/context/stubs/unix/luatools index f9b855f74..1a579eb69 100755 --- a/scripts/context/stubs/unix/luatools +++ b/scripts/context/stubs/unix/luatools @@ -338,6 +338,8 @@ if not modules then modules = { } end modules ['l-lpeg'] = { lpeg = require("lpeg") +lpeg.patterns = lpeg.patterns or { } -- so that we can share + local P, R, S, Ct, C, Cs, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc local match = lpeg.match @@ -488,11 +490,9 @@ end --~ --~ local decode_pattern = lpeg.Ct(utf8^0) * -1 - local cont = R("\128\191") -- continuation byte -lpeg.utf8 = R("\0\127") + R("\194\223") * cont + R("\224\239") * cont * cont + R("\240\244") * cont * cont * cont - +lpeg.patterns.utf8 = R("\0\127") + R("\194\223") * cont + R("\224\239") * cont * cont + R("\240\244") * cont * cont * cont end -- of closure @@ -1868,6 +1868,7 @@ elseif os.type == "windows" then elseif name == "linux" then function os.resolvers.platform(t,k) + -- we sometims have HOSTTYPE set so let's check that first local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or "" if find(architecture,"x86_64") then platform = "linux-64" @@ -1881,17 +1882,28 @@ elseif name == "linux" then return platform end -elseif name == "macosx" then -- a rather inconsistent mess +elseif name == "macosx" then + + --[[ + Identifying the architecture of OSX is quite a mess and this + is the best we can come up with. For some reason $HOSTTYPE is + a kind of pseudo environment variable, not known to the current + environment. And yes, uname cannot be trusted either, so there + is a change that you end up with a 32 bit run on a 64 bit system. + Also, some proper 64 bit intel macs are too cheap (low-end) and + therefore not permitted to run the 64 bit kernel. + ]]-- function os.resolvers.platform(t,k) - local platform, architecture = "", os.resultof("uname -m") or "" + -- local platform, architecture = "", os.getenv("HOSTTYPE") or "" + -- if architecture == "" then + -- architecture = os.resultof("echo $HOSTTYPE") or "" + -- end + local platform, architecture = "", os.resultof("echo $HOSTTYPE") or "" if architecture == "" then - architecture = os.getenv("HOSTTYPE") or "" - end - if architecture == "" then - architecture = os.resultof("echo $HOSTTYPE") or "" - end - if find(architecture,"i386") then + -- print("\nI have no clue what kind of OSX you're running so let's assume an 32 bit intel.\n") + platform = "osx-intel" + elseif find(architecture,"i386") then platform = "osx-intel" elseif find(architecture,"x86_64") then platform = "osx-64" @@ -1931,6 +1943,21 @@ elseif name == "freebsd" then return platform end +elseif name == "kfreebsd" then + + function os.resolvers.platform(t,k) + -- we sometims have HOSTTYPE set so let's check that first + local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or "" + if find(architecture,"x86_64") then + platform = "kfreebsd-64" + else + platform = "kfreebsd-i386" + end + os.setenv("MTX_PLATFORM",platform) + os.platform = platform + return platform + end + else -- platform = "linux" @@ -1967,6 +1994,21 @@ function os.uuid() ) end +local d + +function os.timezone(delta) + d = d or tonumber(tonumber(os.date("%H")-os.date("!%H"))) + if delta then + if d > 0 then + return format("+%02i:00",d) + else + return format("-%02i:00",-d) + end + else + return 1 + end +end + end -- of closure @@ -1985,7 +2027,7 @@ if not modules then modules = { } end modules ['l-file'] = { file = file or { } local concat = table.concat -local find, gmatch, match, gsub, sub = string.find, string.gmatch, string.match, string.gsub, string.sub +local find, gmatch, match, gsub, sub, char = string.find, string.gmatch, string.match, string.gsub, string.sub, string.char local lpegmatch = lpeg.match function file.removesuffix(filename) @@ -2022,14 +2064,33 @@ end file.suffix = file.extname ---~ print(file.join("x/","/y")) ---~ print(file.join("http://","/y")) ---~ print(file.join("http://a","/y")) ---~ print(file.join("http:///a","/y")) ---~ print(file.join("//nas-1","/y")) +--~ function file.join(...) +--~ local pth = concat({...},"/") +--~ pth = gsub(pth,"\\","/") +--~ local a, b = match(pth,"^(.*://)(.*)$") +--~ if a and b then +--~ return a .. gsub(b,"//+","/") +--~ end +--~ a, b = match(pth,"^(//)(.*)$") +--~ if a and b then +--~ return a .. gsub(b,"//+","/") +--~ end +--~ return (gsub(pth,"//+","/")) +--~ end + +local trick_1 = char(1) +local trick_2 = "^" .. trick_1 .. "/+" function file.join(...) - local pth = concat({...},"/") + local lst = { ... } + local a, b = lst[1], lst[2] + if a == "" then + lst[1] = trick_1 + elseif b and find(a,"^/+$") and find(b,"^/") then + lst[1] = "" + lst[2] = gsub(b,"^/+","") + end + local pth = concat(lst,"/") pth = gsub(pth,"\\","/") local a, b = match(pth,"^(.*://)(.*)$") if a and b then @@ -2039,9 +2100,20 @@ function file.join(...) if a and b then return a .. gsub(b,"//+","/") end + pth = gsub(pth,trick_2,"") return (gsub(pth,"//+","/")) end +--~ print(file.join("//","/y")) +--~ print(file.join("/","/y")) +--~ print(file.join("","/y")) +--~ print(file.join("/x/","/y")) +--~ print(file.join("x/","/y")) +--~ print(file.join("http://","/y")) +--~ print(file.join("http://a","/y")) +--~ print(file.join("http:///a","/y")) +--~ print(file.join("//nas-1","/y")) + function file.iswritable(name) local a = lfs.attributes(name) or lfs.attributes(file.dirname(name,".")) return a and sub(a.permissions,2,2) == "w" @@ -2080,16 +2152,22 @@ function file.join_path(tab) return concat(tab,io.pathseparator) -- can have trailing // end +-- we can hash them weakly + function file.collapse_path(str) - str = gsub(str,"/%./","/") - local n, m = 1, 1 - while n > 0 or m > 0 do - str, n = gsub(str,"[^/%.]+/%.%.$","") - str, m = gsub(str,"[^/%.]+/%.%./","") - end - str = gsub(str,"([^/])/$","%1") - str = gsub(str,"^%./","") - str = gsub(str,"/%.$","") + str = gsub(str,"\\","/") + if find(str,"/") then + str = gsub(str,"^%./",(gsub(lfs.currentdir(),"\\","/")) .. "/") -- ./xx in qualified + str = gsub(str,"/%./","/") + local n, m = 1, 1 + while n > 0 or m > 0 do + str, n = gsub(str,"[^/%.]+/%.%.$","") + str, m = gsub(str,"[^/%.]+/%.%./","") + end + str = gsub(str,"([^/])/$","%1") + -- str = gsub(str,"^%./","") -- ./xx in qualified + str = gsub(str,"/%.$","") + end if str == "" then str = "." end return str end @@ -2391,7 +2469,7 @@ function url.hashed(str) end function url.hasscheme(str) - return not url.split(str).nosheme + return url.split(str)[1] ~= "" end function url.addscheme(str,scheme) @@ -2788,7 +2866,7 @@ else --~ print(dir.mkdirs("///a/b/c")) --~ print(dir.mkdirs("a/bbb//ccc/")) - function dir.expand_name(str) + function dir.expand_name(str) -- will be merged with cleanpath and collapsepath if not find(str,"^/") then str = lfs.currentdir() .. "/" .. str end @@ -3503,6 +3581,8 @@ local stripper = lpeg.Cs((number + 1)^0) --~ lpegmatch(stripper,str) --~ print(#str, os.clock()-ts, lpegmatch(stripper,sample)) +lpeg.patterns.strip_zeros = stripper + function aux.strip_zeros(str) return lpegmatch(stripper,str) end @@ -3789,14 +3869,14 @@ end function setters.enable(t,what) local e = t.enable t.enable, t.done = enable, { } - enable(t,string.simpleesc(what)) + enable(t,string.simpleesc(tostring(what))) t.enable, t.done = e, { } end function setters.disable(t,what) local e = t.disable t.disable, t.done = disable, { } - disable(t,string.simpleesc(what)) + disable(t,string.simpleesc(tostring(what))) t.disable, t.done = e, { } end @@ -3847,13 +3927,15 @@ function setters.new(name) return t end -trackers = setters.new("trackers") -directives = setters.new("directives") +trackers = setters.new("trackers") +directives = setters.new("directives") +experiments = setters.new("experiments") -- nice trick: we overload two of the directives related functions with variants that -- do tracing (itself using a tracker) .. proof of concept -local trace_directives = false local trace_directives = false trackers.register("system.directives", function(v) trace_directives = v end) +local trace_directives = false local trace_directives = false trackers.register("system.directives", function(v) trace_directives = v end) +local trace_experiments = false local trace_experiments = false trackers.register("system.experiments", function(v) trace_experiments = v end) local e = directives.enable local d = directives.disable @@ -3868,6 +3950,26 @@ function directives.disable(...) d(...) end +local e = experiments.enable +local d = experiments.disable + +function experiments.enable(...) + commands.writestatus("experiments","enabling: %s",concat({...}," ")) + e(...) +end + +function experiments.disable(...) + commands.writestatus("experiments","disabling: %s",concat({...}," ")) + d(...) +end + +-- a useful example + +directives.register("system.nostatistics", function(v) + statistics.enable = not v +end) + + end -- of closure @@ -4181,6 +4283,14 @@ function statistics.hastimer(instance) return instance and instance.starttime end +function statistics.resettiming(instance) + if not instance then + notimer = { timing = 0, loadtime = 0 } + else + instance.timing, instance.loadtime = 0, 0 + end +end + function statistics.starttiming(instance) if not instance then notimer = { } @@ -4240,6 +4350,12 @@ function statistics.elapsedindeed(instance) return t > statistics.threshold end +function statistics.elapsedseconds(instance,rest) -- returns nil if 0 seconds + if statistics.elapsedindeed(instance) then + return format("%s seconds %s", statistics.elapsedtime(instance),rest or "") + end +end + -- general function function statistics.register(tag,fnc) @@ -4318,6 +4434,23 @@ function statistics.timed(action,report) report("total runtime: %s",statistics.elapsedtime(timer)) end +-- where, not really the best spot for this: + +commands = commands or { } + +local timer + +function commands.resettimer() + statistics.resettiming(timer) + statistics.starttiming(timer) +end + +function commands.elapsedtime() + statistics.stoptiming(timer) + tex.sprint(statistics.elapsedtime(timer)) +end + +commands.resettimer() end -- of closure @@ -4755,8 +4888,8 @@ suffixes['lua'] = { 'lua', 'luc', 'tma', 'tmc' } alternatives['map files'] = 'map' alternatives['enc files'] = 'enc' -alternatives['cid files'] = 'cid' -alternatives['fea files'] = 'fea' +alternatives['cid maps'] = 'cid' -- great, why no cid files +alternatives['font feature files'] = 'fea' -- and fea files here alternatives['opentype fonts'] = 'otf' alternatives['truetype fonts'] = 'ttf' alternatives['truetype collections'] = 'ttc' @@ -4899,8 +5032,10 @@ local function check_configuration() -- not yet ok, no time for debugging now -- bad luck end fix("LUAINPUTS" , ".;$TEXINPUTS;$TEXMFSCRIPTS") -- no progname, hm - fix("FONTFEATURES", ".;$TEXMF/fonts/fea//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") - fix("FONTCIDMAPS" , ".;$TEXMF/fonts/cid//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + -- this will go away some day + fix("FONTFEATURES", ".;$TEXMF/fonts/{data,fea}//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + fix("FONTCIDMAPS" , ".;$TEXMF/fonts/{data,cid}//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + -- fix("LUATEXLIBS" , ".;$TEXMF/luatex/lua//") end @@ -5290,7 +5425,7 @@ function resolvers.load_cnf() else instance.rootpath = instance.cnffiles[1] for k,fname in ipairs(instance.cnffiles) do - instance.cnffiles[k] = file.collapse_path(gsub(fname,"\\",'/')) + instance.cnffiles[k] = file.collapse_path(fname) end for i=1,3 do instance.rootpath = file.dirname(instance.rootpath) @@ -5319,7 +5454,7 @@ function resolvers.load_lua() else instance.rootpath = instance.luafiles[1] for k,fname in ipairs(instance.luafiles) do - instance.luafiles[k] = file.collapse_path(gsub(fname,"\\",'/')) + instance.luafiles[k] = file.collapse_path(fname) end for i=1,3 do instance.rootpath = file.dirname(instance.rootpath) @@ -5444,7 +5579,7 @@ local weird = lpeg.P(".")^1 + lpeg.anywhere(lpeg.S("~`!#$%^&*()={}[]:;\"\'||<>,? --~ local l_forbidden = lpeg.S("~`!#$%^&*()={}[]:;\"\'||\\/<>,?\n\r\t") --~ local l_confusing = lpeg.P(" ") ---~ local l_character = lpeg.utf8 +--~ local l_character = lpeg.patterns.utf8 --~ local l_dangerous = lpeg.P(".") --~ local l_normal = (l_character - l_forbidden - l_confusing - l_dangerous) * (l_character - l_forbidden - l_confusing^2)^0 * lpeg.P(-1) @@ -6184,8 +6319,7 @@ end local function collect_instance_files(filename,collected) -- todo : plugin (scanners, checkers etc) local result = collected or { } local stamp = nil - filename = file.collapse_path(filename) -- elsewhere - filename = file.collapse_path(gsub(filename,"\\","/")) -- elsewhere + filename = file.collapse_path(filename) -- speed up / beware: format problem if instance.remember then stamp = filename .. "--" .. instance.engine .. "--" .. instance.progname .. "--" .. instance.format @@ -6666,12 +6800,13 @@ end function table.sequenced(t,sep) -- temp here local s = { } for k, v in pairs(t) do -- pairs? - s[#s+1] = k .. "=" .. v + s[#s+1] = k .. "=" .. tostring(v) end return concat(s, sep or " | ") end function resolvers.methodhandler(what, filename, filetype) -- ... + filename = file.collapse_path(filename) local specification = (type(filename) == "string" and resolvers.splitmethod(filename)) or filename -- no or { }, let it bomb local scheme = specification.scheme if resolvers[what][scheme] then diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun index 8a2d7a123..ef7eda9b0 100755 --- a/scripts/context/stubs/unix/mtxrun +++ b/scripts/context/stubs/unix/mtxrun @@ -347,6 +347,8 @@ if not modules then modules = { } end modules ['l-lpeg'] = { lpeg = require("lpeg") +lpeg.patterns = lpeg.patterns or { } -- so that we can share + local P, R, S, Ct, C, Cs, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc local match = lpeg.match @@ -497,11 +499,9 @@ end --~ --~ local decode_pattern = lpeg.Ct(utf8^0) * -1 - local cont = R("\128\191") -- continuation byte -lpeg.utf8 = R("\0\127") + R("\194\223") * cont + R("\224\239") * cont * cont + R("\240\244") * cont * cont * cont - +lpeg.patterns.utf8 = R("\0\127") + R("\194\223") * cont + R("\224\239") * cont * cont + R("\240\244") * cont * cont * cont end -- of closure @@ -1952,6 +1952,21 @@ elseif name == "freebsd" then return platform end +elseif name == "kfreebsd" then + + function os.resolvers.platform(t,k) + -- we sometims have HOSTTYPE set so let's check that first + local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or "" + if find(architecture,"x86_64") then + platform = "kfreebsd-64" + else + platform = "kfreebsd-i386" + end + os.setenv("MTX_PLATFORM",platform) + os.platform = platform + return platform + end + else -- platform = "linux" @@ -2021,7 +2036,7 @@ if not modules then modules = { } end modules ['l-file'] = { file = file or { } local concat = table.concat -local find, gmatch, match, gsub, sub = string.find, string.gmatch, string.match, string.gsub, string.sub +local find, gmatch, match, gsub, sub, char = string.find, string.gmatch, string.match, string.gsub, string.sub, string.char local lpegmatch = lpeg.match function file.removesuffix(filename) @@ -2058,14 +2073,33 @@ end file.suffix = file.extname ---~ print(file.join("x/","/y")) ---~ print(file.join("http://","/y")) ---~ print(file.join("http://a","/y")) ---~ print(file.join("http:///a","/y")) ---~ print(file.join("//nas-1","/y")) +--~ function file.join(...) +--~ local pth = concat({...},"/") +--~ pth = gsub(pth,"\\","/") +--~ local a, b = match(pth,"^(.*://)(.*)$") +--~ if a and b then +--~ return a .. gsub(b,"//+","/") +--~ end +--~ a, b = match(pth,"^(//)(.*)$") +--~ if a and b then +--~ return a .. gsub(b,"//+","/") +--~ end +--~ return (gsub(pth,"//+","/")) +--~ end + +local trick_1 = char(1) +local trick_2 = "^" .. trick_1 .. "/+" function file.join(...) - local pth = concat({...},"/") + local lst = { ... } + local a, b = lst[1], lst[2] + if a == "" then + lst[1] = trick_1 + elseif b and find(a,"^/+$") and find(b,"^/") then + lst[1] = "" + lst[2] = gsub(b,"^/+","") + end + local pth = concat(lst,"/") pth = gsub(pth,"\\","/") local a, b = match(pth,"^(.*://)(.*)$") if a and b then @@ -2075,9 +2109,20 @@ function file.join(...) if a and b then return a .. gsub(b,"//+","/") end + pth = gsub(pth,trick_2,"") return (gsub(pth,"//+","/")) end +--~ print(file.join("//","/y")) +--~ print(file.join("/","/y")) +--~ print(file.join("","/y")) +--~ print(file.join("/x/","/y")) +--~ print(file.join("x/","/y")) +--~ print(file.join("http://","/y")) +--~ print(file.join("http://a","/y")) +--~ print(file.join("http:///a","/y")) +--~ print(file.join("//nas-1","/y")) + function file.iswritable(name) local a = lfs.attributes(name) or lfs.attributes(file.dirname(name,".")) return a and sub(a.permissions,2,2) == "w" @@ -2116,16 +2161,22 @@ function file.join_path(tab) return concat(tab,io.pathseparator) -- can have trailing // end +-- we can hash them weakly + function file.collapse_path(str) - str = gsub(str,"/%./","/") - local n, m = 1, 1 - while n > 0 or m > 0 do - str, n = gsub(str,"[^/%.]+/%.%.$","") - str, m = gsub(str,"[^/%.]+/%.%./","") - end - str = gsub(str,"([^/])/$","%1") - str = gsub(str,"^%./","") - str = gsub(str,"/%.$","") + str = gsub(str,"\\","/") + if find(str,"/") then + str = gsub(str,"^%./",(gsub(lfs.currentdir(),"\\","/")) .. "/") -- ./xx in qualified + str = gsub(str,"/%./","/") + local n, m = 1, 1 + while n > 0 or m > 0 do + str, n = gsub(str,"[^/%.]+/%.%.$","") + str, m = gsub(str,"[^/%.]+/%.%./","") + end + str = gsub(str,"([^/])/$","%1") + -- str = gsub(str,"^%./","") -- ./xx in qualified + str = gsub(str,"/%.$","") + end if str == "" then str = "." end return str end @@ -2824,7 +2875,7 @@ else --~ print(dir.mkdirs("///a/b/c")) --~ print(dir.mkdirs("a/bbb//ccc/")) - function dir.expand_name(str) + function dir.expand_name(str) -- will be merged with cleanpath and collapsepath if not find(str,"^/") then str = lfs.currentdir() .. "/" .. str end @@ -3340,6 +3391,8 @@ local stripper = lpeg.Cs((number + 1)^0) --~ lpegmatch(stripper,str) --~ print(#str, os.clock()-ts, lpegmatch(stripper,sample)) +lpeg.patterns.strip_zeros = stripper + function aux.strip_zeros(str) return lpegmatch(stripper,str) end @@ -3626,14 +3679,14 @@ end function setters.enable(t,what) local e = t.enable t.enable, t.done = enable, { } - enable(t,string.simpleesc(what)) + enable(t,string.simpleesc(tostring(what))) t.enable, t.done = e, { } end function setters.disable(t,what) local e = t.disable t.disable, t.done = disable, { } - disable(t,string.simpleesc(what)) + disable(t,string.simpleesc(tostring(what))) t.disable, t.done = e, { } end @@ -3720,6 +3773,13 @@ function experiments.disable(...) d(...) end +-- a useful example + +directives.register("system.nostatistics", function(v) + statistics.enable = not v +end) + + end -- of closure @@ -3995,9 +4055,9 @@ local function attribute_specification_error(str) return str end -function xml.unknown_dec_entity_format(str) return format("&%s;", str) end +function xml.unknown_dec_entity_format(str) return (str == "" and "&error;") or format("&%s;",str) end function xml.unknown_hex_entity_format(str) return format("&#x%s;",str) end -function xml.unknown_any_entity_format(str) return format("&%s;", str) end +function xml.unknown_any_entity_format(str) return format("&#x%s;",str) end local function handle_hex_entity(str) local h = hcache[str] @@ -4111,7 +4171,11 @@ local function handle_any_entity(str) if trace_entities then logs.report("xml","keeping entity &%s;",str) end - a = "&" .. str .. ";" + if str == "" then + a = "&error;" + else + a = "&" .. str .. ";" + end end end acache[str] = a @@ -4132,6 +4196,9 @@ local function handle_any_entity(str) if a then -- one of the predefined acache[str] = a + elseif str == "" then + a = "&error;" + acache[str] = a else a = "&" .. str .. ";" acache[str] = a @@ -4460,7 +4527,7 @@ function xml.checkbom(root) -- can be made faster local dt, found = root.dt, false for k=1,#dt do local v = dt[k] - if type(v) == "table" and v.special and v.tg == "@pi" and find(v.dt,"xml.*version=") then + if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then found = true break end @@ -4842,6 +4909,8 @@ function xml.assign(dt,k,root) end end +-- the following helpers may move + --[[ldx-- <p>The next helper assigns a tree (or string). Usage:</p> <typing> @@ -4860,6 +4929,22 @@ function xml.tocdata(e,wrapper) e.dt = { t } end +function xml.makestandalone(root) + if root.ri then + local dt = root.dt + for k=1,#dt do + local v = dt[k] + if type(v) == "table" and v.special and v.tg == "@pi@" then + local txt = v.dt[1] + if find(txt,"xml.*version=") then + v.dt[1] = txt .. " standalone='yes'" + break + end + end + end + end +end + end -- of closure @@ -5476,8 +5561,13 @@ local register_initial_child = { kind = "axis", axis = "initial-child" local register_all_nodes = { kind = "nodes", nodetest = true, nodes = { true, false, false } } +local skip = { } + local function errorrunner_e(str,cnv) - logs.report("lpath","error in expression: %s => %s",str,cnv) + if not skip[str] then + logs.report("lpath","error in expression: %s => %s",str,cnv) + skip[str] = cnv or str + end return false end local function errorrunner_f(str,arg) @@ -7287,6 +7377,14 @@ function statistics.hastimer(instance) return instance and instance.starttime end +function statistics.resettiming(instance) + if not instance then + notimer = { timing = 0, loadtime = 0 } + else + instance.timing, instance.loadtime = 0, 0 + end +end + function statistics.starttiming(instance) if not instance then notimer = { } @@ -7346,6 +7444,12 @@ function statistics.elapsedindeed(instance) return t > statistics.threshold end +function statistics.elapsedseconds(instance,rest) -- returns nil if 0 seconds + if statistics.elapsedindeed(instance) then + return format("%s seconds %s", statistics.elapsedtime(instance),rest or "") + end +end + -- general function function statistics.register(tag,fnc) @@ -7424,6 +7528,23 @@ function statistics.timed(action,report) report("total runtime: %s",statistics.elapsedtime(timer)) end +-- where, not really the best spot for this: + +commands = commands or { } + +local timer + +function commands.resettimer() + statistics.resettiming(timer) + statistics.starttiming(timer) +end + +function commands.elapsedtime() + statistics.stoptiming(timer) + tex.sprint(statistics.elapsedtime(timer)) +end + +commands.resettimer() end -- of closure @@ -7861,8 +7982,8 @@ suffixes['lua'] = { 'lua', 'luc', 'tma', 'tmc' } alternatives['map files'] = 'map' alternatives['enc files'] = 'enc' -alternatives['cid files'] = 'cid' -alternatives['fea files'] = 'fea' +alternatives['cid maps'] = 'cid' -- great, why no cid files +alternatives['font feature files'] = 'fea' -- and fea files here alternatives['opentype fonts'] = 'otf' alternatives['truetype fonts'] = 'ttf' alternatives['truetype collections'] = 'ttc' @@ -8005,8 +8126,10 @@ local function check_configuration() -- not yet ok, no time for debugging now -- bad luck end fix("LUAINPUTS" , ".;$TEXINPUTS;$TEXMFSCRIPTS") -- no progname, hm - fix("FONTFEATURES", ".;$TEXMF/fonts/fea//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") - fix("FONTCIDMAPS" , ".;$TEXMF/fonts/cid//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + -- this will go away some day + fix("FONTFEATURES", ".;$TEXMF/fonts/{data,fea}//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + fix("FONTCIDMAPS" , ".;$TEXMF/fonts/{data,cid}//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + -- fix("LUATEXLIBS" , ".;$TEXMF/luatex/lua//") end @@ -8396,7 +8519,7 @@ function resolvers.load_cnf() else instance.rootpath = instance.cnffiles[1] for k,fname in ipairs(instance.cnffiles) do - instance.cnffiles[k] = file.collapse_path(gsub(fname,"\\",'/')) + instance.cnffiles[k] = file.collapse_path(fname) end for i=1,3 do instance.rootpath = file.dirname(instance.rootpath) @@ -8425,7 +8548,7 @@ function resolvers.load_lua() else instance.rootpath = instance.luafiles[1] for k,fname in ipairs(instance.luafiles) do - instance.luafiles[k] = file.collapse_path(gsub(fname,"\\",'/')) + instance.luafiles[k] = file.collapse_path(fname) end for i=1,3 do instance.rootpath = file.dirname(instance.rootpath) @@ -8550,7 +8673,7 @@ local weird = lpeg.P(".")^1 + lpeg.anywhere(lpeg.S("~`!#$%^&*()={}[]:;\"\'||<>,? --~ local l_forbidden = lpeg.S("~`!#$%^&*()={}[]:;\"\'||\\/<>,?\n\r\t") --~ local l_confusing = lpeg.P(" ") ---~ local l_character = lpeg.utf8 +--~ local l_character = lpeg.patterns.utf8 --~ local l_dangerous = lpeg.P(".") --~ local l_normal = (l_character - l_forbidden - l_confusing - l_dangerous) * (l_character - l_forbidden - l_confusing^2)^0 * lpeg.P(-1) @@ -9290,8 +9413,7 @@ end local function collect_instance_files(filename,collected) -- todo : plugin (scanners, checkers etc) local result = collected or { } local stamp = nil - filename = file.collapse_path(filename) -- elsewhere - filename = file.collapse_path(gsub(filename,"\\","/")) -- elsewhere + filename = file.collapse_path(filename) -- speed up / beware: format problem if instance.remember then stamp = filename .. "--" .. instance.engine .. "--" .. instance.progname .. "--" .. instance.format @@ -9772,12 +9894,13 @@ end function table.sequenced(t,sep) -- temp here local s = { } for k, v in pairs(t) do -- pairs? - s[#s+1] = k .. "=" .. v + s[#s+1] = k .. "=" .. tostring(v) end return concat(s, sep or " | ") end function resolvers.methodhandler(what, filename, filetype) -- ... + filename = file.collapse_path(filename) local specification = (type(filename) == "string" and resolvers.splitmethod(filename)) or filename -- no or { }, let it bomb local scheme = specification.scheme if resolvers[what][scheme] then diff --git a/tex/context/base/char-tex.lua b/tex/context/base/char-tex.lua index f3af91f79..3e726703a 100644 --- a/tex/context/base/char-tex.lua +++ b/tex/context/base/char-tex.lua @@ -58,7 +58,7 @@ local function remap_commands(c) end local P, C, R, S, Cs, Cc = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cs, lpeg.Cc -local U, lpegmatch = lpeg.utf8, lpeg.match +local U, lpegmatch = lpeg.patterns.utf8, lpeg.match local accents = (P('\\') * C(S(accents)) * (P("{") * C(U) * P("}" * Cc(true)) + C(U) * Cc(false))) / remap_accents local commands = (P('\\') * C(R("az","AZ")^1)) / remap_commands diff --git a/tex/context/base/cont-new.tex b/tex/context/base/cont-new.tex index aada1b888..a80de62a0 100644 --- a/tex/context/base/cont-new.tex +++ b/tex/context/base/cont-new.tex @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2010.03.02 12:34} +\newcontextversion{2010.03.09 10:39} %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 6a89f4cfe..328f3f683 100644 --- a/tex/context/base/context.tex +++ b/tex/context/base/context.tex @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2010.03.02 12:34} +\edef\contextversion{2010.03.09 10:39} %D For those who want to use this: diff --git a/tex/context/base/data-res.lua b/tex/context/base/data-res.lua index 40cd3eb1a..47c29fda9 100644 --- a/tex/context/base/data-res.lua +++ b/tex/context/base/data-res.lua @@ -645,7 +645,7 @@ function resolvers.load_cnf() else instance.rootpath = instance.cnffiles[1] for k,fname in ipairs(instance.cnffiles) do - instance.cnffiles[k] = file.collapse_path(gsub(fname,"\\",'/')) + instance.cnffiles[k] = file.collapse_path(fname) end for i=1,3 do instance.rootpath = file.dirname(instance.rootpath) @@ -674,7 +674,7 @@ function resolvers.load_lua() else instance.rootpath = instance.luafiles[1] for k,fname in ipairs(instance.luafiles) do - instance.luafiles[k] = file.collapse_path(gsub(fname,"\\",'/')) + instance.luafiles[k] = file.collapse_path(fname) end for i=1,3 do instance.rootpath = file.dirname(instance.rootpath) @@ -799,7 +799,7 @@ local weird = lpeg.P(".")^1 + lpeg.anywhere(lpeg.S("~`!#$%^&*()={}[]:;\"\'||<>,? --~ local l_forbidden = lpeg.S("~`!#$%^&*()={}[]:;\"\'||\\/<>,?\n\r\t") --~ local l_confusing = lpeg.P(" ") ---~ local l_character = lpeg.utf8 +--~ local l_character = lpeg.patterns.utf8 --~ local l_dangerous = lpeg.P(".") --~ local l_normal = (l_character - l_forbidden - l_confusing - l_dangerous) * (l_character - l_forbidden - l_confusing^2)^0 * lpeg.P(-1) @@ -1539,8 +1539,7 @@ end local function collect_instance_files(filename,collected) -- todo : plugin (scanners, checkers etc) local result = collected or { } local stamp = nil - filename = file.collapse_path(filename) -- elsewhere - filename = file.collapse_path(gsub(filename,"\\","/")) -- elsewhere + filename = file.collapse_path(filename) -- speed up / beware: format problem if instance.remember then stamp = filename .. "--" .. instance.engine .. "--" .. instance.progname .. "--" .. instance.format @@ -2021,7 +2020,7 @@ end function table.sequenced(t,sep) -- temp here local s = { } for k, v in pairs(t) do -- pairs? - s[#s+1] = k .. "=" .. v + s[#s+1] = k .. "=" .. tostring(v) end return concat(s, sep or " | ") end diff --git a/tex/context/base/font-syn.lua b/tex/context/base/font-syn.lua index 4b892ed8c..1d9bc64f5 100644 --- a/tex/context/base/font-syn.lua +++ b/tex/context/base/font-syn.lua @@ -671,7 +671,7 @@ local function analysefiles() end end if not trace_warnings then - logs.report("fontnames", "warnings are disables (tracker 'fonts.warnings')") + logs.report("fontnames", "warnings are disabled (tracker 'fonts.warnings')") end traverse("tree", function(suffix) -- TEXTREE only resolvers.with_files(".*%." .. suffix .. "$", function(method,root,path,name) diff --git a/tex/context/base/grph-inc.lua b/tex/context/base/grph-inc.lua index 7f786248e..574bece89 100644 --- a/tex/context/base/grph-inc.lua +++ b/tex/context/base/grph-inc.lua @@ -377,8 +377,8 @@ local function register(askedname,specification) end local newname = file.join(newpath,newbase) dir.makedirs(newpath) - oldname = dir.expand_name(oldname) - newname = dir.expand_name(newname) + oldname = file.collapse_path(oldname) + newname = file.collapse_path(newname) local oldtime = lfs.attributes(oldname,'modification') or 0 local newtime = lfs.attributes(newname,'modification') or 0 if oldtime > newtime then @@ -428,7 +428,7 @@ local function register(askedname,specification) return specification end -local resolve_too = true +local resolve_too = true -- urls local function locate(request) -- name, format, cache local askedname = resolvers.clean_path(request.name) @@ -544,7 +544,7 @@ local function locate(request) -- name, format, cache for _, format in ipairs(figures.order) do local list = figures.formats[format].list or { format } for _, suffix in ipairs(list) do ---~ local name = file.replacesuffix(askedbase,suffix) + -- local name = file.replacesuffix(askedbase,suffix) local name = file.replacesuffix(askedname,suffix) for _, path in ipairs(figures.paths) do local check = path .. "/" .. name @@ -553,7 +553,7 @@ local function locate(request) -- name, format, cache if trace_figures then commands.writestatus("figures","warning: skipping path %s",path) end - elseif figures.exists(check,format,resolve_too) then + elseif figures.exists(check,format,true) then return register(askedname, { askedname = askedname, fullname = check, diff --git a/tex/context/base/l-dir.lua b/tex/context/base/l-dir.lua index 3760db2c1..369895c43 100644 --- a/tex/context/base/l-dir.lua +++ b/tex/context/base/l-dir.lua @@ -323,7 +323,7 @@ else --~ print(dir.mkdirs("///a/b/c")) --~ print(dir.mkdirs("a/bbb//ccc/")) - function dir.expand_name(str) + function dir.expand_name(str) -- will be merged with cleanpath and collapsepath if not find(str,"^/") then str = lfs.currentdir() .. "/" .. str end diff --git a/tex/context/base/l-file.lua b/tex/context/base/l-file.lua index 2064fcdd1..0b2c96d8f 100644 --- a/tex/context/base/l-file.lua +++ b/tex/context/base/l-file.lua @@ -139,7 +139,9 @@ end -- we can hash them weakly function file.collapse_path(str) + str = gsub(str,"\\","/") if find(str,"/") then + str = gsub(str,"^%./",(gsub(lfs.currentdir(),"\\","/")) .. "/") -- ./xx in qualified str = gsub(str,"/%./","/") local n, m = 1, 1 while n > 0 or m > 0 do @@ -147,7 +149,7 @@ function file.collapse_path(str) str, m = gsub(str,"[^/%.]+/%.%./","") end str = gsub(str,"([^/])/$","%1") - str = gsub(str,"^%./","") + -- str = gsub(str,"^%./","") -- ./xx in qualified str = gsub(str,"/%.$","") end if str == "" then str = "." end diff --git a/tex/context/base/l-lpeg.lua b/tex/context/base/l-lpeg.lua index e7b319874..227b193da 100644 --- a/tex/context/base/l-lpeg.lua +++ b/tex/context/base/l-lpeg.lua @@ -160,8 +160,6 @@ end --~ --~ local decode_pattern = lpeg.Ct(utf8^0) * -1 - local cont = R("\128\191") -- continuation byte -lpeg.utf8 = R("\0\127") + R("\194\223") * cont + R("\224\239") * cont * cont + R("\240\244") * cont * cont * cont - +lpeg.patterns.utf8 = R("\0\127") + R("\194\223") * cont + R("\224\239") * cont * cont + R("\240\244") * cont * cont * cont diff --git a/tex/context/base/mlib-run.lua b/tex/context/base/mlib-run.lua index 73ce51c89..212b7b7f3 100644 --- a/tex/context/base/mlib-run.lua +++ b/tex/context/base/mlib-run.lua @@ -58,7 +58,7 @@ metapost.finder = finder metapost.parameters = { hash_size = 100000, - main_memory = 2500000, + main_memory = 4000000, max_in_open = 50, param_size = 100000, } diff --git a/tex/context/base/node-tra.lua b/tex/context/base/node-tra.lua index 3534e9719..39ff32209 100644 --- a/tex/context/base/node-tra.lua +++ b/tex/context/base/node-tra.lua @@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['node-tra'] = { --[[ldx-- <p>This is rather experimental. We need more control and some of this -might become a runtime module instead.</p> +might become a runtime module instead. This module will be cleaned up!</p> --ldx]]-- local utf = unicode.utf8 @@ -445,3 +445,20 @@ end --~ \stopluacode nodes.show_simple_list = function(h,depth) show_simple_list(h,depth,0) end + +function nodes.list_to_utf(h,joiner) + local joiner = (joiner ==true and utfchar(0x200C)) or joiner -- zwnj + local w = { } + while h do + if h.id == glyph then -- always true + w[#w+1] = utfchar(h.char) + if joiner then + w[#w+1] = joiner + end + else + w[#w+1] = "[-]" + end + h = h.next + end + return concat(w) +end diff --git a/tex/context/base/s-fnt-25.tex b/tex/context/base/s-fnt-25.tex index a71aaa330..a8b398716 100644 --- a/tex/context/base/s-fnt-25.tex +++ b/tex/context/base/s-fnt-25.tex @@ -44,7 +44,7 @@ \blank} \def\mathfontlistentryhexdectit#1#2#3% - {#1: \ruledhbox{\char#2}\enspace#3\par + {#1: \char#2\enspace\ruledhbox{\char#2}\enspace#3\par \advance\leftskip 1em\relax} \def\mathfontlistentrywdhtdpic#1#2#3#4% @@ -90,7 +90,8 @@ function document.showmathfont(id,slot) names[k] = (name and file.basename(name)) or v.id end end - print(table.serialize(names)) + local round = math.round +-- print(table.serialize(names)) for _, s in next, sorted do local char = characters[s] if char then @@ -98,7 +99,7 @@ function document.showmathfont(id,slot) local cnext, cvert_variants, choriz_variants = char.next, char.vert_variants, char.horiz_variants report("\\startmathfontlistentry") report("\\mathfontlistentryhexdectit{U+%05X}{%s}{%s}",s,s,string.lower(info.description or "no description, private to font")) - report("\\mathfontlistentrywdhtdpic{%s}{%s}{%s}{%s}",char.width or 0,char.height or 0,char.depth or 0,char.italic or 0) + report("\\mathfontlistentrywdhtdpic{%s}{%s}{%s}{%s}",round(char.width or 0),round(char.height or 0),round(char.depth or 0),round(char.italic or 0)) if virtual then local commands = char.commands if commands then diff --git a/tex/context/base/spec-fdf.mkii b/tex/context/base/spec-fdf.mkii index 5d180b38c..4bf4115c6 100644 --- a/tex/context/base/spec-fdf.mkii +++ b/tex/context/base/spec-fdf.mkii @@ -321,7 +321,17 @@ \addPDFdocumentinfo \to \everyfirstshipout -\def\PDFversion{1.\the\pdfminorversion} +\ifx\pdfminorversion\undefined + \ifx\pdfoptionpdfminorversion\undefined + \newcount\pdfminorversion + \else + \let\pdfminorversion\pdfoptionpdfminorversion + \fi +\fi + +\pdfminorversion=5 + +\def\PDFversion{1.\number\pdfminorversion} \appendtoksonce \def\PDFversion{1.\the\pdfminorversion}% diff --git a/tex/context/base/strc-itm.mkiv b/tex/context/base/strc-itm.mkiv index 423508930..6f3f5bb77 100644 --- a/tex/context/base/strc-itm.mkiv +++ b/tex/context/base/strc-itm.mkiv @@ -985,83 +985,6 @@ \fi \fi\fi} -% \def\dodolapitem -% {% todo: align+marge binnen de hbox -% \llap{\hbox to \itemgrouplistwidth{\ifconditional\sublistitem\llap{+\enspace}\fi -% \symalignleft -% \box\itemgroupitembox\hfil -% \hskip\getitemparameter\currentitemlevel\c!distance% T h -% }}} - -% \def\dolistitem % evt aantal items opslaan per niveau, scheelt zoeken -% {\ifconditional\textlistitem -% % begin of item -% \else -% \par -% \fi -% \advance\noflistelements\plusone -% \optimizelistitemsbreak -% \noindent -% \setbox\itemgroupitembox\hbox -% {\ifconditional\headlistitem -% \ifconditional\symbollistitem -% \dosetitemattributes\currentitemlevel\c!symstyle\c!symcolor{\symsymbol}% -% \else -% \dosetitemattributes\currentitemlevel\c!headstyle\c!headcolor{\listitem}% -% \fi -% \else -% \ifconditional\symbollistitem -% \dosetitemattributes\currentitemlevel\c!symstyle\c!symcolor{\symsymbol}% -% \else -% \dosetitemattributes\currentitemlevel\c!style\c!color{\listitem}% -% \fi -% \fi}% -% \ifconditional\fittinglistitems -% \ifdim\wd\itemgroupitembox>\getitemparameter\currentitemlevel\c!maxwidth sp\relax -% \xsetitemparameter\currentitemlevel\c!maxwidth{\number\wd\itemgroupitembox}% -% \fi -% \ifdim\currentitemmaxwidth>\zeropoint -% \setbox\itemgroupitembox\simplealignedbox{\getitemparameter\currentitemlevel\c!itemalign}{\currentitemmaxwidth}{\box\itemgroupitembox}% -% \fi -% \fi -% \doifsomething\doitemdestination -% {\setbox\itemgroupitembox\hbox{\directgotobox{\box\itemgroupitembox}[\doitemdestination]}}% -% \globallet\doitemdestination\empty -% \itemgroupaskedwidth\getitemparameter\currentitemlevel\c!width\relax -% % new, prevents loops when symbol is (not yet found) graphic -% \ht\itemgroupitembox\strutheight -% \dp\itemgroupitembox\strutdepth -% % so that content differs per run (esp mp graphics afterwards) -% \checkforrepeatedlistitem -% \ifdim\itemgroupaskedwidth<\zeropoint\relax -% \llap{\ifconditional\sublistitem\llap{+\enspace}\fi\box\itemgroupitembox\hskip\leftmargindistance}% -% \else -% \ifdim\itemgroupaskedwidth=\zeropoint\relax -% \calculatelistwidth1% -% \else -% \calculatelistwidth\currentitemlevel -% \fi -% \ifconditional\textlistitem -% \hbox{\ifconditional\sublistitem+\enspace\fi\box\itemgroupitembox\hskip\interwordspace}\nobreak -% \else\ifconditional\inlinelistitem -% \hbox to \itemgrouplistwidth{\ifconditional\sublistitem\llap{+\enspace}\fi\box\itemgroupitembox\hss}% was: \hfill -% \else\ifconditional\txtlistitem -% \dodotxtitem -% \else -% \dodolapitem -% \fi\fi\fi -% \fi -% \forceunexpanded % needed for m conversion (\os) / i need to look into this -% \setevalue{\@@currentitemsymbol\currentitemlevel}% -% {\getvalue{\@@localitemsymbol\currentitemlevel}}% still problems with \uchar ? -% %{\noexpand\getvalue{\@@localitemsymbol\currentitemlevel}}% no, spoils subrefs -% \resetunexpanded -% \setfalse\headlistitem -% \setfalse\sublistitem -% \setfalse\symbollistitem -% \EveryPar{\ignorespaces}% needed ? -% \ignorespaces} - \def\dodosubitem {\ifconditional\sublistitem\llap{+\enspace}\fi} @@ -1074,7 +997,7 @@ \hfil \hskip\getitemparameter\currentitemlevel\c!distance}}} -\def\dolistitem % evt aantal items opslaan per niveau, scheelt zoeken +\unprotected\def\dolistitem % evt aantal items opslaan per niveau, scheelt zoeken {\ifconditional\textlistitem % begin of item \else @@ -1082,7 +1005,8 @@ \fi \advance\noflistelements\plusone \optimizelistitemsbreak - \noindent + %\noindent %% WS: don't apply \noindent when the user sets 'first' in the indenting key + \checkindentation\ifindentfirstparagraph\indent\else\noindent\fi \setbox\itemgroupitembox\hbox {\ifconditional\headlistitem \ifconditional\symbollistitem @@ -1204,7 +1128,7 @@ \chardef\autoitemgroupspacing=2 % 0 = voor/na, 1=tussen als geen voor 2=(prev)tussen=old/normal -\def\complexdoitemgroupitem[#1]% +\unprotected\def\complexdoitemgroupitem[#1]% {\def\currentitemreference{#1}% \ifconditional\textlistitem % begin of item @@ -1239,7 +1163,11 @@ \fi \else \ifconditional\textlistitem % was bugged: \inlinelistitem - \removeunwantedspaces\hskip\emwidth\!!plus\interwordstretch\!!minus\interwordshrink\relax % new per 2006/10/20 + \ifhmode + % WS: make the distance between items customizable, think about better default values -> see itemize-1.tex + \normalexpanded{\doassigntextitemdistance{\getitemparameter\currentitemlevel\c!textdistance}}% HH: moved out and made configurable (sort of) + \removeunwantedspaces\hskip\textitemdistance\relax + \fi \else \iteminbetweencommand \fi @@ -1262,6 +1190,28 @@ \hskip\itemsignal % new, concat \getitemparameter\currentitemlevel\c!command} % \defaultitemcommand +% \startitemize[text][space=medium] +% \item one \item two \item three +% \stopitemize + +\setvalue{\??op:\??op:\c!textdistance:\v!none}% + {\let\textitemdistance\zeropoint} + +\def\doassigngiventextitemdistance#1% + {\assignvalue + {#1}% + \textitemdistance + {.5\interwordspace\!!plus.5\emwidth}% + {\interwordspace \!!plus \emwidth}% + {\emwidth \!!plus \interwordstretch\!!minus\interwordshrink}} + +\unexpanded\def\doassigntextitemdistance#1% + {\ifcsname\??op:\??op:\c!textdistance:#1\endcsname + \csname\??op:\??op:\c!textdistance:#1\endcsname + \else + \doassigngiventextitemdistance{#1}% + \fi} + \def\defaultitemcommand {\EveryPar{\ignorespaces}% needed ? \ignorespaces} @@ -1369,6 +1319,7 @@ \c!start=1, \c!criterium=\v!all, % permits 0 and negative numbers %\c!option=, + \c!textdistance=\v!big, \c!command=\defaultitemcommand, \c!symbol=\currentitemlevel] diff --git a/tex/context/base/strc-num.mkiv b/tex/context/base/strc-num.mkiv index 42f59c9e7..c5bad7224 100644 --- a/tex/context/base/strc-num.mkiv +++ b/tex/context/base/strc-num.mkiv @@ -203,7 +203,7 @@ \ctxlua{structure.counters.add("\@@thestructurecounter{#1}",1,1)}} \def\doincrementsubstructurecounter[#1][#2]% - {\docheckstructurecounterbypage{#1} + {\docheckstructurecounterbypage{#1}% \ctxlua{structure.counters.add("\@@thestructurecounter{#1}",#2,1)}} \def\convertedstructurecounter diff --git a/tex/context/base/trac-tra.lua b/tex/context/base/trac-tra.lua index 4c578fcee..5d15d5ad8 100644 --- a/tex/context/base/trac-tra.lua +++ b/tex/context/base/trac-tra.lua @@ -236,14 +236,14 @@ end function setters.enable(t,what) local e = t.enable t.enable, t.done = enable, { } - enable(t,string.simpleesc(what)) + enable(t,string.simpleesc(tostring(what))) t.enable, t.done = e, { } end function setters.disable(t,what) local e = t.disable t.disable, t.done = disable, { } - disable(t,string.simpleesc(what)) + disable(t,string.simpleesc(tostring(what))) t.disable, t.done = e, { } end diff --git a/tex/context/interface/cont-cs.xml b/tex/context/interface/cont-cs.xml index 106f50197..079606e99 100644 --- a/tex/context/interface/cont-cs.xml +++ b/tex/context/interface/cont-cs.xml @@ -6235,6 +6235,13 @@ <cd:parameter name="odsadpristi"> <cd:resolve name="indentnext"/> </cd:parameter> + <cd:parameter name="textdistance"> + <!-- maybe resolve here too --> + <cd:constant type="zadny"/> + <cd:constant type="velke"/> + <cd:constant type="stredni"/> + <cd:constant type="male"/> + </cd:parameter> </cd:assignments> </cd:arguments> </cd:command> diff --git a/tex/context/interface/cont-de.xml b/tex/context/interface/cont-de.xml index f2ce1cfe5..bb011ddbc 100644 --- a/tex/context/interface/cont-de.xml +++ b/tex/context/interface/cont-de.xml @@ -6235,6 +6235,13 @@ <cd:parameter name="ziehefolgendeein"> <cd:resolve name="indentnext"/> </cd:parameter> + <cd:parameter name="textdistance"> + <!-- maybe resolve here too --> + <cd:constant type="kein"/> + <cd:constant type="gross"/> + <cd:constant type="mittel"/> + <cd:constant type="klein"/> + </cd:parameter> </cd:assignments> </cd:arguments> </cd:command> diff --git a/tex/context/interface/cont-en.xml b/tex/context/interface/cont-en.xml index 9d2319722..4c6ef7c7d 100644 --- a/tex/context/interface/cont-en.xml +++ b/tex/context/interface/cont-en.xml @@ -6235,6 +6235,13 @@ <cd:parameter name="indentnext"> <cd:resolve name="indentnext"/> </cd:parameter> + <cd:parameter name="textdistance"> + <!-- maybe resolve here too --> + <cd:constant type="none"/> + <cd:constant type="big"/> + <cd:constant type="medium"/> + <cd:constant type="small"/> + </cd:parameter> </cd:assignments> </cd:arguments> </cd:command> diff --git a/tex/context/interface/cont-fr.xml b/tex/context/interface/cont-fr.xml index 2e38c3667..b07e97936 100644 --- a/tex/context/interface/cont-fr.xml +++ b/tex/context/interface/cont-fr.xml @@ -6235,6 +6235,13 @@ <cd:parameter name="indentesuivant"> <cd:resolve name="indentnext"/> </cd:parameter> + <cd:parameter name="distancetexte"> + <!-- maybe resolve here too --> + <cd:constant type="rien"/> + <cd:constant type="grand"/> + <cd:constant type="moyen"/> + <cd:constant type="petit"/> + </cd:parameter> </cd:assignments> </cd:arguments> </cd:command> diff --git a/tex/context/interface/cont-it.xml b/tex/context/interface/cont-it.xml index 94e61e619..fa86d2159 100644 --- a/tex/context/interface/cont-it.xml +++ b/tex/context/interface/cont-it.xml @@ -6235,6 +6235,13 @@ <cd:parameter name="rientrasuccessivo"> <cd:resolve name="indentnext"/> </cd:parameter> + <cd:parameter name="distanzatesto"> + <!-- maybe resolve here too --> + <cd:constant type="nessuno"/> + <cd:constant type="grande"/> + <cd:constant type="medio"/> + <cd:constant type="piccolo"/> + </cd:parameter> </cd:assignments> </cd:arguments> </cd:command> diff --git a/tex/context/interface/cont-nl.xml b/tex/context/interface/cont-nl.xml index a337bbb6e..a4bd85c61 100644 --- a/tex/context/interface/cont-nl.xml +++ b/tex/context/interface/cont-nl.xml @@ -6235,6 +6235,13 @@ <cd:parameter name="springvolgendein"> <cd:resolve name="indentnext"/> </cd:parameter> + <cd:parameter name="tekstafstand"> + <!-- maybe resolve here too --> + <cd:constant type="geen"/> + <cd:constant type="groot"/> + <cd:constant type="middel"/> + <cd:constant type="klein"/> + </cd:parameter> </cd:assignments> </cd:arguments> </cd:command> diff --git a/tex/context/interface/cont-pe.xml b/tex/context/interface/cont-pe.xml index 9bcda97f7..cf6a91683 100644 --- a/tex/context/interface/cont-pe.xml +++ b/tex/context/interface/cont-pe.xml @@ -6235,6 +6235,13 @@ <cd:parameter name="متنتورفته"> <cd:resolve name="indentnext"/> </cd:parameter> + <cd:parameter name="فاصلهمتن"> + <!-- maybe resolve here too --> + <cd:constant type="هیچکدام"/> + <cd:constant type="بزرگ"/> + <cd:constant type="متوسط"/> + <cd:constant type="کوچک"/> + </cd:parameter> </cd:assignments> </cd:arguments> </cd:command> diff --git a/tex/context/interface/cont-ro.xml b/tex/context/interface/cont-ro.xml index 0e83841d3..44d72a866 100644 --- a/tex/context/interface/cont-ro.xml +++ b/tex/context/interface/cont-ro.xml @@ -6235,6 +6235,13 @@ <cd:parameter name="aliniaturmator"> <cd:resolve name="indentnext"/> </cd:parameter> + <cd:parameter name="textdistance"> + <!-- maybe resolve here too --> + <cd:constant type="niciunul"/> + <cd:constant type="mare"/> + <cd:constant type="mediu"/> + <cd:constant type="mic"/> + </cd:parameter> </cd:assignments> </cd:arguments> </cd:command> diff --git a/tex/generic/context/luatex-fonts-merged.lua b/tex/generic/context/luatex-fonts-merged.lua index 77600a7bd..3d4bf05e8 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 : 03/02/10 12:39:47 +-- merge date : 03/09/10 10:46:16 do -- begin closure to overcome local limits and interference @@ -456,11 +456,9 @@ end --~ --~ local decode_pattern = lpeg.Ct(utf8^0) * -1 - local cont = R("\128\191") -- continuation byte -lpeg.utf8 = R("\0\127") + R("\194\223") * cont + R("\224\239") * cont * cont + R("\240\244") * cont * cont * cont - +lpeg.patterns.utf8 = R("\0\127") + R("\194\223") * cont + R("\224\239") * cont * cont + R("\240\244") * cont * cont * cont end -- closure @@ -1577,7 +1575,9 @@ end -- we can hash them weakly function file.collapse_path(str) + str = gsub(str,"\\","/") if find(str,"/") then + str = gsub(str,"^%./",(gsub(lfs.currentdir(),"\\","/")) .. "/") -- ./xx in qualified str = gsub(str,"/%./","/") local n, m = 1, 1 while n > 0 or m > 0 do @@ -1585,7 +1585,7 @@ function file.collapse_path(str) str, m = gsub(str,"[^/%.]+/%.%./","") end str = gsub(str,"([^/])/$","%1") - str = gsub(str,"^%./","") + -- str = gsub(str,"^%./","") -- ./xx in qualified str = gsub(str,"/%.$","") end if str == "" then str = "." end |