#!/usr/bin/env lua --- For example: --- --- $ ./headers.lua db/c.lua C23 --- assert.h --- ctype.h --- ... local public = {} local private = {} private.tags = {} private.tags_lookup = {} private.headers = {} local tag do local methods = {} function methods:add (header) table.insert(self.headers_, header) end local function headers (self) local result = {} for _, value in pairs(self.headers_) do if type(value) == "function" then value(result) else table.insert(result, value) end end return result end local mt = { __tostring=function (self) return self.name end, __index=function (self, key) if key == "headers" then return headers(self) end return methods[key] end, } function tag (name) return setmetatable({name=name, headers_={}}, mt) end end local alias do local mt = { __tostring = function (self) return string.format("%s (%s)", self.name, tostring(self.tag)) end, __index = function (self, key) return self.tag[key] end, } function alias (name, tag) return setmetatable({name=name, tag=tag}, mt) end end local function include (source) return function (target) for _, header in pairs(source.headers) do table.insert(target, header) end end end local function remove (header) return function (target) for key, value in pairs(target) do if value == header then table.remove(target, key) end end end end local function get_or_create_tag (name) local found = private.tags_lookup[name] if not found then found = tag(name) table.insert(private.tags, found) private.tags_lookup[name] = found end return found end function public.aliases (name) local tag = get_or_create_tag(name) return function (aliases) for _, name in pairs(aliases) do private.tags_lookup[name] = alias(name, tag) end end end function public.headers (name) local tag = get_or_create_tag(name) return function (filenames) for _, header in pairs(filenames) do tag:add(header) end end end function public.include (tag) tag = private.tags_lookup[tag] or error("invalid tag: " .. tag, 2) return include(tag) end function public.remove (header) return remove(header) end local db = loadfile(arg[1], nil, public) db() if arg[2] then local tag = private.tags_lookup[arg[2]] for _, header in pairs(tag.headers) do print(header) end else for _, tag in pairs(private.tags_lookup) do print(tag) end end