1if not modules then modules = { } end modules ['node-shp'] = {
2 version = 1.001,
3 optimize = true,
4 comment = "companion to node-ini.mkiv",
5 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
6 copyright = "PRAGMA ADE / ConTeXt Development Team",
7 license = "see context related readme files"
8}
9
10local nodes, node = nodes, node
11
12local next, type = next, type
13local format = string.format
14local concat, sortedpairs = table.concat, table.sortedpairs
15local setmetatableindex = table.setmetatableindex
16
17local nodecodes = nodes.nodecodes
18local whatsitcodes = nodes.whatsitcodes
19local disccodes = nodes.disccodes
20
21local tasks = nodes.tasks
22local handlers = nodes.handlers
23
24local hlist_code = nodecodes.hlist
25local vlist_code = nodecodes.vlist
26local disc_code = nodecodes.disc
27local whatsit_code = nodecodes.whatsit
28
29local discretionarydisc_code = disccodes.discretionary
30
31local implement = interfaces.implement
32
33local nuts = nodes.nuts
34local tonut = nuts.tonut
35local tonode = nuts.tonode
36local remove_node = nuts.remove
37
38local nextnode = nuts.traversers.node
39
40local setfield = nuts.setfield
41local setlink = nuts.setlink
42local setprev = nuts.setprev
43local setnext = nuts.setnext
44local getid = nuts.getid
45local getdisc = nuts.getdisc
46local getboth = nuts.getboth
47local getnext = nuts.getnext
48local getlist = nuts.getlist
49local getsubtype = nuts.getsubtype
50
51local setlist = nuts.setlist
52
53local getbox = nuts.getbox
54
55local removables = {
56 [whatsitcodes.open] = true,
57 [whatsitcodes.close] = true,
58 [whatsitcodes.write] = true,
59 [whatsitcodes.savepos] = true,
60 [whatsitcodes.latelua] = true,
61
62}
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124handlers.cleanuppage = nuts.flattendiscretionaries
125
126local function cleanup_flushed(head)
127 local start = head
128 while start do
129 local id = getid(start)
130 if id == whatsit_code then
131 if removables[getsubtype(start)] then
132 head, start = remove_node(head,start,true)
133 else
134 start = getnext(start)
135 end
136 elseif id == hlist_code or id == vlist_code then
137 local sl = getlist(start)
138 if sl then
139 local rl = cleanup_flushed(sl)
140 if rl ~= sl then
141 setlist(start,rl)
142 end
143 end
144 start = getnext(start)
145 else
146 start = getnext(start)
147 end
148 end
149 return head
150end
151
152function handlers.cleanupbox(box)
153 cleanup_flushed(getbox(box))
154end
155
156local actions = tasks.actions("shipouts")
157
158function handlers.finalizebox(box)
159 actions(getbox(box))
160end
161
162
163
164implement { name = "cleanupbox", actions = handlers.cleanupbox, arguments = "integer" }
165implement { name = "finalizebox", actions = handlers.finalizebox, arguments = "integer" }
166
167
168
169local frequencies = { }
170
171nodes.tracers.frequencies = frequencies
172
173local data = { }
174local done = false
175
176setmetatableindex(data,function(t,k)
177 local v = { }
178 setmetatableindex(v,function(t,k)
179 local v = { }
180 t[k] = v
181 setmetatableindex(v,function(t,k)
182 t[k] = 0
183 return 0
184 end)
185 return v
186 end)
187 t[k] = v
188 return v
189end)
190
191local function count(head,data,subcategory)
192
193
194
195 for n, id in nextnode, tonut(head) do
196 local dn = data[nodecodes[id]]
197 dn[subcategory] = dn[subcategory] + 1
198 if id == hlist_code or id == vlist_code then
199 count(getlist(n),data,subcategory)
200 end
201 end
202end
203
204local function register(category,subcategory)
205 return function(head)
206 done = true
207 count(head,data[category],subcategory)
208 return head, false
209 end
210end
211
212frequencies.register = register
213frequencies.filename = nil
214
215trackers.register("nodes.frequencies",function(v)
216 if type(v) == "string" then
217 frequencies.filename = v
218 end
219 handlers.frequencies_shipouts_before = register("shipouts", "begin")
220 handlers.frequencies_shipouts_after = register("shipouts", "end")
221 handlers.frequencies_processors_before = register("processors", "begin")
222 handlers.frequencies_processors_after = register("processors", "end")
223 tasks.prependaction("shipouts", "before", "nodes.handlers.frequencies_shipouts_before")
224 tasks.appendaction ("shipouts", "after", "nodes.handlers.frequencies_shipouts_after")
225 tasks.prependaction("processors", "before", "nodes.handlers.frequencies_processors_before")
226 tasks.appendaction ("processors", "after", "nodes.handlers.frequencies_processors_after")
227end)
228
229statistics.register("node frequencies", function()
230 if done then
231 local filename = frequencies.filename or (tex.jobname .. "-frequencies.lua")
232 io.savedata(filename,table.serialize(data,true))
233 return format("saved in %q",filename)
234 end
235end)
236 |