1if not modules then modules = { } end modules ['core-dat'] = {
2 version = 1.001,
3 comment = "companion to core-dat.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9
10
11
12local tonumber, tostring, type = tonumber, tostring, type
13
14local context = context
15local commands = commands
16local ctx_latelua = context.latelua
17
18local trace_datasets = false trackers.register("job.datasets" , function(v) trace_datasets = v end)
19local trace_pagestates = false trackers.register("job.pagestates", function(v) trace_pagestates = v end)
20
21local report_dataset = logs.reporter("dataset")
22local report_pagestate = logs.reporter("pagestate")
23
24local allocate = utilities.storage.allocate
25local settings_to_hash = utilities.parsers.settings_to_hash
26
27local texgetcount = tex.getcount
28local texsetcount = tex.setcount
29
30local formatters = string.formatters
31
32local v_yes = interfaces.variables.yes
33
34local new_latelua = nodes.pool.latelua
35
36local implement = interfaces.implement
37local getnamespace = interfaces.getnamespace
38
39local collected = allocate()
40local tobesaved = allocate()
41
42local datasets = {
43 collected = collected,
44 tobesaved = tobesaved,
45}
46
47job.datasets = datasets
48
49local function initializer()
50 collected = datasets.collected
51 tobesaved = datasets.tobesaved
52end
53
54job.register('job.datasets.collected', tobesaved, initializer, nil)
55
56local sets = { }
57
58table.setmetatableindex(tobesaved, function(t,k)
59 local v = { }
60 t[k] = v
61 return v
62end)
63
64table.setmetatableindex(sets, function(t,k)
65 local v = {
66 index = 0,
67 order = 0,
68 }
69 t[k] = v
70 return v
71end)
72
73local function setdata(settings)
74 local name = settings.name
75 local tag = settings.tag
76 local data = settings.data
77 local list = tobesaved[name]
78 if settings.convert and type(data) == "string" then
79 data = settings_to_hash(data)
80 end
81 if type(data) ~= "table" then
82 data = { data = data }
83 end
84 if not tag then
85 tag = #list + 1
86 else
87 tag = tonumber(tag) or tag
88 end
89 list[tag] = data
90 if settings.delay == v_yes then
91 local set = sets[name]
92 local index = set.index + 1
93 set.index = index
94 data.index = index
95 data.order = index
96 data.realpage = texgetcount("realpageno")
97 if trace_datasets then
98 report_dataset("action %a, name %a, tag %a, index %a","assign delayed",name,tag,index)
99 end
100 elseif trace_datasets then
101 report_dataset("action %a, name %a, tag %a","assign immediate",name,tag)
102 end
103 return name, tag, data
104end
105
106datasets.setdata = setdata
107
108function datasets.extend(name,tag)
109 if type(name) == "table" then
110 name, tag = name.name, name.tag
111 end
112 local set = sets[name]
113 local order = set.order + 1
114 local realpage = texgetcount("realpageno")
115 set.order = order
116 local t = tobesaved[name][tag]
117 t.realpage = realpage
118 t.order = order
119 if trace_datasets then
120 report_dataset("action %a, name %a, tag %a, page %a, index %a","flush by order",name,tag,t.index or 0,order,realpage)
121 end
122end
123
124function datasets.getdata(name,tag,key,default)
125 local t = collected[name]
126 if t == nil then
127 if trace_datasets then
128 report_dataset("error: unknown dataset, name %a",name)
129 end
130 elseif type(t) ~= "table" then
131 return t
132 else
133 t = t[tag] or t[tonumber(tag)]
134 if not t then
135 if trace_datasets then
136 report_dataset("error: unknown dataset, name %a, tag %a",name,tag)
137 end
138 elseif key then
139 return t[key] or default
140 else
141 return t
142 end
143 end
144 return default
145end
146
147local function setdataset(settings)
148 settings.convert = true
149 local name, tag = setdata(settings)
150 if settings.delay ~= v_yes then
151
152 else
153 context(new_latelua { action = job.datasets.extend, name = name, tag = tag })
154 end
155end
156
157local cache = table.setmetatableindex(function(t,k)
158 local v = table.load(k..".tuc")
159 if v then
160 v = v.job
161 if v then
162 v = v.datasets
163 if v then
164 v = v.collected
165 end
166 end
167 end
168 if not v then
169 v = { }
170 if trace_datasets then
171 report_dataset("error: unknown dataset job %a",k)
172 end
173 end
174 t[k] = v
175 return v
176end)
177
178local function datasetvariable(name,tag,key,cache)
179 local t = (cache or collected)[name]
180 if t == nil then
181 if trace_datasets then
182 report_dataset("error: unknown dataset, name %a, tag %a, not passed to tex",name)
183 end
184 elseif type(t) ~= "table" then
185 context(tostring(t))
186 else
187 t = t and (t[tag] or t[tonumber(tag)])
188 if not t then
189 if trace_datasets then
190 report_dataset("error: unknown dataset, name %a, tag %a, not passed to tex",name,tag)
191 end
192 elseif type(t) == "table" then
193 local s = t[key]
194 if type(s) ~= "table" then
195 context(tostring(s))
196 elseif trace_datasets then
197 report_dataset("error: unknown dataset, name %a, tag %a, not passed to tex",name,tag)
198 end
199 end
200 end
201end
202
203local function datasetvariablefromjob(jobnname,name,tag,key)
204 datasetvariable(name,tag,key,cache[jobnname])
205end
206
207implement {
208 name = "setdataset",
209 actions = setdataset,
210 arguments = {
211 {
212 { "name" },
213 { "tag" },
214 { "delay" },
215 { "data" },
216 }
217 }
218}
219
220implement {
221 name = "datasetvariable",
222 actions = datasetvariable,
223 arguments = "3 strings",
224}
225
226implement {
227 name = "datasetvariablefromjob",
228 arguments = { "string", "string", "string", "string" },
229 actions = datasetvariablefromjob
230}
231
232
233
234local collected = allocate()
235local tobesaved = allocate()
236
237local pagestates = {
238 collected = collected,
239 tobesaved = tobesaved,
240}
241
242job.pagestates = pagestates
243
244local function initializer()
245 collected = pagestates.collected
246 tobesaved = pagestates.tobesaved
247end
248
249job.register("job.pagestates.collected", tobesaved, initializer, nil)
250
251table.setmetatableindex(tobesaved, "table")
252
253local function setstate(settings)
254 local name = settings.name
255 local tag = settings.tag
256 local list = tobesaved[name]
257 if not tag then
258 tag = #list + 1
259 else
260 tag = tonumber(tag) or tag
261 end
262 local realpage = texgetcount("realpageno")
263 local data = realpage
264 list[tag] = data
265 if trace_pagestates then
266 report_pagestate("action %a, name %a, tag %a, preset %a","set",name,tag,realpage)
267 end
268 return name, tag, data
269end
270
271local function extend(name,tag)
272 local realpage = texgetcount("realpageno")
273 if trace_pagestates then
274 report_pagestate("action %a, name %a, tag %a, preset %a","synchronize",name,tag,realpage)
275 end
276 tobesaved[name][tag] = realpage
277end
278
279local function realpage(name,tag,default)
280 local t = collected[name]
281 if t then
282 t = t[tag] or t[tonumber(tag)]
283 if t then
284 return tonumber(t or default)
285 elseif trace_pagestates then
286 report_pagestate("error: unknown dataset, name %a, tag %a",name,tag)
287 end
288 elseif trace_pagestates then
289 report_pagestate("error: unknown dataset, name %a, tag %a",name)
290 end
291 return default
292end
293
294local function realpageorder(name,tag)
295 local t = collected[name]
296 if t then
297 local p = t[tag]
298 if p then
299 local n = 1
300 for i=tag-1,1,-1 do
301 if t[i] == p then
302 n = n +1
303 end
304 end
305 return n
306 end
307 end
308 return 0
309end
310
311pagestates.setstate = setstate
312pagestates.extend = extend
313pagestates.realpage = realpage
314pagestates.realpageorder = realpageorder
315
316function pagestates.countervalue(name)
317 return name and texgetcount(getnamespace("pagestatecounter") .. name) or 0
318end
319
320local function setpagestate(settings)
321 local name, tag = setstate(settings)
322
323 ctx_latelua(function() extend(name,tag) end)
324end
325
326local function setpagestaterealpageno(name,tag)
327 local t = collected[name]
328 t = t and (t[tag] or t[tonumber(tag)])
329 texsetcount("realpagestateno",t or texgetcount("realpageno"))
330end
331
332implement {
333 name = "setpagestate",
334 actions = setpagestate,
335 arguments = {
336 {
337 { "name" },
338 { "tag" },
339 { "delay" },
340 }
341 }
342}
343
344implement {
345 name = "pagestaterealpage",
346 actions = { realpage, context },
347 arguments = "2 strings",
348}
349
350implement {
351 name = "setpagestaterealpageno",
352 actions = setpagestaterealpageno,
353 arguments = "2 strings",
354}
355
356implement {
357 name = "pagestaterealpageorder",
358 actions = { realpageorder, context },
359 arguments = { "string", "integer" }
360}
361 |