strc-reg.lua /size: 53 Kb    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
strc-reg
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to strc-reg.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
local
next
,
type
,
tonumber
,
rawget
=
next
,
type
,
tonumber
,
rawget
10
local
char
,
format
,
gmatch
=
string
.
char
,
string
.
format
,
string
.
gmatch
11
local
equal
,
concat
,
remove
=
table
.
are_equal
,
table
.
concat
,
table
.
remove
12
local
lpegmatch
,
P
,
C
,
Ct
=
lpeg
.
match
,
lpeg
.
P
,
lpeg
.
C
,
lpeg
.
Ct
13
local
allocate
=
utilities
.
storage
.
allocate
14 15
local
trace_registers
=
false
trackers
.
register
(
"
structures.registers
"
,
function
(
v
)
trace_registers
=
v
end
)
16 17
local
report_registers
=
logs
.
reporter
(
"
structure
"
,
"
registers
"
)
18 19
local
structures
=
structures
20
local
registers
=
structures
.
registers
21
local
helpers
=
structures
.
helpers
22
local
sections
=
structures
.
sections
23
local
documents
=
structures
.
documents
24
local
pages
=
structures
.
pages
25
local
references
=
structures
.
references
26 27
local
usedinternals
=
references
.
usedinternals
28 29
local
mappings
=
sorters
.
mappings
30
local
entries
=
sorters
.
entries
31
local
replacements
=
sorters
.
replacements
32 33
local
processors
=
typesetters
.
processors
34
local
splitprocessor
=
processors
.
split
35 36
local
texgetcount
=
tex
.
getcount
37 38
local
variables
=
interfaces
.
variables
39
local
v_forward
=
variables
.
forward
40
local
v_all
=
variables
.
all
41
local
v_no
=
variables
.
no
42
local
v_yes
=
variables
.
yes
43
local
v_packed
=
variables
.
packed
44
local
v_current
=
variables
.
current
45
local
v_previous
=
variables
.
previous
46
local
v_first
=
variables
.
first
47
local
v_last
=
variables
.
last
48
local
v_text
=
variables
.
text
49
local
v_section
=
variables
.
section
50 51
local
context
=
context
52
local
ctx_latelua
=
context
.
latelua
53 54
local
implement
=
interfaces
.
implement
55 56
local
matchingtilldepth
=
sections
.
matchingtilldepth
57
local
numberatdepth
=
sections
.
numberatdepth
58
local
currentlevel
=
sections
.
currentlevel
59
local
currentid
=
sections
.
currentid
60 61
local
touserdata
=
helpers
.
touserdata
62 63
local
internalreferences
=
references
.
internals
64
local
setinternalreference
=
references
.
setinternalreference
65 66
local
setmetatableindex
=
table
.
setmetatableindex
67 68
local
absmaxlevel
=
5
-- \c_strc_registers_maxlevel
69 70
local
h_prefixpage
=
helpers
.
prefixpage
71
local
h_prefixlastpage
=
helpers
.
prefixlastpage
72
local
h_title
=
helpers
.
title
73
local
h_prefix
=
helpers
.
prefix
74 75
local
ctx_startregisteroutput
=
context
.
startregisteroutput
76
local
ctx_stopregisteroutput
=
context
.
stopregisteroutput
77
local
ctx_startregistersection
=
context
.
startregistersection
78
local
ctx_stopregistersection
=
context
.
stopregistersection
79
local
ctx_startregisterentries
=
context
.
startregisterentries
80
local
ctx_stopregisterentries
=
context
.
stopregisterentries
81
local
ctx_startregisterentry
=
context
.
startregisterentry
82
local
ctx_stopregisterentry
=
context
.
stopregisterentry
83
local
ctx_startregisterpages
=
context
.
startregisterpages
84
local
ctx_stopregisterpages
=
context
.
stopregisterpages
85
local
ctx_startregisterseewords
=
context
.
startregisterseewords
86
local
ctx_stopregisterseewords
=
context
.
stopregisterseewords
87 88
local
ctx_registerentry
=
context
.
registerentry
89
local
ctx_registerseeword
=
context
.
registerseeword
90
local
ctx_registerpagerange
=
context
.
registerpagerange
91
local
ctx_registeronepage
=
context
.
registeronepage
92
local
ctx_registersection
=
context
.
registersection
93
local
ctx_registerpacked
=
context
.
registerpacked
94 95
-- possible export, but ugly code (overloads)
96
--
97
-- local output, section, entries, nofentries, pages, words, rawtext
98
--
99
-- h_title = function(a,b) rawtext = a end
100
--
101
-- local function ctx_startregisteroutput()
102
-- output = { }
103
-- section = nil
104
-- entries = nil
105
-- nofentries = nil
106
-- pages = nil
107
-- words = nil
108
-- rawtext = nil
109
-- end
110
-- local function ctx_stopregisteroutput()
111
-- inspect(output)
112
-- output = nil
113
-- section = nil
114
-- entries = nil
115
-- nofentries = nil
116
-- pages = nil
117
-- words = nil
118
-- rawtext = nil
119
-- end
120
-- local function ctx_startregistersection(tag)
121
-- section = { }
122
-- output[#output+1] = {
123
-- section = section,
124
-- tag = tag,
125
-- }
126
-- end
127
-- local function ctx_stopregistersection()
128
-- end
129
-- local function ctx_startregisterentries(n)
130
-- entries = { }
131
-- nofentries = 0
132
-- section[#section+1] = entries
133
-- end
134
-- local function ctx_stopregisterentries()
135
-- end
136
-- local function ctx_startregisterentry(n) -- or subentries (nested?)
137
-- nofentries = nofentries + 1
138
-- entry = { }
139
-- entries[nofentries] = entry
140
-- end
141
-- local function ctx_stopregisterentry()
142
-- nofentries = nofentries - 1
143
-- entry = entries[nofentries]
144
-- end
145
-- local function ctx_startregisterpages()
146
-- pages = { }
147
-- entry.pages = pages
148
-- end
149
-- local function ctx_stopregisterpages()
150
-- end
151
-- local function ctx_startregisterseewords()
152
-- words = { }
153
-- entry.words = words
154
-- end
155
-- local function ctx_stopregisterseewords()
156
-- end
157
-- local function ctx_registerentry(processor,internal,seeparent,text)
158
-- text()
159
-- entry.text = {
160
-- processor = processor,
161
-- internal = internal,
162
-- seeparent = seeparent,
163
-- text = rawtext,
164
-- }
165
-- end
166
-- local function ctx_registerseeword(i,n,processor,internal,seeindex,seetext)
167
-- seetext()
168
-- entry.words[i] = {
169
-- processor = processor,
170
-- internal = internal,
171
-- seeparent = seeparent,
172
-- seetext = rawtext,
173
-- }
174
-- end
175
-- local function ctx_registerpagerange(fprocessor,finternal,frealpage,lprocessor,linternal,lrealpage)
176
-- pages[#pages+1] = {
177
-- first = {
178
-- processor = fprocessor,
179
-- internal = finternal,
180
-- realpage = frealpage,
181
-- },
182
-- last = {
183
-- processor = lprocessor,
184
-- internal = linternal,
185
-- realpage = lrealpage,
186
-- },
187
-- }
188
-- end
189
-- local function ctx_registeronepage(processor,internal,realpage)
190
-- pages[#pages+1] = {
191
-- processor = processor,
192
-- internal = internal,
193
-- realpage = realpage,
194
-- }
195
-- end
196 197
-- some day we will share registers and lists (although there are some conceptual
198
-- differences in the application of keywords)
199 200
local
function
filtercollected
(
names
,
criterium
,
number
,
collected
,
prevmode
)
201
if
not
criterium
or
criterium
=
=
"
"
then
202
criterium
=
v_all
203
end
204
local
data
=
documents
.
data
205
local
numbers
=
data
.
numbers
206
local
depth
=
data
.
depth
207
local
hash
=
{
}
208
local
result
=
{
}
209
local
nofresult
=
0
210
local
all
=
not
names
or
names
=
=
"
"
or
names
=
=
v_all
211
local
detail
=
nil
212
if
not
all
then
213
for
s
in
gmatch
(
names
,
"
[^, ]+
"
)
do
214
hash
[
s
]
=
true
215
end
216
end
217
if
criterium
=
=
v_all
or
criterium
=
=
v_text
then
218
for
i
=
1
,
#
collected
do
219
local
v
=
collected
[
i
]
220
if
all
then
221
nofresult
=
nofresult
+
1
222
result
[
nofresult
]
=
v
223
else
224
local
vmn
=
v
.
metadata
and
v
.
metadata
.
name
225
if
hash
[
vmn
]
then
226
nofresult
=
nofresult
+
1
227
result
[
nofresult
]
=
v
228
end
229
end
230
end
231
elseif
criterium
=
=
v_current
then
232
local
collectedsections
=
sections
.
collected
233
for
i
=
1
,
#
collected
do
234
local
v
=
collected
[
i
]
235
local
sectionnumber
=
collectedsections
[
v
.
references
.
section
]
236
if
sectionnumber
then
237
local
cnumbers
=
sectionnumber
.
numbers
238
if
prevmode
then
239
if
(
all
or
hash
[
v
.
metadata
.
name
]
)
and
#
cnumbers
>
=
depth
then
-- is the = ok for lists as well?
240
local
ok
=
true
241
for
d
=
1
,
depth
do
242
if
not
(
cnumbers
[
d
]
=
=
numbers
[
d
]
)
then
-- no zero test
243
ok
=
false
244
break
245
end
246
end
247
if
ok
then
248
nofresult
=
nofresult
+
1
249
result
[
nofresult
]
=
v
250
end
251
end
252
else
253
if
(
all
or
hash
[
v
.
metadata
.
name
]
)
and
#
cnumbers
>
depth
then
254
local
ok
=
true
255
for
d
=
1
,
depth
do
256
local
cnd
=
cnumbers
[
d
]
257
if
not
(
cnd
=
=
0
or
cnd
=
=
numbers
[
d
]
)
then
258
ok
=
false
259
break
260
end
261
end
262
if
ok
then
263
nofresult
=
nofresult
+
1
264
result
[
nofresult
]
=
v
265
end
266
end
267
end
268
end
269
end
270
elseif
criterium
=
=
v_previous
then
271
local
collectedsections
=
sections
.
collected
272
for
i
=
1
,
#
collected
do
273
local
v
=
collected
[
i
]
274
local
sectionnumber
=
collectedsections
[
v
.
references
.
section
]
275
if
sectionnumber
then
276
local
cnumbers
=
sectionnumber
.
numbers
277
if
(
all
or
hash
[
v
.
metadata
.
name
]
)
and
#
cnumbers
>
=
depth
then
278
local
ok
=
true
279
if
prevmode
then
280
for
d
=
1
,
depth
do
281
if
not
(
cnumbers
[
d
]
=
=
numbers
[
d
]
)
then
282
ok
=
false
283
break
284
end
285
end
286
else
287
for
d
=
1
,
depth
do
288
local
cnd
=
cnumbers
[
d
]
289
if
not
(
cnd
=
=
0
or
cnd
=
=
numbers
[
d
]
)
then
290
ok
=
false
291
break
292
end
293
end
294
end
295
if
ok
then
296
nofresult
=
nofresult
+
1
297
result
[
nofresult
]
=
v
298
end
299
end
300
end
301
end
302
elseif
criterium
=
=
variables
[
"
local
"
]
then
303
if
sections
.
autodepth
(
data
.
numbers
)
=
=
0
then
304
return
filtercollected
(
names
,
v_all
,
number
,
collected
,
prevmode
)
305
else
306
return
filtercollected
(
names
,
v_current
,
number
,
collected
,
prevmode
)
307
end
308
else
-- sectionname, number
309
-- beware, this works ok for registers
310
-- to be redone with reference instead
311
local
depth
=
sections
.
getlevel
(
criterium
)
312
local
number
=
tonumber
(
number
)
or
numberatdepth
(
depth
)
or
0
313
if
trace_registers
then
314
detail
=
format
(
"
depth: %s, number: %s, numbers: %s, startset: %s
"
,
depth
,
number
,
concat
(
sections
.
numbers
(
)
,
"
.
"
,
1
,
depth
)
,
#
collected
)
315
end
316
if
number
>
0
then
317
for
i
=
1
,
#
collected
do
318
local
v
=
collected
[
i
]
319
local
r
=
v
.
references
320
if
r
then
321
local
sectionnumber
=
sections
.
collected
[
r
.
section
]
322
if
sectionnumber
then
323
local
metadata
=
v
.
metadata
324
local
cnumbers
=
sectionnumber
.
numbers
325
if
cnumbers
then
326
if
(
all
or
hash
[
metadata
.
name
or
false
]
)
and
#
cnumbers
>
=
depth
and
matchingtilldepth
(
depth
,
cnumbers
)
then
327
nofresult
=
nofresult
+
1
328
result
[
nofresult
]
=
v
329
end
330
end
331
end
332
end
333
end
334
end
335
end
336
if
trace_registers
then
337
if
detail
then
338
report_registers
(
"
criterium %a, detail %a, found %a
"
,
criterium
,
detail
,
#
result
)
339
else
340
report_registers
(
"
criterium %a, detail %a, found %a
"
,
criterium
,
nil
,
#
result
)
341
end
342
end
343
return
result
344
end
345 346
local
tobesaved
=
allocate
(
)
347
local
collected
=
allocate
(
)
348 349
registers
.
collected
=
collected
350
registers
.
tobesaved
=
tobesaved
351
registers
.
filtercollected
=
filtercollected
352 353
-- we follow a different strategy than by lists, where we have a global
354
-- result table; we might do that here as well but since sorting code is
355
-- older we delay that decision
356 357
-- maybe store the specification in the format (although we predefine only
358
-- saved registers)
359 360
local
function
checker
(
t
,
k
)
361
local
v
=
{
362
metadata
=
{
363
language
=
'
en
'
,
364
sorted
=
false
,
365
class
=
class
,
366
}
,
367
entries
=
{
}
,
368
}
369
t
[
k
]
=
v
370
return
v
371
end
372 373
local
function
initializer
(
)
374
tobesaved
=
registers
.
tobesaved
375
collected
=
registers
.
collected
376
setmetatableindex
(
tobesaved
,
checker
)
377
setmetatableindex
(
collected
,
checker
)
378
local
usedinternals
=
references
.
usedinternals
379
for
name
,
list
in
next
,
collected
do
380
local
entries
=
list
.
entries
381
if
not
list
.
metadata
.
notsaved
then
382
for
e
=
1
,
#
entries
do
383
local
entry
=
entries
[
e
]
384
local
r
=
entry
.
references
385
if
r
then
386
local
internal
=
r
and
r
.
internal
387
if
internal
then
388
internalreferences
[
internal
]
=
entry
389
usedinternals
[
internal
]
=
r
.
used
390
end
391
end
392
end
393
end
394
end
395
-- references.sortedinternals = sortedkeys(internalreferences) -- todo: when we need it more than once
396
end
397 398
local
function
finalizer
(
)
399
local
flaginternals
=
references
.
flaginternals
400
local
usedviews
=
references
.
usedviews
401
for
k
,
v
in
next
,
tobesaved
do
402
local
entries
=
v
.
entries
403
if
entries
then
404
for
i
=
1
,
#
entries
do
405
local
r
=
entries
[
i
]
.
references
406
if
r
then
407
local
i
=
r
.
internal
408
local
f
=
flaginternals
[
i
]
409
if
f
then
410
r
.
used
=
usedviews
[
i
]
or
true
411
end
412
end
413
end
414
end
415
end
416
end
417 418
job
.
register
(
'
structures.registers.collected
'
,
tobesaved
,
initializer
,
finalizer
)
419 420
setmetatableindex
(
tobesaved
,
checker
)
421
setmetatableindex
(
collected
,
checker
)
422 423
local
function
defineregister
(
class
,
method
)
424
local
d
=
tobesaved
[
class
]
425
if
method
=
=
v_forward
then
426
d
.
metadata
.
notsaved
=
true
427
end
428
end
429 430
registers
.
define
=
defineregister
-- 4 times is somewhat over the top but we want consistency
431
registers
.
setmethod
=
defineregister
-- and we might have a difference some day
432 433
implement
{
434
name
=
"
defineregister
"
,
435
actions
=
defineregister
,
436
arguments
=
"
2 strings
"
,
437
}
438 439
implement
{
440
name
=
"
setregistermethod
"
,
441
actions
=
defineregister
,
-- duplicate use
442
arguments
=
"
2 strings
"
,
443
}
444 445 446
local
p_s
=
P
(
"
+
"
)
447
local
p_e
=
P
(
"
&
"
)
*
(
1
-
P
(
"
;
"
)
)
^
0
*
P
(
"
;
"
)
448
local
p_r
=
C
(
(
p_e
+
(
1
-
p_s
)
)
^
0
)
449 450
local
entrysplitter_xml
=
Ct
(
p_r
*
(
p_s
*
p_r
)
^
0
)
-- bah
451
local
entrysplitter_tex
=
lpeg
.
tsplitat
(
'
+
'
)
-- & obsolete in mkiv
452 453
local
tagged
=
{
}
454 455
-- this whole splitting is an inheritance of mkii
456 457
local
function
preprocessentries
(
rawdata
)
458
local
entries
=
rawdata
.
entries
459
if
entries
then
460
local
processors
=
rawdata
.
processors
461
local
et
=
entries
.
entries
462
local
kt
=
entries
.
keys
463
local
entryproc
=
processors
and
processors
.
entry
464
local
pageproc
=
processors
and
processors
.
page
465
local
coding
=
rawdata
.
metadata
.
coding
466
if
entryproc
=
=
"
"
then
467
entryproc
=
nil
468
end
469
if
pageproc
=
=
"
"
then
470
pageproc
=
nil
471
end
472
if
not
et
then
473
local
p
,
e
=
splitprocessor
(
entries
.
entry
or
"
"
)
474
if
p
then
475
entryproc
=
p
476
end
477
et
=
lpegmatch
(
coding
=
=
"
xml
"
and
entrysplitter_xml
or
entrysplitter_tex
,
e
)
478
end
479
if
not
kt
then
480
local
p
,
k
=
splitprocessor
(
entries
.
key
or
"
"
)
481
if
p
then
482
pageproc
=
p
483
end
484
kt
=
lpegmatch
(
coding
=
=
"
xml
"
and
entrysplitter_xml
or
entrysplitter_tex
,
k
)
485
end
486
--
487
entries
=
{
}
488
local
ok
=
false
489
for
k
=
#
et
,
1
,
-1
do
490
local
etk
=
et
[
k
]
491
local
ktk
=
kt
[
k
]
492
if
not
ok
and
etk
=
=
"
"
then
493
entries
[
k
]
=
nil
494
else
495
entries
[
k
]
=
{
etk
or
"
"
,
ktk
~
=
"
"
and
ktk
or
nil
}
496
ok
=
true
497
end
498
end
499
rawdata
.
list
=
entries
500
if
pageproc
or
entryproc
then
501
rawdata
.
processors
=
{
entryproc
,
pageproc
}
-- old way: indexed .. will be keys
502
end
503
rawdata
.
entries
=
nil
504
end
505
local
seeword
=
rawdata
.
seeword
506
if
seeword
then
507
seeword
.
processor
,
seeword
.
text
=
splitprocessor
(
seeword
.
text
or
"
"
)
508
end
509
end
510 511
local
function
storeregister
(
rawdata
)
-- metadata, references, entries
512
local
references
=
rawdata
.
references
513
local
metadata
=
rawdata
.
metadata
514
-- checking
515
if
not
metadata
then
516
metadata
=
{
}
517
rawdata
.
metadata
=
metadata
518
end
519
--
520
if
not
metadata
.
kind
then
521
metadata
.
kind
=
"
entry
"
522
end
523
--
524
--
525
if
not
metadata
.
catcodes
then
526
metadata
.
catcodes
=
tex
.
catcodetable
-- get
527
end
528
--
529
local
name
=
metadata
.
name
530
local
notsaved
=
tobesaved
[
name
]
.
metadata
.
notsaved
531
--
532
if
not
references
then
533
references
=
{
}
534
rawdata
.
references
=
references
535
end
536
--
537
local
internal
=
references
.
internal
538
if
not
internal
then
539
internal
=
texgetcount
(
"
locationcount
"
)
-- we assume that it has been set
540
references
.
internal
=
internal
541
end
542
--
543
if
notsaved
then
544
usedinternals
[
internal
]
=
references
.
used
-- todo view (we assume that forward references index entries are used)
545
end
546
--
547
if
not
references
.
realpage
then
548
references
.
realpage
=
0
-- just to be sure as it can be refered to
549
end
550
--
551
local
userdata
=
rawdata
.
userdata
552
if
userdata
then
553
rawdata
.
userdata
=
touserdata
(
userdata
)
554
end
555
--
556
references
.
section
=
currentid
(
)
557
metadata
.
level
=
currentlevel
(
)
558
--
559
local
data
=
notsaved
and
collected
[
name
]
or
tobesaved
[
name
]
560
local
entries
=
data
.
entries
561
internalreferences
[
internal
]
=
rawdata
562
preprocessentries
(
rawdata
)
563
entries
[
#
entries
+
1
]
=
rawdata
564
local
label
=
references
.
label
565
if
label
and
label
~
=
"
"
then
566
tagged
[
label
]
=
#
entries
567
else
568
references
.
label
=
nil
569
end
570
return
#
entries
571
end
572 573
local
function
enhanceregister
(
specification
)
574
local
name
=
specification
.
name
575
local
n
=
specification
.
n
576
local
saved
=
tobesaved
[
name
]
577
local
data
=
saved
.
metadata
.
notsaved
and
collected
[
name
]
or
saved
578
local
entry
=
data
.
entries
[
n
]
579
if
entry
then
580
entry
.
references
.
realpage
=
texgetcount
(
"
realpageno
"
)
581
end
582
end
583 584
-- This can become extendregister(specification)!
585 586
local
function
extendregister
(
name
,
tag
,
rawdata
)
-- maybe do lastsection internally
587
if
type
(
tag
)
=
=
"
string
"
then
588
tag
=
tagged
[
tag
]
589
end
590
if
tag
then
591
local
data
=
tobesaved
[
name
]
.
metadata
.
notsaved
and
collected
[
name
]
or
tobesaved
[
name
]
592
local
entry
=
data
.
entries
[
tag
]
593
if
entry
then
594
local
references
=
entry
.
references
595
references
.
lastrealpage
=
texgetcount
(
"
realpageno
"
)
596
references
.
lastsection
=
currentid
(
)
597
if
rawdata
then
598
local
userdata
=
rawdata
.
userdata
599
if
userdata
then
600
rawdata
.
userdata
=
touserdata
(
userdata
)
601
end
602
if
rawdata
.
entries
then
603
preprocessentries
(
rawdata
)
604
end
605
local
metadata
=
rawdata
.
metadata
606
if
metadata
and
not
metadata
.
catcodes
then
607
metadata
.
catcodes
=
tex
.
catcodetable
-- get
608
end
609
for
k
,
v
in
next
,
rawdata
do
610
local
rk
=
references
[
k
]
611
if
not
rk
then
612
references
[
k
]
=
v
613
else
614
for
kk
,
vv
in
next
,
v
do
615
if
type
(
vv
)
=
=
"
table
"
then
616
if
next
(
vv
)
then
617
rk
[
kk
]
=
vv
618
end
619
elseif
vv
~
=
"
"
then
620
rk
[
kk
]
=
vv
621
end
622
end
623
end
624
end
625
end
626
end
627
end
628
end
629 630
registers
.
store
=
storeregister
631
registers
.
enhance
=
enhanceregister
632
registers
.
extend
=
extendregister
633 634
function
registers
.
get
(
tag
,
n
)
635
local
list
=
tobesaved
[
tag
]
636
return
list
and
list
.
entries
[
n
]
637
end
638 639
implement
{
640
name
=
"
enhanceregister
"
,
641
arguments
=
{
"
string
"
,
"
integer
"
}
,
642
actions
=
function
(
name
,
n
)
643
enhanceregister
{
name
=
name
,
n
=
n
}
-- todo: move to scanner
644
end
,
645
}
646 647
implement
{
648
name
=
"
deferredenhanceregister
"
,
649
arguments
=
{
"
string
"
,
"
integer
"
}
,
650
protected
=
true
,
651
actions
=
function
(
name
,
n
)
652
ctx_latelua
{
action
=
enhanceregister
,
name
=
name
,
n
=
n
}
653
end
,
654
}
655 656
implement
{
657
name
=
"
extendregister
"
,
658
actions
=
extendregister
,
659
arguments
=
"
2 strings
"
,
660
}
661 662
implement
{
663
name
=
"
storeregister
"
,
664
-- actions = function(rawdata)
665
-- local nofentries = storeregister(rawdata)
666
-- setinternalreference { internal = rawdata.references.internal }
667
-- context(nofentries)
668
-- end,
669
actions
=
{
storeregister
,
context
}
,
670
arguments
=
{
671
{
672
{
"
metadata
"
,
{
673
{
"
kind
"
}
,
674
{
"
name
"
}
,
675
{
"
coding
"
}
,
676
{
"
level
"
,
"
integer
"
}
,
677
{
"
catcodes
"
,
"
integer
"
}
,
678
{
"
own
"
}
,
679
{
"
xmlroot
"
}
,
680
{
"
xmlsetup
"
}
681
}
682
}
,
683
{
"
entries
"
,
{
684
{
"
entries
"
,
"
list
"
}
,
685
{
"
keys
"
,
"
list
"
}
,
686
{
"
entry
"
}
,
687
{
"
key
"
}
688
}
689
}
,
690
{
"
references
"
,
{
691
{
"
internal
"
,
"
integer
"
}
,
692
{
"
section
"
,
"
integer
"
}
,
693
{
"
view
"
}
,
694
{
"
label
"
}
695
}
696
}
,
697
{
"
seeword
"
,
{
698
{
"
text
"
}
699
}
700
}
,
701
{
"
processors
"
,
{
702
{
"
entry
"
}
,
703
{
"
key
"
}
,
704
{
"
page
"
}
705
}
706
}
,
707
{
"
userdata
"
}
,
708
}
709
}
710
}
711 712
-- sorting and rendering
713 714
local
compare
=
sorters
.
comparers
.
basic
715 716
function
registers
.
compare
(
a
,
b
)
717
local
result
=
compare
(
a
,
b
)
718
if
result
~
=
0
then
719
return
result
720
else
721
local
ka
=
a
.
metadata
.
kind
722
local
kb
=
b
.
metadata
.
kind
723
if
ka
=
=
kb
then
724
local
ra
=
a
.
references
725
local
rb
=
b
.
references
726
local
pa
=
ra
.
realpage
727
local
pb
=
rb
.
realpage
728
if
not
pa
or
not
pb
then
729
return
0
730
elseif
pa
<
pb
then
731
return
-1
732
elseif
pa
>
pb
then
733
return
1
734
else
735
-- new, we need to pick the right one of multiple and
736
-- we want to prevent oscillation in the tuc file so:
737
local
ia
=
ra
.
internal
738
local
ib
=
rb
.
internal
739
if
not
ia
or
not
ib
then
740
return
0
741
elseif
ia
<
ib
then
742
return
-1
743
elseif
ia
>
ib
then
744
return
1
745
else
746
return
0
747
end
748
end
749
elseif
ka
=
=
"
see
"
then
750
return
1
751
elseif
kb
=
=
"
see
"
then
752
return
-1
753
end
754
end
755
return
0
756
end
757 758
function
registers
.
filter
(
data
,
options
)
759
data
.
result
=
registers
.
filtercollected
(
nil
,
options
.
criterium
,
options
.
number
,
data
.
entries
,
true
)
760
end
761 762
local
seeindex
=
0
763 764
-- meerdere loops, seewords, dan words, anders seewords
765 766
-- todo: split seeword
767 768
local
function
crosslinkseewords
(
result
,
check
)
-- all words
769
-- collect all seewords
770
local
seewords
=
{
}
771
for
i
=
1
,
#
result
do
772
local
data
=
result
[
i
]
773
local
seeword
=
data
.
seeword
774
if
seeword
then
775
local
seetext
=
seeword
.
text
776
if
seetext
and
not
seewords
[
seetext
]
then
777
seeindex
=
seeindex
+
1
778
seewords
[
seetext
]
=
seeindex
779
if
trace_registers
then
780
report_registers
(
"
see word %03i: %s
"
,
seeindex
,
seetext
)
781
end
782
end
783
end
784
end
785 786
-- mark seeparents
787 788
-- local seeparents = { }
789
-- for i=1,#result do
790
-- local data = result[i]
791
-- local word = data.list[1]
792
-- local okay = word and word[1]
793
-- if okay then
794
-- local seeindex = seewords[okay]
795
-- if seeindex then
796
-- seeparents[okay] = data
797
-- data.references.seeparent = seeindex
798
-- if trace_registers then
799
-- report_registers("see parent %03i: %s",seeindex,okay)
800
-- end
801
-- end
802
-- end
803
-- end
804 805
local
entries
=
{
}
806
local
keywords
=
{
}
807
local
seeparents
=
{
}
808
for
i
=
1
,
#
result
do
809
local
data
=
result
[
i
]
810
local
word
=
data
.
list
811
local
size
=
#
word
812
if
data
.
seeword
then
813
-- beware: a seeword has an extra entry for sorting purposes
814
size
=
size
-
1
815
end
816
for
i
=
1
,
size
do
817
local
w
=
word
[
i
]
818
local
e
=
w
[
1
]
819
local
k
=
w
[
2
]
or
e
820
entries
[
i
]
=
e
821
keywords
[
i
]
=
k
822
end
823
-- first try the keys
824
local
okay
,
seeindex
825
for
n
=
size
,
1
,
-1
do
826
okay
=
concat
(
keywords
,
"
+
"
,
1
,
n
)
827
seeindex
=
seewords
[
okay
]
828
-- first try the entries
829
if
seeindex
then
830
break
831
end
832
okay
=
concat
(
entries
,
"
+
"
,
1
,
n
)
833
seeindex
=
seewords
[
okay
]
834
if
seeindex
then
835
break
836
end
837
end
838
if
seeindex
then
839
seeparents
[
okay
]
=
data
840
data
.
references
.
seeparent
=
seeindex
841
if
trace_registers
then
842
report_registers
(
"
see parent %03i: %s
"
,
seeindex
,
okay
)
843
end
844
end
845
end
846 847
-- mark seewords and extend sort list
848
for
i
=
1
,
#
result
do
849
local
data
=
result
[
i
]
850
local
seeword
=
data
.
seeword
851
if
seeword
then
852
local
text
=
seeword
.
text
853
if
text
then
854
local
seeparent
=
seeparents
[
text
]
855
if
seeparent
then
856
local
seeindex
=
seewords
[
text
]
857
data
.
references
.
seeindex
=
seeindex
858
if
trace_registers
then
859
report_registers
(
"
see crosslink %03i: %s
"
,
seeindex
,
text
)
860
end
861
seeword
.
valid
=
true
862
elseif
check
then
863
report_registers
(
"
invalid crosslink : %s, %s
"
,
text
,
"
ignored
"
)
864
seeword
.
valid
=
false
865
else
866
report_registers
(
"
invalid crosslink : %s, %s
"
,
text
,
"
passed
"
)
867
seeword
.
valid
=
true
868
end
869
end
870
end
871
end
872
end
873 874
local
function
removeemptyentries
(
result
)
875
local
i
,
n
,
m
=
1
,
#
result
,
0
876
while
i
<
=
n
do
877
local
entry
=
result
[
i
]
878
if
#
entry
.
list
=
=
0
or
#
entry
.
split
=
=
0
then
879
remove
(
result
,
i
)
880
n
=
n
-
1
881
m
=
m
+
1
882
else
883
i
=
i
+
1
884
end
885
end
886
if
m
>
0
then
887
report_registers
(
"
%s empty entries removed in register
"
,
m
)
888
end
889
end
890 891
function
registers
.
prepare
(
data
,
options
)
892
-- data has 'list' table
893
local
strip
=
sorters
.
strip
894
local
splitter
=
sorters
.
splitters
.
utf
895
local
result
=
data
.
result
896
if
result
then
897
local
seeprefix
=
char
(
0
)
898
for
i
=
1
,
#
result
do
899
local
entry
=
result
[
i
]
900
local
split
=
{
}
901
local
list
=
entry
.
list
902
if
list
then
903
if
entry
.
seeword
then
904
-- we can have multiple seewords, only two levels supported
905
list
[
#
list
+
1
]
=
{
seeprefix
.
.
strip
(
entry
.
seeword
.
text
)
}
906
end
907
for
l
=
1
,
#
list
do
908
local
ll
=
list
[
l
]
909
local
word
=
ll
[
1
]
910
local
key
=
ll
[
2
]
911
if
not
key
or
key
=
=
"
"
then
912
key
=
word
913
end
914
split
[
l
]
=
splitter
(
strip
(
key
)
)
915
end
916
end
917
entry
.
split
=
split
918
end
919
removeemptyentries
(
result
)
920
crosslinkseewords
(
result
,
options
.
check
~
=
v_no
)
921
end
922
end
923 924
function
registers
.
sort
(
data
,
options
)
925
-- if options.pagenumber == false then
926
-- sorters.sort(data.result,compare)
927
-- else
928
sorters
.
sort
(
data
.
result
,
registers
.
compare
)
929
-- end
930
end
931 932
function
registers
.
unique
(
data
,
options
)
933
local
result
=
{
}
934
local
nofresult
=
0
935
local
prev
=
nil
936
local
dataresult
=
data
.
result
937
local
bysection
=
options
.
pagemethod
=
=
v_section
-- normally page
938
for
k
=
1
,
#
dataresult
do
939
local
v
=
dataresult
[
k
]
940
if
prev
then
941
local
vr
=
v
.
references
942
local
pr
=
prev
.
references
943
if
not
equal
(
prev
.
list
,
v
.
list
)
then
944
-- ok
945
elseif
bysection
and
vr
.
section
=
=
pr
.
section
then
946
v
=
nil
947
-- ok
948
elseif
pr
.
realpage
~
=
vr
.
realpage
then
949
-- ok
950
else
951
local
pl
=
pr
.
lastrealpage
952
local
vl
=
vr
.
lastrealpage
953
if
pl
or
vl
then
954
if
not
vl
then
955
-- ok
956
elseif
not
pl
then
957
-- ok
958
elseif
pl
~
=
vl
then
959
-- ok
960
else
961
v
=
nil
962
end
963
else
964
v
=
nil
965
end
966
end
967
end
968
if
v
then
969
nofresult
=
nofresult
+
1
970
result
[
nofresult
]
=
v
971
prev
=
v
972
end
973
end
974
data
.
result
=
result
975
end
976 977
function
registers
.
finalize
(
data
,
options
)
-- maps character to index (order)
978
local
result
=
data
.
result
979
data
.
metadata
.
nofsorted
=
#
result
980
local
split
=
{
}
981
local
nofsplit
=
0
982
local
lasttag
=
nil
983
local
done
=
nil
984
local
nofdone
=
0
985
local
firstofsplit
=
sorters
.
firstofsplit
986
for
k
=
1
,
#
result
do
987
local
v
=
result
[
k
]
988
local
entry
,
tag
=
firstofsplit
(
v
)
989
if
tag
~
=
lasttag
then
990
if
trace_registers
then
991
report_registers
(
"
splitting at %a
"
,
tag
)
992
end
993
done
=
{
}
994
nofdone
=
0
995
nofsplit
=
nofsplit
+
1
996
lasttag
=
tag
997
split
[
nofsplit
]
=
{
tag
=
tag
,
data
=
done
}
998
end
999
nofdone
=
nofdone
+
1
1000
done
[
nofdone
]
=
v
1001
end
1002
data
.
result
=
split
1003
end
1004 1005
-- local function analyzeregister(class,options)
1006
-- local data = collected[class]
1007
-- if data and data.entries then
1008
-- options = options or { }
1009
-- sorters.setlanguage(options.language,options.method,options.numberorder)
1010
-- registers.filter(data,options) -- filter entries into results (criteria)
1011
-- registers.prepare(data,options) -- adds split table parallel to list table
1012
-- registers.sort(data,options) -- sorts results
1013
-- registers.unique(data,options) -- get rid of duplicates
1014
-- registers.finalize(data,options) -- split result in ranges
1015
-- data.metadata.sorted = true
1016
-- return data.metadata.nofsorted or 0
1017
-- else
1018
-- return 0
1019
-- end
1020
-- end
1021 1022
local
function
analyzeregister
(
class
,
options
)
1023
local
data
=
rawget
(
collected
,
class
)
1024
if
not
data
then
1025
local
list
=
utilities
.
parsers
.
settings_to_array
(
class
)
1026
local
entries
=
{
}
1027
local
metadata
=
false
1028
for
i
=
1
,
#
list
do
1029
local
l
=
list
[
i
]
1030
local
d
=
collected
[
l
]
1031
local
e
=
d
.
entries
1032
for
i
=
1
,
#
e
do
1033
entries
[
#
entries
+
1
]
=
e
[
i
]
1034
end
1035
if
not
metadata
then
1036
metadata
=
d
.
metadata
1037
end
1038
end
1039
data
=
{
1040
metadata
=
metadata
or
{
}
,
1041
entries
=
entries
,
1042
}
1043
collected
[
class
]
=
data
1044
end
1045
if
data
and
data
.
entries
then
1046
options
=
options
or
{
}
1047
sorters
.
setlanguage
(
options
.
language
,
options
.
method
,
options
.
numberorder
)
1048
registers
.
filter
(
data
,
options
)
-- filter entries into results (criteria)
1049
registers
.
prepare
(
data
,
options
)
-- adds split table parallel to list table
1050
registers
.
sort
(
data
,
options
)
-- sorts results
1051
registers
.
unique
(
data
,
options
)
-- get rid of duplicates
1052
registers
.
finalize
(
data
,
options
)
-- split result in ranges
1053
data
.
metadata
.
sorted
=
true
1054
return
data
.
metadata
.
nofsorted
or
0
1055
else
1056
return
0
1057
end
1058
end
1059 1060
registers
.
analyze
=
analyzeregister
1061 1062
implement
{
1063
name
=
"
analyzeregister
"
,
1064
actions
=
{
analyzeregister
,
context
}
,
1065
arguments
=
{
1066
"
string
"
,
1067
{
1068
{
"
language
"
}
,
1069
{
"
method
"
}
,
1070
{
"
numberorder
"
}
,
1071
{
"
compress
"
}
,
1072
{
"
criterium
"
}
,
1073
{
"
pagenumber
"
,
"
boolean
"
}
,
1074
}
1075
}
1076
}
1077 1078
-- todo take conversion from index
1079 1080
function
registers
.
userdata
(
index
,
name
)
1081
local
data
=
references
.
internals
[
tonumber
(
index
)
]
1082
return
data
and
data
.
userdata
and
data
.
userdata
[
name
]
or
nil
1083
end
1084 1085
implement
{
1086
name
=
"
registeruserdata
"
,
1087
actions
=
{
registers
.
userdata
,
context
}
,
1088
arguments
=
{
"
integer
"
,
"
string
"
}
1089
}
1090 1091
-- todo: ownnumber
1092 1093
local
function
pagerange
(
f_entry
,
t_entry
,
is_last
,
prefixspec
,
pagespec
)
1094
local
fer
=
f_entry
.
references
1095
local
ter
=
t_entry
.
references
1096
ctx_registerpagerange
(
1097
f_entry
.
metadata
.
name
or
"
"
,
1098
f_entry
.
processors
and
f_entry
.
processors
[
2
]
or
"
"
,
1099
fer
.
internal
or
0
,
1100
fer
.
realpage
or
0
,
1101
function
(
)
1102
h_prefixpage
(
f_entry
,
prefixspec
,
pagespec
)
1103
end
,
1104
ter
.
internal
or
0
,
1105
ter
.
lastrealpage
or
ter
.
realpage
or
0
,
1106
function
(
)
1107
if
is_last
then
1108
h_prefixlastpage
(
t_entry
,
prefixspec
,
pagespec
)
-- swaps page and realpage keys
1109
else
1110
h_prefixpage
(
t_entry
,
prefixspec
,
pagespec
)
1111
end
1112
end
1113
)
1114
end
1115 1116
local
function
pagenumber
(
entry
,
prefixspec
,
pagespec
)
1117
local
er
=
entry
.
references
1118
ctx_registeronepage
(
1119
entry
.
metadata
.
name
or
"
"
,
1120
entry
.
processors
and
entry
.
processors
[
2
]
or
"
"
,
1121
er
.
internal
or
0
,
1122
er
.
realpage
or
0
,
1123
function
(
)
h_prefixpage
(
entry
,
prefixspec
,
pagespec
)
end
1124
)
1125
end
1126 1127
local
function
packed
(
f_entry
,
t_entry
)
1128
local
fer
=
f_entry
.
references
1129
local
ter
=
t_entry
.
references
1130
ctx_registerpacked
(
1131
fer
.
internal
or
0
,
1132
ter
.
internal
or
0
1133
)
1134
end
1135 1136
local
function
collapsedpage
(
pages
)
1137
for
i
=
2
,
#
pages
do
1138
local
first
=
pages
[
i
-1
]
1139
local
second
=
pages
[
i
]
1140
local
first_first
=
first
[
1
]
1141
local
first_last
=
first
[
2
]
1142
local
second_first
=
second
[
1
]
1143
local
second_last
=
second
[
2
]
1144
local
first_last_pn
=
first_last
.
references
.
realpage
1145
local
second_first_pn
=
second_first
.
references
.
realpage
1146
local
second_last_pn
=
second_last
.
references
.
realpage
1147
local
first_last_last
=
first_last
.
references
.
lastrealpage
1148
local
second_first_last
=
second_first
.
references
.
lastrealpage
1149
if
first_last_last
then
1150
first_last_pn
=
first_last_last
1151
if
second_first
=
=
second_last
and
second_first_pn
<
=
first_last_pn
then
1152
-- 2=8, 5 -> 12=8
1153
remove
(
pages
,
i
)
1154
return
true
1155
elseif
second_first
=
=
second_last
and
second_first_pn
>
first_last_pn
then
1156
-- 2=8, 9 -> 2-9
1157
pages
[
i
-1
]
=
{
first_first
,
second_last
}
1158
remove
(
pages
,
i
)
1159
return
true
1160
elseif
second_last_pn
<
first_last_pn
then
1161
-- 2=8, 3-4 -> 2=8
1162
remove
(
pages
,
i
)
1163
return
true
1164
elseif
first_last_pn
<
second_last_pn
then
1165
-- 2=8, 3-9 -> 2-9
1166
pages
[
i
-1
]
=
{
first_first
,
second_last
}
1167
remove
(
pages
,
i
)
1168
return
true
1169
elseif
first_last_pn
+
1
=
=
second_first_pn
and
second_last_pn
>
first_last_pn
then
1170
-- 2=8, 9-11 -> 2-11
1171
pages
[
i
-1
]
=
{
first_first
,
second_last
}
1172
remove
(
pages
,
i
)
1173
return
true
1174
elseif
second_first
.
references
.
lastrealpage
then
1175
-- 2=8, 9=11 -> 2-11
1176
pages
[
i
-1
]
=
{
first_first
,
second_last
}
1177
remove
(
pages
,
i
)
1178
return
true
1179
end
1180
elseif
second_first_last
then
1181
second_first_pn
=
second_first_last
1182
if
first_last_pn
=
=
second_first_pn
then
1183
-- 2-4, 5=9 -> 2-9
1184
pages
[
i
-1
]
=
{
first_first
,
second_last
}
1185
remove
(
pages
,
i
)
1186
return
true
1187
end
1188
elseif
first_last_pn
=
=
second_first_pn
then
1189
-- 2-3, 3-4 -> 2-4
1190
pages
[
i
-1
]
=
{
first_last
,
second_last
}
1191
remove
(
pages
,
i
)
1192
return
true
1193
end
1194
end
1195
return
false
1196
end
1197 1198
local
function
collapsepages
(
pages
)
1199
while
collapsedpage
(
pages
)
do
end
1200
return
#
pages
1201
end
1202 1203
-- todo: create an intermediate structure and flush that
1204 1205
function
registers
.
flush
(
data
,
options
,
prefixspec
,
pagespec
)
1206
local
compress
=
options
.
compress
1207
local
collapse_singles
=
compress
=
=
v_yes
1208
local
collapse_ranges
=
compress
=
=
v_all
1209
local
collapse_packed
=
compress
=
=
v_packed
1210
local
show_page_number
=
options
.
pagenumber
~
=
false
-- true or false
1211
local
bysection
=
options
.
pagemethod
=
=
v_section
1212
local
result
=
data
.
result
1213
local
maxlevel
=
0
1214
--
1215
for
i
=
1
,
#
result
do
1216
local
data
=
result
[
i
]
.
data
1217
for
d
=
1
,
#
data
do
1218
local
m
=
#
data
[
d
]
.
list
1219
if
m
>
maxlevel
then
1220
maxlevel
=
m
1221
end
1222
end
1223
end
1224
if
maxlevel
>
absmaxlevel
then
1225
maxlevel
=
absmaxlevel
1226
report_registers
(
"
limiting level to %a
"
,
maxlevel
)
1227
end
1228
--
1229
ctx_startregisteroutput
(
)
1230
local
done
=
{
}
1231
local
started
=
false
1232
for
i
=
1
,
#
result
do
1233
-- ranges need checking !
1234
local
sublist
=
result
[
i
]
1235
-- local done = { false, false, false, false }
1236
for
i
=
1
,
maxlevel
do
1237
done
[
i
]
=
false
1238
end
1239
local
data
=
sublist
.
data
1240
local
d
=
0
1241
local
n
=
0
1242
ctx_startregistersection
(
sublist
.
tag
)
1243
for
d
=
1
,
#
data
do
1244
local
entry
=
data
[
d
]
1245
if
entry
.
metadata
.
kind
=
=
"
see
"
then
1246
local
list
=
entry
.
list
1247
if
#
list
>
1
then
1248
list
[
#
list
]
=
nil
1249
else
1250
-- we have an \seeindex{Foo}{Bar} without Foo being defined anywhere .. somehow this message is wrong
1251
-- report_registers("invalid see entry in register %a, reference %a",entry.metadata.name,list[1][1])
1252
end
1253
end
1254
end
1255
-- ok, this is tricky: we use e[i] delayed so we need it to be local
1256
-- but we don't want to allocate too many entries so there we go
1257 1258
while
d
<
#
data
do
1259
d
=
d
+
1
1260
local
entry
=
data
[
d
]
1261
local
metadata
=
entry
.
metadata
1262
local
kind
=
metadata
.
kind
1263
local
list
=
entry
.
list
1264
local
e
=
{
false
,
false
,
false
}
1265
for
i
=
3
,
maxlevel
do
1266
e
[
i
]
=
false
1267
end
1268
for
i
=
1
,
maxlevel
do
1269
if
list
[
i
]
then
1270
e
[
i
]
=
list
[
i
]
[
1
]
1271
end
1272
if
e
[
i
]
=
=
done
[
i
]
then
1273
-- skip
1274
elseif
not
e
[
i
]
then
1275
-- see ends up here
1276
-- can't happen any more
1277
done
[
i
]
=
false
1278
for
j
=
i
+
1
,
maxlevel
do
1279
done
[
j
]
=
false
1280
end
1281
elseif
e
[
i
]
=
=
"
"
then
1282
done
[
i
]
=
false
1283
for
j
=
i
+
1
,
maxlevel
do
1284
done
[
j
]
=
false
1285
end
1286
else
1287
done
[
i
]
=
e
[
i
]
1288
for
j
=
i
+
1
,
maxlevel
do
1289
done
[
j
]
=
false
1290
end
1291
if
started
then
1292
ctx_stopregisterentry
(
)
1293
started
=
false
1294
end
1295
if
n
=
=
i
then
1296
-- ctx_stopregisterentries()
1297
-- ctx_startregisterentries(n)
1298
else
1299
while
n
>
i
do
1300
n
=
n
-
1
1301
ctx_stopregisterentries
(
)
1302
end
1303
while
n
<
i
do
1304
n
=
n
+
1
1305
ctx_startregisterentries
(
n
)
1306
end
1307
end
1308
local
references
=
entry
.
references
1309
local
processors
=
entry
.
processors
1310
local
internal
=
references
.
internal
or
0
1311
local
seeparent
=
references
.
seeparent
or
"
"
1312
local
processor
=
processors
and
processors
[
1
]
or
"
"
1313
-- so, we need to keep e as is (local), or we need local title = e[i] ... which might be
1314
-- more of a problem
1315
ctx_startregisterentry
(
0
)
-- will become a counter
1316
started
=
true
1317
if
metadata
then
1318
ctx_registerentry
(
metadata
.
name
or
"
"
,
processor
,
internal
,
seeparent
,
function
(
)
h_title
(
e
[
i
]
,
metadata
)
end
)
1319
else
1320
-- can this happen?
1321
ctx_registerentry
(
"
"
,
processor
,
internal
,
seeindex
,
e
[
i
]
)
1322
end
1323
end
1324
end
1325 1326
local
function
case_1
(
)
1327
-- we collapse ranges and keep existing ranges as they are
1328
-- so we get prebuilt as well as built ranges
1329
local
first
,
last
,
prev
,
pages
,
dd
,
nofpages
=
entry
,
nil
,
entry
,
{
}
,
d
,
0
1330
while
dd
<
#
data
do
1331
dd
=
dd
+
1
1332
local
next
=
data
[
dd
]
1333
if
next
and
next
.
metadata
.
kind
=
=
"
see
"
then
1334
dd
=
dd
-
1
1335
break
1336
else
1337
local
el
,
nl
=
entry
.
list
,
next
.
list
1338
if
not
equal
(
el
,
nl
)
then
1339
dd
=
dd
-
1
1340
--~ first = nil
1341
break
1342
elseif
next
.
references
.
lastrealpage
then
1343
nofpages
=
nofpages
+
1
1344
pages
[
nofpages
]
=
first
and
{
first
,
last
or
first
}
or
{
entry
,
entry
}
1345
nofpages
=
nofpages
+
1
1346
pages
[
nofpages
]
=
{
next
,
next
}
1347
first
,
last
,
prev
=
nil
,
nil
,
nil
1348
elseif
not
first
then
1349
first
,
prev
=
next
,
next
1350
elseif
next
.
references
.
realpage
-
prev
.
references
.
realpage
=
=
1
then
-- 1 ?
1351
last
,
prev
=
next
,
next
1352
else
1353
nofpages
=
nofpages
+
1
1354
pages
[
nofpages
]
=
{
first
,
last
or
first
}
1355
first
,
last
,
prev
=
next
,
nil
,
next
1356
end
1357
end
1358
end
1359
if
first
then
1360
nofpages
=
nofpages
+
1
1361
pages
[
nofpages
]
=
{
first
,
last
or
first
}
1362
end
1363
if
collapse_ranges
and
nofpages
>
1
then
1364
nofpages
=
collapsepages
(
pages
)
1365
end
1366
if
nofpages
>
0
then
-- or 0
1367
d
=
dd
1368
for
p
=
1
,
nofpages
do
1369
local
first
,
last
=
pages
[
p
]
[
1
]
,
pages
[
p
]
[
2
]
1370
if
first
=
=
last
then
1371
if
first
.
references
.
lastrealpage
then
1372
pagerange
(
first
,
first
,
true
,
prefixspec
,
pagespec
)
1373
else
1374
pagenumber
(
first
,
prefixspec
,
pagespec
)
1375
end
1376
elseif
last
.
references
.
lastrealpage
then
1377
pagerange
(
first
,
last
,
true
,
prefixspec
,
pagespec
)
1378
else
1379
pagerange
(
first
,
last
,
false
,
prefixspec
,
pagespec
)
1380
end
1381
end
1382
elseif
entry
.
references
.
lastrealpage
then
1383
pagerange
(
entry
,
entry
,
true
,
prefixspec
,
pagespec
)
1384
else
1385
pagenumber
(
entry
,
prefixspec
,
pagespec
)
1386
end
1387
end
1388 1389
local
function
case_2
(
)
1390
local
first
=
nil
1391
local
last
=
nil
1392
while
true
do
1393
if
not
first
then
1394
first
=
entry
1395
end
1396
last
=
entry
1397
if
d
=
=
#
data
then
1398
break
1399
else
1400
d
=
d
+
1
1401
local
next
=
data
[
d
]
1402
if
next
.
metadata
.
kind
=
=
"
see
"
or
not
equal
(
entry
.
list
,
next
.
list
)
then
1403
d
=
d
-
1
1404
break
1405
else
1406
entry
=
next
1407
end
1408
end
1409
end
1410
packed
(
first
,
last
)
-- returns internals
1411
end
1412 1413
local
function
case_3
(
)
1414
while
true
do
1415
if
entry
.
references
.
lastrealpage
then
1416
pagerange
(
entry
,
entry
,
true
,
prefixspec
,
pagespec
)
1417
else
1418
pagenumber
(
entry
,
prefixspec
,
pagespec
)
1419
end
1420
if
d
=
=
#
data
then
1421
break
1422
else
1423
d
=
d
+
1
1424
local
next
=
data
[
d
]
1425
if
next
.
metadata
.
kind
=
=
"
see
"
or
not
equal
(
entry
.
list
,
next
.
list
)
then
1426
d
=
d
-
1
1427
break
1428
else
1429
entry
=
next
1430
end
1431
end
1432
end
1433
end
1434 1435
local
function
case_4
(
)
1436
local
t
=
{
}
1437
local
nt
=
0
1438
while
true
do
1439
if
entry
.
seeword
and
entry
.
seeword
.
valid
then
1440
nt
=
nt
+
1
1441
t
[
nt
]
=
entry
1442
end
1443
if
d
=
=
#
data
then
1444
break
1445
else
1446
d
=
d
+
1
1447
local
next
=
data
[
d
]
1448
if
next
.
metadata
.
kind
~
=
"
see
"
or
not
equal
(
entry
.
list
,
next
.
list
)
then
1449
d
=
d
-
1
1450
break
1451
else
1452
entry
=
next
1453
end
1454
end
1455
end
1456
for
i
=
1
,
nt
do
1457
local
entry
=
t
[
i
]
1458
local
seeword
=
entry
.
seeword
1459
local
seetext
=
seeword
.
text
or
"
"
1460
local
processor
=
seeword
.
processor
or
(
entry
.
processors
and
entry
.
processors
[
1
]
)
or
"
"
1461
local
seeindex
=
entry
.
references
.
seeindex
or
"
"
1462
ctx_registerseeword
(
1463
metadata
.
name
or
"
"
,
1464
i
,
1465
nt
,
1466
processor
,
1467
0
,
1468
seeindex
,
1469
function
(
)
h_title
(
seetext
,
metadata
)
end
1470
)
1471
end
1472
end
1473 1474
local
function
case_5
(
)
1475
local
first
=
d
1476
while
true
do
1477
if
d
=
=
#
data
then
1478
break
1479
else
1480
d
=
d
+
1
1481
local
next
=
data
[
d
]
1482
if
next
.
metadata
.
kind
=
=
"
see
"
or
not
equal
(
entry
.
list
,
next
.
list
)
then
1483
d
=
d
-
1
1484
break
1485
else
1486
entry
=
next
1487
end
1488
end
1489
end
1490
local
last
=
d
1491
local
n
=
last
-
first
+
1
1492
local
i
=
0
1493
local
name
=
metadata
.
name
or
"
"
1494
local
processor
=
entry
.
processors
and
entry
.
processors
[
1
]
or
"
"
1495
for
e
=
first
,
last
do
1496
local
d
=
data
[
e
]
1497
local
sectionindex
=
d
.
references
.
internal
or
0
1498
i
=
i
+
1
1499
ctx_registersection
(
1500
name
,
1501
i
,
1502
n
,
1503
processor
,
1504
0
,
1505
sectionindex
,
1506
function
(
)
h_prefix
(
d
,
prefixspec
,
true
)
end
1507
)
1508
end
1509
end
1510 1511
if
kind
=
=
"
entry
"
then
1512
if
show_page_number
then
1513
ctx_startregisterpages
(
)
1514
if
bysection
then
1515
case_5
(
)
1516
elseif
collapse_singles
or
collapse_ranges
then
1517
case_1
(
)
1518
elseif
collapse_packed
then
1519
case_2
(
)
1520
else
1521
case_3
(
)
1522
end
1523
ctx_stopregisterpages
(
)
1524
end
1525
elseif
kind
=
=
"
see
"
then
1526
ctx_startregisterseewords
(
)
1527
case_4
(
)
1528
ctx_stopregisterseewords
(
)
1529
end
1530 1531
end
1532 1533
if
started
then
1534
ctx_stopregisterentry
(
)
1535
started
=
false
1536
end
1537
while
n
>
0
do
1538
ctx_stopregisterentries
(
)
1539
n
=
n
-
1
1540
end
1541
ctx_stopregistersection
(
)
1542
end
1543
ctx_stopregisteroutput
(
)
1544
-- for now, maybe at some point we will do a multipass or so
1545
data
.
result
=
nil
1546
data
.
metadata
.
sorted
=
false
1547
-- temp hack for luajittex :
1548
local
entries
=
data
.
entries
1549
for
i
=
1
,
#
entries
do
1550
entries
[
i
]
.
split
=
nil
1551
end
1552
-- collectgarbage("collect")
1553
end
1554 1555
function
registers
.
process
(
class
,
...
)
1556
if
analyzeregister
(
class
,
...
)
>
0
then
1557
local
data
=
collected
[
class
]
1558
registers
.
flush
(
data
,
...
)
1559
end
1560
end
1561 1562
implement
{
1563
name
=
"
processregister
"
,
1564
actions
=
registers
.
process
,
1565
arguments
=
{
1566
"
string
"
,
1567
{
1568
{
"
language
"
}
,
1569
{
"
method
"
}
,
1570
{
"
numberorder
"
}
,
1571
{
"
compress
"
}
,
1572
{
"
criterium
"
}
,
1573
{
"
check
"
}
,
1574
{
"
pagemethod
"
}
,
1575
{
"
pagenumber
"
,
"
boolean
"
}
,
1576
}
,
1577
{
1578
{
"
separatorset
"
}
,
1579
{
"
conversionset
"
}
,
1580
{
"
starter
"
}
,
1581
{
"
stopper
"
}
,
1582
{
"
set
"
}
,
1583
{
"
segments
"
}
,
1584
{
"
connector
"
}
,
1585
}
,
1586
{
1587
{
"
prefix
"
}
,
1588
{
"
separatorset
"
}
,
1589
{
"
conversionset
"
}
,
1590
{
"
starter
"
}
,
1591
{
"
stopper
"
}
,
1592
{
"
segments
"
}
,
1593
}
1594
}
1595
}
1596 1597
-- linked registers
1598 1599
function
registers
.
findinternal
(
tag
,
where
,
n
)
1600
-- local collected = registers.collected
1601
local
current
=
collected
[
tag
]
1602
if
not
current
then
1603
return
0
1604
end
1605
local
entries
=
current
.
entries
1606
if
not
entries
then
1607
return
0
1608
end
1609
local
entry
=
entries
[
n
]
1610
if
not
entry
then
1611
return
0
1612
end
1613
local
list
=
entry
.
list
1614
local
size
=
#
list
1615
--
1616
local
start
,
stop
,
step
1617
if
where
=
=
v_previous
then
1618
start
=
n
-
1
1619
stop
=
1
1620
step
=
-1
1621
elseif
where
=
=
v_first
then
1622
start
=
1
1623
stop
=
#
entries
1624
step
=
1
1625
elseif
where
=
=
v_last
then
1626
start
=
#
entries
1627
stop
=
1
1628
step
=
-1
1629
else
1630
start
=
n
+
1
1631
stop
=
#
entries
1632
step
=
1
1633
end
1634
--
1635
for
i
=
start
,
stop
,
step
do
1636
local
r
=
entries
[
i
]
1637
local
l
=
r
.
list
1638
local
s
=
#
l
1639
if
s
=
=
size
then
1640
local
ok
=
true
1641
for
i
=
1
,
size
do
1642
if
list
[
i
]
[
1
]
~
=
l
[
i
]
[
1
]
then
1643
ok
=
false
1644
break
1645
end
1646
end
1647
if
ok
then
1648
return
r
.
references
.
internal
or
0
1649
end
1650
end
1651
end
1652
return
0
1653
end
1654 1655
interfaces
.
implement
{
1656
name
=
"
findregisterinternal
"
,
1657
arguments
=
{
"
string
"
,
"
string
"
,
"
integer
"
}
,
1658
actions
=
{
registers
.
findinternal
,
context
}
,
1659
}
1660