\section{Weaving a {\tt noweb} file into a \TeX file}
The copyright applies both to the {\tt noweb} source and to the
generated shell script.
<<copyright notice>>=
# Copyright 1991-1997 by Norman Ramsey.  All rights reserved.
# See file COPYRIGHT for more information.
# $Id: noweave.nw,v 1.7 2008/10/06 01:03:24 nr Exp $
@
Here's the organization of the source:
<<noweave>>=
#!/bin/sh
<<copyright notice>>
<<initialization>>
<<scan options and arguments>>
<<emit markup on standard output>> |
                                $backend $noindex $delay $shortxref
exit $?
<<if verbose, show back end>>=
if [ -n "$verbose" ]; then echo $backend $noindex $delay $shortxref 1>&2; fi
@
The first item of initialization is to locate the {\tt noweb} library.
<<initialization>>= 
LIB=|LIBDIR|
@
<<initialization>>=
markup=$LIB/markup backend=$LIB/totex
wrapper= delay= args= markopts= noweboptions= autodefs= verbose= shortxref=
noquote="-noquote" docanchor= noindex="-noindex"
filtera= filterb= filterc= filterd= filtere= filterf= filterg=
# following supported by change in totex back end
noquote=
@
I make two passes over the arguments so as not to require that options
be given in a certain order
<<scan options and arguments>>=
pass2setcmd="set ignore"
for i do
  pass2setcmd="$pass2setcmd '$i'"
done
arg=
while [ $# -gt 0 ]; do
  case $1 in
    <<first pass {\tt noweave} options>>
    -)  arg="$arg $1" ;;
    -*) echo "$0: Unrecognized option '$1'" 1>&2 ; <<show usage>>; exit 1 ;;
    *)  arg="$arg $1" ;;
  esac
  shift
done
<<insist first-pass options are self-consistent>>
if [ -z "$wrapper" ]; then wrapper=latex; fi
eval $pass2setcmd
shift
while [ $# -gt 0 ]; do
  case $1 in
    <<second pass {\tt noweave} options>>
  esac
  shift
done
<<old scan options and arguments>>=
pass2args="$*"
while [ $# -gt 0 ]; do
  case $1 in
    <<first pass {\tt noweave} options>>
    -*) echo "$0: Unrecognized option '$1'" 1>&2 ; <<show usage>>; exit 1 ;;
    *)  arg="$arg $1" ;;
  esac
  shift
done
if [ -z "$wrapper" ]; then wrapper=latex; fi
if [ -n "$pass2args" ]; then
  set ignoreme $pass2args
  shift
  while [ $# -gt 0 ]; do
    case $1 in
      <<second pass {\tt noweave} options>>
    esac
    shift
  done
fi
<<add [[$newopt]] to [[noweboptions]]>>=
if [ -z "$noweboptions" ] ; then noweboptions="$newopt"
else noweboptions="$noweboptions,$newopt"
fi
<<first pass {\tt noweave} options>>=
-latex)      if [ "$wrapper" != "none" ]; then wrapper=latex; fi ;;
-tex)        wrapper=tex ;;
-html)       if [ "$wrapper" != "none" ]; then wrapper=html; fi; 
             backend="$LIB/tohtml -localindex"
             noquote=""; docanchor="-docanchor 10" ;;
-latex+html) if [ "$wrapper" != "none" ]; then wrapper=latex; fi; 
             backend="$LIB/tohtml -localindex -raw"
             noquote=""; docanchor="-docanchor 10" ;;
-ascii)      wrapper=none
             backend="$LIB/toascii" ;;
-troff)      wrapper=mm
             backend="$LIB/toroff" ;;
