The principle concepts of WEB programming are laid out in Knuth's book, the reference to which was given in section INTRODUCTION to @FWEB{}. @FWEB{} follows most conventions introduced by WEB and CWEB, except that the names of some commands have been changed for consistency, symmetry, and/or clarity.
Following Knuth's original design, @FWEB{} consists of two processors, @FTANGLE{} and @FWEAVE{}. Both operate on a single source file, say `test.web'. @FTANGLE{} produces compilable code, say `test.c', whereas @FWEAVE{} produces a TeX file, `test.tex', that can (in principle) be processed with either TeX or LaTeX. (If a file `test.tex' already exists, @FWEAVE{} will ask for confirmation before overwriting it if it does not think that the file was created by a previous run of @FWEAVE{}.)
The output file produced by @FTANGLE{} is not intended for human eyes
(or for editors!); it is for compiling only. All changes to the code
should be made to the web
file, since changes made directly to
the output file would be overwritten the next time the web
source
is tangled. In an attempt to discourage messing with @FTANGLE{}'s
output file, all unnecessary spaces are deliberately removed.
A common way of integrating @FWEB{} into ones program development is to
do all compilations through a make
file, into which one puts an
extra dependency line that explains how to produce the compilable output
file from the web
source. For example,
test.c: test.web ftangle test test.o: test.c gcc -c test test.c
With this approach, one is not so tempted to edit `test.c'.
@FWEB{} development is now based on LaTeX; Plain TeX is no longer supported. For detailed descriptions of the LaTeX support, see section LaTeX support.
An @FWEB{} source file is structured into sections, which correspond to logical subunits of the code (either a function or a fragment of a function). Each section consists of three parts, each of which is optional: the
- TeX part;
- definition part; and
- code part.
When @FTANGLE{} outputs code, it can combine the code parts of (possibly noncontiguous) sections into larger units called modules, as explained in section Modules.
With the aid of sections, one's possibly huge and logically complex code can be broken down into bite-sized pieces, each one easily comprehensible. Since sections may correspond to only a small part of a function or subroutine, 1000-line main programs (they still exist!) should become a thing of the past.
Since sections can be combined into modules, there is no need for sections that must be physically contiguous in the output file to be contiguous in the source file. This allows for great flexibility in structuring the documentation of the code.
A simple example of an @FWEB{} source file consisting of three sections is as follows:
@n/ % Set FWEB language to Fortran, and recognize short // comments. \Title{example.web} % \Title is an FWEB TeX macro. \author{J. A. Krommes} % \author is a LaTeX macro. @* INTRODUCTION. This code is intended to illustrate the use of the |write| statement. It also provides a simple example of the \FWEB\ macro preprocessor. @m A_CONSTANT 1.2345 // \FWEB\ preprocessor macro definition. @a program main call compute end @ The computational routine is pretty boring. @a subroutine compute write(*,*) 'Macro value = ', A_CONSTANT end @* \INDEX.
Commands to @FWEB{} are begun by the `@' symbol (see section @FWEB{} COMMANDS). In this example, the first command, `@n', sets the global language to FORTRAN-77. One should always begin one's code with a language-setting command.
In this example, the language command is invoked with an optional argument `/'. That is necessary in FORTRAN in order to tell @FWEB{} to use the short (single-line) comment form beginning with `//', which otherwise conflicts with the concatenation operator. See section `-n/': Recognize short comments [FORTRAN].
For more information about languages, see section LANGUAGES. For a fuller discussion of optional arguments, see section Setting the language.
The `@*' command begins a major or named section
(corresponding to LaTeX's \section
command); this command is
followed by the section name, terminated by a period. (The period is
essential; if it is omitted, weird errors may result.) Major sections
are entered in an automatically generated Table of Contents. They are
also printed at the top of each output page. If the full section name
is too long to so print, one can shorten it with an optional argument,
as in
@* [INTRO]INTRODUCTION.
The command `@*n' (not illustrated in the above example) begins a major (sub)section of level n, where `@*0' is equivalent to the simple `@*', `@*1' indicates a subsection, and `@*2' indicates a subsubsection. The highest permissible major level is 2 (a subsubsection). Such subsections are also entered in the Table of Contents. For more information, see section Sections in LaTeX.
As the example demonstrates, the name of the very last section, which
should be starred, should be `\INDEX'. Note the backslash;
`\INDEX' is a TeX macro. This command tells @FWEAVE{} to
write out the index in a special two-column format. By default,
`\INDEX' expands to `INDEX', but this name can be overridden
by the style-file parameter `index.name' (see section index.???
). For
more discussion of @FWEB{}'s indexing facilities, see section @FWEB{}'s INDEX..
Minor (unnamed) sections are begun by @ASP{} ("at-space"); these have no associated names and are not entered into the Table of Contents. A newline counts as a space.
All sections begin with (optional) TeX commentary. That can just be straight text; to input that, no knowledge of TeX is required. It can also include mathematical exposition or any of the other advanced features offered by TeX.
Whenever @FWEB{} is in TeX mode, one can temporarily shift into code mode by enclosing the code within vertical bars. That code is typeset just like code in the code part (see below), except that newlines are replaced by spaces. Thus, one can say things like
Consider the C code fragment `|@c for(i=0; i<10; i++){}|', which ...
(If the global language were C instead of FORTRAN, the `@c' inside the vertical bars would not be necessary.) The ability to switch back and forth between text mode and code mode at will allows for a very convenient and flexible style of exposition.
The TeX part is followed by an optional definition part. The beginning of the definition part is signaled by the appearance of any one of the commands `@d', `@f', `@m', `@v', or `@W' (explained later). In the previous example, the first section has a definition part consisting of one @FWEB{} macro definition (`@m'); the second section has no definition part. For more information, see section MACROS and PREPROCESSING.
(Failure to appreciate how easy it is to shift from part to part can get one into trouble. For example, don't write documentation such as `Consider the @m command', because the `@m' will inadvertently terminate the documentation part and begin the definition part. What one needs to do here is to use the literal `@', as in `@@m'.)
An unnamed code part is begun by `@a'. A named code part is begun by the appearance of a module name, such as `@<Global variables@>', followed by an equals sign; see section Modules. Within the code part, one can place any sequence of code or code fragments (they need not be complete subroutines) that are valid for the current language. (Setting the language is described in section LANGUAGES.) The code part is terminated by the next appearance of `@*' or @ASP{} (which signal the beginning of a new section), or by the end of file.
The portion of the source file before the first section (i.e., before
the first `@*' or @ASP{}) is called in limbo or
the limbo section.
The only `@' commands that are allowed in limbo (in addition to
`@@', which stands for the character `@' and is allowed
anywhere) are the language-changing commands, and one of those, such as
`@c', should appear. Other text in limbo is ignored by @FTANGLE{}
and is copied by @FWEAVE{} to the tex
output file. Thus, one can make or
issue TeX macro definitions in limbo that override the defaults in
@FWEB{}'s macro package `fwebmac.sty'. In the above example, see
the \Title
command. This is defined in `fwebmac.sty', and
basically issues LaTeX's \title
command.
(Another way of getting TeX text into the limbo section is by means of the `@l' command; see section `@l': Specify limbo text.)
LaTeX users may need to know that TeX commands in limbo are executed after the `\begin{document}' command (which is issued automatically in `fwebmac.sty'). For more information, see section LaTeX support.
The code parts of (possibly noncontiguous) sections can be combined into modules. For @FWEAVE{}, this is a logical combination, for purposes of cross-referencing different pieces of the code. But for @FTANGLE{}, the combination is physical; @FTANGLE{}'s output proceeds module by module.
Modules can be named or unnamed. There is exactly one unnamed module. The fundamental operation of @FTANGLE{} is that
@FTANGLE{ outputs the unnamed module}.
That output goes to a compilable file with an extension appropriate to the current language.
The contents of a module, either unnamed or named, consists of a mixture of code and comments. @FTANGLE{} ignores the comments; @FWEAVE{} treats them as TeX text. Within any TeX text, including comments, constructions delimited by `|...|' signify a temporary shift into code mode. (In the present design, one cannot enclose a comment within the vertical bars.)
The unnamed code module is introduced by the command `@a'. Subsequent uses of `@a' accrete code to the unnamed module. To repeat, the fundamental operation of @FTANGLE{} is that
@FTANGLE{ outputs the unnamed module}.
Thus, there must be at least one `@a' in the source file or @FTANGLE{} will output nothing.
(Why is the command called `@a'? Historically, it was the first letter of the alphabet, as befits its prominent status. However, one can also think of it as "accrete.")
Named modules represent logically-connected fragments of code.
A module name is specified by the construction
@< Arbitrary TeX text @>
Leading and trailing white space around the name text is ignored. The name text can include the `|...|' construction, which tells @FWEAVE{} to typeset a code fragment. Thus, module names can be highly explicit--for example,
@< Check that |x >= 0.0|; |abort| if not @>
To define a named module, replace the `@a' that begins the unnamed code part of a section by `@< module name @>='. If one uses this construction with the same name in a later section, the effect is to accrete to the contents of the module. Thus, a named module might ultimately consist of the code from sections 2, 5, and 9, for example.
To use a named module, simply use the name anywhere in a code part; @FTANGLE{} will insert the contents of the module at the point where the name is used. For example,
@c @ Here's how to use a named module. @a for(i=1; i<n; i++) @< Inner loop @>@; @ Here's how to define a named module. Definitions may occur after use. @< Inner...@>= { a[i] = i; }
There are several details to notice about the above example. First, @FWEAVE{} considers module names to be simple expressions (such as the single identifier x). In C, expressions are made into complete statements (as is required in the body of a for statement) by appending a semicolon. In this case, a pseudo-semicolon `@;' is appropriate; for more discussion of that, see section `@;': Pseudo-semicolon.
Second, after a name has appeared once in full, it may be abbreviated by a unique prefix followed by three periods, as demonstrated in the above example. By convention, a complete module name cannot be a subset of another. For example, `@<Test@>' and `@<Test of graphics@>' will elicit an error message.
Commonly, the first unnamed section in the code indicates its modular structure. For example, a C code might begin with
@c @* DEMO. @a @<Include files@>@; @<Typedefs@>@; @<Function prototypes@>@; @<Global variables@>@;
Subsequently one can accrete to the above named sections, as often as
desired and in any order. This way, definitions of global variables can
be introduced anywhere in the web
source file as logical and pedagogical
exposition dictates, but will
be guaranteed to appear at the top of the code. Function prototypes
could be handled this way as well; alternatively, they could all be
collected into one section, perhaps at the end of the source file. (The
above organization still guarantees that they will appear at the
beginning of the output.) Functions could be introduced one at a time
in subsequent unnamed sections.
Very rarely, one might try the following construction:
@ @a @< Left side @> = @< Right side @>@;
Here the intent is to construct an assignment statement. However, this will be flagged as an error because @FWEB{} thinks one is trying to define the named module `@<Left side@>', which one shouldn't be doing while in code mode. To make it work, just put the invisible expression `@e' (see section Pseudo (invisible) operators) before the equals sign.
The @FWEB{} processors perform their work in several distinct phases. (The following is somewhat technical. Scan it, then use it for reference later if necessary.)
@FTANGLE{} has two phases. In phase 1, the source file is read; in phase 2, compilable code is written out in the order specified by the web.
More specifically, phase 1
- discards TeX documentation;
- tokenizes the source;
- expands @FWEB{} preprocessor commands such as `@#if' (see section Preprocessing);
- expands `@'...'' (see section Conversion to ASCII), `@"..."' (see section `@"': Convert string to ASCII), and the binary notation `0b...' (see section Special considerations for C) [in FORTRAN, also the octal notation `0...' and the hexadecimal notation `0x...'];
- stores code text in appropriate modules;
- memorizes macro definitions (`@d' and `@m') (see section `@d': Define outer macro, and mark and section `@m': Define @FWEB{} macro, and mark).
Phase 2
- outputs outer macro definitions (`@d');
- outputs the unnamed module (`@a');
- expands @FWEB{} macros (`@m');
- expands built-in macros such as `$IF' or `$PI' (see section Built-in functions);
- translates RATFOR statements (see section RATFOR).
@FWEAVE{} has three phases. In phase 1, the source file is read and cross-reference information is collected. In phase 2, the source file is read again, then pretty-printed with some cross-reference information. (For discussion of pretty-printing, see section Pretty-printing.) In phase 3, an automatically-generated Index, List of Modules, and Table of Contents are written.
More specifically, phase 1
- tokenizes and stores identifiers and module names;
- collects cross-reference information (including, in C and C++, the scanning of `#include' files for `typedef' and/or `class' declarations (see section `-H': Scan C/C++ include files (@FWEAVE{}));
- stores limbo text definitions made with `@l' (see section `@l': Specify limbo text);
- collects information about overloaded operators (`@v') and identifiers (`@W'). See section `@v': Overload operator and section `@W': Overload identifier.
Phase 2
- outputs limbo text;
- outputs special TeX macros for overloaded operators;
- copies TeX material directly to output;
- treats material between vertical bars (`|...|') as code to be typeset;
- tokenizes and stores contents of each code section;
- analyzes code syntax and converts it to appropriate TeX macros.
Phase 3 writes out cross-reference information. (To eliminate some of that, see section `-x': Eliminate or reduce cross-reference information (@FWEAVE{})..) Specifically, it
- writes out the Index (`INDEX.tex' by default, but see section Output files and section Customizing @FWEAVE{}'s index);
- writes out a list of named modules (`MODULES.tex' by default, but see section Output files and section Customizing the module list);
- writes out macros to generate the Table of Contents. (Table of Contents information is actually processed by LaTeX, not @FWEAVE{}. The information is written to the `aux' file.)
Go to the first, previous, next, last section, table of contents.