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