-n)          wrapper=none ;;
-backend)    backend="$2" ; shift ;;
-markup)     markup="$2"  ; shift ;;
@
Note some versions of echo break on [[echo "-n..."]], echoing nothing 
at all.  The leading space is claimed to prevent this problem.
<<option printout for usage>>=
echo "-latex		Emit LaTeX with headers and trailers (default)." 1>&2
echo "-tex		Emit plain TeX with headers and trailers." 1>&2
echo "-html		Emit HTML with headers and trailers." 1>&2
echo "-latex+html	Assume LaTeX in documentation, but use HTML in code." 1>&2
# echo "-ascii            Emit ASCII." 1>&2
echo "-troff            Emit troff (actually GNU groff)." 1>&2
echo " -n		Don't use any header or trailer." 1>&2
echo "-markup frontend  Parse input with frontend (e.g., numarkup)." 1>&2
@ \iffalse
<<noweave man page option table>>=
.TP
.B \-latex
Emit LaTeX, including wrapper in 
.B article
style with the
.B noweb
package and page style. (Default)
.TP 
.B \-tex
Emit plain TeX, including wrapper with
.B nwmac
macros.
.TP
.B \-html
Emit HTML, using HTML wrapper.
The output is uninteresting without \fB-index\fP or \fB-x\fP.
The tags \fB<nowebchunks>\fP and \fB<nowebindex>\fP, on lines by themselves,
produce a list of chunks and an index of identifiers, respectively.
If these tags are not present, the list and index are placed at the end of the file.
.TP
.B \-latex+html
Assume documentation chunks are LaTeX, but generate HTML for code chunks,
suitably marked so conversion with 
.I latex2html(1)
yields reasonable output.
A LaTeX wrapper is implied, but can be turned off with \fB-n\fP.
.I Use of this option is 
.B deprecated; 
use
.B \-html
with 
.B "\-filter l2h"
instead.
<<noweave man page option table>>=
.TP
.B \-troff
Emit 
.IR troff (1)
markup (with no wrapper).
The result should be processed with 
.IR noroff (1).
Bug reports for 
.B \-troff
to Arnold Robbins
.B <arnold@skeeve.com>.
<<bogus noweave man page option table>>=
.TP
.B \-ascii
Emit ASCII (with no wrapper).
Bug reports for 
.B \-ascii
to Phil Bewig
.B <pbewig@netcom.com>.
<<noweave man page option table>>=
.TP
.B \-n
Don't use any wrapper (header or trailer).
This option is useful when \fInoweave\fP's output will be
a part of a larger document.
See also 
.B \-delay.
@ \fi
A common bug seems to be using both [[-x]] and [[-index]] on the same
command line, so I complain about it.
<<insist first-pass options are self-consistent>>=
if [ -n "$using_xref" -a -n "$using_index" ]; then
  echo "$0: you may not use -x with -index or -indexfrom (drop the -x)" 1>&2
  exit 1
fi
<<initialization>>=
using_index= using_xref=
@ 
<<first pass {\tt noweave} options>>=
-filter)    shift                           ;;
-x)                           using_xref=1  ;;
-index)            noindex= ; using_index=1 ;;                 
-indexfrom) shift; noindex= ; using_index=1 ;;
<<second pass {\tt noweave} options>>=
-filter) 
    newfilter="$2" ; shift ;                  <<add [[$newfilter]] (could overflow)>> ;;
-x) newfilter="$LIB/noidx $docanchor $delay"; <<add [[$newfilter]] (could overflow)>> ;;
-index)  
    newfilter="$LIB/finduses $noquote" ;      <<add [[$newfilter]] (could overflow)>>
    newfilter="$LIB/noidx $docanchor $delay"; <<add [[$newfilter]] (could overflow)>> ;;
-indexfrom)
    newfilter="$LIB/finduses $noquote $2";    <<add [[$newfilter]] (could overflow)>>
    newfilter="$LIB/noidx $docanchor $delay"; <<add [[$newfilter]] (could overflow)>>
    shift ;;
