if not modules then modules = { } end modules ['supp-fil'] = {
    version   = 1.001,
    comment   = "companion to supp-fil.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

--[[ldx--
<p>It's more convenient to manipulate filenames (paths) in
<l n='lua'/> than in <l n='tex'/>. These methods have counterparts
at the <l n='tex'/> side.</p>
--ldx]]--

local find, gsub, match, format, concat = string.find, string.gsub, string.match, string.format, table.concat
local texsprint, texwrite, ctxcatcodes = tex.sprint, tex.write, tex.ctxcatcodes

local trace_modules = false  trackers.register("modules.loading", function(v) trace_modules = v end)

support     = support     or { }
environment = environment or { }

environment.outputfilename = environment.outputfilename or environment.jobname

function support.checkfilename(str) -- "/whatever..." "c:..." "http://..."
    commands.chardef("kindoffile",boolean.tonumber(find(str,"^/") or find(str,"[%a]:")))
end

function support.thesanitizedfilename(str)
    texwrite((gsub(str,"\\","/")))
end

function support.splitfilename(fullname)
    local path, name, base, suffix, kind = '', fullname, fullname, '', 0
    local p, n = match(fullname,"^(.+)/(.-)$")
    if p and n then
        path, name, base = p, n, n
    end
    local b, s = match(base,"^(.+)%.(.-)$")
    if b and s then
        name, suffix = b, s
    end
    if path == "" then
        kind = 0
    elseif path == '.' then
        kind = 1
    else
        kind = 2
    end
    commands.def("splitofffull", fullname)
    commands.def("splitoffpath", path)
    commands.def("splitoffbase", base)
    commands.def("splitoffname", name)
    commands.def("splitofftype", suffix)
    commands.chardef("splitoffkind", kind)
end

function support.splitfiletype(fullname)
    local name, suffix = fullname, ''
    local n, s = match(fullname,"^(.+)%.(.-)$")
    if n and s then
        name, suffix = n, s
    end
    commands.def("splitofffull", fullname)
    commands.def("splitoffpath", "")
    commands.def("splitoffname", name)
    commands.def("splitofftype", suffix)
end

function support.doifparentfileelse(n)
    commands.testcase(n==environment.jobname or n==environment.jobname..'.tex' or n==environment.outputfilename)
end

-- saves some .15 sec on 12 sec format generation

local lastexistingfile = ""

function support.doiffileexistelse(name)
    if not name or name == "" then
        lastexistingfile = ""
    else
        lastexistingfile = resolvers.findtexfile(name) or ""
    end
    return commands.testcase(lastexistingfile ~= "")
end

function support.lastexistingfile()
    texsprint(ctxcatcodes,lastexistingfile)
end

-- more, we can cache matches

local finders, loaders, openers = resolvers.finders, resolvers.loaders, resolvers.openers

local found = { } -- can best be done in the resolver itself

-- todo: tracing

local function readfilename(specification,backtrack,treetoo)
    local fnd = found[specification]
    if not fnd then
        local splitspec = resolvers.splitmethod(specification)
        local filename = splitspec.path or ""
        if lfs.isfile(filename) then
            fnd = filename
        end
        if not fnd and backtrack then
            local fname = filename
            for i=1,backtrack,1 do
                fname = "../" .. fname
                if lfs.isfile(fname) then
                    fnd = fname
                    break
                end
            end
        end
        if not fnd and treetoo then
--~             fnd = resolvers.find_file(filename)
            fnd = resolvers.findtexfile(filename)
        end
        found[specification] = fnd
    end
    return fnd or ""
end

support.readfilename = readfilename

function finders.job(filename) return readfilename(filename,nil,false) end -- current path, no backtracking
function finders.loc(filename) return readfilename(filename,2,  false) end -- current path, backtracking
function finders.sys(filename) return readfilename(filename,nil,true ) end -- current path, obeys tex search
function finders.fix(filename) return readfilename(filename,2,  false) end -- specified path, backtracking
function finders.set(filename) return readfilename(filename,nil,false) end -- specified path, no backtracking
function finders.any(filename) return readfilename(filename,2,  true ) end -- loc job sys

openers.job = openers.generic loaders.job = loaders.generic
openers.loc = openers.generic loaders.loc = loaders.generic
openers.sys = openers.generic loaders.sys = loaders.generic
openers.fix = openers.generic loaders.fix = loaders.generic
openers.set = openers.generic loaders.set = loaders.generic
openers.any = openers.generic loaders.any = loaders.generic

function support.doreadfile(protocol,path,name) -- better do a split and then pass table
    local specification
    if url.hasscheme(name) then
        specification = name
    else
        specification = ((path == "") and format("%s:///%s",protocol,name)) or format("%s:///%s/%s",protocol,path,name)
    end
    texsprint(ctxcatcodes,resolvers.findtexfile(specification))
end

-- modules can only have a tex or mkiv suffix or can have a specified one

local prefixes  = { "m", "p", "s", "x", "t" }
local suffixes  = { "tex", "mkiv" }
local modstatus = { }

local function usemodule(name,hassheme)
    local foundname
    if hasscheme then
        -- no auto suffix as http will return a home page or error page
        -- so we only add one if missing
        local fullname = file.addsuffix(name,"tex")
        if trace_modules then
            logs.report("modules","checking scheme driven file '%s'",fullname)
        end
        foundname = resolvers.findtexfile(fullname) or ""
    elseif file.extname(name) ~= "" then
        if trace_modules then
            logs.report("modules","checking suffix driven file '%s'",name)
        end
        foundname = support.readfilename(name,false,true) or ""
    else
        for i=1,#suffixes do
            local fullname = file.addsuffix(name,suffixes[i])
            if trace_modules then
                logs.report("modules","checking suffix driven file '%s'",fullname)
            end
            foundname = support.readfilename(fullname,false,true) or ""
            if foundname ~= "" then
                break
            end
        end
    end
    if foundname ~= "" then
        if trace_modules then
            logs.report("modules","loading '%s'",foundname)
        end
        context.startreadingfile()
        context.input(foundname)
        context.stopreadingfile()
        return true
    else
        return false
    end
end

function support.usemodules(prefix,askedname,truename)
    local hasprefix = prefix and prefix ~= ""
    local hashname = ((hasprefix and prefix) or "*") .. "-" .. truename
    local status = modstatus[hashname]
    if status == 0 then
        -- not found
    elseif status == 1 then
        status = status + 1
    else
        if trace_modules then
            logs.report("modules","locating '%s'",truename)
        end
        local hasscheme = url.hasscheme(truename)
        if hasscheme then
            -- no prefix and suffix done
            if usemodule(truename,true) then
                status = 1
            else
                status = 0
            end
        elseif hasprefix then
            if usemodule(prefix .. "-" .. truename) then
                status = 1
            else
                status = 0
            end
        else
            for i=1,#prefixes do
                -- todo: reconstruct name i.e. basename
                local thename = prefixes[i] .. "-" .. truename
                if usemodule(thename) then
                    status = 1
                    break
                end
            end
            if status then
                -- ok, don't change
            elseif usemodule(truename) then
                status = 1
            else
                status = 0
            end
        end
    end
    if status == 0 then
        if trace_modules then
            logs.report("modules","skipping '%s' (not found)",truename)
        else
            interfaces.showmessage("systems",6,askedname)
        end
    elseif status == 1 then
        if not trace_modules then
            interfaces.showmessage("systems",5,askedname)
        end
    else
        if trace_modules then
            logs.report("modules","skipping '%s' (already loaded)",truename)
        else
            interfaces.showmessage("systems",7,askedname)
        end
    end
    modstatus[hashname] = status
end

statistics.register("loaded tex modules", function()
    if next(modstatus) then
        local t, f = { }, { }
        for k, v in table.sortedhash(modstatus) do
            k = file.basename(k)
            if v == 0 then
                f[#f+1] = k
            else
                t[#t+1] = k
            end
        end
        local ts = (#t>0 and format(" (%s)",concat(t," "))) or ""
        local fs = (#f>0 and format(" (%s)",concat(f," "))) or ""
        return format("%s requested, %s found%s, %s missing%s",#t+#f,#t,ts,#f,fs)
    else
        return nil
    end
end)
