\section{Disambiguating abbreviated chunk names}
This code disambiguates chunk names ending in [[...]].
If used, it belongs right after [[markup]] in the pipeline.

The first pass calls [[remember]] on each name {\em not} ending in dots.
For efficiency, I keep a table of sets indexed by the first character of the name.
<<*>>=
global chunknames

procedure remember(name)
  initial chunknames := table()
  if *name = 0 then fail
  /chunknames[name[1]] := set()
  insert(chunknames[name[1]], name)
  return
end
@ 

The second pass calls [[disambiguate]] on each name that {\em does} end in dots.
<<*>>=
procedure disambiguate(arg)
  local s
  if *arg = 0 then fail
  search := chunknames[arg[1]]
  if /search then fatal("Can't resolve ", arg, "...")
  every match(arg, n := !search) do 
    if /s then s := n
    else fatal("Ambiguous abbreviation: @<<", arg, "...@>> could denote\n\t@<<",
              s, "@>> or\n\t@<<", n, "@>>")
  if *s = 0 then fatal("Can't resolve ", arg, "...")
  return s
end
@ 
The 
<<*>>=
global lines, defns, uses, names, firstdefnout

procedure main(args)
  lines := []
  while put(lines, line := read()) do
    apply(pass1, line)
  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)
  initial chunknames := set()
  case name of {
    "defn" | "use" : 
      if chunkname[0-:3] ~== "..." then remember(chunkname)
  }
  return
end

procedure pass2(name, arg)
  case name of {
    "defn" | "use" : 
        if arg[0:-3] == "..." then arg := disambiguate(arg[1:-3])
  }
  write("@", name, (" " || \arg) | "")
  if name == "fatal" then exit(1)
  return
end
@ 
<<*>>=
procedure fatal(L[])
  write!(["@fatal disambiguate "] ||| L)
  write!([&errout, "noweb error in disambiguate: "] ||| L)
  exit(1)
end

<<*>>=
procedure rcsinfo () 
  return "$Id: disambiguate.nw,v 1.15 2006/06/12 21:03:54 nr Exp nr $" ||
         "$Name: v2_11b $"
end
@