<<option printout for usage>>=
echo "-x		Use the default cross-referencer (needs LaTeX or HTML)." 1>&2
echo "-index		Create index using identifiers defined in input files." 1>&2
echo "-indexfrom defs	Create index of identifers listed in file defs." 1>&2
echo "-filter cmd	Filter through 'cmd' before weaving; cmd could prettyprint" 1>&2
echo "			or perform other functions." 1>&2
@ \iffalse
<<noweave man page indexing options>>=
.TP
.B \-x
For 
.I LaTeX,
add a page number to each chunk name identifying the location of that
chunk's definition, and emit cross-reference information relating definitions and uses.
For 
.I HTML,
create hypertext links between uses and definitions of chunks.
When
.B noweave -x
is used with
.I LaTeX,
the control sequence
.B "\\\\nowebchunks"
expands to a sorted list of all code chunks.
.TP
.B \-index
Build cross-reference information (or hypertext links) for defined identifiers.
Definitions are those found in the input files by
.B \-autodefs
.I language
or by
.BR \-filter btdefn.
Requires
.I LaTeX
or
.I HTML.
.B \-index
implies
.B \-x;
including both will generate strange-looking output.
.I noweave
does not generate
cross-references to identifiers that appear in quoted code (\fB@[[\fP...\fB@]]\fP),
but it does generate hypertext links.
When
.B noweave -index
is used with
.I LaTeX, 
the control sequence
.B "\\\\nowebindex"
expands to an index of identifiers.
.TP
.B \-indexfrom \fIindex\fP
Like 
.B \-index,
but the identifiers to be indexed are taken from file \fIindex\fP.
See
.I noindex(1).
<<noweave man page option table>>=
.TP
.B \-filter \fIcmd\fP
Filters the 
.I noweb
source through 
.I cmd
after converting it to tool form and before converting to
.I TeX.
.I noweave
looks for 
.I cmd
first on the user's
.B PATH,
then in
.B |LIBDIR|.
Such filters
can be used to add features to
.I noweave;
for an example, see
.B |LIBDIR|/noxref.krom.
.I Noweave
supports up to four filters; one can get more by shell trickery, 
for example, \fB-filter "icon.filter | noidx"\fP.
The \fB-autodefs\fP,
\fB-x\fP, \fB-index\fP, and \fB-indexfrom\fP options are implemented as filters.
Filters are executed with the shell's
.B eval
command, so
.I cmd
should be quoted accordingly.
<<description of -markup option>>
@ \fi 
Note that it would be appropriate to look for autodefs
using [[[ -x $newfilter ]]],
but that stupid DEC Ultrix doesn't support [[test -x]], so the best I can
do in a portable way is [[test -r]].
<<first pass {\tt noweave} options>>=
-autodefs) newfilter="$LIB/autodefs.$2"
           if [ -r $newfilter ]; then <<add [[$newfilter]] (could overflow)>>
           else echo "$0: don't know how to find definitions for '$2'" 1>&2; exit 1
           fi
	   shift
           ;;
-showautodefs) <<print all legal [[-autodefs]] or complain>>; exit 1 ;;
<<option printout for usage>>=
echo "-autodefs lang	Source is in language 'lang'; find definitions automatically." 1>&2
echo "-showautodefs	List languages that can be used with -autodefs" 1>&2
@ \iffalse
<<noweave man page indexing options>>=
.TP
.B \-autodefs \fIlang\fP
Discover identifier definitions automatically.
Code in chunks must be in language \fIlang\fP.
Permissible \fIlang\fPs vary but may include
.B tex
or 
.B icon.
Useless without
.B \-index,
which it must precede.
.TP
.B \-showautodefs
Show values of \fIlang\fP usable with \fB-autodefs\fP.
@ \fi 
Same note as above regarding [[test -x]] vs [[test -r]].
<<print all legal [[-autodefs]] or complain>>=
foundautodefs=
for i in $LIB/autodefs.*; do
  if [ -r $i ]; then
    echo "This `basename $0` supports -autodefs $i" | 
                        sed "s@$LIB/autodefs\.@@" 1>&2
    foundautodefs=$i
  fi
done
if [ -z "$foundautodefs" ]; then
  echo "This `basename $0` does not support -autodefs"
