1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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
|
# This Icon program carries out the first phase of preparing the index for
# TeX for the Impatient. The input is the .idx file produced by TeX using
# our macros. The output should be piped through a sort and then to the
# index2 program.
#
# This program was written by Paul Abrahams and is public domain.
#
# An index entry has the form:
# term::type::page suffix
# where `term' is the index term, `type' is T, N, or C,
# `page' is either a folio number or *s, where s is a see-string,
# and `suffix' is either empty or P, E, B, PE, or PB.
# P indicates a principal entry, B and E begin and end a page range.
global printable, specials
record index_item(term, type, pages)
record pgrec(number, pflag)
procedure main(a)
local idx, fn, entry
fn := a[1]
printable := &ascii[33:-1]
specials := string(printable -- (&ucase ++ &lcase ++ &digits))
every entry := !&input do
write(key(entry), "@@@", entry)
write(&errout, "First indexing pass is complete.")
return
end
procedure key(entry)
local symb, symb1, type, page
static collate, hi, sortsequence
initial {
collate := specials || &ucase || &digits
sortsequence := printable -- &lcase
hi := repl(char(128), 26)
}
entry ? (symb := tab(find("::")), move(2), type := move(1),
move(2), page := tab(many('-0123456789*')))
symb := remove_leading_specials(symb)
symb1 := map(symb, &lcase, &ucase)
return map(map_term(symb1, type), collate, sortsequence) ||
map(symb, &ucase, hi) || char(1) || page_key(page)
end
procedure remove_leading_specials(s)
# remove leading period, backslash, or less-than
local a, b, c, k
static kills
initial {kills := '\\.<'}
# a one-character special is left unchanged
c := s[1:upto("//", s) | 0]
if *c = 1 & any(kills, c) then
return s
k := 1
while s ? (a := tab(k), b:= tab(upto(kills)),
tab(many(kills)), c := tab(0)) do
{s := a || b || c; k +:= *b}
return s
end
procedure map_term(t, c)
# t is an index term, c is "N", "T", or "C"
# Encode NTC as char(1), char(2), char(3)
# Replace each // by the NTC code, then follow t by the NTC code and 1
local code
code := char(find(c, "NTC") | 4)
while t[find("//", t)+:2] := code
return t || code || char(1)
end
procedure page_key(p)
# convert p, which may be negative, to a character string key
# Negative numbers must sort with the smallest closest to 0.
# A see-string always starts with *; we replace the * with ~
# so that see references always come last. (They are usually unique.)
if p == "*" then
return "~"
p := integer(p)
return (
if p < 0 then
"-" || right(-p, 4, "0")
else
right(p, 5, 0)
)
end
|