# Copyright 1991 by Norman Ramsey.  All rights reserved.
# See file COPYRIGHT for more information.
procedure main(args)
  local delay, name
  text := 1
  useitemstab := table()
  defns := table("")
  TeXspecials := '\\{}$&#^_ ~%'
  delay := !args == "-delay"
  noindex := !args == "-noindex"
  while inputline := read() do inputline ? {
    if ="@text " then       { text +:= *(line := tab(0))
                              writes(if \quoting then TeXliteral(line)
                                     else if \code then escape(line, '{}\\')
                                     else line)                                      } else
if ="@nl" & pos(0) then { if /code then {if text = 0 then writes("\\nwdocspar")
                                         text := 1}
                          if \quoting then writes("\\nwnewline")
                          if \pendinguses | \pendingprev | \pendingnext then {
                            writes("\\nwstartdeflinemarkup")
                            if \pendinguses then {
                              dumpitems(useitems, "nwusesondefline")
                            }
                            if \pendingprev | \pendingnext then {
                              writes("\\nwprevnextdefs{", \pendingprev | "\\relax", "}{",
                                                          \pendingnext | "\\relax", "}")
                            }
                            writes("\\nwenddeflinemarkup")
                            pendinguses := pendingprev := pendingnext := &null
                          }
                          write()                                                } else
if ="@begin code " then { code := 1     ; writes("\\nwbegincode{", tab(0), "}")
                          every defitems | useitems := []
                          notused := &null                         } else
if ="@end code "   then { dumpitems(defitems, "nwalsodefined")
                          dumpitems(useitems, "nwused")
                          writes("\\nwnotused{", \notused, "}")
every defitems | useitems := []
notused := &null
                          code := &null ; writes("\\nwendcode{}")
                          lastdefnlabel := pendingprev := pendingnext := &null   } else
if ="@defn " then       { writes("\\sublabel{", \lastxreflabel, "}")
                          writes("\\nwmargintag{", label2tag(\lastxreflabel), "}")
                          writes("\\moddef{", convquotes(thischunk := tab(0)),
                                 ("~" || label2tag(\lastxrefref)) | "",
                                 "}\\", defns[thischunk], "endmoddef")
                          useitems := \useitemstab[thischunk]
                          pendinguses := 1
                          lastdefnlabel := lastxreflabel
                          every lastxreflabel | lastxrefref := &null
                          defns[thischunk] := "plus"                           } else
if ="@begin docs " then { if \delay & match(0) then &null
                          else {text := 0; writes("\\nwbegindocs{",tab(0),"}")}  } else
if ="@end docs " then   { if \delay & match(0) then { writes("\\nwfilename{", filename, "}"); delay := &null }
                          else writes("\\nwenddocs{}")                           } else
if ="@use " then        { writes("\\LA{}", convquotes(name := tab(0)),
                                 ("~" || label2tag(\lastxrefref)) | "",
                                 "\\RA{}")
                          every lastxreflabel | lastxrefref := &null                                } else
if ="@xref "               then { if ="label "               then { lastxreflabel := tab(0)                       } else
                                  if ="ref "                 then { lastxrefref   := tab(0)                       } else
                                  if ="begindefs"   & pos(0) then {                                               } else
                                  if ="defitem "             then { put(defitems, tab(0))                         } else
                                  if ="enddefs"     & pos(0) then {                                               } else
                                  if ="beginuses"   & pos(0) then { useitems := []                                } else
                                  if ="useitem "             then { put(useitems, tab(0))                         } else
                                  if ="enduses"     & pos(0) then { useitemstab[thischunk] := useitems            } else
                                  if ="notused "             then { notused := tab(0)                             } else
                                  if ="nextdef "             then { pendingnext := tab(0)                         } else
                                  if ="prevdef "             then { pendingprev := tab(0)                         } else
                                  if ="beginchunks" & pos(0) then {                                                 } else
                                  if ="chunkbegin "          then { label := tab(upto(' ')); =" "
                                                                    writes("\\nwixlogsorted{c}{{", convquotes(tab(0)),
                                                                        "}{", label, "}{")                          } else
                                  if ="chunkuse "            then { writes("\\nwixu{", tab(0), "}")                 } else
                                  if ="chunkdefn "           then { writes("\\nwixd{", tab(0), "}")                 } else
                                  if ="chunkend"    & pos(0) then { write("}}%")                                    } else
                                  if ="endchunks"   & pos(0) then {                                                 } else warn_unknown("xref " || tab(upto(' \t') | 0))                 } else
if ="@index "               then { if ="nl" & pos(0)          then        { write(if \code then "\\eatline" else "%")}else
                                   if =("defn "|"localdefn ") then /noindex & { writes("\\nosublabel{", \lastxreflabel, "}")
                                                                            writes("\\nwindexdefn{\\nwixident{", TeXliteral(name := tab(0)), "}}{", indexlabel(name), "}{",
                                                                                    \lastxrefref, "}")
every lastxreflabel | lastxrefref := &null                   } else
                                   if ="use "                 then /noindex & { if /code then {
                                                                              writes("\\protect\\nosublabel{", \lastxreflabel, "}")
                                                                              writes("\\protect\\nwindexuse{\\nwixident{", TeXliteral(name := tab(0)), "}}{",
                                                                                            indexlabel(name), "}{", \lastxrefref, "}")
                                                                            }
every lastxreflabel | lastxrefref := &null                    } else
                                   if ="begindefs" & pos(0) then /noindex & { dumpitems(defitems, "nwalsodefined")
                                                                          dumpitems(useitems, "nwused")
                                                                          writes("\\nwnotused{", \notused, "}")
every defitems | useitems := []
notused := &null
                                                                          writes("\\nwidentdefs{")                   } else
                                   if ="isused "            then /noindex & { "handled by latex"                         } else
                                   if ="defitem "           then /noindex & { i := tab(0); writes("\\\\{{\\nwixident{", TeXliteral(i), "}}{", indexlabel(i), "}}")   } else
                                   if ="enddefs"   & pos(0) then /noindex & { writes("}")                                } else
                                   if ="beginuses" & pos(0) then /noindex & { dumpitems(defitems, "nwalsodefined")
                                                                          dumpitems(useitems, "nwused")
                                                                          writes("\\nwnotused{", \notused, "}")
every defitems | useitems := []
notused := &null
                                                                          writes("\\nwidentuses{"); ulist := []      } else
                                   if ="isdefined "         then /noindex & { "latex finds the definitions"              } else
                                   if ="useitem "           then /noindex & { i := tab(0); writes("\\\\{{\\nwixident{", TeXliteral(i), "}}{", indexlabel(i), "}}")
                                                                           put(ulist, i);                            } else
                                   if ="enduses"   & pos(0) then /noindex & { writes("}"); every i := !ulist do
                                                                                         writes("\\nwindexuse{\\nwixident{", TeXliteral(i), "}}{", indexlabel(i), "}{", \lastdefnlabel, "}")           } else
                                   if ="beginindex"  & pos(0) then /noindex & {                                          } else
                                   if ="entrybegin "          then /noindex & { label := tab(upto(' ')); =" "; name := tab(0)
                                                                                                                    write("\\nwixlogsorted{i}{{\\nwixident{", TeXliteral(name),
                                                                                                                    "}}{", indexlabel(name), "}}%")                  } else
                                   if ="entryuse "            then /noindex & { "handled by latex"                       } else
                                   if ="entrydefn "           then /noindex & { "handled by latex"                       } else
                                   if ="entryend"    & pos(0) then /noindex & {                                          } else
                                   if ="endindex"    & pos(0) then /noindex & {                                          } else warn_unknown("index " || tab(upto(' \t') | 0))                } else
if ="@quote"    & pos(0)      then { quoting := 1     ; writes("{\\Tt{}")        } else
if ="@endquote" & pos(0)      then { quoting := &null ; writes("}")              } else
if ="@file "                  then { filename := tab(0); every lastxreflabel | lastxrefref := &null
                                     \delay | writes("\\nwfilename{", filename, "}")
                                                                                 } else
if ="@literal "               then { writes(tab(0))                              } else
if ="@header latex "          then { writes("\\documentstyle[noweb]{article}\\pagestyle{noweb}\\noweboptions{", tab(0),
                                            "}\\begin{document}")                   } else
if ="@header tex "            then { writes("\\input nwmac ")                    } else
if ="@trailer latex" & pos(0) then { write("\\end{document}")                    } else
if ="@trailer tex"   & pos(0) then { write("\\bye")                              } else
    if ="@" then                                            # follows last else
      warn_unknown(1(tab(upto(' ')|0), pos(0) | move(1)))
    else
      write(&errout, "Botched line in noweb pipeline: ", tab(0))
  }
  write()