fi
@
Here's an embarrassing hack --- if we spot \verb+-option shortxref+ 
or \verb+-option longxref+ on the
command line, we pass something suitable to the back end, in case we're doing
HTML.
<<first pass {\tt noweave} options>>=
-option) newopt="$2"; shift
         if [ "X$newopt" = "Xshortxref" ]; then shortxref="-shortxref"; fi
         if [ "X$newopt" = "Xlongxref" ];  then shortxref="-longxref";  fi
         <<add [[$newopt]] to [[noweboptions]]>> ;;
<<option printout for usage>>=
echo '-option opt	Add \noweboptions{opt} to header (latex only)' 1>&2
@ \iffalse
<<noweave man page option table>>=
.TP 
.B \-option \fIopt\fP
Adds \fB\enoweboptions{\fP\fIopt\fP\fB}\fP to the
.I LaTeX
header.
See 
.I nowebstyle(1) 
for values of
.I opt.
Normally useful only with the
.B \-latex
option, but 
.B "\-option longxref"
works black magic with 
.B \-html.
@ \fi
<<first pass {\tt noweave} options>>=
# -nodelay) delay= ;;
-delay)   delay="-delay" ; wrapper=none ;;
<<option printout for usage>>=
echo "-delay		Delay markup until after first documentation chunk." 1>&2
@ \iffalse
<<noweave man page option table>>=
.TP
.B \-delay
By default, 
.I noweave
puts file-name and other information into the output before the first chunk
of the program.
.B \-delay
delays that information until after the first documentation chunk, making
act a little bit like the 
.I WEB
``limbo.''
The option is typically used to enable a user to put a specialized
.I LaTeX
.B "\\\\documentclass"
command and other preamble material in the first documentation chunk (i.e., 
.I before
the first @ sign).
This option also forces trailing cross-referencing information to be emitted
just before the final chunk, instead of at the end of the document;
the final chunk is expected to contain
.B "\\\\end{document}."
The 
.B \-delay
option implies the
.B \-n 
option.
@ \fi
% .TP
% .B \-nodelay
% Don't delay, put file-name and other information right after header. (Default)
% @ \fi
<<first pass {\tt noweave} options>>=
-t*) markopts="$markopts $1" ;;
<<option printout for usage>>=
echo "-tk		Expand tab stops every k columns" 1>&2
echo "-t		Copy tabs to the output" 1>&2
@ \iffalse
<<noweave man page option table>>=
.TP
.B \-t\fIk\fP
Expand tabs with stops every \fIk\fP columns.
(Default is to expand every 8 columns.)
.TP
.B \-t
Copy tabs to the output.
@ \fi
<<first pass {\tt noweave} options>>=
-v) echo 'RCS version name $Name:  $' 1>&2
    echo 'RCS id $Id: noweave.nw,v 1.7 2008/10/06 01:03:24 nr Exp $' 1>&2
    verbose=1 ;;
<<option printout for usage>>=
echo "-v		Print pipeline and RCS info on standard error" 1>&2
@ \iffalse
<<noweave man page option table>>=
.TP
.B \-v
Print the pipeline and RCS info on standard error.
@ \fi
\iffalse
<<man page: WEAVING section>>=
Output from \fInoweave\fP can
be used in \fITeX\fP documents that 
.B "\\\\input nwmac,"
in \fILaTeX\fP documents that  use the
.B noweb
package (see \fInowebstyle(1)\fP),
and in \fIHTML\fP documents to be browsed with 
.I Mosaic(1).
.I Noweave
treats code chunks somewhat like
.I LaTeX list environments.
If the ``\fB@ \fP'' that terminates a code chunk is followed immediately by text,
that text follows the code chunk without a paragraph break.
If the rest of the line is blank, 
.I noweave
puts 
.I TeX
into ``vertical mode,'' and later text starts a fresh, indented paragraph.
.PP
No page breaks occur in the middle of code chunks unless necessary to avoid
an overfull vbox.
The documentation chunk immediately preceding a code chunk appears on
the same page as that code chunk unless doing so would violate the previous rule.
.PP
.I Noweave
inserts no extra newlines in its \fITeX\fP output, so the line numbers given
in
.I TeX
error messages are the same as those in the input file.
.PP
.I noweave
has
options that dictate choice of 
formatter
and that support different formatting idioms and tools.
Basic options are described here; options related to index
and cross-reference information are described in the 
INDEXING AND CROSS-REFERENCE section.
<<noweave man page option table>>
@
<<man page: INDEXING AND CROSS-REFERENCE section>>=

