home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-04-10 | 71.6 KB | 1,849 lines |
- Newsgroups: comp.sources.unix
- From: ross@spam.adelaide.edu.au (Ross Williams)
- Subject: v26i139: funnelweb - a tool for literate programming in C, Part19/20
- Sender: unix-sources-moderator@vix.com
- Approved: paul@vix.com
-
- Submitted-By: ross@spam.adelaide.edu.au (Ross Williams)
- Posting-Number: Volume 26, Issue 139
- Archive-Name: funnelweb/part19
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 19 (of 20)."
- # Contents: userman/u_ch1.tex
- # Wrapped by vixie@gw.home.vix.com on Sun Apr 11 11:00:34 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'userman/u_ch1.tex' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'userman/u_ch1.tex'\"
- else
- echo shar: Extracting \"'userman/u_ch1.tex'\" \(70598 characters\)
- sed "s/^X//" >'userman/u_ch1.tex' <<'END_OF_FILE'
- X%==============================================================================%
- X% Start of Ch1.tex %
- X%==============================================================================%
- X%
- X% Copyright
- X% ---------
- X% Copyright (C) 1992 Ross N. Williams.
- X% This file contains a chapter of the FunnelWeb User's Manual.
- X% See the main TeX file for this manual for further information.
- X%
- X%==============================================================================%
- X
- X\chapter{A Tutorial Introduction}
- X\label{chapintroduction}
- X\x{tutorial}
- X
- X\section{What is Literate Programming?}
- X\x{literate programming}
- X
- A traditional computer program consists of a text file containing program
- code. Scattered in amongst the program code are comments which describe the
- various parts of the code.
- X
- In \newterm{literate programming} the emphasis is reversed. Instead of
- writing code containing documentation, the literate programmer writes
- documentation containing code. No longer does the English commentary
- injected into a program have to be hidden in
- comment delimiters at the top of the
- file, or under procedure headings, or at the end of lines.
- Instead, it is wrenched into the daylight and made the main focus.
- The \dq{program} then becomes primarily a document directed at humans,
- with the code being herded between \dq{code delimiters} from where it
- can be extracted and shuffled out sideways to the language system
- by literate programming tools.
- X
- The effect of this simple shift of emphasis can be so
- profound as to change one's whole approach to programming. Under the
- literate programming paradigm, the central activity of programming becomes
- that of conveying meaning to other intelligent beings rather than merely
- convincing the computer to behave in a particular way. It is the difference
- between performing and exposing a magic trick.\x{magic trick}
- X
- In order to program in a literate style, particular tools are
- required.\xx{tools}{literate programming}
- The traditional approach (used in the FunnelWeb system) is to have
- some sort of text-file-in/text-file-out utility that reads a
- literate program (containing a program commentary peppered with scraps
- of program text) and writes out a file containing all the program code and
- a file containing typesetter commands representing the entire input document,
- documentation, code, and all (\figarchitecture{}).
- X
- X\begin{figure}[htbp]
- X\begin{verbatim}
- X
- X +-----------------------------------------+
- X | File containing the program description |
- X | peppered with scraps of program code. |
- X | This is what the programmer works on. |
- X | (e.g. sloth.web) |
- X +-----------------------------------------+
- X |
- X v
- X o---------------------------o
- X | Literate Programming Tool |
- X o---------------------------o
- X |
- X +-------------------+-------------------+
- X | |
- X v v
- X +------------------+ +----------------------------------+
- X | Traditional | | Documentation file suitable for |
- X | Computer Program | | input into a typesetting program |
- X | (e.g. sloth.c) | | (e.g. sloth.tex) |
- X +------------------+ +----------------------------------+
- X
- X\end{verbatim}
- X\mylabel{\figarchitecture{}: Traditional architecture of literate programming tools.}{%
- X%
- Literate programming tools could be organized in a number of ways. However,
- to fit in with current file and command line based environments, most tools
- conform to the traditional architecture shown here in which the user feeds
- in a file containing a literate program, and the literate programming
- utility generates program files and a documentation file.
- X%
- X}
- X\end{figure}
- X
- Given the coming age of hypertext\x{hypertext} systems,
- this is probably not the best approach.
- However, it does mesh beautifully with current text
- files and command line interfaces, the expectation of linear presentations in
- the documents we read, and the particular requirements of current programming
- languages and typesetting systems. It is certainly not a bad approach.
- X
- With this structure in place, the literate programming system can provide
- far more than just a reversal of the priority of comments and code.
- In its full blown form, a good literate programming facility can provide
- total support for the essential thrust of literate programming, which is that
- computer programs should be written more for the human reader
- than for the compiler. In particular, a literate programming system can
- provide:\xs{literate programming}{facilities}
- X
- X\narrowthing{Re-ordering of code:}{Programming languages often force the
- programmer to give the various parts of a computer program in a particular
- order.\xx{program}{ordering}
- XFor example, the Pascal\x{Pascal} programming language\paper{BSI82}
- imposes the ordering:
- constants, types, variables, procedures, code. Pascal also requires that
- procedures appear in an order consistent with the partial ordering
- imposed by the static call graph (but forward
- declarations allow this to be bypassed). In contrast, the literate style
- requires that the programmer be free to present the computer program in
- any order whatsoever. The facility to do this is implemented in literate
- programming tools by providing text \i{macros} that can be defined
- and used in any order.}
- X
- X\narrowthing{Typeset code and documentation:}{Traditionally program
- listings are
- dull affairs consisting of pages of fan-form paper imprinted with meandering
- coastlines of structured text in a boring font. In contrast, literate
- programming systems are capable of producing documentation that is
- superior in two ways. First, because most of the documentation text is
- fed straight to the typesetter, the programmer can make use of all the
- power of the underlying typesetter, resulting in documentation that has the
- same presentation as an ordinary typeset document. Second, because the
- literate programming utility sees all the code, it can use its knowledge
- of the programming language and the features of the typesetting language
- to typeset the program code as if it were appearing in a
- technical journal. It is the difference
- between:}
- X
- X\begin{verbatim}
- X while sloth<walrus loop
- X sloth:=sloth+1;
- X end loop
- X\end{verbatim}
- X
- X\narrowtext{and}
- X
- X\begin{verse}
- X\b{while} \i{sloth}$<$\i{walrus} \b{loop}\\
- X\qquad\qquad \i{sloth}$\leftarrow$\i{sloth}$+1$;\\
- X\b{end} \b{loop}
- X\end{verse}
- X
- X\narrowtext{Unfortunately, while FunnelWeb provides full typesetting
- of the
- documentation, it typesets all of its code in the style of the first of these
- two examples. To typeset in the style of the second requires knowledge of
- the programming language, and the current version of FunnelWeb is
- programming language independent. At a later stage, it is possible that
- XFunnelWeb will be modified to read in a file containing information
- about the target programming language to be used to assist in
- typesetting the code properly.}
- X
- X\narrowthing{Cross referencing:}{Because\x{cross referencing}
- the literate tool sees all the
- code and documentation, it is able to generate extensive cross referencing
- information in the typeset documentation. This makes the printed program
- document more easy to navigate and partially compensates for the lack of
- an automatic searching facility when reading printed documentation.}
- X
- In the end, the details don't matter. The most significant
- benefit that literate programming offers
- is \i{its capacity to transform the state of mind of the
- programmer}.\xs{literate programming}{most significant benefit}
- It is now legend that the act of explaining something can transform
- one's understanding of it. This is one of the justifications behind the
- powerful combination of research and teaching in
- universities\paper{Rosovsky90}.\x{universities}
- Similarly, by constantly explaining the unfolding program code in English to an
- imaginary reader, the programmer transforms his perception of the code,
- laying it open, prone, to the critical eye.\xx{explaining}{code}
- X
- The result of this exposure is a higher quality of programming.
- When exposed to the harsh light of the literate eye,
- bugs crawl out, special cases vanish, and sloppy code evaporates.
- As a rule literate programs
- take longer to write than ordinary programs, but the total
- development time\xx{development}{time}
- is the same or less because the time taken to write and
- document the program carefully is compensated for by a reduced debugging
- and maintenance time.
- Thus literate programming does not merely assist in the preparation of
- documentation, but also makes significant contributes to the process of
- programming itself. In practice this has turned out to be a contribution
- far more important than the mere capacity to produce typeset documentation.
- X
- XFor more information on literate programming, the reader is directed
- to Knuth's early founding work \paper{Knuth83} and \paper{Knuth84}.
- XFor more recent information refer to \paper{Smith91},
- which provides a comprehensive bibliography up to 1990.
- X
- X\section{What is FunnelWeb?}
- X\xx{FunnelWeb}{overview}
- X
- XFunnelWeb is a particular literate programming system that is implemented
- by a single C program. FunnelWeb takes as input a single \p{.fw}
- X\newterm{input file}
- and writes one or more \newterm{product files}
- and a \newterm{documentation file} (\figfunarch{}).
- X
- X\begin{figure}[htbp]
- X\begin{verbatim}
- X +-----------+
- X | sloth.fw |
- X +-----------+
- X |
- X v
- X o-------------------o
- X | FUNNELWEB Program |
- X o-------------------o
- X |
- X +-------------------+----------------+
- X | |
- X v v
- X +-----------------------------+ +--------------------------------+
- X | Product File (e.g. sloth.c) | | Documentation File (sloth.tex) |
- X +-----------------------------+ +--------------------------------+
- X\end{verbatim}
- X\mylabel{\figfunarch{}: Architecture of FunnelWeb.}{%
- X%
- XFunnelWeb follows the traditional architecture of literate programming
- tools.
- X%
- X}
- X\end{figure}
- X
- In literate programming systems, it is usual to refer to the product
- file as a \dq{program file}. However, as FunnelWeb is a general tool that
- can be used to prepare all sorts of text files that are not computer programs,
- the more generic term \dq{product file} was chosen. Product files should
- be carefully distinguished from the term \newterm{output files} which refers
- to all of the output files produced by FunnelWeb.
- X
- XFunnelWeb is distinguished by the following characteristics:
- X
- X\narrowthing{Simplicity:}{A\x{simplicity}
- governing design goal of FunnelWeb is to provide
- a \i{simple} tool that could be easily learnt and completely mastered.
- This manual is thick because it is comprehensive and lingers on the
- ways in which FunnelWeb can be used. The tool itself is quite simple.}
- X
- X\narrowthing{Reliability:}{Another\x{reliability}
- design goal is to provide a tool that will
- protect the user as much as possible from silly errors. Macro preprocessors
- are notorious for causing obscure errors. Every attempt has been made in
- XFunnelWeb to keep the syntax robust.
- XFor example, in FunnelWeb the syntax of
- macro calls has been purposely designed to be highly visible so that the
- reader is always aware when the macro facility is being invoked.}
- X
- X\narrowthing{Language and Typesetter Independence:}{Unlike
- Knuth's original\xx{language}{independence}\xx{typesetter}{independence}
- Web system which was specific to the Pascal programming language\paper{BSI82}
- and the \TeX{} typesetting language\paper{Knuth84}, FunnelWeb strives to
- be language and typesetter independent. The current version of FunnelWeb
- is completely language independent, but is still somewhat dependent on the
- X\TeX{}\x{TeX} typesetter language.}
- X
- X\narrowthing{Portability:}{FunnelWeb\x{portability} has been written in
- the~C programming language with great emphasis on portability.
- XFunnelWeb currently runs on the Sun, VAX, IBM PC, and Mac.}
- X
- X\narrowthing{Controllable:}{FunnelWeb\x{controllability}
- is an extremely controllable tool.
- To protect users' investment in source files constructed in the FunnelWeb
- macro language, the C source code to FunnelWeb has been released under GNU
- license.\xx{GNU}{license}
- This means that it will always be available to everyone. Furthermore,
- license has been granted for the FunnelWeb User's Manual and FunnelWeb
- Hacker's Manual to be copied freely so long as they are not modified. All
- this means that FunnelWeb is not going to disappear suddenly.}
- X
- X\narrowthing{A Production Tool:}{Above\x{production tool}
- all, FunnelWeb has been designed to be
- a production tool and every effort has been made to ensure that it will
- operate effectively in a professional environment. FunnelWeb is \dq{open}
- and portable. There is a comprehensive user manual. Its error messages
- are comprehensive. It is fast. Finally, it has been designed with the
- experience of three years of using FunnelWeb~V1.}
- X
- XFor more information on the history and design of FunnelWeb, see
- the \i{FunnelWeb Hacker's Manual}.
- X
- X\section{The Name FunnelWeb}
- X\xx{FunnelWeb}{name}
- X
- The name \dq{FunnelWeb} was chosen because it contains the name \dq{WEB},
- which is the name of Knuth's system. It was also chosen because it
- has a distinctly Australian flavour.
- X
- XFunnel-web spiders\xx{Funnel-web}{spider}
- are found in Northern and Eastern Australia. They are
- about three to four centimetres long and are very poisonous. The
- Sydney\x{Sydney}
- XFunnel-web spider (\i{Atrax robustus}\x{Atrax robustus}),
- common in Sydney,
- has caused the most trouble and has been responsible for several deaths.
- XFunnel-web spiders love to crawl into temporarily discarded shoes where they
- later react in a hostile manner to an unsuspecting foot. They are known
- to hang on once they sink their fangs in. Funnel-web spiders derive
- their name from the shape of their webs which are horizontally-aligned
- narrowing tubes, open at one end\paper{ANZE}.
- X
- The Funnel-web spider, like the tiger snake\xx{tiger}{snake}
- and the white pointer shark,\xx{white pointer}{shark}
- is secretly regarded by Australians as a kind of national
- treasure.\xn{Edna}{Everage}\xn{Barry}{Humphries}
- X
- X\begin{verse}
- X\b{F} is for Funnel-web\\
- Our furry-legged foe.\\
- He sleeps in your slipper\\
- And breakfasts on toe.\\
- X--- One verse from \i{A Megastar's Mantras: Things that Mean a Lot to Me},\\
- X\qquad{} by Dame Edna Everage\paper{Humphries91}.\\
- X\end{verse}
- X
- X\section{A FunnelWeb Tutorial}
- X\x{tutorial}\xx{tutorial}{introduction}
- X
- The remainder of this chapter consists of an introductory tutorial on
- XFunnelWeb. Ideally you should have a working version of FunnelWeb in front
- of you when reading this chapter so that you can try out the examples
- yourself. There is no need to try all the examples so long as you
- type in enough to feel comfortable with what you are reading. There
- is no harm in reading this chapter offline too, so long as you get to the
- computer within a couple of days to reinforce what you have read.
- X
- XFor best effect, you should create a new, temporary, empty directory in
- which to experiment with FunnelWeb. That way, it will be more obvious
- when FunnelWeb creates an output file. You can either type in the
- examples in this chapter directly, or copy and paste them from the \LaTeX{}
- source file for this chapter or the FunnelWeb
- test suite. The source file for this chapter should be available
- in a file such as \p{/fwdir/userman/ch1.tex}. The test suite should be
- available in a directory such as \p{/fwdir/tests/}. The
- test files called \p{ex01.fw} through \p{ex16.fw} contain the examples in this
- chapter. The test files called \p{hi01.fw} through \p{hi10.fw} contain the
- examples in the next chapter.
- X
- If you do not yet have an installed copy of FunnelWeb, refer to
- Chapter~\ref{chapinstall} for full details on how to obtain and install
- a copy of FunnelWeb. If you are not sure if you have an installed copy,
- try invoking FunnelWeb by giving the command \dqp{fw}. If this yields an error
- such as \dq{command not found} then you do not have a properly
- installed version of FunnelWeb.
- X
- X\section{A Hello World Document}
- X\x{hello world document}
- X
- Just as one starts the process of learning a new programming language with a
- X\dq{Hello World} program, when learning FunnelWeb, you can start with a
- X\dq{Hello World} document! And here it is! Edit a text file
- called \p{hello.fw} and put the following text in it. (Note: The second
- character is the letter \dq{Oh}, not the digit \dq{Zero}).
- X
- X\begin{verbatim}
- X@O@<hello.txt@>@{Hello World@+@}
- X\end{verbatim}
- X
- To \dq{run} this \dq{program}, invoke FunnelWeb using the \dqp{fw}
- command as follows.\x{invoking FunnelWeb}
- X
- X\begin{verbatim}
- fw hello
- X\end{verbatim}
- X
- X\i{If this command doesn't work, then chances are that
- XFunnelWeb has not been installed on your machine. Refer to
- Chapter~\ref{chapinstall} for full details on how to obtain and install
- a copy of FunnelWeb.}
- X
- There should be no errors. If there are, have a look
- at the listing file \p{hello.lis}, which should contain an explanation of the
- error, and compare the area in the file where the error occurred with the
- text above. If there are no errors, you will find that the following
- two files have been created.
- X
- X\begin{verbatim}
- hello.lis - The LISTING file.
- hello.txt - The PRODUCT file.
- X\end{verbatim}
- X
- Take a look at \p{hello.txt}. It should contain a single line with the
- text \p{Hello World}. Let's take another look at the input file.
- X
- X\begin{verbatim}
- X@O@<hello.txt@>@{Hello World@+@}
- X\end{verbatim}
- X
- The whole structure of the input file is controlled by \dqp{@},
- called the \newterm{special character}, which
- introduces \newterm{special sequence}s. A scanner's-eye view of the command
- line looks like this:
- X
- X\begin{verbatim}
- X@O @< "hello.txt" @> @{ "Hello World" @+ @}
- X\end{verbatim}
- X
- The \p{@} character controls everything. In this file we have six different
- special sequences that together
- form a single macro definition. The \p{@<}\x{@<} and \p{@>}\x{@>}
- delimit the name of
- the macro. The \p{@O}\x{@O} signals the start of the macro
- definition and indicates that the macro is to be connected to a product
- file with the same name as the macro (This is is why we got a product file when
- we ran FunnelWeb). The \p{@\{} and \p{@\}}\x{@braces}
- delimit the body of the macro.
- XFinally, the \p{@+}\x{@+} instructs that an end of line sequence should be
- inserted at that point in the product file.
- X
- If you think this syntax looks messy, then you're right.
- It \i{is}
- messy. FunnelWeb \i{could} have employed a \dq{simpler} notation
- in which more of the \p{@} sequences were eliminated. For example:
- X
- X
- X\begin{verbatim}
- Warning: This example is NOT legal FunnelWeb.
- X
- X#hello.txt{Hello World+}
- X\end{verbatim}
- X
- However, if such a syntax were used, the user (you!) would have to remember
- that \p{\#} starts a new macro. You would also have to remember that
- the characters \p{\}} and \p{+} cannot be used in a macro body without a fuss.
- And so on. FunnelWeb is messier, but provides one simple
- rule:\xx{simple}{rule} \i{Nothing special happens
- unless the special character \p{@} appears.}
- X
- This means that in FunnelWeb, you can look at large blocks of text in the
- confidence that (unlike for the C
- pre-processor\xx{C}{preprocessor}) there are no macro calls
- hidden in there. If there were, there would be an \p{@}
- character!\footnote{The only
- exception to this rule occurs where the user has explicitly changed the
- special character using the \p{@=}\x{@=} special sequence.}
- X
- Let's take another look at the hello world program.
- X
- X\begin{verbatim}
- X@O@<hello.txt@>@{Hello World@+@}
- X\end{verbatim}
- X
- In its current form, it consists of a single macro definition. This definition,
- while completely valid on its own, only represents half the power of
- XFunnelWeb. In fact you could say that it is a \dq{Hello
- Northern Hemisphere Program}.\x{Hello Northern Hemisphere Program}
- To turn it into a proper FunnelWeb \dq{Hello
- World} program, we need to add some documentation!
- X
- A FunnelWeb input file consists of a sequence of macro definitions surrounded
- by a sea of documentation which is just ordinary text. Modify your hello
- world document so that it looks like this:
- X
- X\begin{verbatim}
- This hello world document was created by -insert your name here-.
- X
- X@O@<hello.txt@>@{Hello World@+@}
- X
- It writes out a file called hello.txt containing the string ``Hello World''.
- X\end{verbatim}
- X
- Now run it through FunnelWeb, but this time, add a \p{+t} to the command line.
- X
- X\begin{verbatim}
- fw hello +t
- X\end{verbatim}
- X
- If all goes well, you should find that you now have
- X
- X\begin{verbatim}
- hello.lis - A LISTING file.
- hello.tex - A DOCUMENTATION file (in TeX format).
- hello.txt - A PRODUCT file.
- X\end{verbatim}
- X
- Take a look at \p{hello.txt}. You will find that it is identical to the
- X\p{hello.txt} of the previous run. Only macro
- definitions affect the product files that FunnelWeb produces (as a result
- of \p{@O} macro definitions). The surrounding documentation has \i{no}
- effect. In contrast, the new file, \p{hello.tex} (have a look at it now)
- which was created as
- a result of your adding the \p{+t} option contains a fairly full
- representation of the input file. Whereas \p{hello.txt} is the
- X\i{product file} of FunnelWeb, \p{hello.tex} is the \i{documentation file}.
- Try typesetting the documentation file now using
- the \TeX{} typesetting program. Then print it.
- The following commands are an example of the
- sort of commands you will have to give to do this.
- X
- X\begin{verbatim}
- tex hello ! Typeset the documentation.
- lpr -Pcslw -d hello.dvi ! Print the typeset documentation.
- X\end{verbatim}
- X
- The result should be a single page containing the two lines of documentation
- along with a typeset representation of the macro.
- At this point, you have exercised the two main aspects of
- XFunnelWeb.\xx{FunnelWeb}{two main aspects}
- Starting
- with an input file containing macros (or in this case macro) and documentation,
- you have successfully generated a product file based on the macros, and
- a documentation file, based on the entire document. Congratulations!
- X
- The remainder of this tutorial is divided into two parts, which focus on
- XFunnelWeb's macro facilities and its typesetting facilities. By tradition,
- the generation of program files from a literate text is called
- X\newterm{Tangling}, and the generation of typeset documentation is
- called \newterm{Weaving}.\footnote{In FunnelWeb, these two functions
- are aspects of a single computer program. However, in Knuth's WEB\x{WEB}
- system,
- the two functions are embodied in two separate computer programs called
- Tangle and Weave, presumably because, as everyone knows, \dq{it takes
- two to Tangle}.}
- X
- X\section{Macro Facilities}
- X\xx{tutorial}{macro facilities}
- X
- The hello world program of the previous section exercised both the macro
- expansion (product-file) aspect of FunnelWeb, and the typesetting
- X(documentation file) aspect
- of FunnelWeb. This section contains an exposition of the macro facilities,
- and totally ignores the documentation side. This is partly to increase the
- focus of the tutorial, and partly because documentation is usually bulky and
- would take too long for the reader to type in to make the tutorial effective.
- X
- X\subsection{Simple Macros}
- X\xx{tutorial}{simple macros}\xx{tutorial}{macros simple}
- X
- The original \dq{Hello World} program consisted of a single macro definition.
- X
- X\begin{verbatim}
- X@O@<hello.txt@>@{Hello World@+@}
- X\end{verbatim}
- X
- In fact, this is a rather exceptional macro, as it causes its expansion to
- be written to a
- product file. The \p{@O}\x{@O} (for \b{O}utput) signals this.
- In FunnelWeb, most macros are
- defined using \p{@\$}.\x{@dollar}
- This results in a macro that does not generate a product
- file, but which can be called in other macros (including \p{@O} macros).
- Let us expand the hello world program to include some other macros.
- X
- X\begin{verbatim}
- X@O@<hello.txt@>@{@<Greetings@>@+@}
- X
- X@$@<H@>==@{Hello@}
- X@$@<W@>==@{World@}
- X
- X@$@<Greetings@>==@{@<H@> @<W@>@}
- X\end{verbatim}
- X
- Type in the file and run it through FunnelWeb using the command:
- X
- X\begin{verbatim}
- fw hello
- X\end{verbatim}
- X
- The product file (result.out) should look like this:
- X
- X\begin{verbatim}
- Hello World
- X\end{verbatim}
- X
- This short program illustrates some of the features of ordinary macros in
- XFunnelWeb. Consider the \p{@O} macro. Instead of containing
- straight text (\dq{Hello World}), it now contains the macro call
- X\p{@<Greetings@>}. A FunnelWeb macro can be called from within the body of
- another macro just by giving the macro
- name delimited in \p{@<} and \p{@>}.
- X
- At the bottom of the file is the
- definition of the \p{@<Greetings@>}
- macro. The definition is similar to the definition of \p{hello.txt} except
- that it starts with \p{@\$} to indicate that no product file
- is desired from this macro (directly). It also employs the optional
- X\p{==} syntax which has no semantic impact, but
- can be used to make definitions clearer.
- The body of the \p{@<Greetings@>} macro consists of
- calls to the \p{H} and \p{W} macros which are defined immediately above.
- X
- Note that the macros are not constrained to be
- defined in any particular order. One of the main
- features of literate programming tools is that
- they allow the different parts of the text document being developed (usually
- a computer program) to be layed out in any
- order.\xx{order}{program}\xx{program}{layout} So long as there is a
- definition somewhere in the input file for every macro call, FunnelWeb
- will sort it all out.
- X
- In fact, FunnelWeb's macro facility is very simple.\xx{macro}{bindings}
- Unlike many macro preprocessors which allow macros to define other macros,
- XFunnelWeb completely
- finishes parsing and analysing the macros in the input file before it
- starts expanding them into product files. Other preprocessors allow
- macros to
- be redefined like variables (as in, say, \TeX{}\x{TeX}) taking on
- many different values as the macro pre-processor travels through the input
- file. In contrast,
- XFunnelWeb has no concept of \dq{different times} and
- treats the input as one huge static orderless, timeless,
- collection of definitions.
- In FunnelWeb, there is only ever one time, and so there can only ever be
- one value/definition for each macro.
- X
- X
- X\subsection{Number of Times Called}
- X\x{number of times called}\xx{calls}{number}\xx{invocation}{number}
- X
- So far we have seen only tiny, degenerate input files. The next example
- moves up to the level of \dq{trivial}, but starts to convey the flavour of
- the way FunnelWeb can be used in practice. Normally, there would be
- documentation text appearing between the macros, but this has been omitted
- so as to keep the focus on the macros themselves. Although the next
- example is
- much longer than the previous example, the only new construct is \p{@-}
- which can appear only at the end of a line,
- and suppresses it,\xx{EOL}{suppression}
- preventing it from appearing in the text. The \p{@-}\x{@-} construct allows
- the text of a macro to be aligned at the left margin, rather than
- having the first line hanging at the end of the
- X\p{@\{}. FunnelWeb could have been set up so that this end of
- line marker was suppressed. However, it would have been a special case that
- would have broken the very memorable rule \dq{the text of a macro is the
- text appearing between the \p{@\{} and \p{@\}}}.
- X
- Type the following text into the file \p{hello.fw}
- and run it through FunnelWeb. The file contains some intentional errors so
- be sure to type it in exactly and worry only if FunnelWeb \i{doesn't}
- generate some errors.
- X
- X\begin{verbatim}
- X@O@<hello.c@>==@{@-
- X@<Include Files@>
- X@<Include Files@>
- X@<Main Program@>
- X@}
- X
- X@$@<Main Program@>==@{@-
- main()
- X{
- X doit();
- X}
- X@}
- X
- X@$@<Subroutine@>==@{@-
- void doit()
- X{
- X int i;
- X for (i=0;i<10;i++)
- X {
- X @<Print@>
- X @<Print@>
- X }
- X}@}
- X
- X@$@<Print@>==@{@-
- printf("Hello World!");
- printf("\n");@}
- X
- X@$@<Scan@>==@{scanf@}
- X
- X@$@<Include Files@>==@{@-
- X#include <stdio.h>
- X#include <stdlib.h>@}
- X\end{verbatim}
- X
- What happened? Well, if you haven't typed the file in properly, you may
- get some miscellaneous syntax errors. Fix these before continuing.
- If the file has been correctly typed, you should be faced with some error
- messages to do with the number of times some of the macros are called.
- X
- By default, FunnelWeb insists that each macro defined is invoked
- exactly once. However, the file above defines macros that are used
- more than once and a macro that is not used at all. Let us examine the
- errors.
- X
- XFirst, we see that FunnelWeb has alerted us to the fact that
- the \p{Include Files} macro has been called twice. Once alerted to this,
- a quick look at the program convinces us that calling the macro twice is
- a mistake, and that one of the calls should be eliminated.
- X
- Second, we note that FunnelWeb has alerted us to the fact that the
- X\p{@<subroutine@>}
- macro is never called. Again, a quick look at the program tells us that this
- is a mistake (and a very common one in the use of FunnelWeb), and that
- a call to the \p{@<subroutine@>} macro should be inserted just above
- the call to the \p{@<Main Program@>} macro
- in the definition of \p{@<hello.c@>}.
- X
- These two cases demonstrate why these checks have been placed in
- XFunnelWeb. It is nearly always acceptable for a macro to be called once.
- However, if a macro is not called at all, or called more than once,
- this is often a sign
- that the user has made a mistake.
- X
- These checks have a dark side too. In addition to the
- errors mentioned above, FunnelWeb has generated two similar
- errors that do not help us.
- X
- XFirst, we are alerted to the fact that the
- X\p{@<print@>} macro has been called twice. Clearly, in this case, this is not
- a problem, and so here FunnelWeb's fussiness is a nuisance.
- X
- Second, we are alerted to the fact that the \p{@<scan@>} macro has never
- been called. Like the \p{@<print@>} macro,
- this macro was defined as a notational
- convenience, and clearly it does not matter here if it is not used. Again,
- XFunnelWeb is being a nuisance.
- X
- The four cases above demonstrate the light and dark side of
- XFunnelWeb's insistence that each macro be called exactly once. To resolve
- the conflict without reducing the strength of the checking, FunnelWeb
- provides two special sequences \p{@Z} (for \b{Z}ero) and \p{@M} (for \b{M}any)
- that can be attached to macro definitions. Presence of the
- X\p{@Z}\xx{@Z}{tutorial}
- tag allows the designated macro to be called zero times.
- Presence of the
- X\p{@M}\xx{@M}{tutorial}
- tag allows the designated macro to be called more than once.
- A single macro may carry both tags.
- It is always true that all macros are allowed to be called exactly once.
- X
- Here is the revised program with the errors fixed,
- by eliminating or adding macro calls, or by adding tags.
- Try processing the file now. There should be no errors.
- X
- X\begin{verbatim}
- X@O@<hello.c@>==@{@-
- X@<Include Files@>
- X@<Function@>
- X@<Main Program@>
- X@}
- X
- X@$@<Main Program@>==@{@-
- main()
- X{
- X doit();
- X}
- X@}
- X
- X@$@<Function@>==@{@-
- void doit()
- X{
- X int i;
- X for (i=0;i<10;i++)
- X {
- X @<Print@>
- X @<Print@>
- X }
- X}@}
- X
- X@$@<Print@>@M==@{@-
- printf("Hello World!");
- printf("\n");@}
- X
- X@$@<Scan@>@Z==@{scanf@}
- X
- X@$@<Include Files@>==@{@-
- X#include <stdio.h>
- X#include <stdlib.h>@}
- X\end{verbatim}
- X
- X\subsection{Indentation}
- X\xx{indentation}{macro calls}
- X
- The body of the \p{print} macro of the previous example
- contains two lines of text.
- A literal substitution of this macro's body in its context would result in:
- X
- X\begin{verbatim}
- X {
- X printf("Hello World!");
- printf("\n");
- X printf("Hello World!");
- printf("\n");
- X }
- X\end{verbatim}
- X
- But instead, it comes out as (have a look at this part of \p{hello.c} now):
- X
- X\begin{verbatim}
- X {
- X printf("Hello World!");
- X printf("\n");
- X printf("Hello World!");
- X printf("\n");
- X }
- X\end{verbatim}
- X
- The explanation is that FunnelWeb indents each line of multiline macros
- by the level of indentation at the point of call.
- This means that, as in the case above, program texts, which are usually
- highly indented, come out looking \dq{right}.
- X
- In other circumstances, where the model of the text is one dimensional,
- XFunnelWeb's indentation could become an impediment or even a danger.
- In these cases, it
- can be switched off by including the FunnelWeb \newterm{pragma} line
- X
- X\begin{verbatim}
- X@p indentation = none
- X\end{verbatim}
- X
- anywhere in the input file.
- X
- One of the design goals of FunnelWeb is to allow the user total control over
- the product files. This contrasts with the approach of Knuth's WEB\x{WEB}
- system
- X\paper{Knuth83} (upon which FunnelWeb is based), which mangles the input
- text at the Pascal\x{Pascal} program syntax level, truncating identifiers,
- converting
- the text to upper case, and paragraphing text. Here is an example of part of
- a Pascal program produced by WEB\xx{output}{WEB}
- X(from page~14 of \paper{Knuth83}):
- X
- X\begin{verbatim}
- IF R=0 THEN XREF[P]:=XREFPTR ELSE XMEM[R].XLINKFIELD:=XREFPTR;END;{:51}
- X{58:}FUNCTION IDLOOKUP(T:EIGHTBITS):NAMEPOINTER;LABEL 31;
- VAR I:0..LONGBUFSIZE;H:0..HASHSIZE;K:0..MAXBYTES;W:0..1;
- L:0..LONGBUFSIZE;P:NAMEPOINTER;BEGIN L:=IDLOC-IDFIRST;{59:}
- H:=BUFFER[IDFIRST];I=IDFIRST+1;
- WHILE I<IDLOC DO BEGIN H:=(H+H+BUFFER[I])MOD HASHSIZE;I=I+1;END{:59};
- X\end{verbatim}\checked{I can't believe I actually typed this mess in.}
- X
- Knuth's theory is that the program generated by a literate programming
- system should be
- treated as object code and hence should look like object code
- too.\x{object code} While this
- may be an admirable approach in the long run, the present programming
- environment is one of faulty compilers and buggy tools.
- The FunnelWeb view is that, in this environment,
- the programmer needs all the help he can get
- and that therefore he should be allowed total control over
- the product file. Another reason for FunnelWeb's providing total
- control over the product file, is that FunnelWeb is intended to be
- target language independent, and so even if Knuth's view were adopted, it
- would not be clear what a legitimate transformation of the text could be.
- X
- X\subsection{Additive Macros}
- X\xx{additive}{macros}
- X
- Sometimes it is convenient to build up the definition of a macro in
- stages throughout the input file. In FunnelWeb, this can be done using
- an \newterm{additive macro}.
- An additive macro is identical to an ordinary macro except
- that\xx{tutorial}{==}\xx{tutorial}{+=}
- X
- X\begin{enumerate}
- X\item It has \p{+=} instead of \p{==}.
- X\item It can be defined in one or more parts throughout the input file.
- The definition of the macro is the concatenation of all the parts in the
- order in which they appear.
- X\end{enumerate}
- X
- The following example shows how additive macros
- can be used to scatter and regroup information, in this
- case assisting in the lucid construction of a
- data abstraction\xx{data}{abstraction} in a language (Pascal\x{Pascal})
- that does not support them explicitly.
- X
- X\begin{verbatim}
- X@!******************************
- X
- X@O@<prog.pas@>==@{@-
- program adt(input,output);
- X@<Types@>
- X@<Variables@>
- X@<Procedures@>
- begin startproc; end.
- X@}
- X
- X@!******************************
- X
- X@$@<Types@>+=@{@-
- type buffer_type =
- X record
- X length : integer;
- X buf : array[1..100] of char;
- X end;
- X@}
- X
- X@$@<Variables@>+=@{@-
- bigbuf : buffer_type;
- X@}
- X
- X@$@<Procedures@>+=@{@-
- procedure buf_init (var b : buffer_type ) {Body of buf_init}
- procedure buf_add (var b : buffer_type; ch : char) {Body of buf_add}
- procedure buf_get (var b : buffer_type; var ch : char) {Body of buf_get}
- X@}
- X
- X@!******************************
- X
- X@$@<Types@>+=@{@-
- type complex_type = record r,i : real; end;
- X@}
- X
- X@$@<Procedures@>+=@{@-
- procedure cm_set (var c: complex_type; a,b: real) {Body of cm_set}
- procedure cm_add (a,b: complex_type; var c: complex_type) {Body of cm_add}
- X{Other procedures and functions}
- X@}
- X
- X@!******************************
- X
- X{...more pieces of program...}
- X
- X@!******************************
- X\end{verbatim}
- X
- It is important to remember that the definition of each macro does not change
- throughout the input file. FunnelWeb parses the entire input file and
- assembles all the macro definitions before it even starts to expand macros.
- As a result, each additive macro can only have one definition, and that
- definition is the concatenation of all its parts.
- X
- The example above shows how additive macros can be used to rearrange the
- presentation of a computer program in the order in which the user wishes
- to discuss it rather than the order in which the compiler requires that it
- be consumed. It is easy, however, to abuse the feature of additive macros.
- In many cases, the same effect can be obtained more clearly by replacing
- each part of an additive macro in-situ using uniquely named non-additive
- macros, and then collect them together as a group at the point where the
- additive macro is called. Doing this is more work, and is more error
- prone, but can result in a clearer exposition.
- The following program illustrates this alternative approach.
- X
- X\begin{verbatim}
- X@!******************************
- X
- X@O@<prog.pas@>==@{@-
- program adt(input,output);
- X@<Types@>
- X@<Variables@>
- X@<Procedures@>
- begin startproc; end.
- X@}
- X
- X@$@<Types@>==@{@-
- X@<Buffer type@>
- X@<Complex type@>
- X@}
- X
- X@$@<Variables@>==@{@-
- X@<Buffer variable@>
- X@}
- X
- X@$@<Procedures@>==@{@-
- X@<Buffer procedures@>
- X@<Complex procedures@>
- X@}
- X
- X@!******************************
- X
- X@$@<Buffer type@>==@{@-
- type buffer_type = record
- X length : integer;
- X buf : array[1..100] of char;
- X end;
- X@}
- X
- X@$@<Buffer variable@>==@{@-
- bigbuf : buffer_type;
- X@}
- X
- X@$@<Buffer procedures@>==@{@-
- procedure buf_init(var b : buffer_type) {Body of buf_init}
- procedure buf_add(var b : buffer_type; ch : char) {Body of buf_add}
- procedure buf_get(var b : buffer_type; var ch : char) {Body of buf_get}
- X@}
- X
- X@!******************************
- X
- X@$@<Complex type@>==@{@-
- type complex_type = record r,i : real; end;
- X@}
- X
- X@$@<Complex procedures@>+=@{@-
- procedure cm_set(var c: complex_type; a,b : real) {Body of cm_set}
- procedure cm_add(a,b : complex_type; var c: complex_type) {Body of cm_add}
- X{Other procedures and functions}
- X@}
- X
- X@!******************************
- X
- X{...more pieces of program...}
- X
- X@!******************************
- X\end{verbatim}
- X
- One of advantages of FunnelWeb (and literate programming in general) is that
- X(as shown above) it allows the user to lay out the program in whatever order is
- desired\xx{program}{layout}
- with near total independence from the ordering requirements of the
- target programming language.
- X
- Additive macros are allowed to be tagged with \p{@Z} and \p{@M} just as other
- macros can, but the tags must appear only on the first definition of the
- macro. Additive macros cannot be connected directly to product files.
- X
- X\subsection{Parameterized Macros}
- X\xx{parameterized}{macros}
- X
- No self-respecting macro preprocessor would be complete without some form
- of macro parameterization, and FunnelWeb is no exception. FunnelWeb allows
- each macro to have from zero to nine formal parameters\xx{formal}{parameters}
- named \p{@1}\x{@1...}, \p{@2},
- X\p{@3}, \p{@4}, \p{@5}, \p{@6}, \p{@7}, \p{@8}, and \p{@9}.
- X
- To define a macro with one or more parameters, insert a formal parameter
- list\xx{formal}{parameters}
- just after the macro name in the macro definition. Because macro
- parameters have fixed names (\p{@1}$\ldots$\p{@9}), there is no need to
- specify the names of formal parameters in the formal parameter list.
- All that need be conveyed is how many parameters the macro has.
- Here is an example of the definition of a macro having three parameters:
- X
- X\begin{verbatim}
- X@$@<While loop@>@(@3@)@M==@{@-
- X@1
- while (@2)
- X {
- X @3
- X }
- X@}
- X\end{verbatim}
- X
- To call a parameterized macro, an actual
- parameter\xx{actual}{parameters} list must be supplied
- that contains exactly the same number of actual parameters as there are
- formal parameters in the definition of the macro being called. An actual
- parameter list is delimited by \p{@(}\x{@(}
- and \p{@)},\x{@)} and parameters are
- X\i{separated} by \dqp{@,}.\x{@,} The actual parameters themselves are general
- XFunnelWeb expressions (see Chapter~\ref{chapdefinition}
- for the exact syntax) and can
- be inserted into the list directly or can be delimited by \p{@"}\x{@"} so as to
- allow some white space to assist in formatting the actual parameters.
- Here are some examples of calls of the \p{While loop} macro defined above.
- X
- X\begin{verbatim}
- X@! First form of actual parameters without whitespace and double quotes.
- X@<While loop@>@(x=1;@,x<=10@,printf("X=%u\n",x);@)
- X
- X@! Second form of actual parameters. The double quotes allow non-active
- X@! whitespace that helps to lay out the actual parameters neatly.
- X@! This call is functionally identical to the one above.
- X@<While loop@>@(
- X @"x:=1;@" @,
- X @"x<=10@" @,
- X @"printf("X=%u\n",x);@" @)
- X
- X@! The two forms can be mixed in a single call.
- X@<While loop@>@(x=1;@,x<=10@,
- X @"printf("X=%u\n",x);@" @)
- X\end{verbatim}
- X
- A few rules about parameterized macros are worth mentioning.
- Macros that do not have any parameters must have no formal or
- actual parameter lists.\xs{parameter list}{absent}
- Additive macros can have parameters, but the formal parameter list
- must appear in the first definition part only.
- X
- Here is another example of the use of parameterized macros. This time,
- parameters and macro calls are used in a FunnelWeb input file
- that constructs an $O(n)$ representation
- of a song\x{song}\x{twelve bugs of christmas} whose full size is
- X$O(n^2)$ in the number $n$ of unique
- lines.\x{rec.humor.funny}\xn{Pat}{Scannel}
- X
- X\begin{verbatim}
- X
- X@O@<Twelve_bugs.txt@>==@{@-
- The Twelve Bugs of Christmas
- X----------------------------
- X@<Verse@>@(@"first@" @,@<1@>@)
- X@<Verse@>@(@"second@" @,@<2@>@)
- X@<Verse@>@(@"third@" @,@<3@>@)
- X@<Verse@>@(@"fourth@" @,@<4@>@)
- X@<Verse@>@(@"fifth@" @,@<5@>@)
- X@<Verse@>@(@"sixth@" @,@<6@>@)
- X@<Verse@>@(@"seventh@" @,@<7@>@)
- X@<Verse@>@(@"eighth@" @,@<8@>@)
- X@<Verse@>@(@"ninth@" @,@<9@>@)
- X@<Verse@>@(@"tenth@" @,@<A@>@)
- X@<Verse@>@(@"eleventh@" @,@<B@>@)
- X@<Verse@>@(@"twelfth@" @,@<C@>@)
- X
- This song appeared in the internet newsgroup rec.humor.funny on 24-Dec-1991.
- It was contributed by Pat Scannell (scannell@@darkstar.ma30.bull.com).
- X@}
- X
- X@$@<Verse@>@(@2@)@M==@{@-
- XFor the @1 bug of Christmas, my manager said to me
- X @2
- X@}
- X
- X@$@<1@>@M==@{See if they can do it again.@}
- X@$@<2@>@M==@{Ask them how they did it and@+@<1@>@}
- X@$@<3@>@M==@{Try to reproduce it@+@<2@>@}
- X@$@<4@>@M==@{Run with the debugger@+@<3@>@}
- X@$@<5@>@M==@{Ask for a dump@+@<4@>@}
- X@$@<6@>@M==@{Reinstall the software@+@<5@>@}
- X@$@<7@>@M==@{Say they need an upgrade@+@<6@>@}
- X@$@<8@>@M==@{Find a way around it@+@<7@>@}
- X@$@<9@>@M==@{Blame it on the hardware@+@<8@>@}
- X@$@<A@>@M==@{Change the documentation@+@<9@>@}
- X@$@<B@>@M==@{Say it's not supported@+@<A@>@}
- X@$@<C@>@M==@{Tell them it's a feature@+@<B@>@}
- X\end{verbatim}
- X
- X\subsection{Macro Expansion}
- X\xx{macro}{expansion}
- X
- One of the strengths of FunnelWeb is that, when writing product files, it
- does not attempt to evaluate any text expression (\eg{}text block, parameter,
- macro call) in memory\xx{memory}{use of}
- and then write the result out. Instead, it always
- writes out what it is expanding dynamically and directly. This means that
- the user need not fear defining macros that expand to huge amounts of text
- and then calling those macros in other macros, or passing those huge macros
- as parameters to other macros. In all cases, FunnelWeb expands directly to
- the product file, and there can be no danger in running out of memory during
- expansion (except for running out of stack space and other
- marginally used resources in pathological cases).
- X
- The only thing to remember in this regard is that FunnelWeb always stores
- the entire \i{input} file and all included files, in their entirety in
- memory, for the duration of the run.
- X
- Here is an example, that illustrates how robust FunnelWeb is:
- X
- X\begin{verbatim}
- X@! FunnelWeb copes well with the following macro definitions.
- X@! (Providing that it has a little over ten megabytes of memory).
- X
- X@O@<woppa.txt@>==@{@<Quote@>@(@<Humungeous@>@)@+@}
- X
- X@$@<Quote@>@(@1@)==@{"@1"@}
- X
- X@$@<Humungeous@>==@{@-
- X...Ten Megabytes of Text...
- X@}
- X\end{verbatim}
- X
- X\subsection{Include Files}
- X\xx{include}{files}
- X
- XFunnelWeb provides a nested include file facility that can be used for a
- number of purposes. When FunnelWeb runs into a single line containing the
- special sequence \p{@i}\x{@i} followed by a blank, followed by a file name,
- it reads in the designated
- file and replaces the line containing the command (including the end of
- line marker at the end of the line) with the entire contents
- of the designated file. For example, if there was a file called
- X\p{camera.txt} containing the two lines:\xx{poem}{camera}\xx{animal}{poem}
- X
- X\begin{verbatim}
- X'Cos I shoot with a camera instead of a gun.
- The animals flock to be petted and fed,
- X\end{verbatim}
- X
- and another file called \p{poem.fw}
- containing the following four lines\x{shooting}
- X
- X\begin{verbatim}
- I like to go shooting, it's a whole lot of fun,
- X@i camera.txt
- Cos they know my camera isn't loaded with lead.
- X- RNW, 04-Jan-1991.
- X\end{verbatim}
- X
- Then, if FunnelWeb were to process \p{poem.fw}, the result would be
- as if FunnelWeb had read in:
- X
- X\begin{verbatim}
- I like to go shooting, it's a whole lot of fun,
- X'Cos I shoot with a camera instead of a gun.
- The animals flock to be petted and fed,
- X'Cos they know my camera isn't loaded with lead.
- X- RNW, 04-Jan-1991.
- X\end{verbatim}
- X
- XFunnelWeb expands include files before it starts scanning and parsing the
- included text. The result is that include files can contain anything that
- can be found in a FunnelWeb file. The following example illustrates
- the level at which the include mechanism operates. If \p{main.fw} contains
- X
- X\begin{verbatim}
- X@O@<output.dat@>==@{@-
- X@i inc.fw
- This is the text of the sloth macro.
- X@}
- X\end{verbatim}
- X
- and inc.fw contains
- X
- X\begin{verbatim}
- X@<Sloth@>
- X@}
- X
- X@$@<Sloth@>==@{@-
- X\end{verbatim}
- X
- Then if FunnelWeb were applied to \p{main.fw}, it would see:
- X
- X\begin{verbatim}
- X@O@<output.dat@>==@{@-
- X@<Sloth@>
- X@}
- X
- X@$@<Sloth@>==@{@-
- This is the text of the sloth macro.
- X@}
- X\end{verbatim}
- X
- which it would process in the normal manner. The only special
- sequence processing that takes place at a level lower
- than include files is the processing of the \p{<special>=<newspecial>}
- sequence which changes the special character.\xx{special character}{changing}
- X
- A few other facts about include files are worth mentioning here. Include
- files inherit the directory specification supplied using the \p{+I} command
- line option. The special character is saved at the start of each include
- file and restored to its previous value at the end of each include file.
- Include files can be nested up to ten levels.
- Recursive included files\xx{include files}{recursive}
- will always cause an infinite recursion as there
- is no bottoming out mechanism available.
- Include files
- must contain an integer number of lines (\ie{}the last line must be
- terminated with an end of line marker). Once FunnelWeb has seen
- X\dqp{@i\ } at the start of a line, it will grab the rest of the
- line raw and treat it as a file name. There is no place on the
- line for things like FunnelWeb comments (see later) or extraneous text.
- X
- Include files can be used for many purposes, but are particularly useful for
- hauling in macro libraries.\xx{macro}{libraries}
- X
- X\section{Typesetting Facilities}
- X\xx{tutorial}{typesetting}
- X
- The first half of this tutorial focuses solely on the macro facilities
- of FunnelWeb (which it more or less covers completely). As a result,
- the example documents you have seen so far have been gross
- distortions of \dq{normal} FunnelWeb documents which often contain as much
- documentation as
- code.\x{documentation vs code}\x{code vs documentation}\footnote{As
- an example, the author used
- XFunnelWeb to develop a largish computer program and found that on average
- his style of using FunnelWeb resulted in about 30\% documentation and
- X70\% macros (code) (measured by numbers of lines).}
- While there are applications where FunnelWeb can be used solely
- as a macro preprocessor, most applications will use its
- typesetting facilities as well.
- X
- This section restores the balance in this tutorial
- by presenting FunnelWeb's typesetting facilities.
- X
- X\subsection{Overview}
- X\xx{overview}{typesetting}
- X
- The macro definitions discussed in the macro tutorial completely define
- the contents of the product files that FunnelWeb will generate. These macro
- definitions can be arranged in any order and nothing external to them
- can affect the contents of the product files. The macros
- can be thought of as a group of self-contained islands.
- X
- Although FunnelWeb will can process the macros all on their own,
- the full power of FunnelWeb
- is realized only when the macros are surrounded by a sea of documentation.
- This sea can take two forms: directives and free text.
- Some of the directives control things such as the maximum input line
- length. However, most of them are typesetting directives that affect
- the printed documentation.
- Thus a FunnelWeb document can be viewed as a sequence
- of \newterm{macro definitions},
- X\newterm{directives}, and \newterm{free text}.
- X
- Unlike the product files which consist of unscrambled macro calls,
- the documentation file is more or less a
- direct representation of the input file. Each part of the input file
- appears in the documentation file in the order in which it appears in the
- input file. However, each different kind of part is
- typeset\footnote{Here the term \dq{typeset} is used loosely to refer to
- XFunnelWeb's generation of typesetter commands for each construct in the
- input file. Strictly, the term should be used only to describe the actions
- of a typesetter program (\eg{}\TeX{}).} in a different
- manner. Macros are typeset in a particular style, with the macro body
- appearing in \p{tt font} (see some FunnelWeb printed documentation for
- an example). Typesetter directives have specific defined
- effects (more later).
- XFree text is typeset exactly as it is, except that each block of text
- between blank lines is filled and justified as a paragraph.
- X
- The following example demonstrates how all this works. Type in the following
- as \p{example.fw} and run it through FunnelWeb with the
- command \dqp{fw~example~+t}. The \dqp{+t} instructs FunnelWeb to generate
- a documentation file called \p{example.tex}.
- Run the file through \TeX{} and print it.
- XExamine the files \p{example.out} and \p{example.tex}.
- X
- X\begin{verbatim}
- You are reading some free text before the macro. Free text can consist
- of any text (not containing the FunnelWeb special character) including
- typesetter commands
- such as $, %, #, and \TeX{} which
- will be typeset to appear exactly as they do in the input file!
- Look out! Here comes a macro!
- X
- X@O@<example.out@>==@{@-
- This text is part of
- a macro definition.
- X@}
- X
- This is free text following the macro. This sentence contains
- two @{inline@} typesetter @/directives@/.
- Now here is a non-inline typesetting directive.
- X
- X@t new_page
- X
- This sentence will appear on the next page.
- X\end{verbatim}
- X
- At the top of the \p{example.tex} documentation file will be a set of \TeX{}
- macro definitions. The \TeX{} code corresponding to the input above
- appears at the end of the file. It should look something like this.
- X
- X\begin{verbatim}
- You are reading some free text before the macro. Free text can consist
- of any text (not containing the FunnelWeb special character) including
- typesetter commands
- such as \$, \%, \#, and $\backslash$TeX$\{$$\}$ which
- will be typeset to appear exactly as they do in the input file!
- Look out! Here comes a macro!
- X
- X\fwbeginmacro
- X\fwfilename{example.out}{1}\fwequals \fwodef \fwbtx[This text is part of
- a macro definition.
- X]fwetx=%
- X\fwcdef
- X\fwbeginmacronotes
- X\fwisafile{This macro is attached to an output file.}
- X\fwendmacronotes
- X\fwendmacro
- X
- This is free text following the macro. This sentence contains
- two \fwlit{inline} typesetter \fwemp{directives}.
- Now here is a non-inline typesetting directive.
- X
- X\fwnewpage
- X
- This sentence will appear on the next page.
- X\end{verbatim}
- X
- The following points explain the \p{example.tex} file.
- X
- X\narrowthing{You don't have to know TeX:}{If you don't know
- X\TeX{}, don't pay too much
- attention to this section. You don't need to know \TeX{} to use FunnelWeb.}
- X
- X\narrowthing{In order:}{FunnelWeb has merely transformed the
- input. It hasn't rearranged it.}
- X
- X\narrowthing{Free text:}{Most of the free text has been simply copied over.
- The \TeX{} typesetter justifies and fills all paragraphs fed to it by
- default, so most of the text has just been copied verbatim.}
- X
- X\narrowthing{TeX codes:}{The characters and sequences which
- X\TeX{} treats as special have been neutralized in the documentation
- file. For example, \dqp{\$} has become \dqp{\bs\$}. By
- default, FunnelWeb allows the user to write any text as free text and not
- have to worry about accidentally invoking typesetter features.}
- X
- X\narrowthing{fw sequences:}{The \p{fw} sequences (\eg{}\p{\bs{}fwbeginmacro})
- invoke \TeX{} macros defined
- earlier in the documentation file (and not shown here).}
- X
- X\narrowthing{The macro:}{The macro is typeset using a set of predefined
- X\TeX{} macros. See the printed documentation to see what this looks like
- on paper.}
- X
- X\narrowthing{Typesetter directives:}{Unlike the \TeX{}
- command sequences (which
- were neutralized), the FunnelWeb typesetter directives turn into \TeX{} macro
- calls. For example, \dqp{@\{inline@\}} became \dqp{\bs{}fwlit\{inline\}}.}
- X
- In summary, FunnelWeb produces typeset documentation that transforms,
- but does not reorder, the input file. Macros are typeset in a specific
- style. FunnelWeb typesetter directives have particular well-defined effects.
- XFree text is filled and justified, but will otherwise appear in the
- printed documentation exactly as it appears in the input file.
- X
- X\subsection{Typesetter Independence}
- X\xx{typesetter}{independence}
- X
- Although the current version of FunnelWeb can only generate documentation
- files in \TeX{} form,
- it encourages typesetter independence
- by neutralizing all \TeX{} control sequences before writing them out. The
- result is that you don't have worry about upsetting or depending on \TeX{}
- by accidentally including some special character or sequence. By default your
- input file is \newterm{typesetter independent}.
- X
- This scheme differs from other literate programming tools, including
- all earlier versions of FunnelWeb, which copy their free text directly
- to the documentation file, the justification being that the programmer
- can use the full power of the typesetter language to describe the program.
- The disadvantages of doing this are first that the
- programmer is required to know the typesetting language and second that
- the input file becomes typesetter dependent. FunnelWeb avoids these problems
- by knobbling the free text be default.
- X
- However, FunnelWeb does provide a trapdoor for those who want their
- free text to be fed directly to \TeX{}. To open the trapdoor,
- simply include the following pragma somewhere in your input file.
- X
- X\begin{verbatim}
- X@p typesetter = tex
- X\end{verbatim}
- X
- See Section~\ref{typesetterpragma} for more information.
- X
- XFunnelWeb leaves the degree to which
- the user wishes to bind a particular document to a particular typesetter
- up to the user. In some cases, the extra typesetting power may compensate
- for the lack of portability. However, as a rule, it is best to
- avoid typesetter-specific commands, so as to allow your input files to
- be formatted at a later date for different typesetters.
- XFunnelWeb includes a number of its own typesetter commands so as to
- support typesetter-independent input files.
- The following sections describe some of these commands. In particular,
- the next section describes the most powerful FunnelWeb typesetting directives
- which allow the user to structure the document hierarchically.
- X
- X\subsection{Hierarchical Structure}
- X\xx{hierarchical}{structure}
- X
- The tree structure is one of the most effective structuring tools that
- exists, deriving its power from the principal of divide and conquor.
- So effective is it that the internal organization of
- most technical books are tree
- structures which are concisely summarized in the table of contents.
- In contrast, computer programs
- are usually presented as flat sequences of text to be consumed by an
- anonymous compiler.
- X
- In order to bring program documentation up to the structural
- sophistication commonplace in technical books, FunnelWeb provides five levels
- of section headings\xx{section}{headings}
- implemented by the five special sequences \p{@A},\x{@A...} \p{@B},
- X\p{@C}, \p{@D}, and \p{@E}. These must always appear at the start of a line.
- X\p{@A} is the highest level section
- X(\eg{}like \LaTeX{}'s \p{\bs{}chapter}) and \p{@E} is the lowest level
- section (\eg{}like \LaTeX{}'s \p{\bs{}subsubsubsection}).
- Section headings can appear anywhere in
- the free text of a FunnelWeb input file (\ie{}anywhere except inside a
- macro definition).
- X
- XEach section heading\xx{name}{section} in a FunnelWeb document
- has an associated name.
- The name of a section can be provided explicitly by supplying it
- delimited by \p{@<} and \p{@>} immediately after the section sequence
- X(\eg{}\p{@A}), or implicitly by not providing an explicit name, in which
- case the section takes the name of the first macro defined between the
- section header in question and the following section header. An error is
- generated if a section has not been given an explicit name and does not
- contain any macro definitions. Here are some example headings:
- X
- X\begin{verbatim}
- X@A@<Feed the Penguins and Save the World@>
- X@B@<Feed the Penguins@>
- X@C@<Feed the little penguins@>
- X@C@<Feed the big penguins@>
- X@B@<Save the World@>
- X@C@<Save Europe@>
- X@C@<Save Africa@>
- X
- X@C This heading hasn't been given an explicit name, but will inherit the
- name \p{Save the rest of the world} from the macro definition below.
- X
- X@$@<Save the rest of the world@>@Z==@{...@}
- X\end{verbatim}
- X
- The feature of having unnamed sections inherit the name of the first
- macro defined within their scope is present because a common style of
- writing in FunnelWeb is to have one section per macro definition. Because,
- under this style,
- each section describes a single macro, it usually turns out that the
- macro name makes a good name for the section too. The inheritance mechanism
- prevents duplication of the name.\xx{section name}{inheritance}
- X
- Apart from the requirement that each section have an explicit or implicit
- name and that its special sequence appear at the start of a line, the only
- other restriction on section headings is that a section heading at level
- X$n$ cannot appear immediately after a section heading at level $n-1$ or less.
- In other words, the hierarchy cannot be broken. For
- example, an \p{@C} cannot appear after an \p{@A} heading unless there
- is an intervening \p{@B} heading.
- X
- X\begin{verbatim}
- X@A@<The Top Heading@>
- X@C@<Level C here is not allowed after an A and will cause an error@>
- X\end{verbatim}
- X
- This rule extends to the start of the
- file; if there are any headings at all, the first one must be an \p{@A}
- heading. The following file, while short, is in error.
- X
- X\begin{verbatim}
- This FunnelWeb input file is in error because its first section heading
- is at level C rather than level A.
- X@C@<2@>
- X\end{verbatim}
- X
- X\subsection{Understanding the Printed Documentation}
- X
- Type in the following file, and use FunnelWeb and \TeX{} to generate the
- corresponding printed
- documentation.\xx{programmer's}{cheer}\xx{hacker's}{cheer}
- X\xx{hacker's}{dictionary}
- X
- X\begin{verbatim}
- X@A@<Table of Contents@>
- X
- X@t table_of_contents
- X
- X@A@<Macros for Moral Support@>
- X
- The following macro contain comments that provide moral support in the
- output code.
- X
- X@$@<Programmer's Cheer@>@M==@{
- X-- Shift to the left!
- X-- Shift to the right!
- X-- Pop up, push down!
- X-- Byte! Byte! Byte!
- X-- (From "The New Hacker's Dictionary").
- X@}
- X
- The next macro is similar but is distributed throughout the program.
- X@$@<Hacker's Cheer@>+=@{@+-- Pointer to the left@+@}
- X
- X@A@<An Extremely Imperative Stack Abstraction@>
- X
- X@B@<Define the Stack@>
- X@$@<Hacker's Cheer@>+=@{-- Pointer to the right@+@}
- X@$@<Stack Type@>@Z==@{type stack = record ... end;@}
- X
- X@B@<Push the Stack@>
- X@$@<Hacker's Cheer@>+=@{-- Hack that code@+@}
- X@$@<Push Procedure@>@Z==@{@-
- procedure push(var b:stack; v:value); @<Programmer's Cheer@> {...}@}
- X
- X@B@<Pop the Stack@>
- X@$@<Hacker's Cheer@>+=@{-- Tight! Tight! Tight!@+@}
- X@$@<Pop Procedure@>@Z==@{@-
- procedure pop(var b:stack); @<Programmer's Cheer@> {...}@}
- X
- X@B@<Rough the Stack Up a Bit@>
- X@$@<Hacker's Cheer@>+=@{-- (RNW, 04-Jan-1991).@+@}
- X@$@<Rough Procedure@>@Z==@{@-
- procedure rough(var b:stack); @<Hacker's Cheer@> {...}@}
- X
- X@O@<dummy.txt@>==@{dummy@+@}
- X\end{verbatim}
- X
- An examination of the printed documentation reveals a lot about how
- XFunnelWeb's presentation works.
- X
- XFirst, notice how the \p{@t} typesetter directive
- at the top of the file has caused a table of contents to appear.
- This is one of FunnelWeb's typesetting features and is discussed in a later
- section. The table of contents shows that the sections have been
- numbered hierarchically.
- X
- Now take a look at the typeset macro definitions. Most important are the
- numbers in square brackets that follow each macro name. As well as
- numbering the headings \i{hierarchically}, FunnelWeb \i{independently}
- numbers
- the macro definitions \i{sequentially}. The first macro definition
- X(for \dq{Programmer's Cheer}) is numbered 1.
- The second (for \dq{Hacker's Cheer}) is numbered 2 and so on.
- Note that it is not macros that are numbered, but macro definitions.
- The distinction is necessary because some macros (such as the
- X\dq{Hacker's Cheer} macro) are additive.
- It is important to
- realize that there is no relationship between the numbers of the headings
- and the numbers of the macro definitions.
- X
- Now take a look at the notes beneath the body of each macro definition.
- All macro definitions are followed by a note indicating the definitions in
- which the macro is called. Additive macros have an additional list, listing
- the definitions in which they are defined.
- X
- XFinally, take a look at the macro \i{call} of \dq{Programmer's Cheer}
- in section~3.2 of the printed documentation.
- Macro calls are set in slanted roman (so that they can
- be distinguished from the \p{tt font} code) and are followed by
- the number of the defining macro definition. In this case, the macro
- was defined in definition~1. Further down, the call to
- the \dq{Hacker's Cheer} macro
- indicates that the macro was defined in definition~2. In fact the macro is
- additive and definition~2 is just the first of many definitions. To list
- all definitions in a call to an additive macro would be unnecessarily messy.
- X
- X\subsection{Literals and Emphasis}
- X\x{literal construct}\x{emphasis construct}
- X
- When writing about program code, it is often desirable to be able to indicate
- that a particular word or phrase be typeset in the same manner as the code
- being discussed. For example, one might talk about the variable \p{topval}
- or the procedure \p{stack\_pop} and wish for them to be typeset
- as they are in this sentence. This, of course,
- is simple to do using \TeX{} macros, but use of the
- X(more general) FunnelWeb typesetting directives to do the same work has the
- added benefit of keeping the document portable to other typesetters.
- X
- XFunnelWeb provides two in-text type modification constructs: \p{@\{...@\}}
- and \p{@/...@/}\x{@slash}\x{@braces}
- where $\ldots$ is raw text. The \p{@\{...@\}}
- construct sets the enclosed
- text in the same manner as the text of macro definitions is set. The
- X\p{@/...@/} construct emphasises its enclosed text in some
- typesetter-dependent fashion. Typically the emphasised text is set in
- italics.
- X
- Here is an example of how these constructs might be used:
- X
- X\begin{verbatim}
- The following procedure @{put_sloth@} writes the @{sloth@} variable to
- the output file. Note: @/The output file must be opened for writing
- at this point or the program will crash!@/
- X\end{verbatim}
- X
- X\subsection{Adding a Header Page}
- X\x{header page}
- X
- XFunnelWeb provides a few typesetter-independent typesetting constructs
- which are specifically designed for the construction of header pages.
- These constructs are usually best placed at the top
- of your input file, but can be placed anywhere the document if desired to
- create header pages right through. The two main restrictions on these
- constructs is that the \p{@t} must start at the start of a line (which
- cannot contain comments), and that the constructs cannot appear inside
- a macro definition. Here is what the top of an input file might look like:
- X
- X\begin{verbatim}
- X@t vskip 40 mm
- X@t title titlefont centre "Hairy Wombat"
- X@t title titlefont centre "Simulation"
- X@t vskip 10 mm
- X@t title smalltitlefont centre "A Program in Six Parts"
- X@t title smalltitlefont centre "Simulating the Life of Some Hairy Wombats"
- X@t vskip 20 mm
- X@t title normalfont left "By Zqitzypbuswapzra Ypongtatoslrtzz"
- X@t new_page
- X@t table_of_contents
- X@t new_page
- X\end{verbatim}
- X
- The \p{@t} at the start of each line indicates that each entire line is
- a typesetter directive.
- The \p{vskip}\xx{vskip}{directive}
- directive instructs FunnelWeb to skip some vertical space
- X(measured in millimetres). The \p{title} directive\xx{title}{directive}
- instructs FunnelWeb to
- position a string of text on a single line of its own. Options are
- provided for font and alignment. The first word after \p{title} is the font
- which can be one of (in decreasing order of size) \p{titlefont},
- X\p{smalltitlefont}, and \p{normalfont}. The second word after \p{title} is
- the desired alignment of the text. The options here are \p{left}, \p{right},
- and \p{centre}. The \p{new\_page}
- directive\xx{newpage}{directive}
- instructs FunnelWeb to skip to a new page. Finally, the
- X\p{table\_of\_contents} directive\xx{table of contents}{directive}
- instructs FunnelWeb to insert a table of
- contents at that point in the text.
- X
- X\subsection{Comments}
- X\x{comments}
- X
- A FunnelWeb comment commences with the \p{@!}\x{@!} sequence and continues up to,
- but not including, the end of line marker at the end of the line that the
- comment sequence is on. Comments can be placed on any line except
- X\p{@i} include, \p{@p} pragma, and \p{@t} typesetter directive lines.
- X
- The text following the FunnelWeb comment sequence \p{@!} will not appear
- in the product files or the documentation file. It is
- only for the eyes of those who bother to look at the original \p{.fw}
- input file. Typically FunnelWeb comments are used to describe the way in
- which particular FunnelWeb constructs are being used. Example:
- X
- X\begin{verbatim}
- X@! This macro is really revolting. Please forgive me. I had to do it!
- X@$@<Revolt Me@>==@{@-
- X@#X@(@#Y@(@#Z@,@"@#Z@"@)=6@,Teapot@,@"@#Q@(45@)@"@,Tiger@)@}
- X\end{verbatim}
- X
- X\section{A Complete Example}
- X\xx{complete}{example}\xx{FunnelWeb}{Example}
- X
- To finish off the chapter, a complete example of a FunnelWeb input file
- is presented. Although unrealistically short, it gives a better
- idea of what a typical FunnelWeb \p{.fw} file looks like.
- X
- X\begin{verbatim}
- X@!---------------------------------------!
- X@! Start of FunnelWeb Example .fw File !
- X@!---------------------------------------!
- X
- X@t vskip 40 mm
- X@t title titlefont centre "Powers:"
- X@t title titlefont centre "An Example of"
- X@t title titlefont centre "A Short"
- X@t title titlefont centre "FunnelWeb .fw File"
- X@t vskip 10 mm
- X@t title smalltitlefont centre "by Ross Williams"
- X@t title smalltitlefont centre "26 January 1992"
- X@t vskip 20 mm
- X@t table_of_contents
- X
- X@A@<FunnelWeb Example Program@>
- X
- This program writes out each of the first @{p@} powers of the first @{n@}
- integers. These constant parameters are located here so that they are easy to
- change.
- X
- X@$@<Constants@>==@{@-
- n : constant natural := 10; -- How many numbers? (Ans: [1,n]).
- p : constant natural := 5; -- How many powers? (Ans: [1,p]).@}
- X
- X@B Here is the outline of the program. This FunnelWeb file generates a single
- Ada output file called @{Power.ada@}. The main program consists of a loop that
- iterates once for each number to be written out.
- X
- X@O@<Power.ada@>==@{@-
- X@<Pull in packages@>
- X
- procedure example is
- X @<Constants@>
- begin -- example
- X for i in 1..n loop
- X @<Write out the first p powers of i on a single line@>
- X end loop;
- end example;
- X@}
- X
- X@B In this section, we pull in the packages that this program needs to run. In
- fact, all we need is the IO package so that we can write out the results. To use
- the IO package, we first of all need to haul it in (@{with text_io@}) and then
- we need to make all its identifiers visible at the top level (@{use text_io@}).
- X
- X@$@<Pull in packages@>==@{with text_io; use text_io;@}
- X
- X@B Here is the bit that writes out the first @{p@} powers of @{i@}. The power
- values are calculated incrementally in @{ip@} to avoid the use of the
- exponentiation operator.
- X
- X@$@<Write out the first p powers of i on a single line@>==@{@-
- declare
- X ip : natural := 1;
- begin
- X for power in 1..p loop
- X ip:=ip*i;
- X put(natural'image(ip) & " ");
- X end loop;
- X new_line;
- end;@}
- X
- X@!---------------------------------------!
- X@! End of FunnelWeb Example .fw File !
- X@!---------------------------------------!
- X\end{verbatim}
- X
- X\section{Summary}
- X
- This chapter has provided an introduction to FunnelWeb and a tutorial
- that covers most of its features. FunnelWeb's functionality can be split into
- two parts: a macro preprocessor, and support for typesetting.
- The reader should be aware that
- the examples in this chapter, constructed as they were to demonstrate
- particular features of FunnelWeb, do not present a realistic picture
- of the best use of the tool. Only the final example of this chapter
- comes close.
- The reader should study this last example carefully
- and then write some real
- programs using FunnelWeb before proceeding to Chapter~\ref{chapadvanced}
- which provides more advanced information. At this stage it does not
- particularly matter exactly how you use Funnelweb, as everyone develops
- their own style anyway. The important thing is to try it.
- X
- X%==============================================================================%
- X% End of Ch1.tex %
- X%==============================================================================%
- END_OF_FILE
- if test 70598 -ne `wc -c <'userman/u_ch1.tex'`; then
- echo shar: \"'userman/u_ch1.tex'\" unpacked with wrong size!
- fi
- # end of 'userman/u_ch1.tex'
- fi
- echo shar: End of archive 19 \(of 20\).
- cp /dev/null ark19isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 20 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-