end
procedure label2tag(label)
  return "{\\nwtagstyle{}\\subpageref{" || label || "}}"
end
procedure dumpitems(items, cs)
  if *\items > 0 then {
    writes("\\", cs, "{")
    every writes("\\\\{", !items, "}")
    writes("}")
    return
  } else
    fail
end
procedure escape(line, chars, prefix)
  /prefix := "\\"
  line ? {
    s := ""
    while s ||:= tab(upto(chars)) do s ||:= prefix || move(1)
    return s || tab(0)
  }
end
global TeXspecials
procedure TeXliteral(arg)
  static nospace, code
  initial { codes := ["\\", "nwbackslash",
                      "{", "nwlbrace",
                                          "}", "nwrbrace",
                                          "$", "$",
                                          "&", "&",
                                          "#", "#",
                                          "^", "char94",
                      "_", "_",
                                          "%", "%",
                                          "~", "char126"]
            code := table()
            while (c := get(codes), n := get(codes)) do code[c] := string(n)
            if c := !TeXspecials & c ~== " " & not member(code, c) then
              stop("internal error, character-code mismatch, report a bug!")
          }
  s := ""
  arg ? {
    while s ||:= tab(upto(TeXspecials)) do {
      c := move(1)
      if member(code, c) then
        s ||:= "{\\" || code[c] || "}"
      else
        s ||:= "\\" || c
    }
    return s || tab(0)
  }
