\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 /sys/src/cmd/noweb/COPYRIGHT for more information. # $Id: noweave.nw,v 1.6 1998/08/17 00:10:34 nr Exp nr $ # # Translated from sh to rc by Russ Cox # bugs -> rsc@plan9.bell-labs.com @ Here's the organization of the source: <<noweave>>= #!/bin/rc <<copyright notice>> rfork en <<initialization>> <<set up /bin union>> <<scan options and arguments>> { <<emit markup on standard output>> status='' } | { args=(`{echo $noindex $delay $shortxref}) eval $backend $args } exit $status <<if verbose, show back end>>= if(! ~ $verbose '') echo $backend $noindex $delay $shortxref >[1=2] @ The first item of initialization is to locate the {\tt noweb} library. <<initialization>>= LIB=/sys/lib/noweb @ We need to add the {\tt noweb} bin directories to the union mount on {\tt /bin . <<set up /bin union>>= bind -b $LIB/bin/$objtype /bin bind -b $LIB/bin/rc /bin @ We continue with initialization. We use strings throughout rather than {\tt rc} lists, since we're just going to echo it anyway, and it makes keeping the filterlist easy. <<initialization>>= markup=markup backend=totex wrapper='' delay='' args='' markopts='' noweboptions='' autodefs='' verbose='' shortxref='' noquote=-noquote docanchor='' noindex=-noindex filterlist=() # 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>>= saveargs=($*) arg='' while(! ~ $#* 0) { switch($1) { <<first pass {\tt noweave} options>> case - arg=$arg^' '$1 case -* echo $0': unrecognized option '$1 >[1=2] <<show usage>> exit usage case * arg=$arg^' '$1 } shift } <<insist first-pass options are self-consistent>> if(~ $wrapper '') wrapper=latex *=$saveargs shift while(! ~ $#* 0) { switch($1) { <<second pass {\tt noweave} options>> } shift } <<add [[$newopt]] to [[noweboptions]]>>= if(~ $noweboptions '') noweboptions=$newopt if not noweboptions=$noweboptions','$newopt <<first pass {\tt noweave} options>>= case -latex if(! ~ $wrapper none) wrapper=latex case -tex wrapper=tex case -html if(! ~ $wrapper none) wrapper=html backend='tohtml -localindex' noquote='' docanchor='-docanchor 10' case -latex+html if(! ~ $wrapper none) wrapper=latex backend='tohtml -localindex -raw' noquote='' docanchor='-docanchor 10' case -ascii wrapper=none backend=toascii case -troff backend=toroff case -n wrapper=none case -backend backend=$2 shift case -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 Aharon Robbins .B <arnold@gnu.org>. <<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(! ~ $using_xref '' && ! ~ $using_index '') { echo $0': you may not use -x with -index or -indexfrom (drop the -x)' > 1=2] exit -x-index } <<initialization>>= using_index='' using_xref='' @ <<first pass {\tt noweave} options>>= case -filter shift case -x using_xref=1 case -index noindex='' using_index=1 case -indexfrom shift noindex='' using_index=1 <<second pass {\tt noweave} options>>= case -filter newfilter=$2 shift <<add [[$newfilter]]>> case -x newfilter='finduses noquote' <<add [[$newfilter]]>> case -index newfilter='finduses '^$noquote <<add [[$newfilter]]>> newfilter='noidx '^$docanchor^' '^$delay <<add [[$newfilter]]>> case -indexfrom newfilter='finduses '^$noquote^' '^$2 <<add [[$newfilter]]>> newfilter='noidx '^$docanchor^' '^$delay <<add [[$newfilter]]>> 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 pretty rint' >[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 nd 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 identifiers defined by .br .B "@ %def" .I identifiers .br Definitions are those found in input files. 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 filter . 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>>= case -autodefs newfilter='autodefs.'^$2 if(test -r $newfilter) { <<add [[$newfilter]]>> } if not { echo $0^': don''t know how to find definitions for '^$2 exit defns } shift case -showautodefs <<print all legal [[-autodefs]] or complain>> exit complain <<option printout for usage>>= echo '-autodefs lang Source is in language ''lang''; find definitions automa ically.' >[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=no for(i in $LIB/autodefs.*) { if(test -r $i) { echo 'Supports -autodefs '^$i | sed 's!$LIB/autodefs\.!!' >[1=2 foundautodefs=yes } } if(~ $foundautodefs no) echo 'Does not support -autodefs' >[1=2] @ 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>>= case -option newopt=$2 shift if(~ $newopt shortxref) shortxref=-shortxref if(~ $newopt longxref) shortxref=-longxref <<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>>= # case -nodelay # delay='' case -delay delay=-delay wrapper=none <<option printout for usage>>= echo '-delay Delay markup until after first documentation chunk.' >[ =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. 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. (Defaul ) % @ \fi <<first pass {\tt noweave} options>>= case -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>>= case -v echo 'RCS id $Id: noweave.nw,v 1.6 1998/08/17 00:10:34 nr Exp nr $' >[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 te t, 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 ru e. .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]]>>= filterlist=($filterlist $newfilter) <<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. <<emit markup on standard output>>= header='' # whatis wrapper # whatis arg switch($wrapper) { case none ; case latex header='@header '^$wrapper^' '^$noweboptions trailer='@trailer '^$wrapper case * header='@header '^$wrapper^$arg } if(! ~ $header '') echo $header <<if verbose, make noise about pipeline>> <<if verbose, show back end>> if(~ $#filterlist 0) filterlist=cat pipeline='| '^$filterlist pipeline=cat^$"pipeline # whatis pipeline argx=(`{echo $markopts $arg}) # whatis argx $markup $argx | eval $pipeline if(! ~ $trailer '') echo $trailer <<if verbose, make noise about pipeline>>=