diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/data-res.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/data-res.lua | 533 |
1 files changed, 342 insertions, 191 deletions
diff --git a/Master/texmf-dist/tex/context/base/data-res.lua b/Master/texmf-dist/tex/context/base/data-res.lua index 39e4aa208fc..ecef1418860 100644 --- a/Master/texmf-dist/tex/context/base/data-res.lua +++ b/Master/texmf-dist/tex/context/base/data-res.lua @@ -1,9 +1,9 @@ if not modules then modules = { } end modules ['data-inp'] = { version = 1.001, + comment = "companion to luat-lib.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files", - comment = "companion to luat-lib.tex", } -- After a few years using the code the large luat-inp.lua file @@ -15,7 +15,7 @@ if not modules then modules = { } end modules ['data-inp'] = { -- * some public auxiliary functions were made private -- -- TODO: os.getenv -> os.env[] --- TODO: instances.[hashes,cnffiles,configurations,522] -> ipairs (alles check, sneller) +-- TODO: instances.[hashes,cnffiles,configurations,522] -- TODO: check escaping in find etc, too much, too slow -- This lib is multi-purpose and can be loaded again later on so that @@ -36,12 +36,13 @@ if not modules then modules = { } end modules ['data-inp'] = { local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys local next, type = next, type +local lpegmatch = lpeg.match -local trace_locating, trace_detail, trace_verbose = false, false, false +local trace_locating, trace_detail, trace_expansions = false, false, false -trackers.register("resolvers.verbose", function(v) trace_verbose = v end) -trackers.register("resolvers.locating", function(v) trace_locating = v trackers.enable("resolvers.verbose") end) -trackers.register("resolvers.detail", function(v) trace_detail = v trackers.enable("resolvers.verbose,resolvers.detail") end) +trackers.register("resolvers.locating", function(v) trace_locating = v end) +trackers.register("resolvers.details", function(v) trace_detail = v end) +trackers.register("resolvers.expansions", function(v) trace_expansions = v end) -- todo if not resolvers then resolvers = { @@ -65,7 +66,7 @@ resolvers.generators.notfound = { nil } resolvers.cacheversion = '1.0.1' resolvers.cnfname = 'texmf.cnf' resolvers.luaname = 'texmfcnf.lua' -resolvers.homedir = os.env[os.platform == "windows" and 'USERPROFILE'] or os.env['HOME'] or '~' +resolvers.homedir = os.env[os.type == "windows" and 'USERPROFILE'] or os.env['HOME'] or '~' resolvers.cnfdefault = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}' local dummy_path_expr = "^!*unset/*$" @@ -107,8 +108,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' @@ -124,6 +125,11 @@ formats ['sfd'] = 'SFDFONTS' suffixes ['sfd'] = { 'sfd' } alternatives['subfont definition files'] = 'sfd' +-- lib paths + +formats ['lib'] = 'CLUAINPUTS' -- new (needs checking) +suffixes['lib'] = (os.libsuffix and { os.libsuffix }) or { 'dll', 'so' } + -- In practice we will work within one tds tree, but i want to keep -- the option open to build tools that look at multiple trees, which is -- why we keep the tree specific data in a table. We used to pass the @@ -246,8 +252,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 @@ -262,7 +270,7 @@ function resolvers.settrace(n) -- no longer number but: 'locating' or 'detail' end end -resolvers.settrace(os.getenv("MTX.resolvers.TRACE") or os.getenv("MTX_INPUT_TRACE")) +resolvers.settrace(os.getenv("MTX_INPUT_TRACE")) function resolvers.osenv(key) local ie = instance.environment @@ -350,37 +358,43 @@ end -- work that well; the parsing is ok, but dealing with the resulting -- table is a pain because we need to work inside-out recursively +local function do_first(a,b) + local t = { } + for s in gmatch(b,"[^,]+") do t[#t+1] = a .. s end + return "{" .. concat(t,",") .. "}" +end + +local function do_second(a,b) + local t = { } + for s in gmatch(a,"[^,]+") do t[#t+1] = s .. b end + return "{" .. concat(t,",") .. "}" +end + +local function do_both(a,b) + local t = { } + for sa in gmatch(a,"[^,]+") do + for sb in gmatch(b,"[^,]+") do + t[#t+1] = sa .. sb + end + end + return "{" .. concat(t,",") .. "}" +end + +local function do_three(a,b,c) + return a .. b.. c +end + local function splitpathexpr(str, t, validate) -- no need for further optimization as it is only called a - -- few times, we can use lpeg for the sub; we could move - -- the local functions outside the body + -- few times, we can use lpeg for the sub + if trace_expansions then + logs.report("fileio","expanding variable '%s'",str) + end t = t or { } str = gsub(str,",}",",@}") str = gsub(str,"{,","{@,") -- str = "@" .. str .. "@" local ok, done - local function do_first(a,b) - local t = { } - for s in gmatch(b,"[^,]+") do t[#t+1] = a .. s end - return "{" .. concat(t,",") .. "}" - end - local function do_second(a,b) - local t = { } - for s in gmatch(a,"[^,]+") do t[#t+1] = s .. b end - return "{" .. concat(t,",") .. "}" - end - local function do_both(a,b) - local t = { } - for sa in gmatch(a,"[^,]+") do - for sb in gmatch(b,"[^,]+") do - t[#t+1] = sa .. sb - end - end - return "{" .. concat(t,",") .. "}" - end - local function do_three(a,b,c) - return a .. b.. c - end while true do done = false while true do @@ -411,6 +425,11 @@ local function splitpathexpr(str, t, validate) t[#t+1] = s end end + if trace_expansions then + for k=1,#t do + logs.report("fileio","% 4i: %s",k,t[k]) + end + end return t end @@ -450,18 +469,27 @@ end -- also we now follow the stupid route: if not set then just assume *one* -- cnf file under texmf (i.e. distribution) -resolvers.ownpath = resolvers.ownpath or nil -resolvers.ownbin = resolvers.ownbin or arg[-2] or arg[-1] or arg[0] or "luatex" -resolvers.autoselfdir = true -- false may be handy for debugging +local args = environment and environment.original_arguments or arg -- this needs a cleanup + +resolvers.ownbin = resolvers.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex" +resolvers.ownbin = gsub(resolvers.ownbin,"\\","/") function resolvers.getownpath() - if not resolvers.ownpath then - if resolvers.autoselfdir and os.selfdir then - resolvers.ownpath = os.selfdir - else - local binary = resolvers.ownbin - if os.platform == "windows" then - binary = file.replacesuffix(binary,"exe") + local ownpath = resolvers.ownpath or os.selfdir + if not ownpath or ownpath == "" or ownpath == "unset" then + ownpath = args[-1] or arg[-1] + ownpath = ownpath and file.dirname(gsub(ownpath,"\\","/")) + if not ownpath or ownpath == "" then + ownpath = args[-0] or arg[-0] + ownpath = ownpath and file.dirname(gsub(ownpath,"\\","/")) + end + local binary = resolvers.ownbin + if not ownpath or ownpath == "" then + ownpath = ownpath and file.dirname(binary) + end + if not ownpath or ownpath == "" then + if os.binsuffix ~= "" then + binary = file.replacesuffix(binary,os.binsuffix) end for p in gmatch(os.getenv("PATH"),"[^"..io.pathseparator.."]+") do local b = file.join(p,binary) @@ -473,30 +501,39 @@ function resolvers.getownpath() local olddir = lfs.currentdir() if lfs.chdir(p) then local pp = lfs.currentdir() - if trace_verbose and p ~= pp then - logs.report("fileio","following symlink %s to %s",p,pp) + if trace_locating and p ~= pp then + logs.report("fileio","following symlink '%s' to '%s'",p,pp) end - resolvers.ownpath = pp + ownpath = pp lfs.chdir(olddir) else - if trace_verbose then - logs.report("fileio","unable to check path %s",p) + if trace_locating then + logs.report("fileio","unable to check path '%s'",p) end - resolvers.ownpath = p + ownpath = p end break end end end - if not resolvers.ownpath then resolvers.ownpath = '.' end + if not ownpath or ownpath == "" then + ownpath = "." + logs.report("fileio","forcing fallback ownpath .") + elseif trace_locating then + logs.report("fileio","using ownpath '%s'",ownpath) + end end - return resolvers.ownpath + resolvers.ownpath = ownpath + function resolvers.getownpath() + return resolvers.ownpath + end + return ownpath end local own_places = { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARENT", "TEXMFCNF" } local function identify_own() - local ownpath = resolvers.getownpath() or lfs.currentdir() + local ownpath = resolvers.getownpath() or dir.current() local ie = instance.environment if ownpath then if resolvers.env('SELFAUTOLOC') == "" then os.env['SELFAUTOLOC'] = file.collapse_path(ownpath) end @@ -509,10 +546,10 @@ local function identify_own() if resolvers.env('TEXMFCNF') == "" then os.env['TEXMFCNF'] = resolvers.cnfdefault end if resolvers.env('TEXOS') == "" then os.env['TEXOS'] = resolvers.env('SELFAUTODIR') end if resolvers.env('TEXROOT') == "" then os.env['TEXROOT'] = resolvers.env('SELFAUTOPARENT') end - if trace_verbose then + if trace_locating then for i=1,#own_places do local v = own_places[i] - logs.report("fileio","variable %s set to %s",v,resolvers.env(v) or "unknown") + logs.report("fileio","variable '%s' set to '%s'",v,resolvers.env(v) or "unknown") end end identify_own = function() end @@ -544,10 +581,8 @@ end local function load_cnf_file(fname) fname = resolvers.clean_path(fname) local lname = file.replacesuffix(fname,'lua') - local f = io.open(lname) - if f then -- this will go - f:close() - local dname = file.dirname(fname) + if lfs.isfile(lname) then + local dname = file.dirname(fname) -- fname ? if not instance.configuration[dname] then resolvers.load_data(dname,'configuration',lname and file.basename(lname)) instance.order[#instance.order+1] = instance.configuration[dname] @@ -555,8 +590,8 @@ local function load_cnf_file(fname) else f = io.open(fname) if f then - if trace_verbose then - logs.report("fileio","loading %s", fname) + if trace_locating then + logs.report("fileio","loading configuration file %s", fname) end local line, data, n, k, v local dname = file.dirname(fname) @@ -590,14 +625,16 @@ local function load_cnf_file(fname) end end f:close() - elseif trace_verbose then - logs.report("fileio","skipping %s", fname) + elseif trace_locating then + logs.report("fileio","skipping configuration file '%s'", fname) end end end local function collapse_cnf_data() -- potential optimization: pass start index (setup and configuration are shared) - for _,c in ipairs(instance.order) do + local order = instance.order + for i=1,#order do + local c = order[i] for k,v in next, c do if not instance.variables[k] then if instance.environment[k] then @@ -613,19 +650,24 @@ end function resolvers.load_cnf() local function loadoldconfigdata() - for _, fname in ipairs(instance.cnffiles) do - load_cnf_file(fname) + local cnffiles = instance.cnffiles + for i=1,#cnffiles do + load_cnf_file(cnffiles[i]) end end -- instance.cnffiles contain complete names now ! + -- we still use a funny mix of cnf and new but soon + -- we will switch to lua exclusively as we only use + -- the file to collect the tree roots if #instance.cnffiles == 0 then - if trace_verbose then + if trace_locating then logs.report("fileio","no cnf files found (TEXMFCNF may not be set/known)") end else - instance.rootpath = instance.cnffiles[1] - for k,fname in ipairs(instance.cnffiles) do - instance.cnffiles[k] = file.collapse_path(gsub(fname,"\\",'/')) + local cnffiles = instance.cnffiles + instance.rootpath = cnffiles[1] + for k=1,#cnffiles do + instance.cnffiles[k] = file.collapse_path(cnffiles[k]) end for i=1,3 do instance.rootpath = file.dirname(instance.rootpath) @@ -653,8 +695,9 @@ function resolvers.load_lua() -- yet harmless else instance.rootpath = instance.luafiles[1] - for k,fname in ipairs(instance.luafiles) do - instance.luafiles[k] = file.collapse_path(gsub(fname,"\\",'/')) + local luafiles = instance.luafiles + for k=1,#luafiles do + instance.luafiles[k] = file.collapse_path(luafiles[k]) end for i=1,3 do instance.rootpath = file.dirname(instance.rootpath) @@ -686,14 +729,14 @@ end function resolvers.append_hash(type,tag,name) if trace_locating then - logs.report("fileio","= hash append: %s",tag) + logs.report("fileio","hash '%s' appended",tag) end insert(instance.hashes, { ['type']=type, ['tag']=tag, ['name']=name } ) end function resolvers.prepend_hash(type,tag,name) if trace_locating then - logs.report("fileio","= hash prepend: %s",tag) + logs.report("fileio","hash '%s' prepended",tag) end insert(instance.hashes, 1, { ['type']=type, ['tag']=tag, ['name']=name } ) end @@ -717,9 +760,11 @@ end -- locators function resolvers.locatelists() - for _, path in ipairs(resolvers.clean_path_list('TEXMF')) do - if trace_verbose then - logs.report("fileio","locating list of %s",path) + local texmfpaths = resolvers.clean_path_list('TEXMF') + for i=1,#texmfpaths do + local path = texmfpaths[i] + if trace_locating then + logs.report("fileio","locating list of '%s'",path) end resolvers.locatedatabase(file.collapse_path(path)) end @@ -732,11 +777,11 @@ end function resolvers.locators.tex(specification) if specification and specification ~= '' and lfs.isdir(specification) then if trace_locating then - logs.report("fileio",'! tex locator found: %s',specification) + logs.report("fileio","tex locator '%s' found",specification) end resolvers.append_hash('file',specification,filename) elseif trace_locating then - logs.report("fileio",'? tex locator not found: %s',specification) + logs.report("fileio","tex locator '%s' not found",specification) end end @@ -750,7 +795,9 @@ function resolvers.loadfiles() instance.loaderror = false instance.files = { } if not instance.renewcache then - for _, hash in ipairs(instance.hashes) do + local hashes = instance.hashes + for k=1,#hashes do + local hash = hashes[k] resolvers.hashdatabase(hash.tag,hash.name) if instance.loaderror then break end end @@ -764,8 +811,9 @@ end -- generators: function resolvers.loadlists() - for _, hash in ipairs(instance.hashes) do - resolvers.generatedatabase(hash.tag) + local hashes = instance.hashes + for i=1,#hashes do + resolvers.generatedatabase(hashes[i].tag) end end @@ -777,10 +825,27 @@ end local weird = lpeg.P(".")^1 + lpeg.anywhere(lpeg.S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t")) +--~ local l_forbidden = lpeg.S("~`!#$%^&*()={}[]:;\"\'||\\/<>,?\n\r\t") +--~ local l_confusing = lpeg.P(" ") +--~ 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) +--~ ----- l_normal = l_normal * lpeg.Cc(true) + lpeg.Cc(false) + +--~ local function test(str) +--~ print(str,lpeg.match(l_normal,str)) +--~ end +--~ test("ヒラギノ明朝 Pro W3") +--~ test("..ヒラギノ明朝 Pro W3") +--~ test(":ヒラギノ明朝 Pro W3;") +--~ test("ヒラギノ明朝 /Pro W3;") +--~ test("ヒラギノ明朝 Pro W3") + function resolvers.generators.tex(specification) local tag = specification - if trace_verbose then - logs.report("fileio","scanning path %s",specification) + if trace_locating then + logs.report("fileio","scanning path '%s'",specification) end instance.files[tag] = { } local files = instance.files[tag] @@ -796,7 +861,8 @@ function resolvers.generators.tex(specification) full = spec end for name in directory(full) do - if not weird:match(name) then + if not lpegmatch(weird,name) then + -- if lpegmatch(l_normal,name) then local mode = attributes(full..name,'mode') if mode == 'file' then if path then @@ -829,7 +895,7 @@ function resolvers.generators.tex(specification) end end action() - if trace_verbose then + if trace_locating then logs.report("fileio","%s files found on %s directories with %s uppercase remappings",n,m,r) end end @@ -844,11 +910,48 @@ end -- we join them and split them after the expansion has taken place. This -- is more convenient. +--~ local checkedsplit = string.checkedsplit + +local cache = { } + +local splitter = lpeg.Ct(lpeg.splitat(lpeg.S(os.type == "windows" and ";" or ":;"))) + +local function split_kpse_path(str) -- beware, this can be either a path or a {specification} + local found = cache[str] + if not found then + if str == "" then + found = { } + else + str = gsub(str,"\\","/") +--~ local split = (find(str,";") and checkedsplit(str,";")) or checkedsplit(str,io.pathseparator) +local split = lpegmatch(splitter,str) + found = { } + for i=1,#split do + local s = split[i] + if not find(s,"^{*unset}*") then + found[#found+1] = s + end + end + if trace_expansions then + logs.report("fileio","splitting path specification '%s'",str) + for k=1,#found do + logs.report("fileio","% 4i: %s",k,found[k]) + end + end + cache[str] = found + end + end + return found +end + +resolvers.split_kpse_path = split_kpse_path + function resolvers.splitconfig() - for i,c in ipairs(instance) do - for k,v in pairs(c) do + for i=1,#instance do + local c = instance[i] + for k,v in next, c do if type(v) == 'string' then - local t = file.split_path(v) + local t = split_kpse_path(v) if #t > 1 then c[k] = t end @@ -858,21 +961,25 @@ function resolvers.splitconfig() end function resolvers.joinconfig() - for i,c in ipairs(instance.order) do - for k,v in pairs(c) do -- ipairs? + local order = instance.order + for i=1,#order do + local c = order[i] + for k,v in next, c do -- indexed? if type(v) == 'table' then c[k] = file.join_path(v) end end end end + function resolvers.split_path(str) if type(str) == 'table' then return str else - return file.split_path(str) + return split_kpse_path(str) end end + function resolvers.join_path(str) if type(str) == 'table' then return file.join_path(str) @@ -884,8 +991,9 @@ end function resolvers.splitexpansions() local ie = instance.expansions for k,v in next, ie do - local t, h = { }, { } - for _,vv in ipairs(file.split_path(v)) do + local t, h, p = { }, { }, split_kpse_path(v) + for kk=1,#p do + local vv = p[kk] if vv ~= "" and not h[vv] then t[#t+1] = vv h[vv] = true @@ -932,11 +1040,15 @@ function resolvers.serialize(files) end t[#t+1] = "return {" if instance.sortdata then - for _, k in pairs(sortedkeys(files)) do -- ipairs + local sortedfiles = sortedkeys(files) + for i=1,#sortedfiles do + local k = sortedfiles[i] local fk = files[k] if type(fk) == 'table' then t[#t+1] = "\t['" .. k .. "']={" - for _, kk in pairs(sortedkeys(fk)) do -- ipairs + local sortedfk = sortedkeys(fk) + for j=1,#sortedfk do + local kk = sortedfk[j] t[#t+1] = dump(kk,fk[kk],"\t\t") end t[#t+1] = "\t}," @@ -961,12 +1073,18 @@ function resolvers.serialize(files) return concat(t,"\n") end +local data_state = { } + +function resolvers.data_state() + return data_state or { } +end + function resolvers.save_data(dataname, makename) -- untested without cache overload for cachename, files in next, instance[dataname] do local name = (makename or file.join)(cachename,dataname) local luaname, lucname = name .. ".lua", name .. ".luc" - if trace_verbose then - logs.report("fileio","preparing %s for %s",dataname,cachename) + if trace_locating then + logs.report("fileio","preparing '%s' for '%s'",dataname,cachename) end for k, v in next, files do if type(v) == "table" and #v == 1 then @@ -980,24 +1098,25 @@ function resolvers.save_data(dataname, makename) -- untested without cache overl date = os.date("%Y-%m-%d"), time = os.date("%H:%M:%S"), content = files, + uuid = os.uuid(), } local ok = io.savedata(luaname,resolvers.serialize(data)) if ok then - if trace_verbose then - logs.report("fileio","%s saved in %s",dataname,luaname) + if trace_locating then + logs.report("fileio","'%s' saved in '%s'",dataname,luaname) end if utils.lua.compile(luaname,lucname,false,true) then -- no cleanup but strip - if trace_verbose then - logs.report("fileio","%s compiled to %s",dataname,lucname) + if trace_locating then + logs.report("fileio","'%s' compiled to '%s'",dataname,lucname) end else - if trace_verbose then - logs.report("fileio","compiling failed for %s, deleting file %s",dataname,lucname) + if trace_locating then + logs.report("fileio","compiling failed for '%s', deleting file '%s'",dataname,lucname) end os.remove(lucname) end - elseif trace_verbose then - logs.report("fileio","unable to save %s in %s (access error)",dataname,luaname) + elseif trace_locating then + logs.report("fileio","unable to save '%s' in '%s' (access error)",dataname,luaname) end end end @@ -1009,19 +1128,20 @@ function resolvers.load_data(pathname,dataname,filename,makename) -- untested wi if blob then local data = blob() if data and data.content and data.type == dataname and data.version == resolvers.cacheversion then - if trace_verbose then - logs.report("fileio","loading %s for %s from %s",dataname,pathname,filename) + data_state[#data_state+1] = data.uuid + if trace_locating then + logs.report("fileio","loading '%s' for '%s' from '%s'",dataname,pathname,filename) end instance[dataname][pathname] = data.content else - if trace_verbose then - logs.report("fileio","skipping %s for %s from %s",dataname,pathname,filename) + if trace_locating then + logs.report("fileio","skipping '%s' for '%s' from '%s'",dataname,pathname,filename) end instance[dataname][pathname] = { } instance.loaderror = true end - elseif trace_verbose then - logs.report("fileio","skipping %s for %s from %s",dataname,pathname,filename) + elseif trace_locating then + logs.report("fileio","skipping '%s' for '%s' from '%s'",dataname,pathname,filename) end end @@ -1040,15 +1160,17 @@ function resolvers.resetconfig() end function resolvers.loadnewconfig() - for _, cnf in ipairs(instance.luafiles) do + local luafiles = instance.luafiles + for i=1,#luafiles do + local cnf = luafiles[i] local pathname = file.dirname(cnf) local filename = file.join(pathname,resolvers.luaname) local blob = loadfile(filename) if blob then local data = blob() if data then - if trace_verbose then - logs.report("fileio","loading configuration file %s",filename) + if trace_locating then + logs.report("fileio","loading configuration file '%s'",filename) end if true then -- flatten to variable.progname @@ -1069,14 +1191,14 @@ function resolvers.loadnewconfig() instance['setup'][pathname] = data end else - if trace_verbose then - logs.report("fileio","skipping configuration file %s",filename) + if trace_locating then + logs.report("fileio","skipping configuration file '%s'",filename) end instance['setup'][pathname] = { } instance.loaderror = true end - elseif trace_verbose then - logs.report("fileio","skipping configuration file %s",filename) + elseif trace_locating then + logs.report("fileio","skipping configuration file '%s'",filename) end instance.order[#instance.order+1] = instance.setup[pathname] if instance.loaderror then break end @@ -1085,7 +1207,9 @@ end function resolvers.loadoldconfig() if not instance.renewcache then - for _, cnf in ipairs(instance.cnffiles) do + local cnffiles = instance.cnffiles + for i=1,#cnffiles do + local cnf = cnffiles[i] local dname = file.dirname(cnf) resolvers.load_data(dname,'configuration') instance.order[#instance.order+1] = instance.configuration[dname] @@ -1275,7 +1399,7 @@ end function resolvers.expanded_path_list(str) if not str then - return ep or { } + return ep or { } -- ep ? elseif instance.savelists then -- engine+progname hash str = gsub(str,"%$","") @@ -1293,9 +1417,9 @@ end function resolvers.expanded_path_list_from_var(str) -- brrr local tmp = resolvers.var_of_format_or_suffix(gsub(str,"%$","")) if tmp ~= "" then - return resolvers.expanded_path_list(str) - else return resolvers.expanded_path_list(tmp) + else + return resolvers.expanded_path_list(str) end end @@ -1342,9 +1466,9 @@ function resolvers.isreadable.file(name) local readable = lfs.isfile(name) -- brrr if trace_detail then if readable then - logs.report("fileio","+ readable: %s",name) + logs.report("fileio","file '%s' is readable",name) else - logs.report("fileio","- readable: %s", name) + logs.report("fileio","file '%s' is not readable", name) end end return readable @@ -1360,7 +1484,7 @@ local function collect_files(names) for k=1,#names do local fname = names[k] if trace_detail then - logs.report("fileio","? blobpath asked: %s",fname) + logs.report("fileio","checking name '%s'",fname) end local bname = file.basename(fname) local dname = file.dirname(fname) @@ -1376,7 +1500,7 @@ local function collect_files(names) local files = blobpath and instance.files[blobpath] if files then if trace_detail then - logs.report("fileio",'? blobpath do: %s (%s)',blobpath,bname) + logs.report("fileio","deep checking '%s' (%s)",blobpath,bname) end local blobfile = files[bname] if not blobfile then @@ -1410,7 +1534,7 @@ local function collect_files(names) end end elseif trace_locating then - logs.report("fileio",'! blobpath no: %s (%s)',blobpath,bname) + logs.report("fileio","no match in '%s' (%s)",blobpath,bname) end end end @@ -1460,14 +1584,13 @@ 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 if instance.found[stamp] then if trace_locating then - logs.report("fileio",'! remembered: %s',filename) + logs.report("fileio","remembering file '%s'",filename) end return instance.found[stamp] end @@ -1475,7 +1598,7 @@ local function collect_instance_files(filename,collected) -- todo : plugin (scan if not dangerous[instance.format or "?"] then if resolvers.isreadable.file(filename) then if trace_detail then - logs.report("fileio",'= found directly: %s',filename) + logs.report("fileio","file '%s' found directly",filename) end instance.found[stamp] = { filename } return { filename } @@ -1483,13 +1606,13 @@ local function collect_instance_files(filename,collected) -- todo : plugin (scan end if find(filename,'%*') then if trace_locating then - logs.report("fileio",'! wildcard: %s', filename) + logs.report("fileio","checking wildcard '%s'", filename) end result = resolvers.find_wildcard_files(filename) elseif file.is_qualified_path(filename) then if resolvers.isreadable.file(filename) then if trace_locating then - logs.report("fileio",'! qualified: %s', filename) + logs.report("fileio","qualified name '%s'", filename) end result = { filename } else @@ -1499,7 +1622,7 @@ local function collect_instance_files(filename,collected) -- todo : plugin (scan forcedname = filename .. ".tex" if resolvers.isreadable.file(forcedname) then if trace_locating then - logs.report("fileio",'! no suffix, forcing standard filetype: tex') + logs.report("fileio","no suffix, forcing standard filetype 'tex'") end result, ok = { forcedname }, true end @@ -1509,7 +1632,7 @@ local function collect_instance_files(filename,collected) -- todo : plugin (scan forcedname = filename .. "." .. s if resolvers.isreadable.file(forcedname) then if trace_locating then - logs.report("fileio",'! no suffix, forcing format filetype: %s', s) + logs.report("fileio","no suffix, forcing format filetype '%s'", s) end result, ok = { forcedname }, true break @@ -1521,7 +1644,7 @@ local function collect_instance_files(filename,collected) -- todo : plugin (scan -- try to find in tree (no suffix manipulation), here we search for the -- matching last part of the name local basename = file.basename(filename) - local pattern = (filename .. "$"):gsub("([%.%-])","%%%1") + local pattern = gsub(filename .. "$","([%.%-])","%%%1") local savedformat = instance.format local format = savedformat or "" if format == "" then @@ -1531,19 +1654,21 @@ local function collect_instance_files(filename,collected) -- todo : plugin (scan instance.format = "othertextfiles" -- kind of everything, maybe texinput is better end -- - local resolved = collect_instance_files(basename) - if #result == 0 then - local lowered = lower(basename) - if filename ~= lowered then - resolved = collect_instance_files(lowered) + if basename ~= filename then + local resolved = collect_instance_files(basename) + if #result == 0 then + local lowered = lower(basename) + if filename ~= lowered then + resolved = collect_instance_files(lowered) + end end - end - resolvers.format = savedformat - -- - for r=1,#resolved do - local rr = resolved[r] - if rr:find(pattern) then - result[#result+1], ok = rr, true + resolvers.format = savedformat + -- + for r=1,#resolved do + local rr = resolved[r] + if find(rr,pattern) then + result[#result+1], ok = rr, true + end end end -- a real wildcard: @@ -1552,14 +1677,14 @@ local function collect_instance_files(filename,collected) -- todo : plugin (scan -- local filelist = collect_files({basename}) -- for f=1,#filelist do -- local ff = filelist[f][3] or "" - -- if ff:find(pattern) then + -- if find(ff,pattern) then -- result[#result+1], ok = ff, true -- end -- end -- end end if not ok and trace_locating then - logs.report("fileio",'? qualified: %s', filename) + logs.report("fileio","qualified name '%s'", filename) end end else @@ -1578,12 +1703,12 @@ local function collect_instance_files(filename,collected) -- todo : plugin (scan wantedfiles[#wantedfiles+1] = forcedname filetype = resolvers.format_of_suffix(forcedname) if trace_locating then - logs.report("fileio",'! forcing filetype: %s',filetype) + logs.report("fileio","forcing filetype '%s'",filetype) end else filetype = resolvers.format_of_suffix(filename) if trace_locating then - logs.report("fileio",'! using suffix based filetype: %s',filetype) + logs.report("fileio","using suffix based filetype '%s'",filetype) end end else @@ -1595,7 +1720,7 @@ local function collect_instance_files(filename,collected) -- todo : plugin (scan end filetype = instance.format if trace_locating then - logs.report("fileio",'! using given filetype: %s',filetype) + logs.report("fileio","using given filetype '%s'",filetype) end end local typespec = resolvers.variable_of_format(filetype) @@ -1603,9 +1728,7 @@ local function collect_instance_files(filename,collected) -- todo : plugin (scan if not pathlist or #pathlist == 0 then -- no pathlist, access check only / todo == wildcard if trace_detail then - logs.report("fileio",'? filename: %s',filename) - logs.report("fileio",'? filetype: %s',filetype or '?') - logs.report("fileio",'? wanted files: %s',concat(wantedfiles," | ")) + logs.report("fileio","checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | ")) end for k=1,#wantedfiles do local fname = wantedfiles[k] @@ -1626,36 +1749,59 @@ local function collect_instance_files(filename,collected) -- todo : plugin (scan else -- list search local filelist = collect_files(wantedfiles) - local doscan, recurse + local dirlist = { } + if filelist then + for i=1,#filelist do + dirlist[i] = file.dirname(filelist[i][2]) .. "/" + end + end if trace_detail then - logs.report("fileio",'? filename: %s',filename) + logs.report("fileio","checking filename '%s'",filename) end -- a bit messy ... esp the doscan setting here + local doscan for k=1,#pathlist do local path = pathlist[k] if find(path,"^!!") then doscan = false else doscan = true end - if find(path,"//$") then recurse = true else recurse = false end local pathname = gsub(path,"^!+", '') done = false -- using file list - if filelist and not (done and not instance.allresults) and recurse then - -- compare list entries with permitted pattern - pathname = gsub(pathname,"([%-%.])","%%%1") -- this also influences - pathname = gsub(pathname,"/+$", '/.*') -- later usage of pathname - pathname = gsub(pathname,"//", '/.-/') -- not ok for /// but harmless - local expr = "^" .. pathname + if filelist then + local expression + -- compare list entries with permitted pattern -- /xx /xx// + if not find(pathname,"/$") then + expression = pathname .. "/" + else + expression = pathname + end + expression = gsub(expression,"([%-%.])","%%%1") -- this also influences + expression = gsub(expression,"//+$", '/.*') -- later usage of pathname + expression = gsub(expression,"//", '/.-/') -- not ok for /// but harmless + expression = "^" .. expression .. "$" + if trace_detail then + logs.report("fileio","using pattern '%s' for path '%s'",expression,pathname) + end for k=1,#filelist do local fl = filelist[k] local f = fl[2] - if find(f,expr) then - if trace_detail then - logs.report("fileio",'= found in hash: %s',f) - end + local d = dirlist[k] + if find(d,expression) then --- todo, test for readable result[#result+1] = fl[3] resolvers.register_in_trees(f) -- for tracing used files done = true - if not instance.allresults then break end + if instance.allresults then + if trace_detail then + logs.report("fileio","match in hash for file '%s' on path '%s', continue scanning",f,d) + end + else + if trace_detail then + logs.report("fileio","match in hash for file '%s' on path '%s', quit scanning",f,d) + end + break + end + elseif trace_detail then + logs.report("fileio","no match in hash for file '%s' on path '%s'",f,d) end end end @@ -1671,7 +1817,7 @@ local function collect_instance_files(filename,collected) -- todo : plugin (scan local fname = file.join(ppname,w) if resolvers.isreadable.file(fname) then if trace_detail then - logs.report("fileio",'= found by scanning: %s',fname) + logs.report("fileio","found '%s' by scanning",fname) end result[#result+1] = fname done = true @@ -1734,7 +1880,7 @@ function resolvers.find_given_files(filename) local hashes = instance.hashes for k=1,#hashes do local hash = hashes[k] - local files = instance.files[hash.tag] + local files = instance.files[hash.tag] or { } local blist = files[bname] if not blist then local rname = "remap:"..bname @@ -1844,9 +1990,9 @@ function resolvers.load(option) statistics.starttiming(instance) resolvers.resetconfig() resolvers.identify_cnf() - resolvers.load_lua() + resolvers.load_lua() -- will become the new method resolvers.expand_variables() - resolvers.load_cnf() + resolvers.load_cnf() -- will be skipped when we have a lua file resolvers.expand_variables() if option ~= "nofiles" then resolvers.load_hash() @@ -1858,22 +2004,23 @@ end function resolvers.for_files(command, files, filetype, mustexist) if files and #files > 0 then local function report(str) - if trace_verbose then + if trace_locating then logs.report("fileio",str) -- has already verbose else print(str) end end - if trace_verbose then - report('') + if trace_locating then + report('') -- ? end - for _, file in ipairs(files) do + for f=1,#files do + local file = files[f] local result = command(file,filetype,mustexist) if type(result) == 'string' then report(result) else - for _,v in ipairs(result) do - report(v) + for i=1,#result do + report(result[i]) -- could be unpack end end end @@ -1920,18 +2067,19 @@ end function table.sequenced(t,sep) -- temp here local s = { } - for k, v in pairs(t) do -- pairs? - s[#s+1] = k .. "=" .. v + for k, v in next, t do -- indexed? + 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 if trace_locating then - logs.report("fileio",'= handler: %s -> %s -> %s',specification.original,what,table.sequenced(specification)) + logs.report("fileio","handler '%s' -> '%s' -> '%s'",specification.original,what,table.sequenced(specification)) end return resolvers[what][scheme](filename,filetype) -- todo: specification else @@ -1951,8 +2099,9 @@ function resolvers.clean_path(str) end function resolvers.do_with_path(name,func) - for _, v in pairs(resolvers.expanded_path_list(name)) do -- pairs? - func("^"..resolvers.clean_path(v)) + local pathlist = resolvers.expanded_path_list(name) + for i=1,#pathlist do + func("^"..resolvers.clean_path(pathlist[i])) end end @@ -1961,7 +2110,9 @@ function resolvers.do_with_var(name,func) end function resolvers.with_files(pattern,handle) - for _, hash in ipairs(instance.hashes) do + local hashes = instance.hashes + for i=1,#hashes do + local hash = hashes[i] local blobpath = hash.tag local blobtype = hash.type if blobpath then @@ -1976,7 +2127,7 @@ function resolvers.with_files(pattern,handle) if type(v) == "string" then handle(blobtype,blobpath,v,k) else - for _,vv in pairs(v) do -- ipairs? + for _,vv in next, v do -- indexed handle(blobtype,blobpath,vv,k) end end @@ -1988,7 +2139,7 @@ function resolvers.with_files(pattern,handle) end function resolvers.locate_format(name) - local barename, fmtname = name:gsub("%.%a+$",""), "" + local barename, fmtname = gsub(name,"%.%a+$",""), "" if resolvers.usecache then local path = file.join(caches.setpath("formats")) -- maybe platform fmtname = file.join(path,barename..".fmt") or "" |