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

local load, type, tostring  = load, type, tostring

local formatters   = string.formatters
local char         = string.char
local concat       = table.concat

local lpegmatch    = lpeg.match
local p_unquoted   = lpeg.Cs(lpeg.patterns.unquoted)

local f_action_f   = formatters["action%s(%s)"]
local f_action_s   = formatters["local action%s = action[%s]"]
local f_command    = formatters["local action = tokens._action\n%\nt\nreturn function(%s) return %s end"]

local interfaces   = interfaces
local commands     = commands
local register     = interfaces.registerscanner
local knownscanner = interfaces.knownscanner

local compile      = tokens.compile or function() end
local presets      = tokens.presets

local dummy        = function() end

local report       = logs.reporter("interfaces","implementor")

function interfaces.implement(specification)
    local name = specification.name
    if name == "" then
        name = nil
    end
    local actions   = specification.actions
    local arguments = specification.arguments
    local private   = specification.scope == "private"
    local onlyonce  = specification.onlyonce
    if not actions then
        if name then
            report("error: no actions for %a",name)
        else
            report("error: no actions and no name")
        end
        return
    end
    local p = arguments and presets[arguments]
    if p then
        arguments = p
    end
    local scanner
    local resetter = onlyonce and name and commands.ctxresetter(name)
    if resetter then
        local scan = compile(specification)
        if private then
            scanner = function()
                resetter()
                return scan()
            end
        else
            scanner = function()
                commands[name] = dummy
                resetter()
                return scan()
            end
        end
    else
        scanner = compile(specification)
    end
    if not name then
        return scanner
    end
    if knownscanner(name) and not specification.overload then
        report("warning: interface scanner %a is overloaded",name)
    end
 -- register(name,scanner,specification.protected,specification.public,specification.usage)
    register(name,scanner,specification)
    if private then
        return
    end
    local command
    if onlyonce then
        if type(actions) == "function" then
            actions = { actions }
        elseif #actions == 1 then
            actions = { actions[1] }
        end
    end
    if type(actions) == "function" then
        command = actions
    elseif #actions == 1 then
        command = actions[1]
    else
        -- this one is not yet complete .. compare tokens
        tokens._action = actions
        local f = { }
        local args
        if not arguments then
            args = ""
        elseif type(arguments) == "table" then
            local a = { }
            for i=1,#arguments do
                local v = arguments[i]
                local t = type(v)
                if t == "boolean" then
                    a[i] = tostring(v)
                elseif t == "number" then
                    a[i] = tostring(v)
                elseif t == "string" then
                    local s = lpegmatch(p_unquoted,v)
                    if s and v ~= s then
                        a[i] = v -- a string, given as "'foo'" or '"foo"'
                    else
                        a[i] = char(96+i)
                    end
                else
                    -- nothing special for tables
                    a[i] = char(96+i)
                end
            end
            args = concat(a,",")
        else
            args = "a"
        end
        command = args
        for i=1,#actions do
            command = f_action_f(i,command)
            f[i] = f_action_s(i,i)
        end
        command = f_command(f,args,command)
        command = load(command)
        if command then
            if resetter then
                local cmd = command()
                command = function()
                    commands[name] = dummy
                    resetter()
                    cmd()
                end
            else
                command = command()
            end
        end
        tokens._action = nil
    end
    if commands[name] and not specification.overload then
        report("warning: 'commands.%s' is redefined",name)
    end
    commands[name] = command
 -- return scanner, command
end

-- it's convenient to have copies here:

interfaces.defined  = tokens.defined

interfaces.setmacro = tokens.setters.macro
interfaces.setcount = tokens.setters.count
interfaces.setdimen = tokens.setters.dimen