end
procedure convquotes(s)
  r := ""
  s ? {
    while r ||:= tab(find("[[")) do {
      ="[[" | stop("impossible missing [[")
      r ||:= "\\code{}" || TeXliteral(tab(find("]]")))
      r ||:= tab(many(']')-2)
      ="]]" | stop("impossible missing ]]")
      r ||:= "\\edoc{}"
    }
    return r || tab(0)
  }
end
procedure warn_unknown(tag)
  static warned
  initial warned := set()
  if not member(warned, tag) then {
    write(&errout, "Warning: unrecognized escape @", tag, tab(0))
    insert(warned, tag)
  }
  return
end
procedure indexlabel(ident)
  static badset, trans
  initial {
    trans := table()
    trans[" "] := "sp"      # space
    trans["#"] := "has"     # hash
    trans["$"] := "do"      # dollar
    trans["%"] := "pe"      # percent
    trans["&"] := "am"      # ampersand
    trans[","] := "com"     # commad
    trans[":"] := "col"     # colon
    trans["\\"] := "bs"      # backslash
    trans["^"] := "hat"     # hat
    trans["_"] := "un"      # underscore
    trans["{"] := "lb"      # left brace
    trans["}"] := "rb"      # right brace
    trans["~"] := "ti"      # tilde
    badset := ''
    every badset ++:= key(trans)
  }
  ident ? {
    s := ""
    while s ||:= tab(upto(badset)) do s ||:= ":" || trans[move(1)]
    return s || tab(0)
  }
end
