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

local type, tostring = type, tostring

local nodes         = nodes
local ligature_code = nodes.glyphcodes.ligature
local nuts          = nodes.nuts

local getnext       = nuts.getnext
local getsubtype    = nuts.getsubtype
local copynode      = nuts.copy
local flushlist     = nuts.flushlist
local count         = nuts.count
local isglyph       = nuts.isglyph
local getprop       = nuts.getprop
local setprop       = nuts.setprop

local fastcopy      = table.fastcopy

local report_error  = logs.reporter("node-aux:error")

local function setcomponents(base,list)
    local t = { }
    local n = 0
    local l = list
    while list do
        local char = isglyph(list)
        if char then
            n = n + 1
            t[n] = char
        end
        list = getnext(list)
    end
    -- not yet as we need them
    --
    -- flushlist(l)
    --
    setprop(base,"components",n > 0 and t or false)
end

local function getcomponents(base)
    return getprop(base,"components")
end

local function copynocomponents(base)
    local copy = copynode(base)
    setprop(copy,"components",false) -- no metatable lookup!
    return copy
end

local function copyonlyglyphs(base)
    local t = getprop(base,"components") -- also metatable
    if t then
        return fastcopy(t)
    end
end

local function docount(t,marks)
    local n = 0
    if t then
        for i=1,#t do
            local c = t[i]
            if type(c) == "table" then
                n = n + docount(t,marks)
            elseif not marks[c] then
                n = n + 1
            else
                --marks don't count
            end
        end
    end
    return n
end

-- start is a mark and we need to keep that one

local done = false

local function countcomponents(base,marks)
    local char = isglyph(base)
    if char then
        if getsubtype(base) == ligature_code then
            if not done then
                logs.report("fonts","!")
                logs.report("fonts","! check countcomponents with mkiv !")
                logs.report("fonts","!")
                done = true
            end
            local t = getprop(base,"components")
            if t then
                return docount(t,marks)
            end
        elseif not marks[char] then
            return 1
        end
    end
    return 0
end

nuts.components = {
    set              = setcomponents,
    get              = getcomponents,
    copyonlyglyphs   = copyonlyglyphs,
    copynocomponents = copynocomponents,
    count            = countcomponents,
    flush            = flushlist,
}

nuts.setcomponents = function() report_error("unsupported: %a","setcomponents") end
nuts.getcomponents = function() report_error("unsupported: %a","getcomponents") end
