summaryrefslogtreecommitdiff
path: root/web/noweb/src/icon/xchunks.icn
diff options
context:
space:
mode:
Diffstat (limited to 'web/noweb/src/icon/xchunks.icn')
-rw-r--r--web/noweb/src/icon/xchunks.icn142
1 files changed, 142 insertions, 0 deletions
diff --git a/web/noweb/src/icon/xchunks.icn b/web/noweb/src/icon/xchunks.icn
new file mode 100644
index 0000000000..cf1a74b20e
--- /dev/null
+++ b/web/noweb/src/icon/xchunks.icn
@@ -0,0 +1,142 @@
+#line 31 "xchunks.nw"
+record chunk(lines, type)
+ # lines is all the lines of the chunk
+ # type is "code" or "docs" or "unknown"
+
+procedure main(args)
+ local merge, summary
+ while args[1][1] == "-" do
+ case args[1] of {
+ "-merge" : merge := get(args)
+ "-summary" : { get(args); summary := " (summary)" }
+ default : break
+ }
+ *args > 0 | stop("xchunks needs an external database")
+
+
+#line 136 "xchunks.nw"
+db := "markup"
+every db ||:= " " || !args
+db := open(db, "rp") | stop("cannot pipe from ", image(db))
+
+#line 47 "xchunks.nw"
+ dbchunks := readchunks(db)
+ defns := defnstable(dbchunks)
+ # defns maps name to list of code chunks defining that name
+ if \merge then
+ every merge_chunks(!defns)
+ if \summary then
+ every add_defn_string(!defns, summary)
+
+ thisdoc := readchunks(&input)
+ every c := !thisdoc do
+ if c.type ~== "code" | notEmpty(c) | /defns[chunkName(c)] then
+ every write(!c.lines)
+ else {
+ write("@crc_prefix on")
+ every write(!(!defns[chunkName(c)]).lines)
+ write("@crc_prefix off")
+ }
+end
+#line 69 "xchunks.nw"
+procedure readchunks(infile)
+ local chunks, c
+ local file, lnum, lines, startline
+ chunks := []
+ lnum := 1
+ while line := read(infile) do
+ line ?
+ if ="@file " then {
+ file := tab(0)
+ lnum := 1
+ } else if ="@line " then {
+ lnum := integer(tab(0))
+ } else if ="@begin " then {
+ lines := []
+ put(lines, "@file " || \file)
+ put(lines, "@line " || lnum)
+ put(lines, line)
+ startline := line
+ c := chunk(lines, tab(upto(' ')|0))
+ line := read(infile) | stop("unmatched ", startline)
+ while line ? not ="@end " do {
+ put(c.lines, line)
+ line := read(infile) | stop("unmatched ", startline)
+ line ?
+ if ="@file " then { file := tab(0); lnum := 1 }
+ else if ="@line " then { lnum := integer(tab(0)) }
+ else if =("@nl"|"@index nl") & pos(0) then { lnum := lnum + 1 }
+ }
+ put(c.lines, line)
+ put(chunks, c)
+ } else {
+ put(chunks, chunk([line], "unknown"))
+ line ?
+ if ="@file " then { file := tab(0); lnum := 1 }
+ else if ="@line " then { lnum := integer(tab(0)) }
+ else if =("@nl"|"@index nl") & pos(0) then { lnum := lnum + 1 }
+ }
+ return chunks
+end
+#line 111 "xchunks.nw"
+procedure defnstable(chunks)
+ t := table()
+ every c := !chunks & c.type == "code" do {
+ /t[chunkName(c)] := []
+ put(t[chunkName(c)], c)
+ }
+ return t
+end
+#line 124 "xchunks.nw"
+procedure chunkName(c)
+ return (!c.lines ? (="@defn " & tab(0))) | stop("no @defn in code chunk")
+end
+
+procedure notEmpty(c)
+ static nonwhite
+ initial nonwhite := ~' \t'
+ return !c.lines ? ="@use " | (="@text ", upto(nonwhite))
+end
+#line 142 "xchunks.nw"
+procedure merge_chunks(chunks)
+ while *chunks > 1 do {
+ c := get(chunks)
+ strip_code_tail(c)
+ strip_code_head(chunks[1])
+ every put(c.lines, !chunks[1].lines)
+ chunks[1] := c
+ }
+ return chunks
+end
+#line 154 "xchunks.nw"
+procedure strip_code_tail(c)
+ if c.lines[-1] ? match("@end code") then
+ pull(c.lines)
+ else
+ stop("Unexpected line")
+ return c
+end
+
+procedure strip_code_head(c)
+ local pfx
+ pfx := []
+ if match("@begin code", c.lines[1]) then
+ get(c.lines)
+ else
+ stop("bad line " || c.lines[1])
+ while not match("@defn ", c.lines[1]) do
+ push(pfx, get(c.lines))
+ get(c.lines) | stop("this can't happen")
+ while c.lines[1] ~== "@nl" do
+ push(pfx, get(c.lines))
+ get(c.lines) | stop("this can't happen")
+ every push(c.lines, !pfx)
+ return c
+end
+#line 180 "xchunks.nw"
+procedure add_defn_string(chunks, s)
+ every c := !chunks & i := 1 to *c.lines do
+ if match("@defn ", c.lines[i]) then
+ c.lines[i] ||:= s
+ return chunks
+end