diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /web/funnelAC/userman/u_ch3.tex |
Initial commit
Diffstat (limited to 'web/funnelAC/userman/u_ch3.tex')
-rw-r--r-- | web/funnelAC/userman/u_ch3.tex | 2986 |
1 files changed, 2986 insertions, 0 deletions
diff --git a/web/funnelAC/userman/u_ch3.tex b/web/funnelAC/userman/u_ch3.tex new file mode 100644 index 0000000000..7669732fc8 --- /dev/null +++ b/web/funnelAC/userman/u_ch3.tex @@ -0,0 +1,2986 @@ +%==============================================================================% +% Start of Ch3.tex % +%==============================================================================% +% +% Copyright +% --------- +% Copyright (C) 1992 Ross N. Williams. +% This file contains a chapter of the FunnelWeb User's Manual. +% See the main TeX file for this manual for further information. +% +%==============================================================================% + +\chapter{FunnelWeb Definition} +\label{chapdefinition}\xx{FunnelWeb}{definition} + +\section{Introduction} + +This purpose of this chapter is to provide a complete and consistent +definition of the FunnelWeb input language and the behaviour of the +FunnelWeb program. Usually, a chapter such as this is called a +\dq{reference manual}, but this chapter is intended to go further +by actually defining the language and program. This chapter takes +precedence over all other chapters and all implementations of FunnelWeb. +If an implementation contradicts this chapter, then the implementation +is wrong. + +This is the chapter that you should turn if you find yourself asking a +specific question about a specific aspect of FunnelWeb. In many +cases it will be convenient to access this chapter through the index. + +\section{Notation} +\x{notation} + +A particular variant of EBNF\xx{EBNF}{syntax} +(Extended Bachus Naur Form) will be used to +describe the FunnelWeb syntax. In this variant, literal strings are +delimited by double quotes (\eg{}\p{"string"}), optional constructs by +square brackets (\eg{}\p{[optional]}), and constructs repeated zero or +more times by braces (\eg{}\p{\{zeroormore\}}). Constructs to be repeated +a fixed number of times are enclosed in braces followed by a decimal +number indicating the number of times to be repeated +(\eg{}\p{\{sixtimes\}6}). Constructs to be +repeated one or more times are +enclosed in braces and followed by a \p{+} (\eg{}\p{\{oneormore\}+}). +The traditional BNF \dqp{::=} +is replaced by the visually simpler \dqp{=}. The traditional BNF angle +brackets are abandoned. + +Although FunnelWeb allows the special character to be changed using the +construct \dq{$<$special$>$=}, use of \dq{$<$special$>$} to refer to +FunnelWeb's special character is cumbersome and abstract. To simplify +the presentation, the default special character \dqp{@} is used throughout +this chapter to represent the special character. + +\section{Terminology} +\x{terminology} + +A specific terminology has arisen for dealing with FunnelWeb. Some +particularly useful examples are: + +\narrowthing{Journal file:}{An output file containing +a copy of the output sent to +the user's console during an invocation of FunnelWeb. In other systems, +this file is sometimes called a \dq{log file}.} + +\narrowthing{Product file:}{An output file, generated by the Tangle +component of +FunnelWeb, that contains the expansion of the macros in the input +file.\footnote{Other names considered for this were: +generated file, expanded file, result file, program file, and tangle file.}} + +A complete list of all the special FunnelWeb terminology appears in the +glossary. Be sure to refer to it if any of the terms used are unclear. + +\section{An Architectural Overview} +\xx{semantic}{architecture}\xx{FunnelWeb}{overview} + +An understanding of the internals of FunnelWeb assists with understanding +its operation (\figphases{}).\xx{execution}{phases} + +During a single run, FunnelWeb reads and +processes a single input file called the \newterm{input file} or +the \newterm{FunnelWeb file}. The file is processed by passing it through +a series of stages called \newterm{phases}. The result is that some +\newterm{output files} are generated. +A \newterm{journal file} is generated containing a copy of the messages that +appear on the console during the FunnelWeb run. A \newterm{listing file} +is created containing a summary of the run, including any error messages. +A \newterm{documentation} file is generated containing typesetter commands +that when fed into a typesetter program will result in +printed documentation. Finally, one or more \newterm{product files} +are generated containing the result of unscrambling the macro definitions +of the input file. + +These files need not all be generated on any particular FunnelWeb run. +Whether each output file appears is controlled by command line options. + +\begin{figure}[htbp] +\begin{verbatim} + + .fw Input File (FunnelWeb file) + V + +---------+ \ + | Scanner | | + +---------+ | + V | + +--------+ | + | Parser | | + +--------+ | + V | + +----------+ >-------+------------+ + | Analyser | | | | + +----------+ | | | + V | | | + +-----------+------------+ | V V + V V | | | + +--------+ +-------+ | | | + | Tangle | | Weave | | | | + +--------+ +-------+ / | | + | | | | + V V V V + Product Files Documentation File Listing File Journal File + +\end{verbatim} +\mylabel{\figphases{}: FunnelWeb's processing phases.}{% +% +FunnelWeb processes each input file in a sequence of phases. +If an error occurs during a phase, no subsequent phases are executed. +% +} +\end{figure} + +The phases are briefly described below. + +\narrowthing{The Scanner}{reads\x{scanner} the input file, expands +and reads in include files, +scans the input stream, processes pragmas and typesetter directives, +and parses all the +FunnelWeb special sequences. The result is a list of tokens that +is handed to the parser.} + +\narrowthing{The Parser}{reads\x{parser} +the scanner's token list and parses it, constructing a +document list\xx{document}{list} and a macro +table.\xx{macro}{table} which are passed to later phases.} + +\narrowthing{The Analyser}{examines\x{analyser} +the macro table generated by the parser +and performs a number of checks of the macro structures +that the parser could not make on its single pass. +For example, the +analyser detects and flags unused macros and recursive macros. The +analyser forms the final stage of FunnelWeb's front-end processing.} + +\narrowthing{Tangle}{expands certain macros in the macro table +to generate\x{tangle} one or more product files.} + +\narrowthing{Weave}{uses the document list to generate\x{weave} +a documentation file.} + +A single run through these phases constitutes a single invocation of +\newterm{FunnelWeb proper}. Most invocations of the +\newterm{FunnelWeb program} +will consist only of a single execution of FunnelWeb proper. However, +FunnelWeb also provides a command shell that provides many useful commands, +including a command to invoke FunnelWeb proper. Discussion of the command +shell is deferred until Section~\ref{commandshell}. + +\section{Diagnostics} +\label{diagnostics}\x{diagnostics} + +During execution, FunnelWeb proceeds cautiously with each of its phases, +only proceeding with the next phase if the previous phase has been +successful. This means that, when debugging +a FunnelWeb file, you may find that the number of errors \i{increases} +after you fix some of them, as you will be exposing yourself to the +next FunnelWeb phase. + +FunnelWeb employs five levels of diagnostics\xx{diagnostics}{levels of} +at different levels of +severity.\x{severity} +Severity is defined in terms of the level of activity at which the +diagnostic causes FunnelWeb to abort. + +\narrowthing{Warning:}{A warning\xx{warning}{severity} +does not cause FunnelWeb to terminate or +curtail its operation in any way, but serves merely to warn the user of +particular conditions that might be symptomatic of deeper problems.} + +\narrowthing{Error:}{An\xx{error}{severity} error causes +FunnelWeb to terminate processing of the +current input file at the end of the current phase. For example, if an +error occurs during scanning, FunnelWeb will continue scanning (and possibly +generate further scanning diagnostics), but will not invoke the parser.} + +\narrowthing{Severe Error:}{A\xx{severe}{severity} severe error +(or \dq{severe} for short) is the same +as an error except that FunnelWeb terminates the current phase immediately.} + +\narrowthing{Fatal Error:}{A\xx{fatal}{severity} fatal error +causes FunnelWeb not only to terminate +the current phase and run immediately, but also to terminate total +FunnelWeb processing immediately. A severe error will not cause a +FunnelWeb script to terminate, but a fatal error will. A fatal error +causes FunnelWeb to return control to the operating system.} + +\narrowthing{Assertion Error:}{An\xx{assertion}{severity} +assertion error occurs if FunnelWeb detects +an internal inconsistency, in which case FunnelWeb terminates immediately +and ungracefully. Such +an error can occur only if there are bugs in FunnelWeb. With luck, such +errors will be extremely rare.} + +FunnelWeb indicates the level of severity of each diagnostic that it issues +by starting each diagnostic either with the full name of the severity level +or with just the first letter of the severity level followed by a colon. + +FunnelWeb conveys the presence or absence of diagnostics at the operating +system level by returning \p{EXIT\_SUCCESS}\xx{return}{status} +status if no +diagnostics occurred during the run and \p{EXIT\_FAILURE} status +if one or more +diagnostics (including warnings) +occurred during the run.\footnote{From +the symbols of the ANSI standard C library \p{stdlib.h}. +See \paper{Kernighan88}, p.252.} + + +\section{Typesetter Independence} +\xx{typesetter}{independence} + +One of the design goals of FunnelWeb was to provide a \i{target-language} +independent literate programming system. This goal has been achieved +simply by treating the text written to the product file +as homogeneous and typesetting +it in \p{tt font}. A secondary goal was to provide +a \i{typesetter} independent literate programming +system. By this is meant that it be possible to create FunnelWeb input files +that do not contain typesetter-specific commands. +To a lesser extent this goal has also been achieved. + +The difficulty with providing typesetter-independent typesetting is that +each desired typesetting feature must be recreated in a +typesetter-independent FunnelWeb typesetting construct that FunnelWeb can +translate into whatever typesetting language is being targeted by Weave. +Taken to the extreme, this would result in FunnelWeb providing the full +syntactic and semantic power of \TeX{}, but with a more generic, +FunnelWeb-specific syntax. This was unfeasible in the time available, and +undesirable as well. + +The compromise struck in the FunnelWeb design is to provide a set of +primitive typesetter-independent typesetting features that are implemented +by FunnelWeb. These are the \newterm{typesetter directives}. +If the user is prepared to restrict to these directives, +then the user's +FunnelWeb document will be both target-language and typesetter independent. +However, if the user wishes to use the more sophisticated features of the +target typesetting system, the user can specify the typesetter +in a \dqp{typesetter} pragma and then place typesetter commands +in the free text +of the FunnelWeb document where they will be passed verbatim to the +documentation file. The choice of the trade-off between typesetter +independence and typesetting power is left to the user. + +This said, experience with FunnelWeb V1 over a three year period, +indicates that the typesetting facilities provided by FunnelWeb are +sufficient for most documentation. + +\section{Command Line Interface} +\xx{command line}{interface} + +\subsection{Invoking FunnelWeb} +\xx{FunnelWeb}{invoking}\xx{FunnelWeb}{running} + +When a user invokes FunnelWeb at the operating system command level, the +user must provide a command line instructing FunnelWeb what to do. Typically +an operating system command line consists of a \i{verb} indicating that a +particular program should be run, followed by a list of options. For example: + +\begin{verbatim} +$ rename file1 file2 +\end{verbatim} + +In this case, the verb is \p{rename} and the command line options are +\p{file1 file2}. The entire command line begins with the \p{\$} and ends with +the \p{2}. + +Operating systems differ greatly in the depth with which +they process their command\xx{command line}{processing} +lines, ranging from systems that simply pass the entire command line string +to the invoked program (\eg{}MSDOS) through to systems that perform complete +command line parsing (\eg{}VMS). Syntax conventions vary considerably. + +So as to achieve maximum portability and consistency of invocation across +different platforms, FunnelWeb reads its command line as a raw string and +performs all its own parsing.\xx{command line}{parsing} +This is portable because, at the very least, all +operating systems allow invoked programs access to the raw command line. + +The command verb used to invoke FunnelWeb should be +\dqp{fw}.\xx{fw}{command verb} + +\begin{verbatim} +FunnelWeb_verb = "fw" +\end{verbatim} + +If this verb is not available, some alternatives are +\dqp{funweb}, \dqp{fun}, and \dqp{funnelweb}. +The verbs \p{web} or \p{fweb} should be avoided +as they are the names of other literate programming systems. + +\subsection{Command Line Arguments} +\xx{command line}{argument}\xx{syntax}{command line} + +Following the verb is the body of the command line which +FunnelWeb parses into +zero or more \newterm{arguments} separated by runs +of one or more blanks. + +\begin{verbatim} +FunnelWeb_command_line = FunnelWeb_verb {{" "}+ argument} +\end{verbatim} + +Because some operating systems convert +their command line to upper case before handing it to the invoked program, +FunnelWeb has been constructed so as to be \i{insensitive} to the case +of its command line arguments.\xx{case}{dependence} However, when +dealing internally with arguments, FunnelWeb \i{preserves} the case of +its command line arguments so that it will be able to operate with +operating systems (such as Unix\x{Unix}) +whose file names are case dependent. + +A valid FunnelWeb argument consists of a +\newterm{sign}, an identifying \newterm{letter}, and an +optional +\newterm{string} with no spaces separating +them.\xx{command line options}{syntax}\xx{options}{syntax} + +\begin{verbatim} +argument = sign id_letter [non_blank_string] +sign = "+" | "-" | "=" +id_letter = "B" | "C" | "D" | "F" | "H" |"I" | "J" | "K" | + "L" | "O" | "Q" | "S" | "T" | "W" | "X" +\end{verbatim} + +In addition there is a special form of argument that does not begin with +a sign. + +\begin{verbatim} +argument = non_blank_string_not_beginning_with_+_=_or_- +\end{verbatim} + +This form is exactly equivalent to the same string with \dqp{+F} +prepended to it. + +The semantic effect of these arguments is +defined in terms of \newterm{options} which are the +internal parameters of FunnelWeb +and which correspond closely with the set of legal command line arguments. +FunnelWeb has a predefined set of options each identified +by an identifying letter having two attributes: a \i{string}, and a +\i{boolean}. The boolean determines whether an option is turned +\i{on} or \i{off}. The string contains additional information +depending on the option. + +When FunnelWeb starts up, its options have predefined default values. +FunnelWeb then parses its command line sequentially from +left to right +executing the effect of each argument on the argument's corresponding +option. The sign and the +string components of the argument are processed \i{independently}. +A sign of \p{+} turns the option on. A sign of \p{-} turns the option off. +A sign of \p{=} leaves the option's boolean attribute unchanged. The argument +string replaces the string of the corresponding +option, unless the argument string is empty, in which case the +option string is not changed. + +Because FunnelWeb processes its command line arguments from left to right, +a later argument can cancel the effect of an earlier one. +For example \p{fw +t -t} will result in the \p{t} option +ending up \i{off}. This allows users to set up their own default arguments +by defining a symbol in their operating system's command language. For +example, a Unix user who wants FunnelWeb to delete all identical output +files and create a documentation file on each run +with a default \p{.typ} extension could simply place the following definition +in their \dqp{.login} file. + +\begin{verbatim} +alias fw fw +d +t.typ +\end{verbatim} + +These default options can then later be easily overridden on the command line. + +\subsection{Options} +\label{commandlineoptions}\x{options}\xx{list}{options} + +FunnelWeb's options are internal parameters which can be modified by +corresponding arguments on FunnelWeb's command line. A description of each +argument and option follows. + +\narrowthing{B1$\ldots$B6: Tracedumps:}{These\xx{B}{option} +six\xx{tracedump}{options}\xx{dump}{option} options have been provided to +assist in the debugging and testing +of FunnelWeb. They determine which of six possible trace dumps are +to be written to the listing file. Only the boolean attributes +of these options are ever used. The six dumps are identified by the +digits \p{1..6} as +follows:\xx{dump}{mapped file} +\xx{dump}{global line list}\xx{dump}{token list} +\xx{dump}{macro table}\xx{dump}{document list}\xx{dump}{times}} + +\begin{enumerate} +\item Dump a hexdump of each mapped input and include file. +\item Dump the global line list created by the scanner. +\item Dump the token list created by the scanner. +\item Dump the macro table created by the parser. +\item Dump the document list created by the parser. +\item Dump a table summarizing CPU and real time usage. +\end{enumerate} + +\narrowtext{Because these options are so closely related, a hack has been +pulled to enable them to all to be controlled by the \p{B} argument. +The +string argument to the \p{B} argument determines which of the six options +are to be affected by the sign. Examples: \p{+B134} turns on options \p{B1}, +\p{B3}, and \p{B4}. \p{-B1} turns off option \p{B1}. +\p{Default:~-B123456}.} + +\narrowthing{B7: Determinism:}{If the \p{B7} option is turned on, +FunnelWeb suppresses the output of anything +non-deterministic,\x{non-determinism} +or machine dependent. This assists in regression testing. +Only the boolean attribute is used in this option. +This option is controlled by the \p{B7} argument which falls under the +same argument syntax as the other \p{B} options. Examples: \p{+B7}, \p{-B7}. +\p{Default:~-B7}.} + +\narrowthing{C: Listing File Context:}{The\xx{C}{option} +\p{C}\xx{listing file}{context} +option is always turned on and +cannot be turned off. Its only attribute is a number which determines the +number of lines of context that the lister will place around lines flagged +with diagnostics in the listing file (if a listing file is written). +A value of 100 indicates infinite context\xx{infinite}{context} +which means that the entire +listing file will be written out if a single diagnostic occurs. +The value of this number can be specified by specifying it as a string of +decimal digits to the \p{+C} argument. Examples: \p{+C100}, \p{+C10}. +\p{Default:~+C2}.} + +\narrowthing{D: Delete Identical Output Files:}{Only the boolean +attribute of this option is used.\xx{D}{option}\xx{delete output}{option} +When turned on, the option causes the suppression (deletion) +of product files and documentation files +(but not listing or journal files) that +are identical to the currently existing files of the same name. For example, +if FunnelWeb is instructed to generate \p{stack.h} as an product file, and +the text to be written to \p{stack.h} is identical to the currently existing +\p{stack.h}, then FunnelWeb will simply not write any product file, leaving the +currently existing \p{stack.h} as it is (and in particular leaving the +file's date attribute the same). +This prevents unnecessary \p{make} propagations. For example, in a C program, +if \p{stack.fw} is a +FunnelWeb input file that generates \p{stack.h} and \p{stack.c}, +a modification to \p{stack.fw} that affects \p{stack.c} but does not +affect \p{stack.h} will not provoke the recompilation of modules +that \p{\#include stack.h}, so long as the intervening FunnelWeb run has +\p{+D} set. Examples: \p{-D}, \p{+D}. \p{Default:~-D}.} + +\narrowthing{F: FunnelWeb Input File:}{If\xx{F}{option} +this option is turned on, FunnelWeb\xx{input file}{option} +processes the input file whose name is specified by the option string. +Examples: \p{+Fsloth.fw}, \p{+Fwalrus}, \p{-F}. +\p{Default:~-F}.} + +\narrowthing{H: Display Help Message:}{If\xx{H}{option} +this option\xx{help}{option} is turned on, FunnelWeb +displays the message specified by the argument string. +Each message has a name. The main help message is called \dqp{menu} +and contains a list of the other help messages. Examples: \p{+Hregistration}, +\p{+Hoptions}. \p{Default:~-Hmenu}.} + +\narrowthing{I: Include default file specification:}{This\xx{I}{option} +option\xx{include file}{option}\xx{include}{file} is always turned +on and cannot be turned off. Its string attribute is used as the default file +specification for include files. Usually this option is used to specify +a directory from which include files should be obtained. +Examples: \p{=I/usr/dave/includes/}. \p{Default:~+I}.} + +\narrowthing{J: Journal File:}{If\xx{J}{option} this option is turned on, +FunnelWeb generates a\xx{journal file}{option}\xx{journal}{file} +journal file. A journal file contains a log of +all the console input and output to FunnelWeb during a single invocation of +the FunnelWeb program (Note: The \p{Q} option does not affect this.). +The journal file is particularly useful for examining what happened during +a FunnelWeb shell run. The string attribute is the name of the journal +file. Examples: \p{+Jjournfile}, \p{-J}. \p{Default:~-J}.} + +\narrowthing{K: Keyboard:}{If\xx{K}{option} +this option\xx{keyboard}{option}\xx{interactive}{option} +is turned on, FunnelWeb enters an +interactive mode in which the user can enter FunnelWeb shell commands +interactively. The string attribute is unused. +Examples: \p{+K}, \p{-K}. \p{Default:~-K}.} + +\narrowthing{L: Listing File:}{If\xx{L}{option} +this option is turned on, FunnelWeb +generates a\xx{listing file}{option}\xx{listing}{file} +listing file containing a summary of a run on FunnelWeb proper. +The string argument is the name of the listing file to be created. +Examples: \p{+L}, \p{-L}, \p{+Llisting.lis}. +\p{Default:~-L}.} + +\narrowthing{O: Product Files:}{If this option is turned on, +FunnelWeb generates a product file for each macro in the input file +that is bound to an output file. The string attribute contributes to the +name of the product files. This option is controlled +by the \p{O} argument +because product files used to be called \dq{\b{O}utput files}). +Examples: \p{-O}, \p{+O/usr/dave/product/}. \p{Default:~+O}.} + +\narrowthing{Q: Quiet:}{If\xx{Q}{option} this option is turned on, +FunnelWeb suppresses all\xx{quiet}{option}\xx{suppress}{console output} +output to the screen (standard output) unless one or more errors occur, +in which case a single line summarizing the errors is sent to standard +output at the end of the run. If this option is turned off, FunnelWeb +writes to the console in its normal garrulous way. The string +attribute is unused in this option. Examples: \p{-Q}, \p{+Q}. \p{Default:~-Q}.} + +\narrowthing{S: Screen:}{If\xx{S}{option} this option is turned on, +FunnelWeb writes all\xx{screen}{option} +diagnostics to the screen (standard output) +as well as to the listing file. +By default, they are sent only to the listing file. +This option has a single numerical attribute +that can be specified as a decimal string in the string component of the +\p{S} argument. The number is the number of lines of context that should +surround each diagnostic sent to the screen.\x{context} +Examples: \p{-S}, \p{+S6}, \p{+S0}. \p{Default:~-S}.} + +\narrowthing{T: Documentation file:}{If\xx{T}{option} this +option\footnote{This option is controlled by the \p{T} command line +argument because documentation files used to be called typesetter files.} is +turned on, FunnelWeb\xx{typeset}{option}\xx{typeset}{file} +generates a documentation file in \TeX{} format. +The string argument contributes to the +name of the documentation file to be created. +By default this option is turned off, as experience has +shown that most FunnelWeb runs are made during program development; +documentation runs occur far more rarely. Examples: \p{-T}, +\p{+Tsloth.tex}. \p{Default:~-T}.} + +\narrowthing{W: Width of Product Files:}{If\xx{W}{option} +this option\xx{width}{option}\xx{product file}{width} +is turned on, a limit is +placed on the length of lines in product files generated during the +run. Lines that breach the limit are flagged with error messages. +This option has a single numerical attribute +that can be specified as a decimal string in the string component of the +\p{W} argument. The number is the specified maximum width. +This option is one of two limits that are placed on the width of +product files. The other limit is an attribute of the input file that +defaults to 80 characters, +but can be raised or lowered using an output line length +pragma. The width that is enforced is the lower of this value and the +value of the \p{W} option (if turned on). +Examples: \p{-W}, \p{+W100}. \p{Default:~-W80}.} + +\narrowthing{X: Execute:}{If\xx{X}{option} +this option\xx{execute script}{option} +is turned on, FunnelWeb executes the FunnelWeb shell +script file specified by the string attribute. +Examples: \p{+Xmaster}, \p{-X}. +\p{Default:~-X}.} + +\section{File Name Inheritance} +\xx{filename}{inheritance} + +During a single run of FunnelWeb, FunnelWeb can produce many different +output files. As it would be very tedious to have to specify the name +of each of these files explicitly each time FunnelWeb is run, FunnelWeb +provides a system of defaults that allows the user to specify the minimum +required to successfully complete the run. To do this FunnelWeb allows +file specifications to inherit fields from one another. + +FunnelWeb structures filenames into three fields\xx{filename}{fields} +which are inherited +independently. The fields are: \newterm{directory}, \newterm{name}, +and \newterm{extension}. +On systems having other fields (\eg{}\i{network node}, \i{device name}), +the extra fields are considered to be part of the directory field. +Version numbers are +ignored. A field can inherit a value if its current value is +the empty string. + +The following table gives the full inheritance scheme used in FunnelWeb. + +\begin{center} +\begin{tabular}{|l|l|l|l|l|l|l|} \hline +Script & Input & Include & Journal & List & Document & Product \\ \hline + & & \p{@i} & & & & \p{@o} \\ +\p{+x} & \p{+f} & \p{+i} & \p{+j} & \p{+l} & \p{+t} & \p{+o} \\ +\dqp{.fws} & \dqp{.fw} & \dqp{.fwi} & \dqp{.jrn} & \dqp{.lis} & \dqp{.tex} & \\ + & & \p{+f} & \p{+f} & \p{+f} & \p{+f} & \\ +DefDir & Defdir & Defdir & Defdir & Defdir & Defdir & Defdir \\ \hline +\end{tabular} +\end{center} + +The table is arranged with items of highest priority at the top. +The \dqp{+<letter>} cells refer to the file +specification supplied in the given command line argument. +\dqp{+F} is the name of the input file. +\dq{Defdir} refers to the default directory +specification provided by the operating system. Empty cells +do not contribute. + +The following example shows how the table is used. +Suppose that the user invoked FunnelWeb as +follows:\xx{filename inheritance}{example} + +\begin{verbatim} +fw /usr/ross/work/sloth.fw +twalrus +\end{verbatim} + +To work out what the documentation file should be called, FunnelWeb starts +with the empty string and then works down the Document column of the table. +The top entry is empty +so we ignore it and proceed to the second entry which consists of \dqp{+T}. +The user specified the string \dqp{walrus} as the value of this option, and +as our current (empty) +string does not have a name field, we insert the string +\dqp{walrus} into the name field, resulting in the string \dqp{walrus}. +Moving down to the next row, we encounter the constant string \dqp{.tex}. +This string consists of an empty directory and name field, but a \dqp{.tex} +file extension. As our current string \dqp{walrus}, does not already +have a file extension (\ie{}the file extension field of our current string +is empty), we add in \dqp{.tex}, +resulting in the string \dqp{walrus.tex}. Next we encounter the \dqp{+F} field +which is the input filename \dqp{/usr/ross/work/sloth.fw} consisting of +a directory field \dqp{/usr/ross/work/}, a name field \dqp{sloth}, and a +file extension field \dqp{.fw}. Our \dqp{walrus.tex} string already has +name and file extension fields, but its directory field is empty, and +so we add in the directory field from the input file specification, +resulting in the string \dqp{/usr/ross/work/walrus.tex}. Finally, we hit +the default directory specification, which is (say) +\dqp{/usr/ross/play/}. However, as the directory field of our walrus +string is already full, it has no effect. + +In general, there is no need to remember the exact details of FunnelWeb's +filename inheritance. The important thing is to know that it exists, and to +use it. + +\section{FunnelWeb Startup} +\xx{FunnelWeb}{startup}\xx{FunnelWeb}{initialization} + +FunnelWeb's command line options can be divided into two groups. +\newterm{Action options} instruct FunnelWeb to performs some sort of +independent action such as processing a file. \newterm{Ordinary options} +merely modify the way in which FunnelWeb executes the actions. + +The four action options are: \p{+F}, \p{+K}, \p{+X}, and \p{+H}. For +FunnelWeb to be successfully invoked, at least one action option must be +specified. If zero action options are specified, FunnelWeb terminates +with failure status. +If more than one action option is specified, FunnelWeb performs +the specified actions in a predefined order. + +Assuming that the user has specified at least one action, the order in which +actions are executed is as follows:\xx{action execution}{order} + +\narrowthing{Initialization script:}{FunnelWeb\xx{initialization}{script} +starts by +looking in the current +directory for a file called \dqp{fwinit.fws}.\x{fwinit.fws} +If it doesn't find one, it +doesn't raise any error. If it does find one, it executes it as a FunnelWeb +shellscript. Initialization scripts are useful for setting up FunnelWeb +options (\eg{}using the \dqp{set} +command without having to type them each time).} + +\narrowthing{Execute argument script:}{If a shellscript has been specified +using the \dqp{+X} option, FunnelWeb executes it.} + +\narrowthing{Process input file:}{If the user has specified an input file +using the \dqp{+F} option, then this is processed next (by FunnelWeb proper).} + +\narrowthing{Display help message:}{If the user requested, +using the \dqp{+H} option, that a help message be displayed, +the message is displayed at this time.} + +\narrowthing{Interactive mode:}{If the user specified the +\dqp{+K} option, FunnelWeb enters interactive (keyboard) mode.} + +FunnelWeb processes these actions in the above order regardless of the +order in which they appear on the command line. + +It may be hard to see how some of these actions might be combined. +Nevertheless, FunnelWeb allows this. For example, a user might wish +to process a batch of files as specified in a script (\dqp{+Xscript.fws}), +be reminded of the interactive commands available (\dqp{+Hcommand}), and +then enter interactive mode so as to be able to +reprocess files for which FunnelWeb +reported errors (after correcting the errors in a different +workstation window). + + +\section{Scanner} +\x{scanner} + +The scanner reads in the input file and produces a list of tokens +which it hands onto the parser. In addition, some input constructs may cause +the scanner to modify some of FunnelWeb's options. + +\subsection{Basic Input File Processing} + +In order to read in an input file or include file, the scanner calls a +submodule called the \newterm{mapper} +that reads a file in and creates a contiguous copy of +it in memory. The scanner then performs three checks on the file, the first +(file termination) of +which is performed before scanning commences, and the other two of which take +place during scanning before each line is scanned. + +\narrowthing{File Termination:}{The\xx{file}{termination} +first check the scanner makes\xx{line}{termination} +is whether +the file is terminated properly. A file is considered to be properly +terminated if it either contains no lines, or if the last line in the file +is terminated by an end-of-line marker. If the scanner detects that an +input file is not properly terminated, it adds an end-of-line marker +itself (to the copy in memory only).} + +\narrowthing{Unprintable Characters:}{The second check the +scanner makes is for\xx{unprintable}{characters} +unprintable characters (ASCII 0--31 and 127--255 +(except for EOL(10))) which it flags +as errors and replaces by question marks.} + +\narrowthing{Line Lengths:}{The third check +the scanner makes is input line length.\xx{line}{length} +When FunnelWeb starts up, a default maximum +input line length of 80 is set. This can be changed dynamically during scanning +using a \p{@p maximum\_input\_line\_length} pragma. +If the number of characters on a line (not including the end of line marker) +exceeds this limit, FunnelWeb generates an error.\checked{}} + +\subsection{Special Sequences} +\xx{special}{sequences} + +The scanner scans the input file from top to bottom, left to right, treating +the input as ordinary text (to be handed directly to the parser as a text +token) unless it encounters the \newterm{special character}\footnote{This sort +of character is often referred to as the \dq{escape character} or the +\dq{control character} in other +systems. However, as there is great potential to confuse these names +with the \dq{escape} character (ASCII 27) and ASCII \dq{control} characters, +the term \dq{special} has been chosen instead. This results in the terms +\i{special character} and \i{special sequence}.} which introduces +a \newterm{special sequence}. Thus, the +scanner partitions the input file into ordinary text and special sequences. + +\begin{verbatim} +input_file = {ordinary_text | special_sequence} +\end{verbatim} + +Upon startup, the special character\xx{default}{special character} +is \p{@}, but it can +be changed using the $<$special$>$\p{=}$<$new\_special$>$ special sequence. +Rather than using $<$special$>$ whenever the special character appears, +this document uses the default special character \dqp{@} to represent the +current special character. +More importantly, FunnelWeb's +error messages all use the default special character in their error messages +even if the special character has been changed. + +An occurrence of the special character in the input file introduces a +special sequence. The kind of special sequence is determined by the +character following the special character. Only printable characters can +follow the special character. + +The following list gives all the possible characters that can follow the +special character, and the legality of each sequence. +The first column gives the ASCII number of each ASCII character. The second +column gives the special sequence for that character. The next column contains +one of three characters: \dqp{-} means that the sequence is illegal. \dqp{S} +indicates that the sequence is a \newterm{simple sequence} (with no attributes +or side effects) that appears exactly as shown and is +converted directly into a token and fed to the parser. Finally, \dqp{C} +indicates that the special sequence is complex, possibly having a following +syntax or producing funny side effects. + +\begin{verbatim} +ASC SEQ COMMENT +----------------- +000 \ +016 | Unprintable characters and hence illegal specials. +031 / +032 @ - Illegal (space). +033 @! C Comment. +034 @" S Parameter delimeter. +035 @# C Short name sequence. +036 @$ S Start of macro definition. +037 @% - Illegal. +038 @& - Illegal. +039 @' - Illegal. +040 @( S Open parameter list. +041 @) S Close parameter list. +042 @* - Illegal. +043 @+ C Insert newline. +044 @, S Parameter separator. +045 @- C Suppress end of line marker. +046 @. - Illegal. +047 @/ S Open or close emphasised text. +048 @0 - Illegal. +049 @1 S Formal parameter 1. +050 @2 S Formal parameter 2. +051 @3 S Formal parameter 3. +052 @4 S Formal parameter 4. +053 @5 S Formal parameter 5. +054 @6 S Formal parameter 6. +055 @7 S Formal parameter 7. +056 @8 S Formal parameter 8. +057 @9 S Formal parameter 9. +058 @: - Illegal. +059 @; - Illegal. +060 @< S Open macro name. +061 @= C Set special character. +062 @> S Close macro name. +063 @? - Illegal. Reserved for future use. +064 @@ C Insert special character into text. +065 @A S New section (level 1). +066 @B S New section (level 2). +067 @C S New section (level 3). +068 @D S New section (level 4). +069 @E S New section (level 5). +070 @F - Illegal. +071 @G - Illegal. +072 @H - Illegal. +073 @I C Include file. +074 @J - Illegal. +075 @K - Illegal. +076 @L - Illegal. +077 @M S Tag macro as being allowed to be called many times. +078 @N - Illegal. +079 @O S New macro attached to product file. Has to be at start of line. +080 @P C Pragma. +081 @Q - Illegal. +082 @R - Illegal. +083 @S - Illegal. +084 @T C Typesetter directive. +085 @U - Illegal. +086 @V - Illegal. +087 @W - Illegal. +088 @X - Illegal. +089 @Y - Illegal. +090 @Z S Tags macro as being allowed to be called zero times. +091 @[ - Illegal. Reserved for future use. +092 @\ - Illegal. +093 @] - Illegal. Reserved for future use. +094 @^ C Insert control character into text +095 @_ - Illegal. +096 @` - Illegal. +097 @a \ +109 @m | Identical to @A..@Z. +122 @z / +123 @{ S Open macro body/Open literal directive. +124 @| - Illegal. +125 @} S Close macro body/Close literal directive. +126 @~ - Illegal. +127 to 255 are not standard printable ASCII characters and are illegal. +\end{verbatim} + +The most important thing to remember about the scanner is that \i{nothing +happens unless the special character is seen.} There are no funny sequences +that will cause strange things to happen. The best way to view a FunnelWeb +document at the scanner level is as a body of text punctuated by special +sequences that serve to structure the text at a higher level. + +The remaining description of the scanner consists of a detailed description +of the effect of each complex special sequence. + +\subsection{Setting the Special Character} +\xx{setting}{special character} + +The special character can be set using the sequence +$<$special$>$\p{=}$<$newspecialchar$>$. For example, \p{@=\#} would change the +special character to a hash (\p{\#}) character. The special character may +be set to any printable ASCII character except the blank character +(\ie{}any character in the ASCII range $[33,126]$). In normal use, it +should not be necessary to change the special character of FunnelWeb, and it +is probably best to avoid changing the special character so as not to +confuse FunnelWeb readers conditioned to the \p{@} character. +However, the feature is very useful where the text being prepared contains +many \p{@} characters (\eg{}a list of internet electronic mail addresses). + +\subsection{Inserting the Special Character into the Text} +\xx{special character}{inserting into text} + +The special sequence $<$special$>$\p{@} inserts the special character +into the text as if it were not special at all. The \p{@} of this +sequence has nothing to do with the current special character. If the +current special character is \p{P} then the sequence \p{P@} will insert +a \p{P} into the text. Example: \p{@@\#@=\#@\#@\#=@@@} translates +to \p{@\#@\#@}. + +\subsection{Inserting Arbitrary Characters into the Text} +\xx{arbitrary characters}{inserting into text} +\xx{control characters}{inserting into text}\x{@circumflex} + +While FunnelWeb does not tolerate unprintable characters in the input file +(except for the end of line character), +it does allow the user to specify that unprintable characters appear in the +product file. The \p{@\circumflex{}} sequence inserts a single character +of the user's choosing into the text. +The character can be specified by giving its +ASCII number in one of four bases: +binary, octal, decimal, and hexadecimal. Here is the syntax: + +\begin{verbatim} +control_sequence = "@^" char_spec +char_spec = binary | octal | decimal | hexadecimal +binary = ("b" | "B") "(" {binary_digit}8 ")" +octal = ("o" | "O" | "q" | "Q") "(" {octal_digit}3 ")" +decimal = ("d" | "D") "(" {decimal_digit}3 ")" +hexadecimal = ("h" | "H" | "x" | "X") "(" {hex_digit}2 ")" +binary_digit = "0" | "1" +octal_digit = binary_digit | "2" | "3" | "4" | "5" | "6" | "7" +decimal_digit = octal_digit | "8" | "9" +hex_digit = decimal_digit | "A" | "B" | "C" | "D" | "E" | "F" + | "a" | "b" | "c" | "d" | "e" | "f" +\end{verbatim} + +Example: + +\begin{verbatim} +@! Unix Make requires that productions commence with tab characters. +@^D(009)prog.o <- prog.c +\end{verbatim} + +Note that the decimal \dqp{9} is expressed with leading zeros +as \dqp{009}. FunnelWeb requires +a fixed number of digits for each base. Eight digits for base two, three +digits for base ten, three digits for base eight and two digits for base +sixteen. + +FunnelWeb treats the character resulting from a +\p{@\circumflex{}} sequence as ordinary text in every sense. +If your input file contains many instances of a particular control +character, +you can package it up in a macro like any other text. In particular, +quick names can be used to great effect: + +\begin{verbatim} +@! Unix "Make" requires that productions commence with tab characters. +@! So we define a macro with a quick name as a tab character. +$@#T@{@^D(009)@} +@! And use it in our productions. +@#Tprog.o <- prog.c +@#Ta.out <- prog.o +\end{verbatim} + +Warning: If you insert a Unix\x{Unix newline} +newline character (decimal 10) into the text, +FunnelWeb will treat this as an end of line sequence regardless of what +the character sequence for end of line is on the machine upon which it is +running. Unix EOL is FunnelWeb's internal representation for end of line. +Thus, in the current version of FunnelWeb, inserting character 10 into the +text is impossible unless this also happens to be +the character used by the operating system to mark the end of line. + +\subsection{Comments} +\xx{comments}{FunnelWeb} + +When FunnelWeb encounters the \p{@!}\x{@!} +sequence during its left-to-right scan +of the line, it throws away the rest of the line (including the EOL) +without analysing it further. +Comments can appear in any line except \dqp{@i}, +\dqp{@t}, and \dqp{@p} lines. + +FunnelWeb comments can be used to insert +comments into your input file that will +neither appear in the product files nor in the documentation file, +but will be +solely for the benefit of those reading and editing the input +file directly. Example: + +\begin{verbatim} +@! I have used a quick macro for this definition as it will be used often. +@$@#C@{--@} +\end{verbatim} + +Because comments are defined to include the end-of-line marker, +care must be taken when they are being added or removed within the text +of macro bodies. For example +the text fragment + +\begin{verbatim} +for (i=0;i<MAXVAL;i++) @! Print out a[0..MAXVAL-1]. + printf("%u\n",a[i]); +\end{verbatim} + +will expand to + +\begin{verbatim} +for (i=0;i<MAXVAL;i++) printf("%u\n",a[i]); +\end{verbatim} + +This problem really has no solution; if FunnelWeb comments were defined to +omit the end of line marker, the expanded text would contain trailing blanks! +As it is, FunnelWeb comments are designed to support single line comments +which can be inserted and removed as a line without causing trouble. +For example: + +\begin{verbatim} +@! Print out a[0..MAXVAL-1]. +for (i=0;i<MAXVAL;i++) + printf("%u\n",a[i]); +\end{verbatim} + +If you want a comment construct that does not enclose the end of line +marker, combine the insert end of line construct \p{@+} with the comment +construct \p{@!} as in + +\begin{verbatim} +for (i=0;i<MAXVAL;i++) @+@! Print out a[0..MAXVAL-1]. + printf("%u\n",a[i]); +\end{verbatim} + +FunnelWeb comments should really only be used to comment the FunnelWeb +constructs being used in the input file. Comments on the target code are +best placed in comments in the target language or in the documenting text +surrounding the macro definitions. In the example above, a C +comment would have been more appropriate. + +\subsection{Quick Names} +\xx{quick}{names} + +FunnelWeb provides a \newterm{quick name} syntax as an alternative, +for macros whose name consists of a single character, to the +angle bracket syntax usually used (\eg{}\p{@<Sloth@>}). +A quick name sequence consists of \p{@\#}$x$\x{@hash} +where $x$, the name of the macro, +can be any printable character except space. + +\begin{verbatim} +quick_name = "@#" non_space_printable +\end{verbatim} + +The result is identical to the +equivalent ordinary name syntax, but is +shorter. For example, \p{@\#X} is equivalent to \p{@<X@>}. +This shorter way of writing one-character macro names is more convenient where +a macro must be used very often. For example, the macro calls in the +following fragment of an Ada program are a little clumsy. + +\begin{verbatim} +@! Define @<D@> as "" to turn on debug code and "--" to turn it off. +@$@<D@>@{--@} +@<D@>assert(b>3); +@<D@>if x>7 then write("error") end if +\end{verbatim} + +The calls can be shortened using the alternative syntax. + +\begin{verbatim} +@! Define @#| as "" to turn on debug code and "--" to turn it off. +@$@#|@{--@} +@#|assert(b>3); +@#|if x>7 then write("error") end if +\end{verbatim} + +\subsection{Inserting End of Line Markers} +\xx{EOL markers}{inserting} + +An end of line marker/character can be inserted into the text +using the \p{@+}\x{@+} sequence. This is +exactly equivalent to a real end of line in the text at the point where +it occurs. +While this feature may sound rather useless, +it is very useful for laying out the input file. For +example, the following input data for a database program + +\begin{verbatim} +Animal = Kangaroo +Size = Medium +Speed = Fast + +Animal = Sloth +Size = Medium +Speed = Slow + +Animal = Walrus +Size = Big +Speed = Medium +\end{verbatim} + +can be converted into + +\begin{verbatim} +Animal = Kangaroo @+Size = Medium @+Speed = Fast @+ +Animal = Sloth @+Size = Medium @+Speed = Slow @+ +Animal = Walrus @+Size = Big @+Speed = Medium @+ +\end{verbatim} + +which is easier to read, and more easily allows comparisons between +records. + +\subsection{Suppressing End of Line Markers} +\xx{EOL markers}{suppressing} + +End of line markers can be suppressed by the \p{@-}\x{@-} +sequence. +A single occurrence of a \p{@-} sequence serves to suppress only the end of line +marker following it and must appear \i{exactly} before the end of line marker to +be suppressed. No trailing spaces, \p{@!} comments, or any other characters +are permitted between a \p{@-} sequence and the end of line that it is +supposed to suppress. The \p{@-} sequence is useful for constructing +long output lines without them having to appear in the input. +It can also be used in the same way as the \p{@+} +was used in the previous section to assist in exposing the structure of output +text without affecting the output text itself. Finally, it is invaluable for +suppressing the EOL after the opening macro text \p{@\{} construct. +For example: + +\begin{verbatim} +@$@<Walrus@>@{@- +I am the walrus!@} +\end{verbatim} + +is equivalent to + +\begin{verbatim} +@$@<Walrus@>@{I am the walrus!@} +\end{verbatim} + +The comment construct (\p{@!}) can also be used to suppress end of lines. +However, the \p{@-} construct should be preferred for this purpose as it +makes explicit the programmer's intent to suppress the end of line. + +\subsection{Include Files} +\xx{include}{files} + +FunnelWeb provides an include file facility with a maximum depth of 10. +When FunnelWeb sees a line of the form \p{@i <filename>},\x{@i} +it replaces the entire line (including the EOL) with the +contents of the specified include file. FunnelWeb's include file +facility is intended to operate at the line level. If the last line of the +include file is not terminated by an EOL, FunnelWeb issues a warning +and interts one (in the copy in memory). + +The +\p{@i} construct is illegal if it appears anywhere except +at the start of a line. +The construct must be followed by a single blank. The file +name is defined to be everything +between the blank and the end of the line (no +comments (\p{@!}) please!). Example: If the input file is + +\begin{verbatim} +"Uh Oh, It's the Fuzz. We're busted!" said Baby Bear. +@i mr_plod.txt +"Quick! Flush the stash down the dunny and let's split." said Father Bear. +\end{verbatim} + +and there is a file called \p{mr\_plod.txt} containing + +\begin{verbatim} +"'Ello, 'Ello, 'Ello! What's all this 'ere then?" Mr Plod exclaimed. +\end{verbatim} + +then the scanner translates the input file into + +\begin{verbatim} +"Uh Oh, It's the Fuzz. We're busted!" said Baby Bear. +"'Ello, 'Ello, 'Ello! What's all this 'ere then?" Mr Plod exclaimed. +"Quick! Flush the stash down the dunny and let's split." said Father Bear. +\end{verbatim} + +As a point of terminology, FunnelWeb calls the original input file the +\newterm{input file} and calls include files and their included files +\newterm{include files}. + +The include file construct operates at a very low level. An include +line can appear anywhere in the input file regardless of the context +of the surrounding lines. + +FunnelWeb sets the special character to the default (\p{@}) at the +start of each include file and restores it to its previous value at the end +of the include file. This allows macro libraries to be constructed and +included that are independent of the prevailing special character +at the point of inclusion. +The same goes for the input line length limit +which is reset to the default +value at the start of each include file and +restored to its previous value afterwards. + +\subsection{Pragmas} +\x{pragmas}\xx{pragmas}{visible}\xx{pragmas}{invisible} + +Most tools have to support some essential, but rather inelegant features. +In FunnelWeb these messy bits have all been stuffed into the +scanner's \newterm{pragma} (for \i{pragma}tic) construct. + +A pragma consists of a single line of input (including the EOL) +commencing with \p{@p}. This +must be followed by a single space, and then the pragma verb. +This must +be followed by a sequence of zero or more arguments separated by one or +more spaces. Four pragmas are available + +\begin{verbatim} +pragma = pragma_ident | pragma_mill | pragma_moll | pragma_typesetter +\end{verbatim} +The following syntax definitions assist in defining the pragmas. + +\begin{verbatim} +s = {" "}+ +ps = ("@p" | "@P") " " +number = { decimal_digit }+ +numorinf = number | "infinity" +\end{verbatim} + +The arguments to pragmas are case-sensitive and must be specified in +lower case. + +Pragmas are processed and consumed entirely by the scanner. The parser +never sees them and so they can play +no part in the parser level syntax. As a result, pragma lines +can appear anywhere in the entire input file regardless of the surrounding +context (\eg{}even in the middle of a macro definition). +The sole effect of a pragma is to modify some internal parameter of +FunnelWeb. + +The following sections describe the four FunnelWeb pragmas. + +\subsubsection{Indentation} +\label{indentationpragma}\xx{indentation}{macro expansion} + +When FunnelWeb expands a macro, it can do so in two ways. First it can treat +the text it is processing as a one-dimensional stream of text, and merely +insert the body of the macro in place of the macro call. Second, it can +treat the text of the macro as a two dimensional object and +indent each line of the macro body by the amount that the macro +call itself was indented. Consider the following macros. + +\begin{verbatim} +@$@<Loop Structure@>@{@- +i=1; +while (i<=N) + @<Loop body@> +endwhile +@} + +@$@<Loop body@>@{@- +a[i]:=0; +i:=i+1;@} +\end{verbatim} + +Under the regime of \newterm{no indentation}\xx{indentation}{none} +the loop structure +macro expands to: + +\begin{verbatim} +i=1; +while (i<=N) + a[i]:=0; +i:=i+1; +endwhile +\end{verbatim} + +Under the regime of \newterm{blank indentation}\xx{indentation}{blank} +the loop structure macro expands to: + +\begin{verbatim} +i=1; +while (i<=N) + a[i]:=0; + i:=i+1; +endwhile +\end{verbatim} + +The \p{indentation} pragma determines which of these two regimes will be used +to expand the macros when constructing the product files. The syntax of the +pragma is: + +\begin{verbatim} +pragma_ident = ps "indentation" s "=" s ("blank" | "none") +\end{verbatim} + +Its two forms look like this: + +\begin{verbatim} +@p indentation = blank +@p indentation = none +\end{verbatim} + +In the current version of FunnelWeb, the indentation regime is an attribute +that is attached to an entire run of Tangle; it is not possible to bind it +to particular product files or to particular macros. As a result, it doesn't +matter where indentation pragmas occur in the input file or how many +there are so long as they are all the same. By default FunnelWeb uses +blank indentation. + +\subsubsection{Maximum Input Line Length} +\label{millpragma}\xx{input}{line length}\xx{maximum}{input line length} + +FunnelWeb generates an error for each input line +that exceeds a certain maximum number of characters. At the start of the +processing of each input +file and each include file, this maximum is set to a default value of 80. +However, +the maximum can be changed using a maximum input line length +pragma.\xx{pragma}{input line length} + +\begin{verbatim} +pragma_mill = ps "maximum_input_line_length" s "=" s numorinf +\end{verbatim} + +The maximum input line length can be varied +\i{dynamically} throughout the input file. Each maximum input line length +pragma's scope covers the line following the pragma through to and including +the next maximum input line length pragma, but not covering any intervening +include files. At the start of an include file, FunnelWeb resets +the maximum input line length to the default value. It restores it to +its previous value at the end of the include file. + +This pragma is useful for detecting text that has strayed off the +right side of the screen when editing. If you use FunnelWeb, and set the +maximum input line length to be the width of your editing window, you will +never be caught by, for example, off-screen opening comment symbols. +You can also be sure that your source text can be printed raw, if necessary, +without lines wrapping around. + +\subsubsection{Maximum Output File Line Length} +\label{mollpragma}% +\xx{maximum}{product file line length}% +\xx{pragma}{maximum product file line length}% +\xx{maximum}{output file line length}% +\xx{pragma}{maximum output file line length} + +As well as keeping an eye on input line lengths, FunnelWeb also keeps an +eye on the line lengths of product files and flags all lines longer +than a certain limit with error messages. +Unlike the +maximum input line length, which can vary dynamically throughout the input +file, the maximum product file line length remains fixed throughout the +generation +of all the product files. The maximum product file +line length pragma allows this +value to be set. If there is more than one such pragma in an input file, the +pragmas must all specify the same value. + +\begin{verbatim} +pragma_moll = ps "maximum_output_line_length" s "=" s numorinf +\end{verbatim} + +The default value is 80 characters. + +This pragma is only one of two constraints on the length of the lines of the +product files. The \p{+W} command line option also contributes. +The actual value that FunnelWeb uses is the minimum of the limits +specified in the command line and pragmas. + +FunnelWeb does not monitor the length of the lines of its other output files +(journal file, listing file, documentation file). + +\subsubsection{Typesetter} +\xx{typesetter}{pragma}\xx{typesetter}{independence} + +The \p{typesetter} pragma allows the user to specify whether the input +file is supposed to be typesetter-independent, or whether it contains +commands in a particular typesetter language. The pragma has the +following syntax. + +\begin{verbatim} +pragma_typesetter = ps "typesetter" s "=" s ("none" | "tex") +\end{verbatim} + +The two forms of the pragma look like this. + +\begin{verbatim} +@ typesetter = none +@ typesetter = tex +\end{verbatim} + +A source file can contain more than one typesetter pragma, but they must +all specify the same value. The default is \p{none}. +The typesetter setting affects two things: + +\narrowthing{Handling of free text:}{If the typesetter is not \p{none}, +Weave writes the free text \i{directly} +to the documentation file without changing it whatsoever. This means that +if (say) \p{\char`\\ centerline} appears in the input file, it will copied +directly to the documentation file. If the typesetter is \p{none}, Weave +intercepts any characters or sequences that might have a special +meaning to the target typesetter and replaces them +with typesetter commands to typeset the sequences so that they will appear +as they do in the input. For example, if the typesetter is \p{none} and +the target typesetter is \TeX{}, then if +\p{\$} (the \TeX{} \dq{mathematics mode} character) +appears in the input file, it will be +be written to the documentation file as \p{\char`\\ \$}.} + +\narrowthing{Restrictions on the target typesetter:}{At a later date, +different weave modules might be incorporated into FunnelWeb to cater +for a variety +of different typesetters. If this happens, it will be important to ensure +that typesetter-specific source files +(\ie{}\p{typesetter} $\ne$ \p{none}) are not processed with different +target typesetters. For example, a user might innocently attempt to generate +a \p{troff} documentation file from a +FunnelWeb source file containing a \p{typesetter = tex} (and by +implication \TeX{} control sequences). The pragma could also be useful +for catching typesetter clashes in source and include files. The setting +\p{none} is special because it is guaranteed to work with any +future target typesetter.} + +The aim of all this is +to ensure that any typesetter dependency is correctly proclaimed. +Because \p{none} is the default typesetter, +a user who creates a source file without a \p{typesetter = x} pragma +will soon find that the control sequences they are inserting into +the source document are appearing verbatim in the printed documentation! +In order to activate these sequences, they will be forced to add a +\p{typesetter} pragma, thus making the dependency explicit. + +It may seem strange to place the \p{typesetter} setting facility within +a pragma (\p{@p}) when there is a separate typesetting construct (\p{@t}). +This has been done to sustain the rule of thumb that says that +pragmas do not participate in the parser-level syntax, but typesetter +directives do. + +\subsection{Freestanding Typesetter Directives} +\xx{typesetter}{directives} + +FunnelWeb provides two kinds of typesetter directive to assist the user +to produce documentation. These are \newterm{inline} and +\newterm{freestanding}. Unlike pragmas, +each of these categories of directive participates in the parser-level +syntax and can appear only in certain contexts (see the parser section). +Inline directives are +designed to be used within paragraphs to alter the look of the enclosed +text. Freestanding typesetter directives are designed to +appear on lines of their own and have a bigger typographical impact. + +The syntax of freestanding typesetter directives is almost identical to that +of pragmas. All the same syntax rules apply (except that the actual +keywords are different). +The following subsections describe the four typesetter directives +available. + +\begin{verbatim} +ftd = ftd_newpage | ftd_toc | ftd_vskip | ftd_title +ts = "@t " +\end{verbatim} + +\subsubsection{New Page} +\x{new page}\xx{pragma}{new page} + +The new page pragma is a typesetting pragma with the following syntax. + +\begin{verbatim} +ftd_newpage = ts "new_page" +\end{verbatim} + +It only form looks like this. + +\begin{verbatim} +@t new_page +\end{verbatim} + +Its sole effect is to cause a \dq{skip to a new page} command to be inserted +into the documentation file. +The new page command is such that if the typesetter is already at +the top of a page, it will skip to the top of the next page. + +\subsubsection{Table of Contents} +\xx{table of}{contents}\xx{pragma}{table of contents} + +The new page pragma is a typesetting pragma with the following syntax. + +\begin{verbatim} +ftd_toc = ts "table_of_contents" +\end{verbatim} + +It only form looks like this. + +\begin{verbatim} +@t table_of_contents +\end{verbatim} + +Its sole effect is to instruct Weave to insert a table of contents at +this point in the printed documentation. +This pragma does not skip to a top of a new page first. + +\subsubsection{Vertical Skip} +\xx{vertical}{skip}\xx{pragma}{vskip} + +The vertical skip pragma is a typesetting pragma that +instructs Weave to insert a specified amount of +vertical space into the documentation. The pragma has the following syntax. + +\begin{verbatim} +ftd_vskip = ts "vskip" s number s "mm" +\end{verbatim} + +For example: + +\begin{verbatim} +@t vskip 26 mm +\end{verbatim} + +\subsubsection{Title} +\x{title}\xx{pragma}{title} + +The title pragma is a typesetting pragma with the following syntax. + +\begin{verbatim} +ftd_title = ts "title" s font s alignment text +font = "normalfont" | "titlefont" | "smalltitlefont" +alignment = "left" | "centre" | "right" +text = """" {printable_char} """" +\end{verbatim} + +It's effect is to instruct Weave to insert a single line +into the printed documentation +containing the specified text set in the specified font +and aligned in the specified manner. The double quotes delimiting +the text are for show only; if you want to put a double quote in the string, +you don't need to double them. + +Here is an example of the pragma. + +\begin{verbatim} +@t title smalltitlefont centre "How to Flip a Bit" +\end{verbatim} + +\subsection{Scanner/Parser Interface} + +If the scanner terminates without any errors, control +is passed to the parser. The parser parses the token list generated by +the scanner. The token list consists of text scraps, freestanding +typesetter directives, +and special sequence tokens. + +The user should bear in mind that +\i{the scanner finishes running before the +parser starts running.} This means that the scanner cannot be influenced +in any way by higher order structures such as the parser might parse. +For example, +it is impossible to write a FunnelWeb macro to include a file, or insert +a \p{vskip} pragma into the input text. + +\section{Parser} +\x{parser} + +By the time the parser starts, the scanner has completely terminated. +At this point, it +is not possible for any more files to be included, and special characters are +no longer present to confuse things. All that remains is a list of +\newterm{text tokens}, +\newterm{special tokens}, and \newterm{typesetter directive tokens}. +Text tokens consist entirely of +sequences of printable characters and end of line markers. Special tokens +represent the special sequences that the scanner found in the input file. +Typesetter directive tokens represent the freestanding typesetter directives +that the scanner encountered. +The parser consumes the token list and builds a macro table that is +later used to generate product files. It also constructs +a document list that is used to generate the documentation file. + +The syntax rules appearing in the following sections refer to the +token list. + +\subsection{High Level Structure} +\xx{syntax}{high level} + +At the highest level, the FunnelWeb parser parses the input file (token +list) into a sequence of text scraps, macro definitions, +and typesetter directives. + +\begin{verbatim} +input_file = {text | macro | directive} +\end{verbatim} + +All three of these kinds of components contribute to the documentation file, +but only macro definitions +contribute to the product files. If all the free text +and directives were removed from a FunnelWeb input file, the +product files would not be affected. + +\subsection{Free Text} +\xx{free}{text} + +\newterm{Free text} is any text that is not part of a macro definition or a +directive. A scrap of free text consists of a sequence of items drawn +from the following list: +non-special printable characters, insert-eol special +sequences, insert special character special sequences, insert arbitrary +character special sequence. + +\begin{verbatim} +free_text = ordinary_text +ordinary_text = {ordinary_char | eol | text_special}+ +text_special = "@+" | "@@" | "@^" char_spec +ordinary_char = " ".."~"-special +\end{verbatim} + +An example of some rather messy free text is as follows: + +\begin{verbatim} +This@@ is a very@+ messy +@^D(009)chunk of text indeed. +But FunnelWeb still views it as +a single chunk of text. +\end{verbatim} + +FunnelWeb never sees two text chunks next to each other in the input; +they are always merged into a single text token. + +The free text in an input file +does not affect the product files. However, by default, it appears in the +printed documentation exactly as it is given in the input file, except +that it is filled and justified into paragraphs. + +Any printable character +or particular sequence of characters +may appear in the free text of a document. FunnelWeb ensures that they +will appear exactly as given in the input file, even if they happen to be +escape characters or commands in the target typesetter. +However, FunnelWeb also provides a special mode that allows +this censoring to be +overridden. See Section~\label{typesetterpragma} for more information. + +\subsection{Typesetter Directives} +\x{directives} + +FunnelWeb provides a variety of typesetter directives to assist the +user to typeset the document in a typesetter-independent way. These are +divided into \newterm{freestanding typesetter directives} (ftd) and +\newterm{inline typesetter directives} (itd). The internal syntax of the +freestanding typesetter directives has already been discussed +in the scanner section. The following syntax rule defines +the context in which these constructs can appear. + +\begin{verbatim} +directive = ftd | itd +itd = section | literal | emphasis +\end{verbatim} + +The remainder of this section describes the inline typesetter directives. + +\subsubsection{Section} +\xx{section}{constructs} + +The section directive +provides a way for the user to structure the program and documentation into +a hierarchical tree structure,\xx{tree}{structure} +just as in most large documents. +A section construct consists of a case-insensitive +identifying letter, which determines the +absolute level of the section in the document, and an optional section +name, which has exactly the same syntax as a macro name. + +\begin{verbatim} +section = "@" levelchar [name] +levelchar = "A" | "B" | "C" | "D" | "E" | + "a" | "b" | "c" | "d" | "e" +\end{verbatim} + +The section construct is not quite \dq{inline} as it must appear only +at the start of a line. However, unlike the \dqp{@i}, \dqp{@p}, and +\dqp{@t} constructs, it does not consume the remainder of the line +(although it would be silly to place anything on the same line anyway). + +FunnelWeb provides five levels of sections, ranging from the highest level +of \p{A} (like a \LaTeX{}\x{LaTeX} +chapter) to the lowest level of \p{E} (like a \LaTeX{} +subsubsubsection). FunnelWeb input files need not contain +any sections at all, but if they do, the first section must be at level \p{A}, +and following sections must not skip hierarchical levels (\eg{}an \p{@D} cannot +follow an \p{@C}). FunnelWeb generates an error if a level is skipped. + +All section \i{must} have names associated with them, but for convenience, +the section name is optional if the section contains one or more +macro definitions +(\ie{}at least one macro definition appears between the section construct +in question and the +next section construct in the input file.). In this case, the section +\i{inherits} the name of the first macro defined in the section. This +feature streamlines the input file, avoiding duplicate name inconsistencies. + +Any sequence of printable characters can be used in the +section name,\xx{section}{name} +even the target typesetter's escape sequence (\eg{}in \TeX{}, +\dqp{\bs{}}). + +The following example demonstrates the section construct. + +\begin{verbatim} +@A@<Life Simulation@> + +This is the main simulation module for planet earth, simulated down to the +molecular level. This is a REALLY big program. I mean really big. I mean, +if you thought the X-Windows source code was big, you're in for a shock... + +@B We start by looking at the code for six legged stick insects as they +form a good example of a typical object-oriented animal implementation. + +@$@<Six Legged Stick Insects@>@{@- +slsi.creep; slsi.crawl; slsi.creep;@} +\end{verbatim} + +In the above example, the name for the level A section is provided +explicitly, while the name for the level B section will be inherited from the +macro name. + +\subsubsection{Literal Directive} +\xx{literal}{directive} + +Experience has shown that one of the most common typesetting requirement +is that of being able to typeset small program fragments +in the middle of the documenting free text. Typically +there is a frequent need to refer to program identifiers, and it +assists the reader to have such identifiers typeset in the same manner +as the program text in the macro definition. +FunnelWeb~V1 +defined a \TeX{} macro for this (called \p{p}) that simply typeset its +argument in \p{tt font}. This proved so +useful, that the facility has been made typesetter-independent in +FunnelWeb~V3. + +To specify that some text be typeset in \p{tt font}, +enclose the text in curly brace special sequences as follows. + +\begin{verbatim} +literal = "@{" ordinary_text "@}" +\end{verbatim} + +As in macro names, section names, and macro bodies, the text contained +within the literal +construct is protected by FunnelWeb from any non-literal interpretation by +the typesetter and the user is +free to enclose \i{any} text covered by the definition \p{ordinary\_text}. +FunnelWeb guarantees that, no matter what the text is, it will +be typeset in \p{tt font} exactly as it appears. However, the text will be +filled and justified into a paragraph as usual. + +Here is an example of the use of the construct: + +\begin{verbatim} +@C The @{WOMBAT@} (Waste Of Money, Brains, And Time) function +calls the @{kangaroo@} input function which has been +known to cause keybounce. +This keybounce can be dampened using the @{wet_sloth@} subsystem. +\end{verbatim} + +\subsubsection{Emphasis Directive} +\xx{emphasis}{directive} + +The emphasis directive is very similar to the literal directive except that +it causes its argument to be typeset in an emphasised manner +(\eg{}italics). Like the literal directive, +the emphasis directive protects its text argument. + +\begin{verbatim} +emphasise = "@/" ordinary_text "@/" +\end{verbatim} + +Example: + +\begin{verbatim} +@C What you @/really@/ need, of course, is a @/great@/, @/big@/, +network with packets just flying @/everywhere@/. +This section implements an interface +to such a @/humungeous@/ network. +\end{verbatim} + +\subsection{Macros} +\xx{macro}{definition} + +The third category of +construct appearing at the highest syntactic level in a FunnelWeb +input file is the macro definition. +A macro definition binds a unique +\newterm{macro name} to a \newterm{macro body} containing an +\newterm{expression} consisting of text, calls to +other macros, and formal parameters. The syntax for a macro definition is as +follows: + +\begin{verbatim} +macro = ("@O" | "@$") name [formal_parameter_list] + ["@Z"] ["@M"] ["==" | "+="] "@{" expression "@}" +\end{verbatim} + +The complexity of the macro definition syntax is mostly to enable the user +to attach various attributes to the macro.\xx{macro}{attributes} +If the user chooses \p{@O}, +then the macro cannot be called, but is instead +attached to a product file. If the user chooses \p{@\$}, then the macro is +an ordinary macro definition that is not attached to a file. + +By default, a non-file macro must be invoked exactly once by one other +macro. Macros that +aren't are flagged with errors by the FunnelWeb analyser. However, if the +user uses the \p{@Z}\x{@Z} sequence in the macro definition, the macro is then +permitted to be invoked zero times, as well as once. Similarly, if the +user uses the \p{@M}\x{@M} +sequence in the macro definition, the macro is +permitted to be called many times as well as once. If both \p{@Z} and +\p{@M} are present then the macro is permitted to be invoked zero, one, +or many times. + +The purpose of enforcing the default \dq{exactly one call} rule is to +flag pieces of code that the user may have defined in a macro but not +hooked into the rest of the program. Experience shows that this is a +common error. Similarly, it can be dangerous to multiply invoke a +macro intended to be invoked only once. For example, it may be dangerous +to invoke a scrap of non-idempotent initialization code in two different +parts of the main function of a program! However, FunnelWeb will not +generate an error if a macro without \p{@M} is called by another +macro that is called more than once. + +If the text string \p{==}\x{==} (or nothing) follows the macro name, +the expression that follows +is the entire text of the macro body. If the text string \p{+=}\x{+=} +follows +the macro name, then more than one such definition is allowed +(but not required) in the document +and the body of +the macro consists of the concatenation of all such expressions in the order +in which they occur in the input file. Such a macro is said to be +additive and is +\newterm{additively defined}. Thus a macro body can either be defined +in one place using one definition (using \p{==}) or it can be \i{distributed} +throughout the input file in a sequence of one or more macro definitions (using +\p{+=}). If neither \p{==} and \p{+=} are present, FunnelWeb assumes a +default of \p{==}. + +Macros attached to product files cannot be additively defined. +Additively defined macros can have parameter lists and \p{@Z} and \p{@M} +attributes, but these must be specified only in the first definition of the +macro. However, \p{+=} must appear in each definition. + +\subsubsection{Names} +\x{names}\xx{macro}{names}\xx{section}{names} + +Names are used to identify macros and sections. +A name consists of a sequence of from zero to 80 printable characters, +including the blank +character. End of line characters are not permitted in names. +Names are case sensitive; two different macros are permitted to have names +that differ in case only. Like free text, names are typeset by FunnelWeb and +are safe from misinterpretation by the target typesetter. For example, it +is quite acceptable to use the macro name \p{@<\bs{}medskip@>} +even if the target typesetter is \TeX{}. + +\begin{verbatim} +name = "@<" name_text "@>" +name_text = {ordinary_char | text_special} +\end{verbatim} + +\subsubsection{Formal Parameter Lists} +\xx{parameter lists}{formal} + +FunnelWeb allows macros to have up to nine macro parameters, named +\p{@1},\x{@1...} +\p{@2}, $\ldots$, \p{@9}. If a macro does not have a formal +parameter list, +it is defined to have no parameters, and an actual parameter list must not +appear at the point of call. If a macro has a formal parameter list, it +is defined to have one or more parameters, and a corresponding actual +parameter must be supplied for each formal parameter, at the point of call. + +Because FunnelWeb parameters have predictable names, the only information +that a formal parameter list need convey is \i{how many} parameters a macro +has. For this reason a formal parameter list takes the form of the highest +numbered formal parameter desired, enclosed in parentheses sequences. + +\begin{verbatim} +formal_parameter_list = "@(" formal_parameter "@)". +formal_parameter = "@1" | "@2" | "@3" | "@4" | "@5" | + "@6" | "@7" | "@8" | "@9" +\end{verbatim} + +\subsection{Expressions} +\xx{macro}{expressions} + +Expressions are FunnelWeb's most powerful form of expressing a text +string. +Macro bodies are defined as expressions. Actual parameters consist of +expressions. + +An expression consists of a sequence of zero or more expression elements. +An expression element can be ordinary text, a macro call, or a formal +parameter of the macro \i{definition} in which the formal parameter occurs. + +\begin{verbatim} +expression = {ordinary_text | macro_call | formal_parameter} +\end{verbatim} + +\subsection{Macro Calls} +\xx{macro}{calls} + +A macro call consists of a name optionally followed by an actual parameter +list. The +number of parameters in the actual parameter list must be the same as +the number of formal parameters specified in the definition of the +macro. If the macro has no formal parameter list, its call must have no +actual parameter list. + +\begin{verbatim} +macro_call = name [actual_parameter_list] +actual_parameter_list = "@(" actpar { "@," actpar } "@)" +actpar = expression | + ( whitespace "@""" expression "@""" whitespace ) +whitespace = {" " | eol} +\end{verbatim} + +FunnelWeb allows parameters to be passed directly, or delimited by +special double +quotes.\xx{macro parameter}{delimiting} +Each form is useful under different circumstances. Direct specification +is useful where the parameters are short and can be all placed on one line. +Double quoted parameters allow whitespace on either side +(that is not considered part of the parameter) and are useful for laying out +rather messy parameters. Here are examples of the two forms. + +\begin{verbatim} +@<Generic Loop@>@( + @"x:=1;@" @, + @"x<=10;@" @, + @"print "x=%u, x^2=%u",x,x*x; + x:=x+1;@+@" +@) + +@<Colours@>@(red@,green@,blue@,yellow@) +\end{verbatim} + +As shown, the two forms may be mixed within the same parameter list. + +Experience has shown that the vast majority of macros have no parameters. + +\subsection{Formal Parameters} +\xx{formal}{parameters} + +Formal parameters can appear in the expressions forming macro bodies +in accordance with the syntax rules defined above. A formal parameter +expands to the text of the expansion of its corresponding +actual parameter. There is nothing preventing a formal +parameter being provided as part of an expression that forms an actual +parameter. +In that happens, the formal parameter is bound to the actual parameter of the +calling macro, not the called macro. +After the following definitions, + +\begin{verbatim} +@$@<One@>@(@1@)=@{A walrus in @1 is a walrus in vain.@} +@$@<Two@>@(@1@)=@{@<One@>@(S@1n@)@} +\end{verbatim} + +the call + +\begin{verbatim} +@<Two@>@(pai@) +\end{verbatim} + +will result in the expansion + +\begin{verbatim} +A walrus in Spain is a walrus in vain. +\end{verbatim} + +\subsection{Macros are Static} +\xx{macro}{definition}\xx{macro}{expansion}\xx{macros}{static} + +In FunnelWeb, the actions of \i{macro definition} and \i{macro +expansion} occur during two separate phases (parser and tangle) +and cannot be interleaved. As a result, the FunnelWeb macro facility is +completely static. +It is not possible for one macro to +define another while the first macro is being +expanded; each must be defined statically. It is not possible to define a +macro to even assist in the definition of other macros. Because the scanner, +parser, analyser, and tangler phases are all invoked sequentially, there is +no room for feedback of definitions between different levels (\eg{}the user +cannot define a macro for the \p{vskip} pragma). + +This lack of power is fully intentional. By totally excluding the more +incomprehensible ways in which a general purpose macro preprocessor can be +used, FunnelWeb provides definite guarantees to the reader of its input files: + +\begin{itemize} +\item FunnelWeb guarantees that a piece of text does not contain a macro call +unless it contains the special character followed by \p{$<$} or \p{\#}. +\item FunnelWeb allows calls to be made to macros that are defined later +in the input file. +\end{itemize} + +\section{Analyser} +\x{analyser}\xx{checks}{macro} + +The effect of the parser is to construct a macro table containing a +representation of all the macros defined within the document, and a document +list which contains a complete representation of the entire document. +If there are no error diagnostics (or worse) at the end of the parser +run, FunnelWeb invokes the analyser which tests for the following conditions +and flags them with errors if they arise. + +\begin{itemize} +\item No macros defined in the input file. +\item No macros connected to output files. +\item Call of an undefined macro. +\item Call having the wrong number of parameters. +\item Call of a macro that is connected to an output file. +\item No calls made to a macro without the \p{@Z} option. +\item More than one call made to a macro without the \p{@M} option. +\item Directly or indirectly recursively defined macros. +\item Unnamed sections that contain no macro definitions. +\end{itemize} + +FunnelWeb performs a static analysis\xx{static}{analysis} to detect +recursion.\xx{macro}{recursion} +Unfortunately, the recursion detection algorithm +flags all macros that have an infinite expansion +rather than just all macros +with a recursive definition. If A calls B, and B calls +C, and C calls B, then FunnelWeb will flag A as well +as B and C. It is hoped that this problem will be fixed in a later version. + +Because FunnelWeb does not provide any kind of conditional feature, the +prevention of recursion does not represent a curtailment of expressive power. + +Macros may be invoked recursively, but may not be recursive. Thus: + +\begin{verbatim} +@<Sloth@>@(@<Sloth@>@(Walrus@)@) @! LEGAL recursive invocation. + +@$@<Teapot@>==@{@<Teapot@>@} @! ILLEGAL recursive definition. +\end{verbatim} + +\section{Tangle} +\x{tangle} + +If the scanner, parser, and analyser have successfully (\ie{}with no +errors, severe errors, or fatal errors) completed, and the Tangle option +(\p{+O}) is turned on (it is by default), then the Tangle component of +FunnelWeb is invoked to generate the product files specified in the \p{@O} +macros of the input file. + +The operation of Tangle is very simple. Each \p{@O} macro is expanded and +written to a file of the same name. As there are a finite number of macros, +and the analyser guarantees that the +macro structure is non-recursive, Tangle is guaranteed to terminate. + +Three remaining points are worth discussing. + +\begin{enumerate} + +\item Tangle expands macros using blank indentation unless the +user has specified otherwise in an indentation pragma in the +input file (see Section~\ref{indentationpragma}). + +\item Tangle keeps track of the +length of the lines that it is writing +and issues an error if any line of any product file that it generates is +longer than the maximum. The maximum is the minimum of a value defaulted +or specified in the input file (Section~\ref{mollpragma}), +and the value (if any) provided by the +\p{+w} command line argument (Section~\ref{commandlineoptions}). + +\item It is worth the user obtaining +some understanding of the resources +that FunnelWeb requires to perform its task. + +\end{enumerate} + +When FunnelWeb's scanner +executes, it reads each file into memory where it is kept for the duration +of the run. Thus, there must be room in memory for the entire +input file, including all include files. While this approach may seem +expensive in memory, it is almost necessary in order to support +forward references. To merely scan the input file, recording the macro +names, but leaving the text on disk, would require many random +access disk seeks. + +In contrast, FunnelWeb never builds an internal representation +of the product file. +Instead, each piece of output is written immediately to the +product file. This means that as long as the input file fits in memory, +the product file can be arbitrarily large. It also means that users need +not fear to define or call macros that they know will expand to megabytes +of text. Nor need they fear placing a call to such a macro as part of +an actual parameter. FunnelWeb does not ever expand actual parameters +internally. In fact, it does not expand them until it hits the corresponding +formal parameter during its expansion of the called macro. At that point, it +looks up the \i{expression} (not the expansion of the expression) for the +corresponding actual parameter, and starts expanding it. + +\section{Weave} +\x{weave}\x{typesetting} + +If the scanner, parser, and analyser have successfully (\ie{}with no +errors, severe errors, or fatal errors) completed, and the Weave option +(\p{+T}) is turned on (it is \i{off} by default), then the Weave component of +FunnelWeb is invoked to generate a text file in the format of a particular +typesetter. The result, when fed through the particular typesetter and printed, +is a fully typeset representation of the entire input file complete with +cross referencing information. + +\subsection{Target Typesetter} +\xx{target}{typesetter} + +Currently, FunnelWeb produces documentation files +in the format of only one typesetter --- +\TeX{}. However, the Weave package of FunnelWeb is fairly small, and it +is hoped that it can be rewritten so as to provide +a collection of typesetter modules from which +the user will be able to choose using a command line argument. + +\subsection{Cross Reference Numbering} +\xx{cross}{referencing}\xx{cross reference}{numbering} +\xx{section}{numbering} + +When FunnelWeb produces its typeset documentation, it \i{numbers} each +section and each macro definition and cross references the macro definitions. +The exact scheme used has been carefully thought out. However, as it can +be a little confusing to the beginner, it is explained here in full. + +The most important thing is that there is \i{no relation} between the +macro numbering and the section numbering. In Knuth's Web there are only +section numbers. In FunnelWeb, the numbering of sections and macros +is separated. + +In FunnelWeb, \i{sections} are numbered +hierarchically in ascending order. For example, the second level-C section +of the third level-B section of the first level-A section is +numbered \dq{1.3.2}. In contrast, \i{macro definitions} are numbered +sequentially in ascending order. For example, the first macro definition is +number 1, the second is number 2, and so on. Note that it is \i{macro +definitions} that are numbered, not \i{macros}. This distinction is necessary +because additive macros (\ie{}the ones with \p{+=}) +can be defined by a collection +of partial definitions scattered throughout the input file. A single additive +macro may be defined in definitions 5, 67, 128, and 153. + +\section{FunnelWeb Shell} +\label{commandshell}% +\xx{FunnelWeb}{command shell}\xx{commands}{FunnelWeb}\xx{FunnelWeb}{shell} + +\subsection{Introduction} + +One of the goals of FunnelWeb is +that it must be extremely portable. Huge efforts, desperate actions, +and great sacrifices were made in the name of portability. +For example, FunnelWeb is written in~C. + +An equally important goal was that of correctness and reliability. To this +end, it was determined that a large automated suite of test programs be +prepared to assist in regression testing. Preparing the test suite was +tedious, but achievable. Automating it portably was more difficult. + +The difficulty faced was that if FunnelWeb was implemented in the form of +a utility that could be +invoked from the operating system command language, the only way to set up +regression testing was in the command language of the operating system +of the target machine (shellscripts for UNIX, DCL for VMS, batch files +for MSDOS, and \i{nothing} on the Macintosh). The huge variation in these +command languages led to the conclusion that either the automation of +regression testing would have to be rewritten on each target machine, or +a small command language would have to be created within FunnelWeb. In the +end, the twin goals of portability and regression testing were considered so +important that a small command +shell was constructed inside FunnelWeb. This is called the +\newterm{FunnelWeb command shell}, or just \dq{the shell} for short. + +By default, when FunnelWeb is invoked, it does not enter its shell. If +just given the name of an input file, it will simple process the input file +in the normal manner and then terminate. To instruct FunnelWeb to +invoke its shell, the \p{+K} or \p{+X} command line option must be specified +when FunnelWeb is invoked from the operating system. It is also +invoked upon startup if the file \p{fwinit.fws} exists. + +Most FunnelWeb users will never need to use the shell and need not even +know about it. There are four main uses of the shell:\xx{uses}{shell} + +\begin{enumerate} + +\item As a tool to support automated regression testing. + +\item As a development tool on machines that do not have a built in shell +(\eg{}the Macintosh). The shell can be used to process whole groups of +files automatically. + +\item As a convenience. A user working on a multi-tasking, multi-window +workstation\x{workstation} +may wish to keep an interactive session of FunnelWeb going in +one window rather than having to run up the utility each time it is required. + +\item As a convenient +vehicle for enclosing utilities. The FunnelWeb shell contains +useful general purpose commands such as the +differences command \p{diff}. + +\end{enumerate} + +\subsection{Return Statuses} +\xx{errors}{shell}\xx{status}{success}% +\xx{status}{warning}\xx{status}{error}\xx{status}{severe}\xx{status}{fatal}% +\xx{status}{assertion} + +The hierarchy of diagnostics described in Section~\ref{diagnostics} +is also used in the +shell commands. Each shell command returns a status which can affect +further processing. + +\narrowthing{Success}{status is the normal command return status.} + +\narrowthing{Warning}{status is returned if some minor problem +arose with the execution of the command.} + +\narrowthing{Error}{status is returned if a significant problem +arises during the execution of the command. +However, unlike a severe error, +it does \i{not} cause termination of the enclosing shellscript.} + +\narrowthing{Severe error}{status is returned if a problem arises +during the execution of the command that prevents the command from +delivering on its \dq{promise}. A severe error causes FunnelWeb +to abort the script (and any stacked scripts) to the interactive level. +(However, the \p{tolerate} command allows this to be temporarily +overridden).} + +\narrowthing{Fatal error}{status is returned if a problem arises +that is so serious that execution of FunnelWeb cannot continue. +A fatal error causes FunnelWeb to abort to the operating system level.} + +\narrowthing{Assertion error}{status is never returned. If an assertion +error occurs, FunnelWeb bombs out ungracefully to the operating system. +Assertion errors should never happen. If they do, then there is a bug +in FunnelWeb.} + +To be precise, the status returned by each command +is a vector of numbers being the number of each of the different kinds of +diagnostic generated by the command. Usually only one kind +of diagnostic is generated. However, the \p{fw} command and a few of the other +commands can generate more than one kind of diagnostic. +These status vectors are summed internally where they may later be accessed +using the \p{status} command. However, the current diagnostic state +evaporates as soon as the next command is encountered. + +\subsection{Command Line Length} +\xx{command}{length} + +The maximum length of a shell command line is guaranteed to be +at least 300 characters. + +\subsection{String Substitution} +\label{stringsubstitution}\xx{string}{substitution} + +Most command shells provide some form of string substitution so +as to provide some degree of parameterization. +The FunnelWeb shell provides 36 different string variables named +\p{\$0..\$9} and \p{\$A..\$Z} (case insensitive). +Each variable can hold a string containing +any sequence of printable characters and can be as long as a command line. + +The \p{define} command\xx{define}{command} +allows the user to assign a value to these variables. +The \p{define} command takes two arguments. The first is the digit or letter +of the +variable to be defined. The second is a double quote delimited string being the +string value to be assigned to the variable. If you want to include a +double quote character within the string, you don't need to double it. + +Examples: + +\begin{verbatim} +define 3 "/root/usr/usrs/users/users5/thisuser/workdir/fwdir/testdir" +define M "/user/local/rubbish/bin/fw" +define Q "You don't need to double" double quotes" +\end{verbatim} + +Only the identifying character of the variable being assigned +is used in the definition. This syntax is a simple way of preventing +the variable from being substituted before it has a chance to be +defined! + +The following points clean up the remaining semantic details: + +\begin{itemize} + +\item There is only one set of variables and they are global to all +shellscripts. There are \i{no local variables}. + +\item When a shellscript is invoked using the \p{execute} command, the +substitution variables \p{0} through \p{9} are affected. See +Section~\ref{executecommand} for more details. + +\item If you want to include a dollar sign character in a command +use \dqp{\$\$}. + +\item FunnelWeb also defines \dqp{\$/} which translates to the character +that separates directory and file name fields in file names on the host +machine. For example: Sun=\dqp{/}, Vax=\dqp{]}, Mac=\dqp{:}, +PC=\dqp{\bs{}}. + +\item Substitution is not performed recursively. + +\end{itemize} + +\subsection{How a Command Line is Processed} +\xx{command line}{processing} + +When FunnelWeb reads in a command line (from the console or a script file), +it processes it in the following sequence: + +\begin{enumerate} + +\item The command line is checked for non-printable characters. If there +are any, they are flagged with a severe error. + +\item All dollar string substitution variables in the command line are +replaced by their corresponding string. +The command line is processed from left to right. Substitutions are +performed non recursively. + +\item At this point, if the line is empty, or consists entirely of +blanks, it is ignored and the interpreter moves to the next line. + +\item A severe error is generated if the line at this stage begins with +a blank. + +\item If the first character of the line is \dqp{!}, the line is a +comment line and is ignored. + +\item The run of non-blanks commencing at the start of the line is +compared case-insensitively to each of the legal command verbs. If the +command is illegal, a severe error is generated, otherwise the command +is processed. + +\end{enumerate} + +\subsection{Options} +\xx{command}{options}\xx{default}{options} + +The FunnelWeb shell maintains three sets of command line options. + +\begin{enumerate} + +\item The set of options resulting from applying the operating system +level command line +arguments to the default option settings. + +\item A set of shell options that prevail during the shell invocation. + +\item The set of option values active during a particular invocation +of FunnelWeb proper. + +\end{enumerate} + +When FunnelWeb is invoked from the operating system with just \p{+F}, +only the first of these three sets comes into existence. If the user +invokes the FunnelWeb shell, the shell options come into existence and are +initialized with the value of the first set. These shell options are +used as the default for all subsequent \p{fw} commands. However, +they can be altered using the script command \p{set}. If a +\p{fw} command executed in a shell contains additional command line options, +these override the shell options for that run, but do not change the +shell options. An example follows: + +\begin{verbatim} +$ fw +k +t ! Original invocation of FunnelWeb from OS. + ! Shell options are now default with "+t". +FunnelWeb>fw sloth ! Equivalent to fw sloth +t. +FunnelWeb>set -l ! Change the l shell option. +FunnelWeb>fw sloth +q ! Equivalent to fw sloth +t -l +q. +FunnelWeb>fw sloth ! Equivalent to fw sloth +t -l. +\end{verbatim} + +The existence of the shell option set means that the user can set up +a set of defaults to be applied to all \p{fw} commands issued within +the shell. + +\subsection{Shell Commands} +\xx{shell commands}{list}\xx{commands}{shell} + +This section describes each of the FunnelWeb shell commands. The syntax +is: + +\begin{verbatim} +shell_command = absent | codify | compare | define | diff | diffsummary | + diffzero | eneo | execute | exists | fixeols | help | + here | quit | set | show | skipto | status | + tolerate | trace | write | writeu +s = {" "}+ +\end{verbatim} + +As a rule, FunnelWeb shell commands return severe status if their +arguments are syntactically incorrect or if they are +unable to successfully operate on argument files. + +\subsubsection{Absent} +\xx{command}{absent} + +The \p{absent} command performs no action except to return a status. If the +file specified in its argument doesn't exist +it returns success status, otherwise it returns severe status. + +\begin{verbatim} +Syntax : absent = "absent" s filename +Example: absent result.out +\end{verbatim} + +This command is useful in regression testing +for making sure that +FunnelWeb \i{hasn't} produced a particular output file. + +\subsubsection{Codify} +\xx{command}{codify} + +The \p{codify} command takes two arguments: an input file and an output file. +It reads each line of the input file and writes a corresponding line to the +output file. The corresponding line consists of a C macro call containing +a string containing the input line. The command converts all backslashes in +input lines to double backslashes so as to avoid unwanted interpretations by +the C compiler. It also converts double quotes in the line to backslashed +double quotes. + +\begin{verbatim} +Syntax : codify = "codify" s filename s filename +Example: codify header.tex header.c +\end{verbatim} + +The following example demonstrates the transformation. + +\begin{verbatim} +Input Line: \def\par{\leavevmode\endgraf}% A "jolly good hack". +Output Line: WX("\\def\\par{\\leavevmode\\endgraf}% A \"jolly good hack\"."); +\end{verbatim} + +The \p{codify} command was introduced to assist in the +development of FunnelWeb. +It is used to convert longish text files +into C code to write them out. The C code is then included within +the FunnelWeb C program. For example, +the set of \TeX{} definitions that appears at the top of every +documentation file was \p{codif}ied and inserted into the +FunnelWeb code so that FunnelWeb would not have to look for a file containing +the definitions at run time. + +\subsubsection{Compare} +\xx{command}{compare} + +The \p{compare} command takes two filename arguments and performs a binary +comparison of the two files. If the files are identical, success status +is returned. If they are different, severe status is returned. No information +about the manner in which the files differ is conveyed. + +\begin{verbatim} +Syntax : compare = "compare" s filename s filename +Example: compare result.txt answer.txt +\end{verbatim} + +The \p{compare} command was created as the main checking mechanism for +regression testing. However, its binary output was soon found to be +unworkable and the more sophisticated \p{diff} command was added so +that the actual differences between the files could be examined. + +\subsubsection{Define} +\xx{command}{define}\xx{string}{substitution} + +The \p{define} command +assigns a value to a shell string substitution variable. +The \p{define} command takes two arguments. The first is the digit or letter +of the +variable to be defined. The second is a double quote delimited string being the +string value to be assigned to the variable. If you want to include a +double quote character within the string, you don't need to double it. + +\begin{verbatim} +Syntax : define = "define" s letter s """" text """" +Examples: define 3 "/usr/usrs/thisuser/workdir/fwdir/testdir" + define M "/user/local/rubbish/bin/fw" + define Q "You don't need to double" double quotes" +\end{verbatim} + +The command interpreter expands the command line before it executes the +\p{define} command. This means that you can define string substitution +variables in terms of each other with static binding. + +The \p{define} command was introduced to allow the parameterization +of the directories involved in regression testing. + +See Section~\ref{stringsubstitution} for more details. + +\subsubsection{Diff} +\xx{command}{diff}\xx{file}{differences} + +The \p{diff} command reads in two text files and \i{appends} a report to a log +file containing a list of the differences between the two input +files. If the log file does not already exist, an empty one is created first. + +\begin{verbatim} +Syntax : diff = "diff" s filename s filename s filename s ["ABORT"] +Examples: diff result.tex answer.tex diff.log + diff $Otest23.out $Atest23.out $Ldiff.log ABORT +\end{verbatim} + +The \p{diff} command performs a full line-based differences operation. +It will identify different sections in a file, even if they are of differing +length. + +The implementation of the \p{diff} command is quite complicated. To be +sure that it is at least getting its same/different proclamation right, +the \p{diff} command performs a binary comparison as an extra check. + +The following points describe the rules for determining the result status. + +\begin{enumerate} + +\item \p{diff} aborts with a +severe error if the log file cannot be opened or +created for appending. + +\item An ordinary error is generated if either or both of the input files +cannot be opened. + +\item If, at the end of the run, the two input files have not +been proven to be identical, and the \p{ABORT} keyword is present, \p{diff} +returns severe status. + +\item \p{diff} returns success status if none of the above conditions +(or similar conditions) occur, even if the two files are different. + +\end{enumerate} + +The \p{diff} command \i{appends} its differences report rather than +merely writing it. This allows a regression test script to perform +a series of regression tests and produce a report for the user. + +The \p{diff} command was added to the shell after it had become apparent +that the simpler \p{compare} command was not yielding enough information. +Whereas early on, regression testing was treated +mainly as a tool to ensure that FunnelWeb was being ported to other machines +correctly, it began to place an increasing role during development in +identifying the effects of changes made to the code. The \p{diff} command +supports this application of regression testing by pinpointing the +differences between nearly-identical text files. + +\subsubsection{Diffsummary} +\xx{command}{diffsummary} + +The \p{diffsummary} command writes a short report to the +console giving the number of +difference operations that have taken place and how many of the pairs +of files compared were identical. Counting starts at the most recent +execution of a \p{diffzero} command, or if there has been none, when +FunnelWeb started up. + +\begin{verbatim} +Syntax : diffsummary = "diffsummary" +Examples: diffsummary +\end{verbatim} + +The \p{diffsummary} command was added so as to allow regression testing +scripts to display a summary of the results of the test. If the summary +indicates that no pair of files differed, then there is no need to look +in the \p{diff} log file. + +\subsubsection{Diffzero} +\xx{command}{diffzero} + +The \p{diffzero} command zeros the different summary counters used by the +\p{diff} and \p{diffsummary} commands. + +\begin{verbatim} +Syntax : diffzero = "diffzero" +Examples: diffzero +\end{verbatim} + +The \p{diffzero} command was added so as to allow regression testing +shellscripts to zero their differences counters at the start of a run. +This allows testers to invoke the same regression testing script +twice in one interactive session without receiving an inflated +differences summary. + +\subsubsection{Eneo} +\xx{command}{eneo} + +The \p{eneo} command takes one filename argument. If the file does +not exist, no action is taken. If the file does exist, it is deleted. +In both cases success status is returned. However, if the file exists +and cannot be deleted, \p{eneo} returns severe status. + +\begin{verbatim} +Syntax : eneo = "eneo" s filename +Examples: eneo result.out +\end{verbatim} + +The \p{eneo} command was added so as to allow regression testing scripts +to ensure that existing output files were not present before proceeding +with a test run. If FunnelWeb were to fail to generate an output file, it +would be +extremely undesirable for the old version to be used. + +ENEO stands for \b{E}stablish the \b{N}on \b{E}xistence \b{O}f. +Most operating systems provide a command to delete files. Typically +these commands are verbs such as \dq{delete}, \dq{remove}, and \dq{kill}. +As a consequence, the designers of delete commands usually +consider the command to have failed if it fails to find the file to be +deleted. However, in my experience, the most common use +for the delete command +is to \i{establish the non-existence of} one or more files. Typically, a +script is starting up and needs to clear the air before getting started. +If the files are there, they should be deleted; if they are not, then that's +OK too.\footnote{As far as I know, the \p{eneo} command is original.} + +\subsubsection{Execute} +\label{executecommand}\xx{command}{execute} + +The \p{execute} command causes a specified text file to be +executed as a FunnelWeb shellscript. The first argument is the +name of the script file. +The remaining arguments are assigned to the substitution +variables \p{\$1}, \p{\$2}, $\ldots$, \p{\$9}. +Substitution variables in the range +\p{\$1} to \p{\$9} that do not correspond to an argument are set to +the empty string \p{""}. \p{\$0} is set to the empty string regardless. +The execute command can be used recursively, allowing shell scripts to +invoke each other. A file extension default of \dqp{.fws} +(FunnelWeb Script) applies to script files. + +\begin{verbatim} +Syntax : execute = "execute" s filename {argument_string} +Examples: execute megatest.fws /usr/users/ross/fwtest ! + execute sloth +\end{verbatim} + +The first example above will result in the following substitution variable +assignments. + +\begin{verbatim} +$0 = "" +$1 = "/usr/users/ross/fwtest" +$2 = "!" +$3 = "" +... +$9 = "" +\end{verbatim} + +It should be stressed that there are no local variables in the FunnelWeb +command language; the variables above are globally modified. + +The \p{execute} command was added to allow the creation of sub-scripts +to test FunnelWeb in particular ways. + +\subsubsection{Exists} +\xx{command}{exists} + +The \p{exists} command performs no action except to return a status. If the +file specified in its argument exists +it returns success status, otherwise it returns severe status. + +\begin{verbatim} +Syntax : exists = "exists" s filename +Example: exists test6.fw +\end{verbatim} + +This command is useful in regression testing +for ensuring that +FunnelWeb has produced a particular output file. + +\subsubsection{Fixeols} +\xx{command}{fixeols} + +The \p{fixeols} command takes two filename arguments: an input file and +an output file. It reads in the input file and writes it to the output file +changing all the end of line control character +sequences to the local format. It can also take one filename argument, in +which case it replaces the target file with its transformation. + +\begin{verbatim} +Syntax : fixeols = "fixeols" s filename [s filename] +Examples: fixeols imported.hak result.kln + fixeols sloth.dat +\end{verbatim} + +The \p{fixeols} command works by parsing the input file into alternating +runs of +printable characters (ASCII 20 to ASCII 126) and runs of non-printable +characters (all the others). +It then\xx{non-printable}{characters} +parses each run of non-printable characters from left to right into +subruns of non-printables not containing the same character twice. +It then replaces each subrun with a native EOL.\footnote{Note: A native +EOL can be inserted into a text file in a portable manner +simply by writing \dqp{\bs{}n} to the text output stream.} +For example, +if a native EOL is \p{X}, and \p{ABCD} are non-printable characters, and +the file to be converted is + +\begin{verbatim} +thisABisABCDanABABexampleABCCCof the conversion. +\end{verbatim} + +then \p{fixeols} would produce + +\begin{verbatim} +thisXisXanXXexampleXXXof the conversion. +\end{verbatim} + +The \p{fixeols} command was devised to solve the problem created sometimes +when text files are moved from one machine to another +(\eg{}with the kermit program) +using a binary transfer mode rather than a text transfer mode. +If such a transfer is made, and the text file line termination conventions +differ on the two machines, one can wind up with a set of +text files with improperly terminated lines. This can cause problems +on a number of fronts, but in particular affects regression testing +which relies heavily on exact comparisons between files. The \p{fixeols} +command provides a solution to this problem by providing a portable way +to \dq{purify} text files whose end of lines have become incorrect. +The regression testing scripts all apply \p{fixeols} to their input and +output files before each test. + +\subsubsection{Fw} +\xx{command}{fw} + +The \p{fw} command allows FunnelWeb proper to be invoked from a shell +script. The syntax is almost identical to the syntax with which FunnelWeb is +invoked from the operating system. + +\begin{verbatim} +Syntax : fw = "fw" s ordinary_funnelweb_command_line +Examples: fw sloth +t +d + fw -l walrus +\end{verbatim} + +Some important points about this \p{fw} command are: + +\begin{itemize} +\item Options are inherited from the default shell options. +\item The \p{F} (input file option) must be turned on. +\item The \p{K}, \p{H}, and \p{X} options must be turned off. +\item The \p{J} option must be turned off. +\item The options specified in a \p{fw} command do not affect the default +shell options. +\item This command performs no action in the VAX VMS version of FunnelWeb. +\end{itemize} + +\subsubsection{Help} +\xx{command}{help} + +The \p{help} command provides online help from within the FunnelWeb shell. +It provides access to all of the same messages that the \p{+H} command +line option does. + +\begin{verbatim} +Syntax : help = "help" [s help_message_name] +Examples: help + help commands +\end{verbatim} + +If no message name is given, the default message is displayed. It contains +a list of the other help messages and their names. The actual messages +themselves are not listed here. + +\subsubsection{Here} +\xx{command}{here} + +The \p{here} command acts as a target for the \p{skipto} command. When +the shell interpreter encounters a \p{skipto} command, it ignores all +the following commands until it encounters a \p{here} command. + +\begin{verbatim} +Syntax : here = "here" +Example: here +\end{verbatim} + +The \p{skipto}/\p{here} mechanism was created to allow groups of +regression tests to be skipped during debugging without having to comment +them out. For more information, see Section~\ref{skiptocommand}. + +\subsubsection{Quit} +\xx{command}{quit} + +The \p{quit} command terminates FunnelWeb immediately and returns +control to the operating system. This applies regardless of the depth +of the script being executed. + +\begin{verbatim} +Syntax : quit = "quit" +Example: quit +\end{verbatim} + +\subsubsection{Set} +\xx{command}{set} + +The \p{set} command modifies the default shell options. +For example, \p{set +t} sets the \p{+t} option for all subsequent +FunnelWeb runs within the shell until another set command +sets \p{-t}. + +\begin{verbatim} +Syntax : set = "set" s ordinary_funnelweb_command_line +Examples: set sloth +t +d + set -lwalrus +\end{verbatim} + +The restrictions on the \p{set} command are identical to those on the +\p{fw} command except that, in addition, +the \p{+F} option cannot be turned on in the \p{set} command. + +The set command is useful for setting option defaults before a long run +of regression tests. It could also be useful to set default options in +a FunnelWeb shell kept by a user in a workstation window. + +\subsubsection{Show} +\xx{command}{show} + +The \p{show} command displays the current default shell options. +These options are the options that subsequent \p{fw} commands will +inherit. + +\begin{verbatim} +Syntax : show = "show" +Example: show +\end{verbatim} + +\subsubsection{Skipto} +\label{skiptocommand}\xx{command}{skipto} + +The \p{skipto} command causes the shell to ignore all subsequent commands +until a \p{here} command is encountered. + +\begin{verbatim} +Syntax : skipto = "skipto" +Examples: skipto +\end{verbatim} + +The \p{skipto}/\p{here} mechanism was created to allow groups of +regression tests to be skipped during debugging without having to comment +them out. It is like a cut price \p{goto}. +For example, supposing that there were eight tests and that +you had debugged the first five. You might want to skip the first five +tests so that you can concentrate on the next three. The following +code shows how this can be done. + +\begin{verbatim} +skipto +execute test infile1 +execute test infile2 +execute test infile3 +execute test infile4 +execute test infile5 +here +execute test infile6 +execute test infile7 +execute test infile8 +\end{verbatim} + +It should be stressed that FunnelWeb performs full command line processing +including the dollar substitutions before testing the line to see if +it is \p{here}. This can lead to non-obvious problems. For example. + +\begin{verbatim} +skipto +! Test the Parser +! --------------- +define X "execute parsertest.fws" +$X infile1 +$X infile2 +$X infile3 +$X infile4 +$X infile5 +here +\end{verbatim} + +The above looks correct, but, because the \p{define} command isn't executed +(and \p{\$X} is not defined) the subsequent \p{\$X} lines result in a +leading blanks error. The problem can be corrected by defining \p{\$X} +before the \p{skipto} command. + +\subsubsection{Status} +\xx{command}{status} + +The \p{status} command takes two forms. In its first form in which +no arguments are given, it writes out the number of warnings, errors +and severe errors that 1) were generated by the previous command +and 2) have been generated during the entire shell invocation. +In its second form it takes from one to three arguments each of which +specifies a diagnostic severity and a number. The \p{status} command +compares each of these numbers with the number of that diagnostic +generated by the previous command and generates a severe error if +they differ. + +\begin{verbatim} +Syntax : status = "status" {s ("w"|"e"|"s") num}0..3 +Examples: status + status w1 e5 s1 + status w4 + status s1 e2 +\end{verbatim} + +The \p{status} command was introduced to test the status results of +commands during their debugging. It is also useful for checking to see that +the right number of diagnostics have been generated at particular points +in test scripts. + +\subsubsection{Tolerate} +\xx{command}{tolerate} + +The \p{tolerate} command instructs the shell not to abort processing +of the script if the next command generates one or more warnings, errors, +or severe errors. For the purposes of this command, a blank line counts +as a command, so be sure to place the \p{tolerate} command immediately +above the command about which you wish to be tolerant. + +\begin{verbatim} +Syntax : tolerate = "tolerate" +Example: tolerate +\end{verbatim} + +The tolerate command was introduced to allow FunnelWeb (\ie{}the +\p{fw} command) to be tested +in a script under conditions which would normally cause it to abort the +script. + +\subsubsection{Trace} +\xx{command}{trace} + +The \p{trace} command turns on or off command tracing during script +execution. By default, tracing is turned off. + +\begin{verbatim} +Syntax : trace = "trace" [s ("on" | "off")] +Examples: trace on + trace off +\end{verbatim} + +The \p{trace} command was introduced to assist in the debugging of +regression test scripts. + +\subsubsection{Write} +\xx{command}{write} + +The \p{write} command accepts a double-quoted argument and writes it followed +by an EOL to the console (standard output). +There is no need to double any double quotes +occurring within the string. + +\begin{verbatim} +Syntax : write = "write" s string +Examples: write "Now about to start the next test." + write "You don't need to " double enclosed double quotes." +\end{verbatim} + +The \p{write} command was added so as to allow regression testing scripts +to inform the user of their progress. + +\subsubsection{Writeu} +\xx{command}{writeu} + +The \p{writeu} command is identical to the \p{write} command except that it +underlines the text on an additional following output line. + +\begin{verbatim} +Syntax : writeu = "writeu" s string +Examples: writeu "Test 6" +\end{verbatim} + +\section{Concluding Remarks} + +This chapter defines the semantics of the FunnelWeb program. As stated +at the start of this chapter, this document takes precedence over the +FunnelWeb program. While the +definition of FunnelWeb in this chapter is reasonably solid, it is far +from watertight, and it is hoped that it can be tightened further in +future versions. All constructive criticism will be gratefully received +by the author Ross Williams (\p{ross@spam.adelaide.edu.au}). + +%==============================================================================% +% End of Ch3.tex % +%==============================================================================% |