diff options
Diffstat (limited to 'tex/context/base/mkxl/core-dat.lmt')
-rw-r--r-- | tex/context/base/mkxl/core-dat.lmt | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/tex/context/base/mkxl/core-dat.lmt b/tex/context/base/mkxl/core-dat.lmt new file mode 100644 index 000000000..fd8aa0fb6 --- /dev/null +++ b/tex/context/base/mkxl/core-dat.lmt @@ -0,0 +1,225 @@ +if not modules then modules = { } end modules ['core-dat'] = { + version = 1.001, + comment = "companion to core-dat.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This module provides a (multipass) container for arbitrary data. It replaces the +-- twopass data mechanism. + +local tonumber, tostring, type = tonumber, tostring, type + +local context = context + +local trace_datasets = false trackers.register("job.datasets" , function(v) trace_datasets = v end) + +local report_dataset = logs.reporter("dataset") + +local allocate = utilities.storage.allocate +local settings_to_hash = utilities.parsers.settings_to_hash + +local texgetcount = tex.getcount +local texsetcount = tex.setcount + +local v_yes = interfaces.variables.yes + +local new_latelua = nodes.pool.latelua + +local implement = interfaces.implement + +local c_realpageno = tex.iscount("realpageno") + +local collected = allocate() +local tobesaved = allocate() + +local datasets = { + collected = collected, + tobesaved = tobesaved, +} + +job.datasets = datasets + +local function initializer() + collected = datasets.collected + tobesaved = datasets.tobesaved +end + +job.register('job.datasets.collected', tobesaved, initializer, nil) + +local sets = { } + +table.setmetatableindex(tobesaved, function(t,k) + local v = { } + t[k] = v + return v +end) + +table.setmetatableindex(sets, function(t,k) + local v = { + index = 0, + order = 0, + } + t[k] = v + return v +end) + +local function setdata(settings) + local name = settings.name + local tag = settings.tag + local data = settings.data + local list = tobesaved[name] + if settings.convert and type(data) == "string" then + data = settings_to_hash(data) + end + if type(data) ~= "table" then + data = { data = data } + end + if not tag then + tag = #list + 1 + else + tag = tonumber(tag) or tag -- autonumber saves keys + end + list[tag] = data + if settings.delay == v_yes then + local set = sets[name] + local index = set.index + 1 + set.index = index + data.index = index + data.order = index + data.realpage = texgetcount(c_realpageno) + if trace_datasets then + report_dataset("action %a, name %a, tag %a, index %a","assign delayed",name,tag,index) + end + elseif trace_datasets then + report_dataset("action %a, name %a, tag %a","assign immediate",name,tag) + end + return name, tag, data +end + +datasets.setdata = setdata + +function datasets.extend(name,tag) + if type(name) == "table" then + name, tag = name.name, name.tag + end + local set = sets[name] + local order = set.order + 1 + local realpage = texgetcount(c_realpageno) + set.order = order + local t = tobesaved[name][tag] + t.realpage = realpage + t.order = order + if trace_datasets then + report_dataset("action %a, name %a, tag %a, page %a, index %a","flush by order",name,tag,t.index or 0,order,realpage) + end +end + +function datasets.getdata(name,tag,key,default) + local t = collected[name] + if t == nil then + if trace_datasets then + report_dataset("error: unknown dataset, name %a",name) + end + elseif type(t) ~= "table" then + return t + else + t = t[tag] or t[tonumber(tag)] + if not t then + if trace_datasets then + report_dataset("error: unknown dataset, name %a, tag %a",name,tag) + end + elseif key then + return t[key] or default + else + return t + end + end + return default +end + +local function setdataset(settings) + settings.convert = true + local name, tag = setdata(settings) + if settings.delay ~= v_yes then + -- + else + context(new_latelua { action = job.datasets.extend, name = name, tag = tag }) + end +end + +local cache = table.setmetatableindex(function(t,k) + local v = table.load(k..".tuc") + if v then + v = v.job + if v then + v = v.datasets + if v then + v = v.collected + end + end + end + if not v then + v = { } + if trace_datasets then + report_dataset("error: unknown dataset job %a",k) + end + end + t[k] = v + return v +end) + +local function datasetvariable(name,tag,key,cache) + local t = (cache or collected)[name] + if t == nil then + if trace_datasets then + report_dataset("error: unknown dataset, name %a, tag %a, not passed to tex",name) -- no tag + end + elseif type(t) ~= "table" then + context(tostring(t)) + else + t = t and (t[tag] or t[tonumber(tag)]) + if not t then + if trace_datasets then + report_dataset("error: unknown dataset, name %a, tag %a, not passed to tex",name,tag) + end + elseif type(t) == "table" then + local s = t[key] + if type(s) ~= "table" then + context(tostring(s)) + elseif trace_datasets then + report_dataset("error: unknown dataset, name %a, tag %a, not passed to tex",name,tag) + end + end + end +end + +local function datasetvariablefromjob(jobnname,name,tag,key) + datasetvariable(name,tag,key,cache[jobnname]) +end + +implement { + name = "setdataset", + actions = setdataset, + arguments = { + { + { "name" }, + { "tag" }, + { "delay" }, + { "data" }, + } + } +} + +implement { + name = "datasetvariable", + actions = datasetvariable, + arguments = "3 strings", +} + +implement { + name = "datasetvariablefromjob", + arguments = { "string", "string", "string", "string" }, + actions = datasetvariablefromjob +} |