#!/bin/sh delay=0 anchordist=0 while [ $# -gt 0 ]; do case $1 in -delay) delay=1 ;; -docanchor) anchordist="$2"; shift ;; *) echo "This can't happen -- $1 passed to noidx" 1>&2 ; exit 1 ;; esac shift done nawk 'function insertafter(i, s, n) { for(n = nextline++; n - 1 > i; n--) lines[n] = lines[n-1] lines[n] = s } function slipin(s) { lines[nextline++] = s } function fill_charcode_table(i) { if (charcode_table[64]) return for (i = 0; i < 256; i++) { charcode_table[sprintf("%c", i)] = i } } function charcode(s, i) { fill_charcode_table() return charcode_table[substr(s, i, 1)] } function fill_crc_table(POLY, sum, i, j) { POLY = 245 * 4096 * 4096 if (crc_table[0]) { return } for (i = 0; i < 256; i ++) { sum = 0 for (j = 7; j >= 0; j -= 1) { if (and(i, lshift(1, j)) != 0) { sum = xor(sum, rshift(POLY, j)) } } crc_table[i] = sum } } function crc(s, sum, i) { fill_crc_table() sum = 0 for (i = 1; i <= length(s); i++) { sum = xor(rshift(sum, 8), crc_table[and(xor(sum, charcode(s, i)), 255)]) } return sum } function newdefnlabel(arg, label) { defcount[arg] = defcount[arg] + 1 label = "NW" curfile "-" uniqueid(arg) "-" alphacode(defcount[arg]) return label } function newdocslabel() { newdocslabelcount++ return "NWD" alphacode(newdocslabelcount) } function addlabel(tbl, arg, label, marker) { marker = " " label if (!tailmatch(tbl[arg], marker)) tbl[arg] = tbl[arg] marker return label } function tailmatch(string, tail, pos) { pos = length(string) - length(tail) + 1 if (pos > 0 && substr(string, pos) == tail) return 1 else return 0 } function addud(udlist, name, arg, label, s) { s = " " name "{" label "}" if (!tailmatch(udlist[arg], s)) udlist[arg] = udlist[arg] s } function listget(l, i, n, a) { n = split(l, a) return a[i] } function uniqueid(name, key) { if (uidtable[name] == "") { key = make_key(name) # gsub(/[\]\[ \\{}`#%&~_^<>"-]/, "*", key) # old gsub(/[^a-zA-Z0-9!$()*+,.\/:;=?@|]/, "*", key) keycounts[key] = keycounts[key] + 1 uidtable[name] = key if (keycounts[key] > 1) uidtable[name] = uidtable[name] "." alphacode(keycounts[key]) } return uidtable[name] } function old_make_key(name, key, l) { l = length(name) sub(/^.*\//, "", name) key = substr(name, 1, 3) if (l >= 3) key = key alphacode(l) return key } function make_key(name) { return alphacode(crc(name)) } function lognowebchunks(l, j, n, x) { if (loggednowebchunks > 0) return loggednowebchunks = 1 delete allchunks[0] n = alphasort(allchunks) print "@xref beginchunks" for (j = 0; j < n; j++) { name = sorted[j]; delete sorted[j] printf "@xref chunkbegin %s %s\n", (anchorlabel[name] != "" ? anchorlabel[name] : "nw@notdef"), name m = split(chunkud[name], a) for (k = 1; k <= m; k++) if (a[k] ~ /^use/) printf "@xref chunkuse %s\n", substr(a[k], 5, length(a[k])-5) else if (a[k] ~ /^defn/) printf "@xref chunkdefn %s\n", substr(a[k], 6, length(a[k])-6) print "@xref chunkend" } print "@xref endchunks" } function lognowebindex(l, j, n, x) { if (loggednowebindex > 0) return loggednowebindex = 1 delete allidents[0] n = alphasort(allidents) print "@index beginindex" for (j = 0; j < n; j++) { name = sorted[j]; delete sorted[j] printf "@index entrybegin %s %s\n", (indexanchorlabel[name] != "" ? indexanchorlabel[name] : "nw@notdef"), name m = split(indexud[name], a) for (k = 1; k <= m; k++) if (a[k] ~ /^use/) printf "@index entryuse %s\n", substr(a[k], 5, length(a[k])-5) else if (a[k] ~ /^defn/) printf "@index entrydefn %s\n", substr(a[k], 6, length(a[k])-6) print "@index entryend" } print "@index endindex" } function alphasort(a, x, n) { n = 0 for (x in a) n = insertitem(x, n) return n } function insertitem(x, n, i, tmp) { sorted[n] = x sortkeys[n] = sortkey(x) i = n while (i > 0 && (sortkeys[i] < sortkeys[i-1] || sortkeys[i] == sortkeys[i-1] && sorted[i] < sorted[i-1])) { tmp = sortkeys [i]; sortkeys [i] = sortkeys [i-1]; sortkeys [i-1] = tmp tmp = sorted[i]; sorted[i] = sorted[i-1]; sorted[i-1] = tmp i = i - 1 } return n + 1 } function sortkey(s) { return tolower(s) "\n" s # relies on \n sorting lower than other characters } function alphacode(n) { if (n < 0) return "-" alphacode(-n) else if (n >= alphacodelen) return alphacode(n / alphacodelen) alphacode(n % alphacodelen) else return substr(alphacodes, n+1, 1) } BEGIN { curfile = "standard input?" lastchunkbegin = "never any chunks?" ; allchunks[0] = 0 ; allidents[0] = 0 ; indexlabels[0] = 0 defanchors[0] = 0 ; uses[0] = 0 ; anchorlabel[0] = 0 ; indexanchorlabel[0] = 0 thesedefns[0] = 0; theseuses[0] = 0 ; defcount[0] = 0 ; udlist[0] = 0 ; uidtable[0] = 0 keycounts[0] = 0 ; sorted[0] = 0; sortkeys[0] = 0; alphacodes = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" alphacodelen = length(alphacodes) ; nextline = 0 } /^@file / { curfile = uniqueid(substr($0, 7)) } /^@begin / { lastchunkbegin = $0 } /^@end docs / { if (anchordist > 0) { n = anchordist lastanchorlabel = newdocslabel() for(i = nextline - 1; i >= 0; i--) { if (n == 0 || lines[i] ~ /^@begin docs /) { insertafter(i, "@xref label " lastanchorlabel) i = -1 # cause loop to terminate } else if (lines[i] == "@nl") { n-- } } } } /^@end code / { lastanchorlabel = "" } /^@defn / { arg = substr($0, 7) allchunks[arg] = 1 lastdefnlabel = newdefnlabel(arg) slipin("@xref label " lastdefnlabel) if (lastanchorlabel == "") lastanchorlabel = lastdefnlabel if (anchorlabel[arg] == "") anchorlabel[arg] = lastanchorlabel addlabel(defanchors, arg, lastanchorlabel) addud(chunkud, "defn", arg, lastanchorlabel) thisusecount = 0 } /^@use / { if (lastchunkbegin ~ /^@begin code /) { arg = substr($0, 6) allchunks[arg] = 1 slipin("@xref label " lastdefnlabel "-u" (++thisusecount)) addlabel(uses, arg, lastanchorlabel) addud(chunkud, "use", arg, lastanchorlabel) } } /^@index use / { arg = substr($0, 12) allidents[arg] = 1 if (lastanchorlabel != "") addud(indexud, "use", arg, lastanchorlabel) } /^@index defn / { arg = substr($0, 13) allidents[arg] = 1 if (lastanchorlabel != "") { l = lastanchorlabel } else { l = newdocslabel() slipin("@xref label " l) } addud(indexud, "defn", arg, l) if (indexanchorlabel[arg] == "") indexanchorlabel[arg] = l slipin("@xref ref " l) # bug fix } /^@index localdefn / { arg = substr($0, 18) allidents[arg] = 1 if (lastanchorlabel != "") { l = lastanchorlabel } else { l = newdocslabel() slipin("@xref label " l) } addud(indexud, "defn", arg, l) if (indexanchorlabel[arg] == "") indexanchorlabel[arg] = l slipin("@xref ref " l) # bug fix } { lines[nextline] = $0; nextline++ } END { for (i = 0; i < nextline; i ++) { line = lines[i] if (line ~ /^@begin /) { if (delay && lastchunkbegin == line) { print "@nl" print "@nl" lognowebchunks() lognowebindex() } print line for (x in thesedefns) delete thesedefns[x] for (x in theseuses) delete theseuses[x] thischunk = "" } else if (line ~ /^@defn /) { thischunk = substr(line, 7) printf "@xref ref %s\n", anchorlabel[thischunk] print line defout[thischunk]++ if (defout[thischunk] > 1) printf "@xref prevdef %s\n", listget(defanchors[thischunk], defout[thischunk]-1) if (defout[thischunk] < defcount[thischunk]) printf "@xref nextdef %s\n", listget(defanchors[thischunk], defout[thischunk]+1) if (defout[thischunk] == 1) {if (defcount[thischunk] > 1) { print "@xref begindefs" n = split(defanchors[thischunk], a) for (j = 2; j <= n; j++) printf "@xref defitem %s\n", a[j] print "@xref enddefs" } if (uses[thischunk] != "") { print "@xref beginuses" n = split(uses[thischunk], a) for (j = 1; j <= n; j++) printf "@xref useitem %s\n", a[j] print "@xref enduses" } else { printf "@xref notused %s\n", thischunk }} } else if (line ~ /^@use /) { arg = substr(line, 6) printf "@xref ref %s\n", (anchorlabel[arg] == "" ? "nw@notdef" : anchorlabel[arg]) print line } else if (line ~ /^@index defn /) { arg = substr(line, 13) thesedefns[arg] = 1 # no xref ref because of bug fix # if (indexanchorlabel[arg] != "") # printf "@xref ref %s\n", indexanchorlabel[arg] print line } else if (line ~ /^@index localdefn /) { arg = substr(line, 18) thesedefns[arg] = 1 # no xref ref because of bug fix # if (indexanchorlabel[arg] != "") # printf "@xref ref %s\n", indexanchorlabel[arg] print line } else if (line ~ /^@index use /) { arg = substr(line, 12) theseuses[arg] = 1 if (indexanchorlabel[arg] != "") printf "@xref ref %s\n", indexanchorlabel[arg] print line } else if (line ~ /^@end code/) { for (x in thesedefns) delete theseuses[x] delete thesedefns[0] n = alphasort(thesedefns) if (n > 0) { print "@index begindefs" for (j = 0; j < n; j++) { m = split(indexud[sorted[j]], a) for (k = 1; k <= m; k++) if (a[k] ~ /^use/) printf "@index isused %s\n", substr(a[k], 5, length(a[k])-5) printf "@index defitem %s\n", sorted[j] delete sorted[j] } print "@index enddefs" } delete theseuses[0] n = alphasort(theseuses) if (n > 0) { print "@index beginuses" for (j = 0; j < n; j++) { m = split(indexud[sorted[j]], a) for (k = 1; k <= m; k++) if (a[k] ~ /^defn/) printf "@index isdefined %s\n", substr(a[k], 6, length(a[k])-6) printf "@index useitem %s\n", sorted[j] delete sorted[j] } print "@index enduses" } print line } else if (line ~ /^@text /) { # grotesque hack to get indexes in HTML if (thischunk == "") { # docs mode arg = substr(line, 7) if (arg == "") lognowebchunks() else if (arg == "") lognowebindex() else print line } else { print line } } else { print line } delete lines[i] } if (!delay) { print "@nl" print "@nl" lognowebchunks() lognowebindex() } }' delay=$delay anchordist=$anchordist