\section{Cross-reference for noweb/latex} <<*>>= global lines, defns, uses, names, firstdefnout procedure main(args) lines := [] defns := table() uses := table() names := table() while put(lines, line := read()) do apply(pass1, line) firstdefnout := set() every apply(pass2, !lines) end procedure apply(pass, line) line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null)) end <<*>>= procedure pass1(name, chunkname) static curfile, defined initial {curfile := "????"; defined := set()} case name of { "file" : curfile := modid(chunkname || (chunkname[4+:3] | chunkname[4:0] | "")) "defn" | "use" : { if name == "defn" then tbl := defns else tbl := uses if name == "defn" & not member(defined, chunkname) then { label := "sublabel" insert(defined, chunkname) } else label := "label" /tbl[chunkname] := [] id := map(name, &lcase, &ucase) || ":" || curfile || ":" || modid(chunkname) || "-" || (1+*tbl[chunkname]) put(tbl[chunkname], id) put(lines, "@literal \\" || label || "{" || id || "}") names[chunkname] := lettersonly(chunkname) } } return end <<*>>= procedure modid(name) local key static idtable, keycounts initial { idtable := table() ; keycounts := table(0) } if not member(idtable, name) then { key := map(name, " \\{}-[]`#%&~_^", "**************") if *key > 6 then key := key[1:4] || key[0:-3] keycounts[key] +:= 1 idtable[name] := key || if keycounts[key] > 1 then "-" || keycounts[key] else "" } return idtable[name] end <<*>>= global thischunk procedure pass2(name, arg) case name of { "defn" : { thischunk := arg write("@defn ", arg, "~{\\footnotesize\\Rm\\subpageref{", defns[arg][1], "}}") } "use" : write("@use ", arg, "~{\\footnotesize\\Rm\\subpageref{", (\defns[arg])[1], "}}") | write("@use ", arg, "~{\\footnotesize\\Rm (never defined)}") "end" : { if match("code", arg) & not member(firstdefnout, thischunk) then { insert(firstdefnout, thischunk) if *defns[thischunk] > 1 then { writes("@literal \\alsodefined{") every i := 2 to *defns[thischunk] do writes("\\\\{", defns[thischunk][i], "}") write("}") } if \uses[thischunk] then { writes("@literal \\used{") every i := 1 to *uses[thischunk] do writes("\\\\{", uses[thischunk][i], "}") write("}") } else write("@literal \\notused{", escapeTeXspecials(thischunk), "}") } write("@", name, " ", arg) } "text" : if \arg == "\\nowebchunks" then nowebchunks() else write("@text", (" " || \arg) | "") default : write("@", name, (" " || \arg) | "") } return end <<*>>= procedure nowebchunks() l := sort(names,2) while name := get(l)[1] do { write("@literal {") write("@use ", name, "~{\\footnotesize\\Rm\\subpageref{", (\defns[name])[1], "}}") | write("@use ", name, "~{\\footnotesize\\Rm (never defined)}") write("@literal }") if *l > 0 then write("@literal \\\\") } end <<*>>= procedure lettersonly(s) static keep initial keep := &lcase ++ ' ' s := map(s) r := "" s ? while tab(upto(keep)) do r ||:= move(1) return r end <<*>>= procedure escapeTeXspecials(name) name ? { s := "" while s ||:= tab(upto('{}$&%#^_~\\')) do s ||:= "\\" || move(1) return s || tab(0) } end