@ \fi
<<add [[$newfilter]] (could overflow)>>=
if   [ -z "$filtera" ]; then
  filtera="$newfilter"
elif [ -z "$filterb" ]; then
  filterb="$newfilter"
elif [ -z "$filterc" ]; then
  filterc="$newfilter"
elif [ -z "$filterd" ]; then
  filterd="$newfilter"
elif [ -z "$filtere" ]; then
  filtere="$newfilter"
elif [ -z "$filterf" ]; then
  filterf="$newfilter"
elif [ -z "$filterg" ]; then
  filterg="$newfilter"
else
  echo "$0: ran out of filters" 1>&2
  exit 1
fi
<<show usage>>=
echo "Usage: $0 [options] [files]" 1>&2
echo "Options recognized are:" 1>&2
<<option printout for usage>>
@
To avoid inserting any extra newlines into the output, 
I use [[@literal]]to insert headers and trailers.
The altered [[PATH]] provides a convenience to people who want to
use simple names to refer to filters in [[$LIB]].
<<emit markup on standard output>>=
(
header=
case $wrapper in
  none) ;;
  latex)  header="@header $wrapper $noweboptions" 
	  trailer="@trailer $wrapper" ;;
  *)  header="@header $wrapper$arg" 
      trailer="@trailer $wrapper" ;;
esac
if [ -n "$header" ]; then echo "$header"; fi
PATH="$PATH:$LIB" 
export PATH
<<if verbose, make noise about pipeline>>
<<if verbose, show back end>>
if   [ -z "$filtera" ]; then
  $markup $markopts $arg
elif [ -z "$filterb" ]; then
  $markup $markopts $arg | eval $filtera
elif [ -z "$filterc" ]; then
  $markup $markopts $arg | eval $filtera | eval $filterb
elif [ -z "$filterd" ]; then
  $markup $markopts $arg | eval $filtera | eval $filterb | eval $filterc
elif [ -z "$filtere" ]; then
  $markup $markopts $arg | eval $filtera | eval $filterb | eval $filterc |
                           eval $filterd
elif [ -z "$filterf" ]; then
  $markup $markopts $arg | eval $filtera | eval $filterb | eval $filterc |
                           eval $filterd | eval $filtere
elif [ -z "$filterg" ]; then
  $markup $markopts $arg | eval $filtera | eval $filterb | eval $filterc |
                           eval $filterd | eval $filtere | eval $filterf
else
  $markup $markopts $arg | eval $filtera | eval $filterb | eval $filterc |
                           eval $filterd | eval $filtere | eval $filterf |
                           eval $filterg
fi
if [ -n "$trailer" ]; then echo $trailer; fi
)
<<if verbose, make noise about pipeline>>=
if [ -n "$verbose" ]; then
  if [ -n "$header" -o -n "$trailer" ]; then
    parenpfx="("
    if [ -n "$header" ]; then echo "(echo $header" 1>&2; parenpfx=" "; fi
    echo "$parenpfx$markup" $markopts $arg 1>&2
    if [ -n "$trailer" ]; then echo " echo $trailer" 1>&2; fi
    echo ") |" 1>&2
  else
    echo $markup $markopts $arg '|' 1>&2
  fi
  if   [ -n "$filtera" ]; then echo $filtera '|' 1>&2; fi
  if   [ -n "$filterb" ]; then echo $filterb '|' 1>&2; fi
  if   [ -n "$filterc" ]; then echo $filterc '|' 1>&2; fi
  if   [ -n "$filterd" ]; then echo $filterd '|' 1>&2; fi
  if   [ -n "$filtere" ]; then echo $filtere '|' 1>&2; fi
  if   [ -n "$filterf" ]; then echo $filterf '|' 1>&2; fi
  if   [ -n "$filterg" ]; then echo $filterg '|' 1>&2; fi
fi
