summaryrefslogtreecommitdiff
path: root/web/funnelAC/fwACsrc
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /web/funnelAC/fwACsrc
Initial commit
Diffstat (limited to 'web/funnelAC/fwACsrc')
-rw-r--r--web/funnelAC/fwACsrc/HTML.txt2379
-rw-r--r--web/funnelAC/fwACsrc/Makefile65
-rw-r--r--web/funnelAC/fwACsrc/Makefile.os268
-rw-r--r--web/funnelAC/fwACsrc/Makefile.unix61
-rw-r--r--web/funnelAC/fwACsrc/README.ABC347
-rw-r--r--web/funnelAC/fwACsrc/analyse.c326
-rw-r--r--web/funnelAC/fwACsrc/analyse.h61
-rw-r--r--web/funnelAC/fwACsrc/as.c72
-rw-r--r--web/funnelAC/fwACsrc/as.h119
-rw-r--r--web/funnelAC/fwACsrc/autoccln.fwi45
-rw-r--r--web/funnelAC/fwACsrc/ccline.fwi74
-rw-r--r--web/funnelAC/fwACsrc/clock.c125
-rw-r--r--web/funnelAC/fwACsrc/clock.h107
-rw-r--r--web/funnelAC/fwACsrc/command.c2147
-rw-r--r--web/funnelAC/fwACsrc/command.h61
-rw-r--r--web/funnelAC/fwACsrc/data.c50
-rw-r--r--web/funnelAC/fwACsrc/data.h684
-rw-r--r--web/funnelAC/fwACsrc/dump.c900
-rw-r--r--web/funnelAC/fwACsrc/dump.h78
-rw-r--r--web/funnelAC/fwACsrc/environ.h316
-rw-r--r--web/funnelAC/fwACsrc/err.status1
-rw-r--r--web/funnelAC/fwACsrc/fw-latex.sty327
-rw-r--r--web/funnelAC/fwACsrc/fw.def3
-rw-r--r--web/funnelAC/fwACsrc/fwmem.c371
-rw-r--r--web/funnelAC/fwACsrc/fwmem.h116
-rw-r--r--web/funnelAC/fwACsrc/fwtest.cmd5
-rw-r--r--web/funnelAC/fwACsrc/help.c631
-rw-r--r--web/funnelAC/fwACsrc/help.h164
-rw-r--r--web/funnelAC/fwACsrc/help_gnu.c105
-rw-r--r--web/funnelAC/fwACsrc/help_gnu.ctx339
-rw-r--r--web/funnelAC/fwACsrc/help_gnu.h58
-rw-r--r--web/funnelAC/fwACsrc/help_gnu.txt339
-rw-r--r--web/funnelAC/fwACsrc/htmlhead.c112
-rw-r--r--web/funnelAC/fwACsrc/htmlhead.cht42
-rw-r--r--web/funnelAC/fwACsrc/htmlhead.h125
-rw-r--r--web/funnelAC/fwACsrc/htmlhead.htm42
-rw-r--r--web/funnelAC/fwACsrc/list.c328
-rw-r--r--web/funnelAC/fwACsrc/list.h207
-rw-r--r--web/funnelAC/fwACsrc/lister.c370
-rw-r--r--web/funnelAC/fwACsrc/lister.h75
-rw-r--r--web/funnelAC/fwACsrc/machin.c355
-rw-r--r--web/funnelAC/fwACsrc/machin.h342
-rw-r--r--web/funnelAC/fwACsrc/main.c115
-rw-r--r--web/funnelAC/fwACsrc/mapper.c343
-rw-r--r--web/funnelAC/fwACsrc/mapper.h69
-rw-r--r--web/funnelAC/fwACsrc/misc.c235
-rw-r--r--web/funnelAC/fwACsrc/misc.h126
-rw-r--r--web/funnelAC/fwACsrc/option.c454
-rw-r--r--web/funnelAC/fwACsrc/option.h180
-rw-r--r--web/funnelAC/fwACsrc/parser.c1476
-rw-r--r--web/funnelAC/fwACsrc/parser.h65
-rw-r--r--web/funnelAC/fwACsrc/scanner.c2559
-rw-r--r--web/funnelAC/fwACsrc/scanner.h67
-rw-r--r--web/funnelAC/fwACsrc/section.c151
-rw-r--r--web/funnelAC/fwACsrc/section.h123
-rw-r--r--web/funnelAC/fwACsrc/style.h270
-rw-r--r--web/funnelAC/fwACsrc/table.c433
-rw-r--r--web/funnelAC/fwACsrc/table.h189
-rw-r--r--web/funnelAC/fwACsrc/tangle.c887
-rw-r--r--web/funnelAC/fwACsrc/tangle.h56
-rw-r--r--web/funnelAC/fwACsrc/texhead.c108
-rw-r--r--web/funnelAC/fwACsrc/texhead.ctx320
-rw-r--r--web/funnelAC/fwACsrc/texhead.h125
-rw-r--r--web/funnelAC/fwACsrc/texhead.tex320
-rw-r--r--web/funnelAC/fwACsrc/weave.c2330
-rw-r--r--web/funnelAC/fwACsrc/weave.h55
-rw-r--r--web/funnelAC/fwACsrc/writfile.c319
-rw-r--r--web/funnelAC/fwACsrc/writfile.h196
68 files changed, 24113 insertions, 0 deletions
diff --git a/web/funnelAC/fwACsrc/HTML.txt b/web/funnelAC/fwACsrc/HTML.txt
new file mode 100644
index 0000000000..f3e05ba499
--- /dev/null
+++ b/web/funnelAC/fwACsrc/HTML.txt
@@ -0,0 +1,2379 @@
+Hypertext Markup Language (HTML) Tim Berners-Lee, CERN
+Internet Draft Daniel Connolly, Atrium
+IIIR Working Group June 1993
+
+
+ Hypertext Markup Language (HTML)
+
+ A Representation of Textual Information and MetaInformation
+ for Retrieval and Interchange
+
+
+Status of this Document
+
+ This document is an Internet Draft. Internet Drafts are working
+ documents of the Internet Engineering Task Force (IETF), its Areas,
+ and its Working Groups. Note that other groups may also distribute
+ working documents as Internet Drafts.
+
+ Internet Drafts are working documents valid for a maximum of six
+ months. Internet Drafts may be updated, replaced, or obsoleted by
+ other documents at any time. It is not appropriate to use Internet
+ Drafts as reference material or to cite them other than as a
+ "working draft" or "work in progress".
+
+ Distribution of this document is unlimited. The document is a
+ draft form of a standard for interchange of information on the
+ network which is proposed to be registered as a MIME (RFC1341)
+ content type. Please send comments to timbl@info.cern.ch or the
+ discussion list www-talk@info.cern.ch.
+
+ This is version 1.2 of this draft. This document is available in
+ hypertext on the World-Wide Web as
+ http://info.cern.ch/hypertext/WWW/MarkUp/HTML.html
+
+Abstract
+
+ HyperText Markup Language (HTML) can be used to represent
+
+ Hypertext news, mail, online documentation, and collaborative
+ hypermedia;
+
+ Menus of options;
+
+ Database query results;
+
+ Simple structured documents with inlined graphics.
+
+ Hypertext views of existing bodies of information
+
+ The World Wide Web (W3) initiative links related information
+ throughout the globe. HTML provides one simple format for
+ providing linked information, and all W3 compatible programs are
+ required to be capable of handling HTML. W3 uses an Internet
+
+
+
+Berners-Lee and Connolly 1
+
+ protocol (Hypertext Transfer Protocol, HTTP), which allows transfer
+ representations to be negotiated between client and server, the
+ result being returned in an extended MIME message. HTML is
+ therefore just one, but an important one, of the representations
+ used with W3.
+
+ HTML is proposed as a MIME content type.
+
+ HTML refers to the URL specification of RFCxxxx.
+
+ Implementations of HTML parsers and generators can be found in the
+ various W3 servers and browsers, in the public domain W3 code, and
+ may also be built using various public domain SGML parsers such as
+ [SGMLS] . HTML is an SGML document type with fairly generic
+ semantics appropriate for representing information from a wide
+ range of applications. It is more generic than many specific SGML
+ applications, but is still completely device-independent.
+
+ IN THIS DOCUMENT
+
+ This document contains the following parts:
+
+ Vocabulary used in this document, degrees of imperative.
+
+ HTML and MIME with discussion of character sets.
+
+ HTML and SGML and the relationship between them, and
+ Structured text : an introduction for
+ beginners to SGML.
+
+ HTML Elements A list with description, example, and
+ typical rendering.
+
+ HTML Entities Entities used to describe characters.
+
+ The HTML DTD The text of the SGML DTD for HTML
+
+ Link relationship values .
+ A provisional list. Not part of the
+ standard.
+
+ Registration Authority
+ The authority for extending lists of valid
+ vales.
+
+ References to related documents
+
+ Authors addresses Contact information.
+
+ table of contents
+
+Vocabulary
+
+
+
+
+Berners-Lee and Connolly 2
+
+ This specification uses the words below with the precise meaning
+ given.
+
+ Representation The encoding of information for interchange.
+ For example, HTML is a representation of
+ hypertext.
+
+ Rendering The form of presentation to information to
+ the human reader.
+
+ IMPERATIVES
+
+ may The implementation is not obliged to follow
+ this in any way.
+
+ must If this is not followed, the implementation
+ does not conform to this specification.
+
+ shall as "must"
+
+ should If this is not followed, though the
+ implementation officially conforms to the
+ standard, undesirable results may occur in
+ practice.
+
+ typical Typical rendering is described for many
+ elements. This is not a mandatory part of the
+ standard but is given as guidance for
+ designers and to help explain the uses for
+ which the elements were intended.
+
+ NOTES
+
+ Sections marked "Note:" are not mandatory parts of the
+ specification but for guidance only.
+
+ STATUS OF FEATURES
+
+ Mainstream All parsers must recognize these features.
+ Features are mainstream unless otherwise
+ mentioned.
+
+ Extra Standard HTML features which may safely be
+ ignored by parsers. It is legal to ignore
+ these, treat the contents as though the tags
+ were not there. (e.g. EM, and any undefined
+ elements)
+
+ Obsolete Not standard HTML. Parsers should implement
+ these features as far as possible in order to
+ preserve back-compatibility with previous
+ versions of this specification.
+
+
+
+
+Berners-Lee and Connolly 3
+
+ HTML AND MIME
+
+ The definition of the HTML content subtype is
+
+ MIME Type name text
+
+ MIME subtype name: html
+
+ Required parameters: none
+
+ Optional parameters: charset
+
+Character sets
+
+ The base character set (the SGML BASESET) for HTML is ISO Latin-1.
+ This is the set referred to by any numeric character references .
+ The actual character set used in the representation of an HTML
+ document may be ISO Latin 1, or its 7-bit subset which is ASCII.
+ There is no obligation for an HTML document to contain any
+ characters above decimal 127. It is possible that a transport
+ medium such as electronic mail imposes constraints on the number of
+ bits in a representation of a document, though the HTTP access
+ protocol used by W3 always allows 8 bit transfer.
+
+ When an HTML document is encoded using 7-bit characters, then the
+ mechanisms of character references and entity references may be
+ used to encode characters in the upper half of the ISO Latin-1 set.
+ In this way, documents may be prepared which are suitable for
+ mailing through 7-bit limited systems.
+
+ INTRODUCTION
+
+ The HyperText Markup Language is defined in terms of the ISO
+ Standard Generalized Markup Language []. SGML is a system for
+ defining structured document types and markup languages to
+ represent instances of those document types.
+
+ Every SGML document has three parts:
+
+ An SGML declaration, which binds SGML processing quantities and
+ syntax token names to specific values. For example, the SGML
+ declaration in the HTML DTD specifies that the string that opens
+ a tag is </ and the maximum length of a name is 40 characters.
+
+ A prologue including one or more document type declarations,
+ which specifiy the element types, element relationships and
+ attributes, and references that can be represented by markup.
+ The HTML DTD specifies, for example, that the HEAD element
+ contains at most one TITLE element.
+
+ An instance, which contains the data and markup of the document.
+
+ We use the term HTML to mean both the document type and the markup
+
+
+
+Berners-Lee and Connolly 4
+
+ language for representing instances of that document type.
+
+ All HTML documents share the same SGML declaration an prologue.
+ Hence implementations of the WorldWide Web generally only transmit
+ and store the instance part of an HTML document. To construct an
+ SGML document entity for processing by an SGML parser, it is
+ necessary to prefix the text from ``HTML DTD'' on page 10 to the
+ HTML instance.
+
+ Conversely, to implement an HTML parser, one need only implement
+ those parts of an SGML parser that are needed to parse an instance
+ after parsing the HTML DTD.
+
+
+
+Structured Text
+
+ An HTML instance is like a text file, except that some of the
+ characters are interpreted as markup. The markup gives structure to
+ the document.
+
+ The instance represents a hierarchy of elements. Each element has a
+ name , some attributes , and some content. Most elements are
+ represented in the document as a start tag, which gives the name
+ and attributes, followed by the content, followed by the end tag.
+ For example:
+
+ <HTML>
+ <TITLE>
+ A sample HTML instance
+ </TITLE>
+ <H1>
+ An Example of Structure
+ </H1>
+ Here's a typical paragraph.
+ <P>
+ <UL>
+ <LI>
+ Item one has an
+ <A NAME="anchor">
+ anchor
+ </A>
+ <LI>
+ Here's item two.
+ </UL>
+ </HTML>
+
+ Some elements (e.g. P, LI) are empty. They have no content. They
+ show up as just a start tag.
+
+ For the rest of the elements, the content is a sequence of data
+ characters and nested elements. Note that the HTML DTD in fact
+ severely limits the amount of nesting which is allowed: most things
+
+
+
+Berners-Lee and Connolly 5
+
+ cannot be nested, in fact. No elements may be recursively nested.
+ Anchors and character highlighting may be put inside other
+ constructs.
+
+ TAGS
+
+ Every element starts with a tag, and every non-empty element ends
+ with a tag. Start tags are delimited by < and >, and end tags are
+ delimited by </ and >.
+
+ Names
+
+ The element name immediately follows the tag open delimiter. Names
+ consist of a letter followed by up to 33 letters, digits, periods,
+ or hyphens. Names are not case sensitive.
+
+ Attributes
+
+ In a start tag, whitespace and attributes are allowed between the
+ element name and the closing delimiter. An attribute consists of a
+ name, an equal sign, and a value. Whitespace is allowed around the
+ equal sign.
+
+ The value is specified in a string surrounded by single quotes or a
+ string surrounded by double quotes. (See: other tolerated forms @@)
+
+ The string is parsed like RCDATA (see below ) to determine the
+ attribute value. This allows, for example, quote characters in
+ attribute values to be represented by character references.
+
+ The length of an attribute value (after parsing) is limited to 1024
+ characters.
+
+ ELEMENT TYPES
+
+ The name of a tag refers to an element type declaration in the HTML
+ DTD. An element type declaration associates an element name with
+
+ A list of attributes and their types and statuses
+
+ A content type (one of EMPTY, CDATA, RCDATA, ELEMENT, or MIXED)
+ which determines the syntax of the element's content
+
+ A content model, which specifies the pattern of nested elements
+ and data
+
+ Empty Elements
+
+ Empty elements have the keyword EMPTY in their declaration. For
+ example:
+
+ <!ELEMENT NEXTID - O EMPTY>
+ <!ATTLIST NEXTID N NUMBER #REQUIRED>
+
+
+
+Berners-Lee and Connolly 6
+
+ This means that the following:
+
+ <nextid n=''27''>
+
+ is legal, but these others are not:
+
+ <nextid>
+ <nextid n=''abc''>
+
+ Character Data
+
+ The keyword CDATA indicates that the content of an element is
+ character data. Character data is all the text up to the next end
+ tag open delimiter-in-context. For example:
+
+<!ELEMENT XMP - - CDATA>
+
+ specifies that the following text is a legal XMP element:
+
+ <xmp>Here's an example. It looks like it has
+ <tags> and <!--comments-->
+ in it, but it does not. Even this
+ </ is data.</xmp>
+
+ The string </ is only recognized as the opening delimiter of an end
+ tag when it is ``in context,'' that is, when it is followed by a
+ letter. However, as soon as the end tag open delimiter is
+ recognized, it terminates the CDATA content. The following is an
+ error:
+
+ <xmp>There is no way to represent </end> tags
+ in CDATA </xmp>
+
+ Replaceable Character Data
+
+ Elements with RCDATA content behave much like those with CDATA,
+ except for character references and entity references. Elements
+ declared like:
+
+<!ELEMENT TITLE - - RCDATA>
+
+ can have any sequence of characters in their content.
+
+ Character References
+
+ To represent a character that would otherwise be recognized as
+ markup, use a character reference. The string &# signals a
+ character reference when it is followed by a letter or a digit. The
+ delimiter is followed by the decimal character number and a
+ semicolon. For example:
+
+<title>You can even represent &#60;/end> tags in RCDATA </title>
+
+
+
+
+Berners-Lee and Connolly 7
+
+ Entity References
+
+ The HTML DTD declares entities for the less than, greater than, and
+ ampersand characters and each of the ISO Latin 1 characters so that
+ you can reference them by name rather than by number.
+
+ The string & signals an entity reference when it is followed by a
+ letter or a digit. The delimiter is followed by the entity name and
+ a semicolon. For example:
+
+Kurt G&ouml;del was a famous logician and mathematician.
+
+ Note: To be sure that a string of characters has
+ no markup, HTML writers should represent all
+ occurrences of <, >, and & by character or
+ entity references.
+
+ Element Content
+
+ Some elements have, in stead of a keyword that states the type of
+ content, a content model, which tells what patterns of data and
+ nested elements are allowed. If the content model of an element
+ does not include the symbol #PCDATA , the content is element
+ content.
+
+ Whitespace in element content is considered markup and ignored. Any
+ characters that are not markup, that is, data characters, are
+ illegal.
+
+ For example:
+
+<!ELEMENT HEAD - - (TITLE? & ISINDEX? & NEXTID? & LINK*)>
+
+ declares an element that may be used as follows:
+
+<head>
+ <isindex>
+ <title>Head Example</title>
+</head>
+
+ But the following are illegal:
+
+<head> no data allowed! </head>
+<head><isindex><title>Two isindex tags</title><isindex></head>
+
+ Mixed Content
+
+ If the content model includes the symbol #PCDATA, the content of
+ the element is parsed as mixed content. For example:
+
+<!ELEMENT PRE - - (#PCDATA | A | B | I | U | P)+>
+<!ATTLIST PRE
+ WIDTH NUMBER #implied
+
+
+
+Berners-Lee and Connolly 8
+
+ >
+
+ This says that the PRE element contains one or more A, B, I, U, or
+ P elements or data characters. Here's an example of a PRE element:
+
+<pre>
+<b>NAME</b>
+ cat -- concatenate<a href=''terms.html#file''>files</a>
+<b>EXAMPLE</b>
+ cat <xyz
+</pre>
+
+ The content of the above PRE element is:
+
+ A B element
+
+ The string `` cat -- concatenate''
+
+ An A element
+
+ The string ``\n''
+
+ Another B element
+
+ The string ``\n cat <xyz''
+
+ COMMENTS AND OTHER MARKUP
+
+ To include comments in an HTML document that will be ignored by the
+ parser, surround them with <!-- and -->. After the comment
+ delimiter, all text up to the next occurrence of -- is ignored.
+ Hence comments cannot be nested. Whitespace is allowed between the
+ closing -- and >. (But not between the opening <! and --.)
+
+ For example:
+
+<HEAD>
+<TITLE>HTML Guide: Recommended Usage</TITLE>
+<!-- $Id: recommended.html,v 1.3 93/01/06 18:38:11 connolly Exp $ -->
+</HEAD>
+
+ There are a few other SGML markup constructs that are deprecated or
+ illegal.
+
+ Delimiter Signals...
+
+ <? Processing instruction. Terminated by >.
+
+ <![ Marked section. Marked sections are
+ deprecated. See the SGML standard for
+ complete information.
+
+ <! Markup declaration. HTML defines no short
+
+
+
+Berners-Lee and Connolly 9
+
+ reference maps, so these are errors.
+ Terminated by >.
+
+ LINE BREAKS
+
+ A line break character is considered markup (and ignored) if it is
+ the first or last piece of content in an element. This allows you
+ to write either
+
+<PRE>some example text</pre>
+
+ or
+
+<pre>
+some example text
+</pre>
+
+ and these will be processed identically.
+
+ Also, a line that's not empty but contains no content will be
+ ignored altogether. For example, the element
+
+<pre>
+<!-- this line is ignored, including the linebreak character -->
+first line
+
+third line<!-- the following linebreak is content: -->
+fourth line<!-- this one's ignored because it's the last piece of cont
+ent: -->
+</pre>
+
+ contains only the strings
+
+
+ first line
+
+ third line
+ fourth line.
+
+ SPACES AND TABS
+
+ Space characters must be rendered as horizontal white space. In
+ HTML, multiple spaces should be rendered as proportionally larger
+ spaces.
+
+ The rendering of a horizontal tab (HT) character is not defined,
+ and HT should therefore not be used, except within a PRE (or
+ obsolete XMP, LISTING or PLAINTEXT) element.
+
+ Neither spaces nor tabs should be used to make SGML source layout
+ more attractive or easier to read.
+
+ SUMMARY OF MARKUP SIGNALS
+
+
+
+Berners-Lee and Connolly 10
+
+ The following delimiters may signal markup, depending on context.
+
+ Delimiter Signals
+
+ <!-- Comment
+
+ &# Character reference
+
+ & Entity reference
+
+ </ End tag
+
+ <! Markup declaration
+
+ ]]> Marked section close (an error)
+
+ < Start tag
+
+ HTML ELEMENTS
+
+ This is a list of elements used in the HTML language. Documents
+ should (but need not absolutely) contain an initial HEAD element
+ followed by a BODY element.
+
+ Old style documents may contain a just the contents of the normal
+ HEAD and BODY elements, in any order. This is deprecated but must
+ be supported by parsers.
+
+ See also: Status of elements
+
+Properties of the whole document
+
+ Properties of the whole document are defined by the following
+ elements. They should appear within the HEAD element. Their order
+ is not significant.
+
+ TITLE The title of the document
+
+ ISINDEX Sent by a server in a searchable document
+
+ NEXTID A parameter used by editors to generate
+ unique identifiers
+
+ LINK Relationship between this document and
+ another. See also the Anchor element ,
+ Relationships . A document may have many
+ LINK elements.
+
+ BASE A record of the URL of the document when
+ saved
+
+Text formatting
+
+
+
+
+Berners-Lee and Connolly 11
+
+ These are elements which occur within the BODY element of a
+ document. Their order is the logical order in which the elements
+ should be rendered on the output device.
+
+ Headings Several levels of heading are supported.
+
+ Anchors Sections of text which form the beginning
+ and/or end of hypertext links are called
+ "anchors" and defined by the A tag.
+
+ Paragraph marks The P element marks the break between two
+ paragraphs.
+
+ Address style An ADDRESS element is displayed in a
+ particular style.
+
+ Blockquote style A block of text quoted from another source.
+
+ Lists Bulleted lists, glossaries, etc.
+
+ Preformatted text Sections in fixed-width font for
+ preformatted text.
+
+ Character highlighting
+ Formatting elements which do not cause
+ paragraph breaks.
+
+Graphics
+
+ IMG The IMG tag allows inline graphics.
+
+Obsolete elements
+
+ The other elements are obsolete but should be recognised by parsers
+ for back-compatibility.
+
+HEAD
+
+ The HEAD element contains all information about the document in
+ general. It does not contain any text which is part of the
+ document: this is in the BODY. Within the head element, only
+ certain elements are allowed.
+
+BODY
+
+ The BODY element contains all the information which is part of the
+ document, as opposed information about the document which is in the
+ HEAD .
+
+ The elements within the BODY element are in the order in which they
+ should be presented to the reader.
+
+ See the list of things which are allowed within a BODY element .
+
+
+
+Berners-Lee and Connolly 12
+
+Anchors
+
+ An anchor is a piece of text which marks the beginning and/or the
+ end of a hypertext link.
+
+ The text between the opening tag and the closing tag is either the
+ start or destination (or both) of a link. Attributes of the anchor
+ tag are as follows.
+
+ HREF OPTIONAL. If the HREF attribute is present,
+ the anchor is sensitive text: the start of a
+ link. If the reader selects this text, (s)he
+ should be presented with another document
+ whose network address is defined by the value
+ of the HREF attribute . The format of the
+ network address is specified elsewhere . This
+ allows for the form HREF="#identifier" to
+ refer to another anchor in the same document.
+ If the anchor is in another document, the
+ attribute is a relative name , relative to
+ the documents address (or specified base
+ address if any).
+
+ NAME OPTIONAL. If present, the attribute NAME
+ allows the anchor to be the destination of a
+ link. The value of the attribute is an
+ identifier for the anchor. Identifiers are
+ arbitrary strings but must be unique within
+ the HTML document. Another document can
+ then make a reference explicitly to this
+ anchor by putting the identifier after the
+ address, separated by a hash sign .
+
+ REL OPTIONAL. An attribute REL may give the
+ relationship (s) described by the hypertext
+ link. The value is a comma-separated list of
+ relationship values. Values and their
+ semantics will be registered by the HTML
+ registration authority . The default
+ relationship if none other is given is void.
+ REL should not be present unless HREF is
+ present. See Relationship values , REV .
+
+ REV OPTIONAL. The same as REL , but the
+ semantics of the link type are in the reverse
+ direction. A link from A to B with REL="X"
+ expresses the same relationship as a link
+ from B to A with REV="X". An anchor may
+ have both REL and REV attributes.
+
+ URN OPTIONAL. If present, this specifies a
+ uniform resource number for the document. See
+ note .
+
+
+
+Berners-Lee and Connolly 13
+
+ TITLE OPTIONAL. This is informational only. If
+ present the value of this field should equal
+ the value of the TITLE of the document whose
+ address is given by the HREF attribute. See
+ note .
+
+ METHODS OPTIONAL. The value of this field is a
+ string which if present must be a comma
+ separated list of HTTP METHODS supported by
+ the object for public use. See note .
+
+ All attributes are optional, although one of NAME and HREF is
+ necessary for the anchor to be useful. See also: LINK .
+
+ EXAMPLE OF USE:
+
+ See <A HREF="http://info.cern.ch/">CERN</A>'s information for
+ more details.
+
+ A <A NAME=serious>serious</A> crime is one which is associated
+ with imprisonment.
+ ...
+ The Organization may refuse employment to anyone convicted
+ of a <a href="#serious">serious</A> crime.
+
+
+ NOTE : UNIVERSAL RESOURCE NUMBERS
+
+ URNs are provided to allow a document to be recognized if duplicate
+ copies are found. This should save a client implementation from
+ picking up a copy of something it already has.
+
+ The format of URNs is under discussion (1993) by various working
+ groups of the Internet Engineering Task Force.
+
+ NOTE: TITLE ATTRIBUTE OF LINKS
+
+ The link may carry a TITLE attribute which should if present give
+ the title of the document whose address is given by the HREF
+ attribute.
+
+ This is useful for at least two reasons
+
+ The browser software may chose to display the title of the
+ document as a preliminary to retrieving it, for example as a
+ margin note or on a small box while the mouse is over the
+ anchor, or during document fetch.
+
+ Some documents -- mainly those which are not marked up text,
+ such as graphics, plain text and also Gopher menus, do not come
+ with a title themselves, and so putting a title in the link is
+ the only way to give them a title. This is how Gopher works.
+ Obviously it leads to duplication of data, and so it is
+
+
+
+Berners-Lee and Connolly 14
+
+ dangerous to assume that the title attribute of the link is a
+ valid and unique title for the destination document.
+
+ NOTE: METHODS ATTRIBUTE OF LINKS
+
+ The METHODS attributes of anchors and links are used to provide
+ information about the functions which the user may perform on an
+ object. These are more accurately given by the HTTP protocol when
+ it is used, but it may, for similar reasons as for the TITLE
+ attribute, be useful to include the information in advance in the
+ link.
+
+ For example, The browser may chose a different rendering as a
+ function of the methods allowed (for example something which is
+ searchable may get a different icon)
+
+Address
+
+ This element is for address information, signatures, authorship,
+ etc, often at the top or bottom of a document.
+
+ TYPICAL RENDERING
+
+ Typically, an address element is italic and/or right justified or
+ indented. The address element implies a paragraph break. Paragraph
+ marks within the address element do not cause extra white space to
+ be inserted.
+
+ EXAMPLES OF USE:
+
+ <ADDRESS><A HREF="Author.html">A.N.Other</A></ADDRESS>
+
+
+ <ADDRESS>
+ Newsletter editor<p>
+ J.R. Brown<p>
+ JimquickPost News, Jumquick, CT 01234<p>
+ Tel (123) 456 7890
+ </ADDRESS>
+
+
+BASE
+
+ This element allows the URL of the document itself to be recorded
+ in situations in which the document may be read out of context.
+ URLs within the document may be in a "partial" form relative to
+ this base address.
+
+ Where the base address is not specified, the reader will use the
+ URL it used to access the document to resolve any relative URLs.
+
+ The one attribute is:
+
+
+
+
+Berners-Lee and Connolly 15
+
+ HREF the URL
+
+BLOCKQUOTE
+
+ The BLOCKQUOTE element allows text quoted from another source to be
+ rendered specially.
+
+ TYPICAL RENDERING
+
+ A typical rendering might be a slight extra left and right indent,
+ and/or italic font. BLOCKQUOTE causes a paragraph break, and
+ typically a line or so of white space will be allowed between it
+ and any text before or after it.
+
+ Single-font rendition may for example put a vertical line of ">"
+ characters down the left margin to indicate quotation in the
+ Internet mail style.
+
+ EXAMPLE
+
+I think it ends
+<BLOCKQUOTE>Soft you now, the fair Ophelia. Nymph, in thy orisons,
+be all my sins remembered.
+</BLOCKQUOTE>
+but I am not sure.
+
+Headings
+
+ Six levels of heading are supported. (Note that a hypertext node
+ within a hypertext work tends to need less levels of heading than
+ a work whose only structure is given by the nesting of headings.)
+
+ A heading element implies all the font changes, paragraph breaks
+ before and after, and white space (for example) necessary to render
+ the heading. Further character emphasis or paragraph marks are not
+ required in HTML.
+
+ H1 is the highest level of heading, and is recommended for the
+ start of a hypertext node. It is suggested that the the text of
+ the first heading be suitable for a reader who is already browsing
+ in related information, in contrast to the title tag which should
+ identify the node in a wider context.
+
+ The heading elements are
+
+ <H1>, <H2>, <H3>, <H4>, <H5>, <H6>
+
+ It is not normal practice to jump from one header to a header level
+ more than one below, for example for follow an H1 with an H3.
+ Although this is legal, it is discouraged, as it may produce
+ strange results for example when generating other representations
+ from the HTML.
+
+
+
+
+Berners-Lee and Connolly 16
+
+ EXAMPLE:
+
+ <H1>This is a heading</H1>
+ Here is some text
+ <H2>Second level heading</H2>
+ Here is some more text.
+
+ PARSER NOTE:
+
+ Parsers should not require any specific order to heading elements,
+ even if the heading level increases by more than one between
+ successive headings.
+
+ TYPICAL RENDERING
+
+ H1 Bold very large font, centered. One or two
+ lines clear space between this and anything
+ following. If printed on paper, start new
+ page.
+
+ H2 Bold, large font,, flush left against left
+ margin, no indent. One or two clear lines
+ above and below.
+
+ H3 Italic, large font, slightly indented from
+ the left margin. One or two clear lines above
+ and below.
+
+ H4 Bold, normal font, indented more than H3.
+ One clear line above and below.
+
+ H5 Italic, normal font, indented as H4. One
+ clear line above.
+
+ H6 Bold, indented same as normal text, more
+ than H5. One clear line above.
+
+ These typical values are just an indication, and it is up to the
+ designer of the presentation software to define the styles. The
+ reader may have options to customize these. When writing
+ documents, you should assume that whatever is done it is designed
+ to have the same sort of effect as the styles above.
+
+ The rendering software is responsible for generating suitable
+ vertical white space between elements, so it is NOT normal or
+ required to follow a heading element with a paragraph mark.
+
+IMG: Embedded Images
+
+ Status: Extra
+
+ The IMG element allows another document to be inserted inline. The
+ document is normally an icon or small graphic, etc. This element is
+
+
+
+Berners-Lee and Connolly 17
+
+ NOT intended for embedding other HTML text.
+
+ Browsers which are not able to display inline images ignore IMG
+ elements. Authors should note that some browsers will be able to
+ display (or print) linked graphics but not inline graphics. If the
+ graphic is essential, it may be wiser to make a link to it rather
+ than to put it inline. If the graphic is essentially decorative,
+ then IMG is appropriate.
+
+ The IMG element is empty: it has no closing tag. It has two
+ attributes:
+
+ SRC The value of this attribute is the URL of
+ the document to be embedded. Its syntax is
+ the same as that of the HREF attribute of the
+ A tag. SRC is mandatory.
+
+ ALIGN Take values TOP or MIDDLE or BOTTOM,
+ defining whether the tops or middles of
+ bottoms of the graphics and text should be
+ aligned vertically.
+
+ ALT Optional alternative text as an alternative
+ to the graphics for display in text-only
+ environments.
+
+ Note that IMG elements are allowed within anchors.
+
+ EXAMPLE
+
+ Warning: < IMG SRC ="triangle.gif" ALT="Warning:"> This must b
+e done by a
+ qualified technician.
+
+ < A HREF="Go">< IMG SRC ="Button"> Press to start</A>
+
+
+
+
+
+ISINDEX
+
+ This element informs the reader that the document is an index
+ document. As well as reading it, the reader may use a keyword
+ search.
+
+ The node may be queried with a keyword search by suffixing the node
+ address with a question mark, followed by a list of keywords
+ separated by plus signs. See the network address format .
+
+ Note that this tag is normally generated automatically by a server.
+ If it is added by hand to an HTML document, then the client will
+ assume that the server can handle a search on the document.
+
+
+
+Berners-Lee and Connolly 18
+
+ Obviously the server must have this capability for it to work:
+ simply adding <ISINDEX> in the document is not enough to make
+ searches happen if the server does not have a search engine!
+
+ Status: standard.
+
+ EXAMPLE OF USE:
+
+ <ISINDEX>
+
+LINK
+
+ The LINK element occurs within the HEAD element of an HTML
+ document. It is used to indicate a relationship between the
+ document and some other object. A document may have any number of
+ LINK elements.
+
+ The LINK element is empty, but takes the same attributes as the
+ anchor element .
+
+ Typical uses are to indicate authorship, related indexes and
+ glossaries, older or more recent versions, etc. Links can indicate
+ a static tree structure in which the document was authored by
+ pointing to a "parent" and "next" and "previous" document, for
+ example.
+
+ Servers may also allow links to be added by those who do not have
+ the right to alter the body of a document.
+
+Forms of list in HTML
+
+ GLOSSARIES
+
+ A glossary (or definition list) is a list of paragraphs each of
+ which has a short title alongside it. Apart from glossaries, this
+ element is useful for presenting a set of named elements to the
+ reader. The elements within a glossary follow are
+
+ DT The "term", typically placed in a wide left
+ indent
+
+ DD The "definition", which may wrap onto many
+ lines
+
+ These elements must appear in pairs. Single occurrences of DT
+ without a following DD are illegal. The one attribute which DL can
+ take is
+
+ COMPACT suggests that a compact rendering be used,
+ because the enclosed elements are
+ individually small, or the whole glossary is
+ rather large, or both.
+
+
+
+
+Berners-Lee and Connolly 19
+
+ Typical rendering
+
+ The definition list DT, DD pairs are arranged vertically. For
+ each pair, the DT element is on the left, in a column of about a
+ third of the display area, and the DD element is in the right hand
+ two thirds of the display area. The DT term is normally small
+ enough to fit on one line within the left-hand column. If it is
+ longer, it will either extend across the page, in which case the DD
+ section is moved down to separate them, or it is wrapped onto
+ successive lines of the left hand column.
+
+ White space is typically left between successive DT,DD pairs unless
+ the COMPACT attribute is given. The COMPACT attribute is
+ appropriate for lists which are long and/or have DT,DD pairs which
+ each take only a line or two. It is of course possible for the
+ rendering software to discover these cases itself and make its own
+ decisions, and this is to be encouraged.
+
+ The COMPACT attribute may also reduce the width of the left-hand
+ (DT) column.
+
+ Examples of use
+
+ <DL>
+ <DT>Term the first<DD>definition paragraph is reasonably
+ long but is still displayed clearly
+ <DT>Term2 follows<DD>Definition of term2
+ </DL>
+
+ <DL COMPACT>
+ <DT>Term<DD>definition paragraph
+ <DT>Term2<DD>Definition of term2
+ </DL>
+
+
+
+
+ LISTS
+
+ A list is a sequence of paragraphs, each of which may be preceded
+ by a special mark or sequence number. The syntax is:
+
+
+ <UL>
+ <LI> list element
+ <LI> another list element ...
+ </UL>
+
+ The opening list tag may be any of UL, OL, MENU or DIR. It must
+ be immediately followed by the first list element.
+
+ Typical rendering
+
+
+
+
+Berners-Lee and Connolly 20
+
+ The representation of the list is not defined here, but a bulleted
+ list for unordered lists, and a sequence of numbered paragraphs
+ for an ordered list would be quite appropriate. Other possibilities
+ for interactive display include embedded scrollable browse panels.
+
+ List elements with typical rendering are:
+
+ UL A list of multi-line paragraphs, typically
+ separated by some white space and/or marked
+ by bullets, etc.
+
+ OL As UL, but the paragraphs are typically
+ numbered in some way to indicate the order as
+ significant.
+
+ MENU A list of smaller paragraphs. Typically one
+ line per item, with a style more compact than
+ UL.
+
+ DIR A list of short elements, typically less
+ than 20 characters. These may be arranged in
+ columns across the page, typically 24
+ character in width. If the rendering software
+ is able to optimize the column width as
+ function of the widths of individual
+ elements, so much the better.
+
+ Example of use
+
+ <OL>
+ <LI> When you get to the station, leave
+ by the southern exit, on platform one.
+ <LI>Turn left to face toward the mountain
+ <LI>Walk for a mile or so until you reach the
+ "Asquith Arms" then
+ <LI>Wait and see...
+ </OL>
+
+ < MENU >
+ <LI>The oranges should be pressed fresh
+ <LI>The nuts may come from a packet
+ <LI>The gin must be good quality
+ </MENU>
+
+ < DIR >
+ <LI>A-H<LI>I-M
+ <LI>M-R<LI>S-Z
+ </DIR>
+
+
+
+Next ID
+
+
+
+
+Berners-Lee and Connolly 21
+
+ This tag takes a single attribute which is the number of the next
+ document-wide numeric identifier to be allocated of the form z123.
+
+ When modifying a document, old anchor ids should not be reused, as
+ there may be references stored elsewhere which point to them. This
+ is read and generated by hypertext editors. Human writers of HTML
+ usually use mnemonic alphabetical identifiers. Browser software may
+ ignore this tag.
+
+ EXAMPLE OF USE:
+
+ <NEXTID N=27>
+
+
+P: Paragraph mark
+
+ The empty P element indicates a paragraph break. The exact
+ rendering of this (indentation, leading, etc) is not defined here,
+ and may be a function of other tags, style sheets etc.
+
+ <P> is used between two pieces of text which otherwise would be
+ flowed together.
+
+ You do NOT need to use <P> to put white space around heading,
+ list, address or blockquote elements which imply a paragraph break.
+ It is the responsibility of the rendering software to generate that
+ white space. A paragraph mark which is preceded or followed by
+ such elements which imply a paragraph break is has undefined effect
+ and should be avoided.
+
+ TYPICAL RENDERING
+
+ Typically, <P> will generate a small vertical space (of a line or
+ half a line) between the paragraphs. This is not the case
+ (typically) within ADDRESS or (ever) within PRE elements. With
+ some implementations, in normal text, <P> may generate a small
+ extra left indent on the first line.
+
+ EXAMPLES OF USE
+
+ <h1>What to do</h1>
+ This is a one paragraph.< p >This is a second.
+ < P >
+ This is a third.
+
+ BAD EXAMPLE
+
+ <h1><P>What not to do</h1>
+ <p>I found that on my XYZ browser it looked prettier to
+ me if I put some paragraph marks
+ <p>
+ <ul><p><li>Around lists, and
+ <li>After headings.
+
+
+
+Berners-Lee and Connolly 22
+
+ </ul>
+ <p>
+ None of the paragraph marks in this example should
+ be there.
+
+
+
+
+PRE: Preformatted text
+
+ Preformatted elements in HTML are displayed with text in a fixed
+ width font, and so are suitable for text which has been formatted
+ for a teletype by some existing formatting system.
+
+
+
+ The optional attribute is:
+
+ WIDTH This attribute gives the maximum number of
+ characters which will occur on a line. It
+ allows the presentation system to select a
+ suitable font and indentation. Where the
+ WIDTH attribute is not recognized, it is
+ recommended that a width of 80 be assumed.
+ Where WIDTH is supported, it is recommended
+ that at least widths of 40, 80 and 132
+ characters be presented optimally, with other
+ widths being rounded up.
+
+ Within a PRE element,
+
+ Line boundaries within the text are rendered as a move to the
+ beginning of the next line, except for one immediately following
+ or immediately preceding a tag.
+
+ The <p> tag should not be used. If found, it should be rendered
+ as a move to the beginning of the next line.
+
+ Anchor elements and character highlighting elements may be used.
+
+ Elements which define paragraph formatting (Headings, Address,
+ etc) must not be used.
+
+ The ASCII Horizontal Tab (HT) character must be interpreted as
+ the smallest positive nonzero number of spaces which will leave
+ the number of characters so far on the line as a multiple of 8.
+ Its use is not recommended however.
+
+ Example of use
+
+ <PRE WIDTH="80">
+ This is an example line
+ </PRE>
+
+
+
+Berners-Lee and Connolly 23
+
+ Note: Highlighting
+
+ Within a preformatted element, the constraint that the rendering
+ must be on a fixed horizontal character pitch may limit or prevent
+ the ability of the renderer to render highlighting elements
+ specially.
+
+ Note: Margins
+
+ The above references to the "beginning of a new line" must not be
+ taken as implying that the renderer is forbidden from using a
+ (constant) left indent for rendering preformatted text. The left
+ indent may of course be constrained by the width required.
+
+TITLE
+
+ The title of a document is specified by the TITLE element. The
+ TITLE element should occur in the HEAD of the document.
+
+ There may only be one title in any document. It should identify the
+ content of the document in a fairly wide context.
+
+ The title is not part of the text of the document, but is a
+ property of the whole document. It may not contain anchors,
+ paragraph marks, or highlighting. The title may be used to identify
+ the node in a history list, to label the window displaying the
+ node, etc. It is not normally displayed in the text of a document
+ itself. Contrast titles with headings . The title should ideally
+ be less than 64 characters in length. That is, many applications
+ will display document titles in window titles, menus, etc where
+ there is only limited room. Whilst there is no limit on the length
+ of a title (as it may be automatically generated from other data),
+ information providers are warned that it may be truncated if long.
+
+ Examples of use
+
+ Appropriate titles might be
+
+ <TITLE>Rivest and Neuman. 1989(b)</TITLE>
+
+ or
+
+ <TITLE>A Recipe for Maple Syrup Flap-Jack</TITLE>
+
+ or
+
+ <TITLE>Introduction -- AFS user's Guide</TITLE>
+
+ Examples of inappropriate titles are those which are only
+ meaningful within context,
+
+ <TITLE>Introduction</TITLE>
+
+
+
+
+Berners-Lee and Connolly 24
+
+ or too long,
+
+ <TITLE>Remarks on the Quantum-Gravity effects of "Bean
+ Pole" diversification in Mononucleosis patients in Developing
+ Countries under Economic Conditions Prevalent during
+ the Second half of the Twentieth Century, and Related Papers:
+ a Summary</TITLE>
+
+
+
+
+Character highlighting
+
+ Status: Extra
+
+ These elements allow sections of text to be formatted in a
+ particular way, to provide emphasis, etc. The tags do NOT cause a
+ paragraph break, and may be used on sections of text within
+ paragraphs.
+
+ Where not supported by implementations, like all tags, these tags
+ should be ignored but the content rendered.
+
+ All these tags have related closing tags, as in
+
+ This is <EM>emphasized</EM> text.
+
+ Some of these styles are more explicit than others about how they
+ should be physically represented. The logical styles should be
+ used wherever possible, unless for example it is necessary to refer
+ to the formatting in the text. (Eg, "The italic parts are
+ mandatory".)
+
+ Note:
+
+ Browsers unable to display a specified style may render it in some
+ alternative, or the default, style, with some loss of quality for
+ the reader. Some implementations may ignore these tags altogether,
+ so information providers should attempt not to rely on them as
+ essential to the information content.
+
+ These element names are derived from TeXInfo macro names.
+
+ PHYSICAL STYLES
+
+ TT Fixed-width typewriter font.
+
+ B Boldface, where available, otherwise
+ alternative mapping allowed.
+
+ I Italic font (or slanted if italic
+ unavailable).
+
+
+
+
+Berners-Lee and Connolly 25
+
+ U Underline.
+
+ LOGICAL STYLES
+
+ EM Emphasis, typically italic.
+
+ STRONG Stronger emphasis, typically bold.
+
+ CODE Example of code. typically monospaced font.
+ (Do not confuse with PRE )
+
+ SAMP A sequence of literal characters.
+
+ KBD in an instruction manual, Text typed by a
+ user.
+
+ VAR A variable name.
+
+ DFN The defining instance of a term. Typically
+ bold or bold italic.
+
+ CITE A citation. Typically italic.
+
+ EXAMPLES OF USE
+
+ This text contains an <em>emphasized</em> word.
+ <strong>Don't assume</strong> that it will be italic!
+ It was made using the <CODE>EM</CODE> element. A citation is
+ typically italic and has no formal necessary structure:
+ <cite>Moby Dick</cite> is a book title.
+
+
+
+
+Obsolete elements
+
+ The following elements of HTML are obsolete. It is recommended
+ that client implementors implement the obsolete forms for
+ compatibility with old servers.
+
+ Plaintext
+
+ Status: Obsolete .
+
+ The empty PLAINTEXT tag terminates the HTML entity. What follows is
+ not SGML. In stead, there's an old HTTP convention that what
+ follows is an ASCII (MIME "text/plain") body.
+
+ An example if its use is:
+
+ <PLAINTEXT>
+ 0001 This is line one of a ling listing
+ 0002 file from <any@host.inc.com> which is sen
+
+
+
+Berners-Lee and Connolly 26
+
+t
+
+ This tag allows the rest of a file to be read efficiently without
+ parsing. Its presence is an optimization. There is no closing tag.
+ The rest of the data is not in SGML.
+
+ XMP and LISTING: Example sections
+
+ Status: Obsolete . This are in use and should be recognized by
+ browsers. New servers should use <PRE> instead.
+
+ These styles allow text of fixed-width characters to be embedded
+ absolutely as is into the document. The syntax is:
+
+ <LISTING>
+ ...
+ </LISTING>
+
+ or
+
+ <XMP>
+ ...
+ </XMP>
+
+ The text between these tags is to be portrayed in a fixed width
+ font, so that any formatting done by character spacing on
+ successive lines will be maintained. Between the opening and
+ closing tags:
+
+ The text may contain any ISO Latin printable characters, but not
+ the end tag opener. (See Historical note )
+
+ Line boundaries are significant, except any occurring
+ immediately after the opening tag or before the closing tag. and
+ are to be rendered as a move to the start of a new line.
+
+ The ASCII Horizontal Tab (HT) character must be interpreted as
+ the smallest positive nonzero number of spaces which will leave
+ the number of characters so far on the line as a multiple of 8.
+ Its use is not recommended however.
+
+ The LISTING element is portrayed so that at least 132 characters
+ will fit on a line. The XMP elementis portrayed in a font so that
+ at least 80 characters will fit on a line but is otherwise
+ identical to LISTING.
+
+ Highlighted Phrase HP1 etc
+
+ Status: Obsolete . These tags like all others should be ignored if
+ not implemented. Replaced will more meaningful elements -- see
+ character highlighting .
+
+ Examples of use:
+
+
+
+Berners-Lee and Connolly 27
+
+ <HP1>...</HP1> <HP2>... </HP2> etc.
+
+ Comment element
+
+ Status: Obsolete
+
+ A comment element used for bracketing off unneed text and comment
+ has been introduced in some browsers but will be replaced by the
+ SGML command feature in new implementations.
+
+ HISTORICAL NOTE: XMP AND LISTING
+
+ The XMP and LISTING elements used historically to have non SGML
+ conforming specifications, in that the text could contain any ISO
+ Latin printable characters, including the tag opener, so long as it
+ does not contain the closing tag in full.
+
+ This form is not supported by SGML and so is not the specified HTML
+ interpretation. Providers should be warned that implementations
+ may vary on how they interpret end tags apparently within these
+ elements
+
+ ENTITIES
+
+ The following entity names are used in HTML , always prefixed by
+ ampersand (&) and followed by a semicolon as shown. They represent
+ particular graphic characters which have special meanings in places
+ in the markup, or may not be part of the character set available to
+ the writer.
+
+ &lt; The less than sign <
+
+ &gt; The "greater than" sign >
+
+ &amp; The ampersand sign & itself.
+
+ &quot; The double quote sign "
+
+ Also allowed are references to any of the ISO Latin-1 alphabet,
+ using the entity names in the following table.
+
+ISO Latin 1 character entities
+
+ This list is derived from "ISO 8879:1986//ENTITIES Added Latin
+ 1//EN".
+
+ &AElig; capital AE diphthong (ligature)
+
+ &Aacute; capital A, acute accent
+
+ &Acirc; capital A, circumflex accent
+
+ &Agrave; capital A, grave accent
+
+
+
+Berners-Lee and Connolly 28
+
+ &Aring; capital A, ring
+
+ &Atilde; capital A, tilde
+
+ &Auml; capital A, dieresis or umlaut mark
+
+ &Ccedil; capital C, cedilla
+
+ &ETH; capital Eth, Icelandic
+
+ &Eacute; capital E, acute accent
+
+ &Ecirc; capital E, circumflex accent
+
+ &Egrave; capital E, grave accent
+
+ &Euml; capital E, dieresis or umlaut mark
+
+ &Iacute; capital I, acute accent
+
+ &Icirc; capital I, circumflex accent
+
+ &Igrave; capital I, grave accent
+
+ &Iuml; capital I, dieresis or umlaut mark
+
+ &Ntilde; capital N, tilde
+
+ &Oacute; capital O, acute accent
+
+ &Ocirc; capital O, circumflex accent
+
+ &Ograve; capital O, grave accent
+
+ &Oslash; capital O, slash
+
+ &Otilde; capital O, tilde
+
+ &Ouml; capital O, dieresis or umlaut mark
+
+ &THORN; capital THORN, Icelandic
+
+ &Uacute; capital U, acute accent
+
+ &Ucirc; capital U, circumflex accent
+
+ &Ugrave; capital U, grave accent
+
+ &Uuml; capital U, dieresis or umlaut mark
+
+ &Yacute; capital Y, acute accent
+
+ &aacute; small a, acute accent
+
+
+
+Berners-Lee and Connolly 29
+
+ &acirc; small a, circumflex accent
+
+ &aelig; small ae diphthong (ligature)
+
+ &agrave; small a, grave accent
+
+ &aring; small a, ring
+
+ &atilde; small a, tilde
+
+ &auml; small a, dieresis or umlaut mark
+
+ &ccedil; small c, cedilla
+
+ &eacute; small e, acute accent
+
+ &ecirc; small e, circumflex accent
+
+ &egrave; small e, grave accent
+
+ &eth; small eth, Icelandic
+
+ &euml; small e, dieresis or umlaut mark
+
+ &iacute; small i, acute accent
+
+ &icirc; small i, circumflex accent
+
+ &igrave; small i, grave accent
+
+ &iuml; small i, dieresis or umlaut mark
+
+ &ntilde; small n, tilde
+
+ &oacute; small o, acute accent
+
+ &ocirc; small o, circumflex accent
+
+ &ograve; small o, grave accent
+
+ &oslash; small o, slash
+
+ &otilde; small o, tilde
+
+ &ouml; small o, dieresis or umlaut mark
+
+ &szlig; small sharp s, German (sz ligature)
+
+ &thorn; small thorn, Icelandic
+
+ &uacute; small u, acute accent
+
+ &ucirc; small u, circumflex accent
+
+
+
+Berners-Lee and Connolly 30
+
+ &ugrave; small u, grave accent
+
+ &uuml; small u, dieresis or umlaut mark
+
+ &yacute; small y, acute accent
+
+ &yuml; small y, dieresis or umlaut mark
+
+ THE HTML DTD
+
+ The HTML DTD follows . Its relationship to the content of an SGML
+ document is explained in the section "HTML and SGML" .
+
+
+<!SGML "ISO 8879:1986"
+--
+ Document Type Definition for the HyperText Markup Language
+ as used by the World Wide Web application (HTML DTD).
+
+ NOTE: This is a definition of HTML with respect to
+ SGML, and assumes an understanding of SGML terms.
+--
+
+CHARSET
+ BASESET "ISO 646:1983//CHARSET
+ International Reference Version (IRV)//ESC 2/5 4/0"
+ DESCSET 0 9 UNUSED
+ 9 2 9
+ 11 2 UNUSED
+ 13 1 13
+ 14 18 UNUSED
+ 32 95 32
+ 127 1 UNUSED
+ BASESET "ISO Registration Number 100//CHARSET
+ ECMA-94 Right Part of Latin Alphabet Nr. 1//ESC 2/13 4
+/1"
+ DESCSET 128 32 UNUSED
+ 160 95 32
+ 255 1 UNUSED
+
+
+CAPACITY SGMLREF
+ TOTALCAP 150000
+ GRPCAP 150000
+
+SCOPE DOCUMENT
+SYNTAX
+ SHUNCHAR CONTROLS 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
+ 18
+ 19 20 21 22 23 24 25 26 27 28 29 30 31 127
+255
+ BASESET "ISO 646:1983//CHARSET
+ International Reference Version (IRV)//ESC 2/5 4/0"
+
+
+
+Berners-Lee and Connolly 31
+
+ DESCSET 0 128 0
+ FUNCTION RE 13
+ RS 10
+ SPACE 32
+ TAB SEPCHAR 9
+ NAMING LCNMSTRT ""
+ UCNMSTRT ""
+ LCNMCHAR ".-"
+ UCNMCHAR ".-"
+ NAMECASE GENERAL YES
+ ENTITY NO
+ DELIM GENERAL SGMLREF
+ SHORTREF SGMLREF
+ NAMES SGMLREF
+ QUANTITY SGMLREF
+ NAMELEN 34
+ TAGLVL 100
+ LITLEN 1024
+ GRPGTCNT 150
+ GRPCNT 64
+
+FEATURES
+ MINIMIZE
+ DATATAG NO
+ OMITTAG NO
+ RANK NO
+ SHORTTAG NO
+ LINK
+ SIMPLE NO
+ IMPLICIT NO
+ EXPLICIT NO
+ OTHER
+ CONCUR NO
+ SUBDOC NO
+ FORMAL YES
+ APPINFO NONE
+>
+
+<!DOCTYPE HTML [
+<!-- Jul 1 93 -->
+<!-- Regarding clause 6.1, SGML Document:
+
+ [1] SGML document = SGML document entity,
+ (SGML subdocument entity |
+ SGML text entity | non-SGML data entity)*
+
+ The role of SGML document entity is filled by this DTD,
+ followed by the conventional HTML data stream.
+-->
+
+<!-- DTD definitions -->
+
+<!ENTITY % heading "H1|H2|H3|H4|H5|H6" >
+
+
+
+Berners-Lee and Connolly 32
+
+<!ENTITY % list "UL|OL|DIR|MENU">
+<!ENTITY % literal "XMP|LISTING">
+
+<!ENTITY % headelement
+ "TITLE|NEXTID|ISINDEX" >
+
+<!ENTITY % bodyelement
+ "P | %heading |
+ %list | DL | HEADERS | ADDRESS | PRE | BLOCKQUOTE
+ | %literal">
+
+<!ENTITY % oldstyle "%headelement | %bodyelement | #PCDATA">
+
+<!ENTITY % URL "CDATA"
+ -- The term URL means a CDATA attribute
+ whose value is a Uniform Resource Locator,
+ as defined. (A URN may also be usable here when defined.)
+ -->
+
+<!ENTITY % linkattributes
+ "NAME NMTOKEN #IMPLIED
+ HREF %URL; #IMPLIED
+ REL CDATA #IMPLIED -- forward relationship type --
+ REV CDATA #IMPLIED -- reversed relationship type
+ to referent data:
+
+ PARENT CHILD, SIBLING, NEXT, TOP,
+ DEFINITION, UPDATE, ORIGINAL etc. --
+
+ URN CDATA #IMPLIED -- universal resource number --
+
+ TITLE CDATA #IMPLIED -- advisory only --
+
+ METHODS NAMES #IMPLIED -- supported public methods of the obje
+ct:
+ TEXTSEARCH, GET, HEAD, ... --
+
+ ">
+
+
+<!-- Document Element -->
+
+<!ELEMENT HTML O O (( HEAD | BODY | %oldstyle)*, PLAINTEXT?)>
+
+<!ELEMENT HEAD - - (TITLE? & ISINDEX? & NEXTID? & LINK*
+ & BASE?)>
+
+<!ELEMENT TITLE - - RCDATA
+ -- The TITLE element is not considered part of the flow of t
+ext.
+ It should be displayed, for example as the page header or
+ window title.
+ -->
+
+
+
+Berners-Lee and Connolly 33
+
+<!ELEMENT ISINDEX - O EMPTY
+ -- WWW clients should offer the option to perform a search o
+n
+ documents containing ISINDEX.
+ -->
+
+<!ELEMENT NEXTID - O EMPTY>
+<!ATTLIST NEXTID N NAME #REQUIRED
+ -- The number should be a name suitable for use
+ for the ID of a new element. When used, the value
+ has its numeric part incremented. EG Z67 becomes Z68
+ -->
+<!ELEMENT LINK - O EMPTY>
+<!ATTLIST LINK
+ %linkattributes>
+
+<!ELEMENT BASE - O EMPTY -- Reference context for URLS -->
+<!ATTLIST BASE
+
+ HREF %URL; #IMPLIED
+
+ >
+<!ENTITY % inline "EM | TT | STRONG | B | I | U |
+ CODE | SAMP | KBD | KEY | VAR | DFN | CITE "
+ >
+
+<!ELEMENT (%inline;) - - (#PCDATA)>
+
+<!ENTITY % text "#PCDATA | IMG | %inline;">
+
+<!ENTITY % htext "A | %text">
+
+<!ELEMENT BODY - - (%bodyelement|%htext;)*>
+
+
+<!ELEMENT A - - (%text)>
+<!ATTLIST A
+ %linkattributes;
+ >
+
+<!ELEMENT IMG - O EMPTY -- Embedded image -->
+<!ATTLIST IMG
+ SRC %URL; #IMPLIED -- URL of document to embed --
+ >
+
+
+<!ELEMENT P - O EMPTY -- separates paragraphs -->
+
+<!ELEMENT ( %heading ) - - (%htext;)+>
+
+<!ELEMENT DL - - (DT | DD | P | %htext;)*>
+<!-- Content should match ((DT,(%htext;)+)+,(DD,(%htext;)+))
+ But mixed content is messy.
+
+
+
+Berners-Lee and Connolly 34
+
+ -->
+
+<!ELEMENT DT - O EMPTY>
+<!ELEMENT DD - O EMPTY>
+
+<!ELEMENT (UL|OL) - - (%htext;|LI|P)+>
+<!ELEMENT (DIR|MENU) - - (%htext;|LI)+>
+<!-- Content should match ((LI,(%htext;)+)+)
+ But mixed content is messy.
+ -->
+<!ATTLIST (%list)
+ COMPACT NAME #IMPLIED -- COMPACT, etc.--
+ >
+
+<!ELEMENT LI - O EMPTY>
+
+<!ELEMENT BLOCKQUOTE - - (%htext;|P)+
+ -- for quoting some other source -->
+
+<!ELEMENT ADDRESS - - (%htext;|P)+>
+
+<!ELEMENT PRE - - (#PCDATA|%inline|A|P)+>
+<!ATTLIST PRE
+ WIDTH NUMBER #implied
+ >
+
+<!-- Mnemonic character entities. -->
+<!ENTITY AElig "&#198;" -- capital AE diphthong (ligature) -->
+<!ENTITY Aacute "&#193;" -- capital A, acute accent -->
+<!ENTITY Acirc "&#194;" -- capital A, circumflex accent -->
+<!ENTITY Agrave "&#192;" -- capital A, grave accent -->
+<!ENTITY Aring "&#197;" -- capital A, ring -->
+<!ENTITY Atilde "&#195;" -- capital A, tilde -->
+<!ENTITY Auml "&#196;" -- capital A, dieresis or umlaut mark -->
+<!ENTITY Ccedil "&#199;" -- capital C, cedilla -->
+<!ENTITY ETH "&#208;" -- capital Eth, Icelandic -->
+<!ENTITY Eacute "&#201;" -- capital E, acute accent -->
+<!ENTITY Ecirc "&#202;" -- capital E, circumflex accent -->
+<!ENTITY Egrave "&#200;" -- capital E, grave accent -->
+<!ENTITY Euml "&#203;" -- capital E, dieresis or umlaut mark -->
+<!ENTITY Iacute "&#205;" -- capital I, acute accent -->
+<!ENTITY Icirc "&#206;" -- capital I, circumflex accent -->
+<!ENTITY Igrave "&#204;" -- capital I, grave accent -->
+<!ENTITY Iuml "&#207;" -- capital I, dieresis or umlaut mark -->
+<!ENTITY Ntilde "&#209;" -- capital N, tilde -->
+<!ENTITY Oacute "&#211;" -- capital O, acute accent -->
+<!ENTITY Ocirc "&#212;" -- capital O, circumflex accent -->
+<!ENTITY Ograve "&#210;" -- capital O, grave accent -->
+<!ENTITY Oslash "&#216;" -- capital O, slash -->
+<!ENTITY Otilde "&#213;" -- capital O, tilde -->
+<!ENTITY Ouml "&#214;" -- capital O, dieresis or umlaut mark -->
+<!ENTITY THORN "&#222;" -- capital THORN, Icelandic -->
+<!ENTITY Uacute "&#218;" -- capital U, acute accent -->
+
+
+
+Berners-Lee and Connolly 35
+
+<!ENTITY Ucirc "&#219;" -- capital U, circumflex accent -->
+<!ENTITY Ugrave "&#217;" -- capital U, grave accent -->
+<!ENTITY Uuml "&#220;" -- capital U, dieresis or umlaut mark -->
+<!ENTITY Yacute "&#221;" -- capital Y, acute accent -->
+<!ENTITY aacute "&#225;" -- small a, acute accent -->
+<!ENTITY acirc "&#226;" -- small a, circumflex accent -->
+<!ENTITY aelig "&#230;" -- small ae diphthong (ligature) -->
+<!ENTITY agrave "&#224;" -- small a, grave accent -->
+<!ENTITY amp "&amp;" -- ampersand -->
+<!ENTITY aring "&#229;" -- small a, ring -->
+<!ENTITY atilde "&#227;" -- small a, tilde -->
+<!ENTITY auml "&#228;" -- small a, dieresis or umlaut mark -->
+<!ENTITY ccedil "&#231;" -- small c, cedilla -->
+<!ENTITY eacute "&#233;" -- small e, acute accent -->
+<!ENTITY ecirc "&#234;" -- small e, circumflex accent -->
+<!ENTITY egrave "&#232;" -- small e, grave accent -->
+<!ENTITY eth "&#240;" -- small eth, Icelandic -->
+<!ENTITY euml "&#235;" -- small e, dieresis or umlaut mark -->
+<!ENTITY gt "&#62;" -- greater than -->
+<!ENTITY iacute "&#237;" -- small i, acute accent -->
+<!ENTITY icirc "&#238;" -- small i, circumflex accent -->
+<!ENTITY igrave "&#236;" -- small i, grave accent -->
+<!ENTITY iuml "&#239;" -- small i, dieresis or umlaut mark -->
+<!ENTITY lt "&lt;" -- less than -->
+<!ENTITY ntilde "&#241;" -- small n, tilde -->
+<!ENTITY oacute "&#243;" -- small o, acute accent -->
+<!ENTITY ocirc "&#244;" -- small o, circumflex accent -->
+<!ENTITY ograve "&#242;" -- small o, grave accent -->
+<!ENTITY oslash "&#248;" -- small o, slash -->
+<!ENTITY otilde "&#245;" -- small o, tilde -->
+<!ENTITY ouml "&#246;" -- small o, dieresis or umlaut mark -->
+<!ENTITY szlig "&#223;" -- small sharp s, German (sz ligature) -->
+<!ENTITY thorn "&#254;" -- small thorn, Icelandic -->
+<!ENTITY uacute "&#250;" -- small u, acute accent -->
+<!ENTITY ucirc "&#251;" -- small u, circumflex accent -->
+<!ENTITY ugrave "&#249;" -- small u, grave accent -->
+<!ENTITY uuml "&#252;" -- small u, dieresis or umlaut mark -->
+<!ENTITY yacute "&#253;" -- small y, acute accent -->
+<!ENTITY yuml "&#255;" -- small y, dieresis or umlaut mark -->
+
+<!-- deprecated elements -->
+
+<!ELEMENT (%literal) - - CDATA>
+
+<!ELEMENT PLAINTEXT - O EMPTY>
+
+<!-- Local Variables: -->
+<!-- mode: sgml -->
+<!-- compile-command: "sgmls -s -p " -->
+<!-- end: -->
+]>
+
+
+
+
+
+Berners-Lee and Connolly 36
+
+ LINK RELATIONSHIP VALUES
+
+ Status: This list is not part of the standard. It is intended to
+ illustrate the use of link relationships and to provide a framework
+ for further development.
+
+ Additions to this list will be controlled by the HTML registration
+ authority . Experimental values may be used on the condition that
+ they begin with "X-".
+
+ These values of the REL attribute of hypertext links have a
+ significance defined here, and may be treated in special ways by
+ HTML applications.
+
+ These relationships relate whole documents (objects), rather than
+ particular anchors within them. If the relationship value is used
+ with a link between anchors rather than whole documents, the
+ semantics are considered to apply to the documents.
+
+ In the explanations which follows, A is the source document of the
+ link and B is the destination document specified by the HREF
+ attribute.
+
+ A relationship marked "Acyclic" has the property that no sequence
+ of links with that relationship may be followed from any document
+ back to itself. These types of links may therefore be used to
+ define trees.
+
+Relationships between documents
+
+ These relationships are between the documents themselves rather
+ than the subjects of the documents.
+
+ USEINDEX
+
+ B is a related index for a search by a user reading this document
+ who asks for an index search function.
+
+ A document may have any number of index links, causing several
+ indexes top be searched in a client-defined manner.
+
+ B must support SEARCH operations under its access protocol.
+
+ USEGLOSSARY
+
+ B is an index which should be used to resolve glossary queries in
+ the document. (Typically, a double-click on a word which is not
+ within an anchor).
+
+ A document may have any number of glossary links.
+
+ ANNOTATION
+
+
+
+
+Berners-Lee and Connolly 37
+
+ The information in B is additional to and subsidiary to that in A.
+
+ Annotation is used by one person to write the equivalent of "margin
+ notes" or other criticism on another's document, for example.
+
+ Example: The relationship between a newsgroup and its articles.
+
+ Acyclic.
+
+ REPLY
+
+ Similar to Annotation, but there is no suggestion that B is
+ subsidiary to A: A and B are on equal footings.
+
+ Example: The relationship between a mail message and its reply, a
+ news article and its reply.
+
+ Acyclic.
+
+ EMBED
+
+ If this link is followed, the node at the end of it is embedded
+ into the display of the source document.
+
+ Acyclic.
+
+ PRECEDES
+
+ In an ordered structure defined by the author, A precedes B, B is
+ followed by A.
+
+ Acyclic.
+
+ Any document may only have one link of this relationship, and/or
+ one link of the reverse relationship.
+
+ Note: May be used to control navigational aids, generate printed
+ material, etc. In conjunction with " subdocument ", may be used to
+ define a tree such as a printed book made of hypertext document.
+ The document can only have one such tree.
+
+ SUBDOCUMENT
+
+ B is a lower part in the author's hierarchy to A. Acyclic. See
+ also Precedes .
+
+ PRESENT
+
+ Whenever A is presented, B must also be presented. This implies
+ that whenever A is retrieved, B must also be retrieved.
+
+ SEARCH
+
+
+
+
+Berners-Lee and Connolly 38
+
+ When the link is followed, the node B should be searched rather
+ than presented. That is, where the client software allows it, the
+ user should immediately be presented with a search panel and
+ prompted for text. The search is then performed without an
+ intermediate retrieval or presentation of the node B
+
+ SUPERSEDES
+
+ B is a previous version of A.
+
+ Acyclic.
+
+ HISTORY
+
+ B is a list of versions of A
+
+ A link reverse link must exist from B to A and to all other known
+ versions of A.
+
+Relationships about subjects of documents
+
+ These relationships convey semantics about objects described by
+ documents, rather than the documents themselves.
+
+ INCLUDES
+
+ A includes B, B is part of A. For example, a person described by
+ document A is a part of the group described by document B.
+
+ Acyclic.
+
+ MADE
+
+ Person (etc) described by node A is author of, or is responsible
+ for B
+
+ This information can be used for protection, and informing authors
+ of interest, for sending mail to authors, etc.
+
+ INTERESTED
+
+ Person (etc) described by A is interested in node B.
+
+ This information can be used for notification of changes.
+
+ Typically, this is a request that, when object B changes in some
+ way, a new link is made to object A.
+
+ The phrase "object B changes" may be interpreted narrowly (as "B
+ itself changes") or widely (as "B or anythink linked to it or
+ related to it closely changes"). The amount of change considered
+ worth notifying people about is also subject to interpretation,
+ varying from bit changes in the source to a "new edition" statement
+
+
+
+Berners-Lee and Connolly 39
+
+ by the publisher.
+
+ REGISTRATION AUTHORITY
+
+ The HTTP Registration Authority is responsible for maintaining
+ lists of:
+
+ Relationship names for link and anchor elements
+
+ It is proposed that the Internet Assigned Numbers Authority or
+ their successors take this role.
+
+ Unregistered values may be used for experimental purposes if they
+ are start with "X-".
+
+ REFERENCES
+
+ SGML ISO 8879:1986, Information Processing Text
+ and Office Systems Standard Generalized
+ Markup Language (SGML).
+
+ sgmls an SGML parser by James Clark
+ <jjc@jclark.com> derived from the ARCSGML
+ parser materials which were written by
+ Charles F. Goldfarb. The source is available
+ on the ifi.uio.no FTP server in the directory
+ /pub/SGML/SGMLS .
+
+ WWW The World-Wide Web , a global information
+ initiative. For bootstrap information, telnet
+ info.cern.ch or find documents by
+ ftp://info.cern.ch/pub/www/doc
+
+ URL Universal Resource Locators. RFCxxx.
+ Currently available by anonymous FTP from
+ info.cern.ch in /pub/ietf.
+
+ AUTHOR'S ADDRESSES
+
+ This document was prepared with the help and advice of many people
+ across the net. Dan Connolly prepared the DTD and the section on
+ HTML and SGML whilst with Convex Computer Corporation of 3000
+ Waterview Parkway Richardson, TX 75083. He is now with Atrium
+ Technology Inc., and is not a current editor of the document.
+
+ Tim Berners-Lee
+ Address CERN
+ 1211 Geneva 23
+ Switzerland
+ Telephone: +41(22)767 3755
+ Fax: +41(22)767 7155
+ email: timbl@info.cern.ch
+
+
+
+
+Berners-Lee and Connolly 40
+
+ Daniel Connolly
+ Address: Atrium Technologies, Inc.
+ 5000 Plaza on the Lake, Suite 275
+ Austin, TX 78746
+ USA
+ email: connolly@atrium.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee and Connolly 41
+
diff --git a/web/funnelAC/fwACsrc/Makefile b/web/funnelAC/fwACsrc/Makefile
new file mode 100644
index 0000000000..adaff3ccbb
--- /dev/null
+++ b/web/funnelAC/fwACsrc/Makefile
@@ -0,0 +1,65 @@
+# ABC Anthony B. Coates, makefile for FunnelWeb
+
+.SUFFIXES: .c .o .a
+
+# Set the C compiler to be CC or GCC as appropriate
+#CC=cc
+#CC=gcc -g -O -c -Wall
+CC=c89 -O2 -w1 -c
+
+# Linker/loader
+#LD=gcc -g -O
+LD=c89 -O2 -w1
+
+# Libraries, etc.
+#LIBS=
+LIBS=-call_shared
+
+# Make
+MAKE=make
+
+# Remove/delete
+RM=\rm
+
+# List directory
+LS=ls
+
+# Directory separator
+DSP=/
+
+# FunnelWeb executable file name
+FWX=fw
+
+# Command script for running tests
+TEST=cd ../scripts ; ../fwACsrc/fw +xmaster
+
+# The full list of FunnelWeb C source files
+SRC=\
+analyse.c as.c clock.c command.c data.c \
+dump.c help.c help_gnu.c list.c lister.c \
+machin.c main.c mapper.c fwmem.c misc.c \
+option.c parser.c scanner.c section.c table.c \
+tangle.c texhead.c weave.c writfile.c htmlhead.c
+
+# The full list of FunnelWeb object files
+OBJ=$(SRC:.c=.o)
+
+# The list of FunnelWeb object files/libraries
+OBJLIST=$(OBJ)
+
+all: $(FWX) test
+
+$(FWX): $(OBJLIST)
+ $(LD) -o $(FWX) $(OBJLIST) $(LIBS)
+ strip $(FWX)
+
+.c.o:
+ $(CC) $<
+
+test:
+ $(TEST)
+
+clean:
+ $(RM) *.o
+
+# end of Makefile
diff --git a/web/funnelAC/fwACsrc/Makefile.os2 b/web/funnelAC/fwACsrc/Makefile.os2
new file mode 100644
index 0000000000..12eacac0ec
--- /dev/null
+++ b/web/funnelAC/fwACsrc/Makefile.os2
@@ -0,0 +1,68 @@
+# ABC Anthony B. Coates, GNU `make' (OS/2) makefile for FunnelWeb
+
+ZTYPE=
+OBJEXT=o
+#ZTYPE=-Zomf
+#OBJEXT=obj
+
+.SUFFIXES: .c .$(OBJEXT) .exe
+
+SHELL=cmd.exe
+
+# Set the C compiler to be CC or GCC as appropriate
+#CC=cc
+CC=gcc -g -O -Wall $(ZTYPE) -c
+
+# Linker/loader
+LD=gcc -g -O $(ZTYPE)
+
+# Libraries, etc.
+LIBS=fw.def -Zmtd
+
+# Make
+MAKE=nmake
+
+# Remove/delete
+RM=del
+
+# List directory
+LS=dir/w
+
+# Directory separator
+DSP=\\
+
+# FunnelWeb executable file name
+FWX=fw.exe
+
+# Command script for running tests
+TEST=fwtest.cmd
+
+# The full list of FunnelWeb C source files
+SRC=\
+analyse.c as.c clock.c command.c data.c \
+dump.c help.c help_gnu.c list.c lister.c \
+machin.c main.c mapper.c fwmem.c misc.c \
+option.c parser.c scanner.c section.c table.c \
+tangle.c texhead.c weave.c writfile.c htmlhead.c
+
+# The full list of FunnelWeb object files
+OBJ=$(SRC:.c=.$(OBJEXT))
+
+# The list of FunnelWeb object files/libraries
+OBJLIST=$(OBJ)
+
+all: $(FWX) test
+
+$(FWX): $(OBJLIST)
+ $(LD) -o $(FWX) $(OBJLIST) $(LIBS)
+
+.c.$(OBJEXT):
+ $(CC) $<
+
+test:
+ $(TEST)
+
+clean:
+ $(RM) *.$(OBJEXT)
+
+# end of Makefile
diff --git a/web/funnelAC/fwACsrc/Makefile.unix b/web/funnelAC/fwACsrc/Makefile.unix
new file mode 100644
index 0000000000..adf04618e1
--- /dev/null
+++ b/web/funnelAC/fwACsrc/Makefile.unix
@@ -0,0 +1,61 @@
+# ABC Anthony B. Coates, makefile for FunnelWeb
+
+.SUFFIXES: .c .o .a
+
+# Set the C compiler to be CC or GCC as appropriate
+#CC=cc
+CC=gcc -g -O -c -Wall
+
+# Linker/loader
+LD=gcc -g -O
+
+# Libraries, etc.
+LIBS=
+
+# Make
+MAKE=make
+
+# Remove/delete
+RM=\rm
+
+# List directory
+LS=ls
+
+# Directory separator
+DSP=/
+
+# FunnelWeb executable file name
+FWX=fw
+
+# Command script for running tests
+TEST=cd ../scripts ; ../fwACsrc/fw +xmaster
+
+# The full list of FunnelWeb C source files
+SRC=\
+analyse.c as.c clock.c command.c data.c \
+dump.c help.c help_gnu.c list.c lister.c \
+machin.c main.c mapper.c fwmem.c misc.c \
+option.c parser.c scanner.c section.c table.c \
+tangle.c texhead.c weave.c writfile.c htmlhead.c
+
+# The full list of FunnelWeb object files
+OBJ=$(SRC:.c=.o)
+
+# The list of FunnelWeb object files/libraries
+OBJLIST=$(OBJ)
+
+all: $(FWX) test
+
+$(FWX): $(OBJLIST)
+ $(LD) -o $(FWX) $(OBJLIST) $(LIBS)
+
+.c.o:
+ $(CC) $<
+
+test:
+ $(TEST)
+
+clean:
+ $(RM) *.o
+
+# end of Makefile
diff --git a/web/funnelAC/fwACsrc/README.ABC b/web/funnelAC/fwACsrc/README.ABC
new file mode 100644
index 0000000000..a529539304
--- /dev/null
+++ b/web/funnelAC/fwACsrc/README.ABC
@@ -0,0 +1,347 @@
+In case you are using emacs, this is a -*- text -*- file.
+
+ Documentation for FunnelWeb 3.05AC
+ 10th October, 1995.
+ Anthony B. Coates
+ Department of Physics
+ The University of Queensland
+ QLD 4072
+ Australia
+ coates@physics.uq.edu.au
+
+This document lists the features which I [ABC] have added to Ross
+Williams' FunnelWeb v3.0 in developing FunnelWeb 3.05AC. Although
+Ross does not want bogus copies of FunnelWeb to be distributed, for
+the very good reason that existing FunnelWeb code should not break
+because someone unknowingly installs an improperly modified version of
+the program, he has allowed me to distribute FunnelWeb 3.05AC freely.
+However, note that while the features of FunnelWeb 3.05AC may appear
+in the next official release of FunnelWeb, there is no guarantee that
+they will, as this will be up to Ross Williams to decide.
+
+Note too that when my version of FunnelWeb is run, it automatically
+prints out a message pointing out that it is not FunnelWeb v3.0.
+Please do not remove or change this message without my express
+permission [ABC].
+
+****ATTENTION****
+FunnelWeb is currently written using K&R C. This means that it can be
+compiled by both old-style K&R C compilers and new-style ANSI/ISO C
+compilers, but not (as C++) by C++ compilers, as C++ uses the ANSI/ISO
+syntax. In future releases, FunnelWeb AC may change from K&R to
+ANSI/ISO syntax. This is because the number of people who wish to
+compile FunnelWeb using a C++ compiler will probably outnumber those
+who wish to use a K&R C compiler. However, if you have a strong
+opinion as to whether FunnelWeb should be written in K&R or ANSI/ISO
+C, send an email message to coates@physics.uq.edu.au, so that users'
+opinions can be gauged.
+****ATTENTION****
+
+To avoid problems with existing FunnelWeb code breaking when processed
+with FunnelWeb 3.05AC, new features are only enabled by the explicit
+setting of pragmas. As such, this version of FunnelWeb should process
+all existing sources without problems, and all product files,
+including the documentation, should be exactly the same as produced by
+FunnelWeb v3.0. The one exception to this is if the FunnelWeb
+document contains macro names that begin with the hash character '#'.
+This will be discussed later in this document.
+
+Differences from FunnelWeb 3.0AC:
+ 1. Fixed a serious bug in the HTML code generation
+ (the characters '<' and '>' should have been escaped in the
+ generated HTML documentation, but were not).
+ 2. Added the concept of source code types. Currently, this is used
+ only to allow line directives to be generated in some product
+ files but not others.
+ 3. Added the internal macro #timestamp to allow timestamping of
+ product files.
+ 4. Added PC32 machine type for 32-bit DOS code (no 64K boundary
+ restrictions).
+ 5. Added +Qb command line switch for true batch mode
+ (no interaction with the user is attempted if FunnelWeb
+ has to abort).
+ 6. Mapping of files into memory changed to try and avoid problems
+ of differing EOL conventions when taking FunnelWeb sources from
+ one type of system to another (e.g. DOS to Unix).
+
+Modifications:
+ 1. Addition of OSF64, OS2, and LINUX machine types to environ.h,
+ machin.h, and machin.c. The OSF64 machine type is for a 64-bit
+ processor running the OSF/1.3 version of UNIX, such as a DEC
+ AXP (Alpha). The OS2 machine type is for a PC386/486 running OS/2
+ 2.1. The code now checks for `PATH_MAX' before `FILENAME_MAX'
+ as the constant giving the maximum fully qualified filename
+ length for an operating system. This is to accomodate
+ Unix System V. The PC32 machine type has also been added for
+ 32-bit DOS code.
+
+ 2. Additions to `typesetter' pragma:
+ FunnelWeb v.3.0 supports the `@p typesetter = tex' pragma, which
+ allows (La)TeX expressions to be imbedded in the documentation
+ text without being escaped. Without this pragma, FunnelWeb
+ treats all documentation text as literal ASCII.
+ My version [ABC] of FunnelWeb also supports the additional
+ typesetter choices `@p typesetter = hypertext' and
+ `@p typesetter = html'. The `hypertext' option causes FunnelWeb
+ to output an HTML hypertext file rather than a TeX file. This
+ HTML file can be viewed using `Mosaic', and indeed `Mosaic' is
+ the only HTML viewer with which the HTML code produced by this
+ FunnelWeb 3.05AC has been tested. In `hypertext' mode, the
+ standard FunnelWeb typesetting commands are converted to
+ hypertext equivalents, so an existing FunnelWeb file which does
+ NOT contain a `@p typesetter = tex' pragma should be able to be
+ used for hypertext by simply adding `@p typesetter = hypertext'
+ as the first line. The resulting hypertext output is not be
+ formatted exactly the same as the TeX version (in particular,
+ vertical skips are currently ignored for hypertext), but the
+ formatting should nonetheless be reasonable for a hypertext
+ document, and includes appropriate hypertext links for macro
+ invocations and the table of contents. The
+ `@p typesetter = html' option allows HTML expressions to be
+ included in the documentation without being escaped, and so is
+ the HTML equivalent of the `@p typesetter = tex' option.
+
+ 3. no_doc_header pragma:
+ `@p no_doc_header' is used to suppress the TeX (or HTML)
+ header definitions that FunnelWeb normally includes in the output
+ file. It is mainly intended for users who use
+ `@p typesetter = tex' so that they can write their documentation
+ using LaTeX. The file `fw-latex.sty' contains all of the
+ standard FunnelWeb header definitions, and can be included as an
+ optional style file for the LaTeX `\documentstyle' command. Note
+ that it is not necessary to do this for LaTeX files, as the
+ FunnelWeb TeX definitions work perfectly well under LaTeX;
+ however, by separating the definitions into a single style file,
+ the same definitions are not repeated in every documentation
+ file, which can offer a useful saving in disk space. Leaving the
+ TeX header intact *and* using the FunnelWeb style file as well
+ will lead to a LaTeX error, so you must choose one or the other
+ if you are writing your documentation this way. Using
+ `@p no_doc_header' also suppresses the automatic inclusion of a
+ TeX `\bye' command at the end of the documentation file. For
+ LaTeX, the `\end{document}' command makes `\bye' unnecessary.
+
+ 4. raw_macro_and_section_names pragma:
+ Normally, FunnelWeb escapes all TeX (or HTML) expressions that
+ occur in section names (if you use the FunnelWeb sectioning
+ commands) or in macro names. The
+ `@p raw_macro_and_section_names' pragma inhibits this escaping of
+ expressions in section and macro names, unless the macro is
+ attached to a file (TeX or HTML in file names almost certainly
+ have no practical value, and would more likely be unintentional,
+ particularly with file systems that use `\' as the directory
+ separator).
+
+ 4. ignore_text_after_special_minus pragma:
+ Normally, it is an error to have any text on a line after a
+ FunnelWeb `@-' command, which suppresses the return at the end of
+ a line. However, in some cases it may be useful to allow the
+ text appearing after a `@-' command on a line to be treated as a
+ comment which does not appear in the final documentation (in
+ particular, this style of comment allows the automatic setting of
+ emacs buffer modes for editing code scraps when using certain
+ emacs WEB modes). The `@p ignore_text_after_special_minus'
+ allows the use of such trailing comments after `@-' (assuming
+ that `@' is the special character as per usual; the use of `@' as
+ the special is not at all necessary for this pragma to work).
+
+ 5. no_paragraph_markups pragma:
+ For the hypertext settings `@p typesetter = hypertext' and
+ `@p typesetter = html', HTML paragraph markups (`<P>') are
+ inserted in the documentation text wherever one or more blank
+ lines occur in a row. However, particularly for users writing
+ HTML documentation directly and using `@p typesetter = html', it
+ may be undesirable to have these `<P>' markups automatically
+ inserted, since they may already exist as desired in the
+ documentation text. The `@p no_paragraph_markups' pragma
+ suppresses the automatic insertion of `<P>' markups in HTML
+ documentation (but has no effect on TeX documentation).
+
+ 6. automatic_line_directive_macro pragma:
+ This pragma allows the *automatic* insertion of line directives
+ into the product files, similarly to the manner supported by
+ `noweb'. For example, `@p automatic_line_directive_macro = line'
+ would make FunnelWeb call the macro `@<line@>' whenever a line
+ directive was needed (an appropriate definition of @<line@> for
+ C/C++ is given in `autoccln.fwi'. The fact that this macro is
+ user defined means that the user can support any type of line
+ directive convention, or just add comments to show where a
+ section of a product file came from in the original FunnelWeb
+ source. New line directive types can be defined using
+ `@<#line@>' and `@<#file@>', which are described in the next
+ section.
+ There are some caveats that go with using automatic line
+ directive insertion. The same macro is used for all the line
+ directives, which means that a single FunnelWeb source cannot
+ support multiple language/file types unless the line directive
+ style happens to be the same for all of them. Also, when adding
+ line directives, there is the need to insert carriage returns
+ into the product files before and after macro invocations. So
+ your code may break unless macros are only used where adding
+ newlines before or after the macro invocations does not affect
+ the meaning of the product code. For many languages, such as
+ C/C++ or Pascal, this is generally the case; it isn't for
+ Fortran, though. Using a macro in the middle of a string
+ definition would probably also do the wrong thing, breaking
+ the string up across multiple lines.
+
+ 7. allow_source_code_typing and declare_source_code_type pragmas:
+ As originally implemented, the `automatic_line_directive_macro'
+ pragma added the same line directives to every product file
+ (except the documentation file). This is O.K. when all of the
+ files are, say, C files, but if you also generate the makefile
+ from the FunnelWeb file, you would then have to remove the #line
+ directives from the makefile, or use two separate FunnelWeb
+ files. The `allow_source_code_typing' macro tells FunnelWeb that
+ you wish apply the insertion of line directives selectively to
+ the product files. This pragma is required so that the new
+ features remain inactive unless explicitly asked for, to protect
+ existing FunnelWeb code.
+ Continuing the example of a FunnelWeb file from which is produced
+ a C file and a makefile, the product makefile should not have any
+ line directives. Since the FunnelWeb default is no line
+ directives, the makefile can be produced with the default source
+ code type. Then `@p declare_source_code_type "C"' can be used to
+ declare a source code type for the C file. You can declare as
+ many source code types as are required. Do not create a special
+ source code type for files without line directives, though, since
+ the default already provides this.
+ With source code types, the `automatic_line_directive_macro'
+ pragma can have two forms. The first form is
+ `@p automatic_line_directive_macro = <macro>', which sets the
+ automatic line directive macro for the default source type. If
+ you are using source code typing, you probably will have some
+ files to generate without line directives, and so you will not
+ want to set a line directive type for the default source code
+ type. Having defined a "C" source code type, you set the
+ automatic line directive macro for C files by
+ `@p automatic_line_directive_macro = <macro> "C"', i.e. you add
+ the source code type name to the end of the line.
+ There is only one more thing to do. Source code types apply only
+ to macros which are attached to files. So when you generate your
+ C file `main.c', you change its definition from
+ `@O@<main.c>==@{...@}' to `@O@<main.c@,C@>==@{...@}'. Note the
+ special use of `@,' here, and also that in the file macro
+ definition the source code type name is not surrounded by double
+ quotes as it is in the pragmas.
+ If you have followed all of this, you should be able to
+ understand the following sample FunnelWeb file which uses these
+ pragmas.
+
+ -----------sample FunnelWeb file----------------
+ @p allow_source_code_typing
+ @p declare_source_code_type "C"
+ @p automatic_line_directive_macro = "line" "C"
+ @i autoccln.fwi
+
+ @O@<main.c@,C@>==@{int main(void) { return 0; }@}
+
+ @$@<TAB@>==@{@^D(009)@} @! ASCII TAB character is decimal 9.
+ @O@<Makefile@>==@{@-
+ main.exe: main.c
+ @<TAB@>$(CC) -o $@@ main.c
+ @}
+ -----------end of sample FunnelWeb file----------
+
+ 8. A command switch `+Qb' has been added. The `b' stands for
+ `batch', and this switch stops FunnelWeb from asking the user
+ for confirmation if it has to abort. This means that FunnelWeb
+ will run as a completely batch-mode program, which apparently is
+ important for users who want to integrate it into the Borland
+ C/C++ IDE (development environment).
+
+ 9. The way FunnelWeb AC maps files into memory has been modified in
+ order to avoid problems with Unix systems choking on the CR/LF
+ pair used to terminate lines in DOS files. While the new system
+ has been checked under OS/2, OSF/1(Unix), and DOS, I would
+ appreciate knowing if this system works for Macintoshes as I
+ believe it should.
+ In principle this change could make FunnelWeb 3.05AC act
+ differently to FunnelWeb 3.0 for some files, but only files
+ so perverse as to be unreasonable in any case. If this is not
+ the case, report it to the author immediately.
+
+Special Internal Macros:
+ Some special `internal' macros have been added to FunnelWeb 3.05AC
+ to support imbedding of references to the original FunnelWeb
+ source(s) in the product files. In particular, the FunnelWeb
+ include file `ccline.fwi' defines a macro called @<line@> which can
+ be used to insert a C/C++ #line directive into a product file (for
+ manual line directive insertion, i.e. where the user types
+ `@<line@>' wherever needed. The version of `@<line@>' to be used
+ for automatic line directive insertion is to be found in
+ `autoccln.fwi'). These internal macros, of which only three
+ currently exist (@<#line@>, @<#file@>, and @<#timestamp@>), have
+ names which start with the hash character '#'.
+ This is the one place where existing FunnelWeb code might be
+ expected to break when processed by this experimental version of
+ FunnelWeb, if the name of an internal macro also used for a
+ user-defined macro. As such, it is strongly recommended that the
+ user avoid macro names which start with the '#' character.
+ The @<#line@> macro causes a FunnelWeb source line number to
+ be inserted into the product file, while the @<#file@> macro inserts
+ a FunnelWeb source file name. See `ccline.fwi' for an example.
+ There are two pragmas related to this pair of internal macros.
+ `@p #line_offset = <num>' is used to set a value which is added to
+ the actual FunnelWeb source file line on which @<#line@> is invoked
+ before the line number is printed in the product file. This is
+ necessary for C/C++ #line directives because the directive much
+ specify the source line number of the line *after* the directive,
+ not the source line number of the directive itself. Thus, the
+ offset value needs to be 1 for C/C++ (and is defined to be in
+ `ccline.fwi').
+ `@p #line_depth = <num>' controls *which* line number and file name
+ are actually printed by @<#line@> and @<#file@>. Taking
+ `ccline.fwi' as an example, this file defines a @<line@> macro in
+ which @<#line@> and @<#file@> are then called. My first naive
+ version of @<line@> [ABC] ended up printing the line number and file
+ name for `ccline.fwi' (which is then the same for every case)!!!
+ What I [ABC] wanted was the line number and file name for where
+ @<line@> was invoked, not where @<#line@> and @<#file@> were
+ actually invoked inside @<line@>. This means that it is necessary
+ to climb up the current stack of macro invocations until you arrive
+ at the one you want. `@p #line_depth = <num>' allows the user to
+ define how far up the macro invocation stack you must go in order to
+ get the desired line number and file name. The appropriate value
+ for C/C++ #line directives is set in `ccline.fwi'.
+ The @<#timestamp@> macro is converted in the product files
+ (but not in the documentation file)to a date/time string in the form
+ `yyyy/mm/dd/hh/mm/ss'. Although most file systems will date the
+ product files anyway, timestamping may be useful for having the
+ program itself print a message saying when FunnelWeb was last used
+ to generate the product files. The actually date and time used for
+ the timestamp are only checked once, the first time that
+ @<#timestamp@> is processed by FunnelWeb. Thus, all product files
+ produced by the same run of FunnelWeb will contain the same
+ timestamp. This seems more reasonable than having slightly
+ different times in each of the product files. If you have more
+ complicated timestamp or version control requirements, try using GNU
+ RCS (revision control system), which has been found to work well
+ with FunnelWeb. *WARNING*: if you use @<#timestamp@> in a product
+ file, the FunnelWeb `+D' command line flag will not affect that
+ file, since the timestamp in the file will be different every time
+ FunnelWeb is run. Hence, if you use makefiles, and do not want to
+ recompile/regenerate everything every time, be careful about using
+ @<#timestamp@>.
+
+Other changes:
+ Ross Williams once posted a message to the FunnelWeb mailing list
+ stating that FunnelWeb allocated a maximally-sized string to every
+ macro name, and that this was a waste of space. In my version,
+ this has been modified so that only the amount of string space
+ necessary is allocated. How much is saved will depend greatly on
+ the nature of the FunnelWeb source. I [ABC] did manage in one case
+ to save 100k on the memory that needed to be allocated, but this was
+ on a project where FunnelWeb allocated itself just over 11M while
+ running; thus the saving is not necessarily significant.
+
+Compiling the code:
+ I have included some example makefiles, but the standard FunnelWeb
+ creed of `just compile it all together at once' should work fine. I
+ [ABC] tend not to do this because my compiler is not lightning fast.
+ Because of the modifications, when you run the FunnelWeb tests, you
+ will not get the same errors as with FunnelWeb v.3.0. The number of
+ errors and differences that you should get is to be found in the
+ file `err.status'.
+
+This is the end of this documentation file.
diff --git a/web/funnelAC/fwACsrc/analyse.c b/web/funnelAC/fwACsrc/analyse.c
new file mode 100644
index 0000000000..3a2490c845
--- /dev/null
+++ b/web/funnelAC/fwACsrc/analyse.c
@@ -0,0 +1,326 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 03-Sep-1994 ABC Added support for the automatic insertion of
+ line directives when `aldmname' is a non-null
+ string referring to a macro without parameters.
+ It is necessary to ignore @M or @Z for the
+ given line directive insertion macro.
+ 25-Jul-1995 ABC Replaced `aldmname' with a list of structures
+ containing a source code type name (or NULL)
+ and a corresponding automatic line directive
+ insertion macro name.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* ANALYSE.C */
+/******************************************************************************/
+
+#include "style.h"
+
+#include "analyse.h"
+#include "as.h"
+#include "data.h"
+#include "lister.h"
+#include "misc.h"
+#include "table.h"
+
+/******************************************************************************/
+
+LOCAL void chk_mac P_((p_ma_t));
+LOCAL void chk_mac (p_ma)
+p_ma_t p_ma;
+{
+ mc_t *call;
+ /* ABC { */
+ p_srcnmac_t p_srctype;
+ bool isaldmQ;
+ /* } ABC */
+
+ /* Deal with undefined macros by flagging the first invocation. */
+ if (!p_ma->ma_defn.md_isdef)
+ {
+ ls_loo(p_ma->ma_calls,(ulong) 1,PPV &call);
+ as_cold(call!=NULL,"check_macro: No instances of \"undefined\" macro!");
+ lr_err(&call->mc_ps,"Call to undefined macro.");
+ return;
+ }
+
+ /* Assert: The macro has a definition. */
+
+ /* Check that all the calls to the macro have the correct number of params. */
+ ls_fir(p_ma->ma_calls);
+ ls_nxt(p_ma->ma_calls,PPV &call);
+ while (call!=NULL)
+ {
+ if (call->mc_npar != p_ma->ma_defn.md_npar)
+ {
+ sprintf(linet1,"Call has %lu parameter%s, but the macro",
+ (ulong) call->mc_npar,
+ call->mc_npar==1 ? "" : "s");
+ lr_err(&(call->mc_ps),linet1);
+ sprintf(linet1,"definition at line %lu specifies %lu parameter%s.",
+ (ulong) p_ma->ma_defn.md_ps.ps_line,
+ (ulong) p_ma->ma_defn.md_npar,
+ p_ma->ma_defn.md_npar==1 ? "" : "s");
+ lr_mes(&(call->mc_ps),linet1);
+ if (p_ma->ma_defn.md_npar==0 && call->mc_npar==1)
+ {
+ lr_mes(&(call->mc_ps),"Note: If your call looks like this: @<Macro@>@(@) then you");
+ lr_mes(&(call->mc_ps),"should be aware that FunnelWeb treats this as a call with");
+ lr_mes(&(call->mc_ps),"a single parameter consisting of the empty string. This");
+ lr_mes(&(call->mc_ps),"is a consequence of parameter delimiters @\"@\" being optional.");
+ }
+ }
+ ls_nxt(p_ma->ma_calls,PPV &call);
+ }
+
+/* ABC { */
+ /* Check if the macro is an automatic line directive insertion macro */
+ isaldmQ = FALSE;
+ ls_fir(srctlist);
+ for (;;) { /* forever */
+ ls_nxt(srctlist, (pp_lsel_t)&p_srctype);
+ if (p_srctype == NULL) break;
+ if (p_srctype->lnmac == NULL) continue;
+ if (!strcmp(p_srctype->lnmac, p_ma->ma_name)) {
+ isaldmQ = TRUE;
+ break;
+ } /* end if */
+ } /* end forever */
+/* } ABC */
+
+ /* Check that the number of calls of the macro is legal. */
+ if (p_ma->ma_defn.md_isfil)
+ {
+ /* Flag all calls to a file macro as errors. */
+ if (ls_len(p_ma->ma_calls)>0)
+ {
+ lr_mes(&p_ma->ma_defn.md_ps,
+ "This file macro is called one or more times.");
+ lr_mes(&p_ma->ma_defn.md_ps,
+ "Each call has been flagged with an error message.");
+ }
+ ls_fir(p_ma->ma_calls);
+ ls_nxt(p_ma->ma_calls,PPV &call);
+ while (call!=NULL)
+ {
+ lr_err(&(call->mc_ps),"Calls to file macros are not allowed.");
+ lr_mes(&(call->mc_ps),"Reason: It should be possible to comment out a");
+ lr_mes(&(call->mc_ps),"file macro without a big fuss. Calling a file macro");
+ lr_mes(&(call->mc_ps),"just tangles it up in the macro structure,");
+ lr_mes(&(call->mc_ps),"making it more difficult to comment out later.");
+ ls_nxt(p_ma->ma_calls,PPV &call);
+ }
+ }
+ /* ABC { */
+ else if (!isaldmQ)
+ /* } ABC */
+ {
+ /* Non-file macros. */
+ if (ls_len(p_ma->ma_calls)==0 && !p_ma->ma_defn.md_iszer)
+ lr_err(&p_ma->ma_defn.md_ps,
+ "This macro is never used (and has no @Z).");
+
+ if (ls_len(p_ma->ma_calls)>1 && !p_ma->ma_defn.md_isman)
+ lr_err(&p_ma->ma_defn.md_ps,
+ "This macro is used more than once (and has no @M).");
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void chk_rec P_((void));
+LOCAL void chk_rec()
+/* This macro analyses the calls between the macros in the macro */
+/* table and flags all recursive macros with an error message. */
+/* */
+/* Def: A macro is a "level 0 macro" if it does not call any macros. */
+/* Def: A macro is a "level n macro" if it calls at least one macro of level */
+/* n-1, but does not call any macros of level n or higher. */
+/* Def: A macro is a "level infinity macro" if it directly or indirectly */
+/* calls itself. */
+/* */
+/* This function totally ignores undefined macros. This means that it can be */
+/* invoked even if problems are detected by the other checks. */
+/* */
+/* Although the actions of this may seem rather time expensive, they may not */
+/* be. The function repeatedly runs through the macro table and each macro's */
+/* bodypart list and expression lists. However, there are not likely to be */
+/* many macros and each definition expression list is likely to be quite */
+/* short, as each macro will be mainly text. */
+/* Even if this stuff does take a while, it is better to detect recursion now */
+/* than at tangle time! */
+{
+ p_ma_t p_ma; /* General purpose pointer to macro. */
+ name_t dummy_name; /* Dummy name variable acts as a placeholder in calls. */
+ uword level; /* Level of macro currently being tagged. */
+ bool gotone; /* TRUE iff current loop iteration tagged >0 macros. */
+
+/* We need a concrete number to stand for level infinity. */
+/* 30000 is a nice, large 15 bit number. */
+#define LEVINF 30000
+
+ /* Make sure that our idea of infinity is big enough. */
+ as_cold(tb_len(macro_table)<LEVINF,"ana_rec: too many macros.");
+
+ /* Tag all the macros as being at level infinity. */
+ /* This could be done in the parser, but it's neater to do it here. */
+ tb_fir(macro_table);
+ while (tb_rea(macro_table,PV dummy_name,PV &p_ma))
+ if (p_ma->ma_defn.md_isdef)
+ p_ma->ma_level=LEVINF;
+
+ gotone=TRUE;
+ /* Work from level 0 upwards identifying macros of successive levels. */
+ for (level=0; level<LEVINF && gotone; level++)
+ {
+ /* Identify all macros of level 'level'. */
+ /* Gotone tells us if we managed to tag a macro during this iteration. */
+ gotone=FALSE;
+
+ /* Run through table tagging all macros at level 'level'. */
+ tb_fir(macro_table);
+ while (tb_rea(macro_table,PV dummy_name,PV &p_ma))
+ {
+ if (p_ma->ma_defn.md_isdef && p_ma->ma_level == LEVINF)
+ {
+ p_bpls_t p_bpls = p_ma->ma_defn.md_body;
+ /* Run through each body part of the macro. */
+ ls_fir(p_bpls);
+ while (TRUE)
+ {
+ p_bp_t p_bp;
+ ls_nxt(p_bpls,PPV &p_bp);
+ if (p_bp==NULL) break;
+ /* Run through the list of expression elements. */
+ ls_fir(p_bp->bp_ex);
+ while (TRUE)
+ {
+ p_el_t p_el;
+ ls_nxt(p_bp->bp_ex,PPV &p_el);
+ if (p_el==NULL) break;
+ /* Don't tag anything that calls anything that isn't tagged. */
+ if ((p_el->el_kind==EL_INVC ) &&
+ (p_el->el_p_mac->ma_defn.md_isdef) &&
+
+ (p_el->el_p_mac->ma_level==LEVINF))
+ goto nextmacro;
+ }
+ }
+ /* If we got this far, then our macro must have called nothing but */
+ /* macros of levels [0,level-1]. Thus, we can tag it level 'level'. */
+ p_ma->ma_level=level;
+ gotone=TRUE;
+ } /* End if */
+ nextmacro:;
+ } /* End while */
+ } /* End for loop. */
+
+ /* At this point, we have tagged all macros with their level number. Note */
+ /* that level infinity macros are discovered simply because they do not get */
+ /* tagged. The following loop flags all such recursive macros with errors. */
+ tb_fir(macro_table);
+ while (tb_rea(macro_table,PV dummy_name,PV &p_ma))
+ if (p_ma->ma_defn.md_isdef && p_ma->ma_level==LEVINF)
+ lr_err(&p_ma->ma_defn.md_ps,"This macro has an infinite expansion.");
+
+ /* Note: The above message is not "This macro is defined recursively", */
+ /* because this function catches not only recursive macros, but also all the */
+ /* non-recursive macros that call the recursive macros!! To detect only */
+ /* the recursive macros, we really ought to use Tarjan's algorithm for the */
+ /* detection of strongly connected components. However, I don't have the */
+ /* reference handy right now and I want to finish this version of FunnelWeb */
+ /* soon, so I'll leave the installation of Tarjan's algorithm as a possible */
+ /* future enhancement. Then the error message can be changed. */
+}
+
+/******************************************************************************/
+
+EXPORT void analyse()
+{
+ name_t dummy_name;
+ p_ma_t p_ma;
+
+ /* Issue an error if there are no macros. */
+ if (tb_len(macro_table)==0)
+ {
+ char *m="E: No macros defined.";
+ wl_l(m);
+ if (option.op_s_b)
+ wl_sj(m);
+ num_err++;
+ }
+
+ /* Issue an error if there are no product (output) files. */
+ if (tb_len(file_table)==0)
+ {
+ char *m="E: No output files specified.";
+ wl_l(m);
+ if (option.op_s_b)
+ wl_sj(m);
+ num_err++;
+ }
+
+ /* Take a look at each macro and issue appropriate diagnostics. */
+ tb_fir(macro_table);
+ while (tb_rea(macro_table,PV dummy_name,PV &p_ma))
+ chk_mac(p_ma);
+
+ /* Check for recursive macros. */
+ chk_rec();
+
+ /* Run through the document list and flag any sections that still have not */
+ /* been given names. */
+ ls_fir(document_list);
+ while (TRUE)
+ {
+ p_dc_t p_dc;
+ ls_nxt(document_list,PPV &p_dc);
+ if (p_dc==NULL) break;
+ if (p_dc->dc_kind==DC_TYPE &&
+ p_dc->dc_ty.ty_kind==TY_NSEC &&
+ !p_dc->dc_ty.ty_isnam)
+ {
+ lr_err(&p_dc->dc_ps,"This section has no name.");
+ lr_mes(&p_dc->dc_ps,"You can give it one explicitly (As in @A@<Sloth@>) or implicitly by");
+ lr_mes(&p_dc->dc_ps,"defining a macro (whose name will be inherited) within the section.");
+ }
+ }
+}
+
+/******************************************************************************/
+/* End of ANALYSE.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/analyse.h b/web/funnelAC/fwACsrc/analyse.h
new file mode 100644
index 0000000000..3c2826b810
--- /dev/null
+++ b/web/funnelAC/fwACsrc/analyse.h
@@ -0,0 +1,61 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* ANALYSE.H */
+/******************************************************************************/
+/* */
+/* This package exports a single function called analyse() that should be */
+/* invoked just after the parser has finished. The scanner and parser */
+/* serve only to construct a structured representation of the input file in */
+/* memory; they do not critique it beyond syntax. In contrast, analyse() */
+/* analyses the representation, checking it for "semantic" errors. Any */
+/* problems that are found are sent to the lister package with appropriate */
+/* positioning information so that the messages appear at exactly the right */
+/* spot in the listing. */
+/* */
+/******************************************************************************/
+
+#include "style.h"
+
+/******************************************************************************/
+
+EXPORT void analyse P_((void));
+
+/******************************************************************************/
+/* End of ANALYSE.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/as.c b/web/funnelAC/fwACsrc/as.c
new file mode 100644
index 0000000000..f47d25b35e
--- /dev/null
+++ b/web/funnelAC/fwACsrc/as.c
@@ -0,0 +1,72 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 16-Aug-1995 ABC Added support for batch mode (via `batchQ') in
+ which there is no interaction at all with the
+ user.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* AS.C */
+/******************************************************************************/
+
+#include "style.h"
+/* ABC { */
+#include "data.h"
+/* } ABC */
+
+#include "as.h"
+#include "machin.h"
+
+/******************************************************************************/
+
+EXPORT void as_bomb(message)
+char *message;
+{
+ fprintf(stderr,"%s\n",message);
+ fprintf(stderr,"An assertion has failed! See the line above.\n");
+ /* ABC { */
+ if (batchQ) {
+ fprintf(stderr,"FunnelWeb aborted immediately without finishing.\n");
+ } else {
+ fprintf(stderr,"Press return to abort FunnelWeb>\n"); (void) getchar();
+ } /* end if */
+ /* } ABC */
+ exit(EXIT_FAILURE);
+}
+
+/******************************************************************************/
+/* AS.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/as.h b/web/funnelAC/fwACsrc/as.h
new file mode 100644
index 0000000000..ab89d73e83
--- /dev/null
+++ b/web/funnelAC/fwACsrc/as.h
@@ -0,0 +1,119 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* AS.H */
+/******************************************************************************/
+/* */
+/* ASSERTION PACKAGE */
+/* ================= */
+/* This package contains macros and functions that support assertions. An */
+/* assertion is a boolean condition that is supposed always to be true at a */
+/* particular point during program execution. An assertion statement tests */
+/* such a condition and bombs the program if it is false; better to be */
+/* alerted to such a condition rather than suffer and erroneous execution. */
+/* */
+/* Standard C supports asertions with the <assert.h> header file providing */
+/* the "assert" macro. Unfortunately, this does not meet the needs of */
+/* FunnelWeb for two reasons: */
+/* */
+/* 1) Portability is emphasised in FunnelWeb and the assert macro is fairly */
+/* recent. Its only argument is the boolean condition, which means that */
+/* without the ANSI macros __FILE__ and __LINE__, the macro would be */
+/* unable to indicate where an assertion failure occurred, in a non-ANSI */
+/* environment. */
+/* */
+/* 2) There is only one assert macro and it can be either on or off, the */
+/* implication being that in production code, it should be turned off. In */
+/* contrast, the execution speed of the assert macro will usually matter */
+/* only in a small portion of the code as, in most programs, a small */
+/* portion of the code accounts for most of the execution time. By having */
+/* two categories of assertion, we can leave most of the assertions turned */
+/* on in the production program. */
+/* */
+/* This reasoning leads to the slightly different assertion facilty provided */
+/* by this package. Here, there are two assertion routines/macros, HOT */
+/* assertions for HOT code (code in a program hot spot) and COLD assertions */
+/* for COLD code (not in a hot spot). Only the HOT assertions can be turned */
+/* off. */
+/* */
+/******************************************************************************/
+
+/* Ensure that the body of this header file is included at most once. */
+#ifndef DONE_AS
+#define DONE_AS
+
+/******************************************************************************/
+
+#include "style.h"
+
+/******************************************************************************/
+
+/* The following #define determines whether hot assertions are to be turned */
+/* on or off. Set to 0 for OFF and 1 for ON. */
+/* Note: I have left hot assertions on in the production version as FunnelWeb */
+/* doesn't go slowly enough to make me want to turn it off. */
+#define AS_DOHOT 1
+
+/******************************************************************************/
+
+EXPORT void as_bomb P_((char *));
+/* This function writes out its argument string and then bombs the program. */
+/* It should be called at any point where it has been determined that an */
+/* illegal condition has been detected. The other assertion routines/macros */
+/* call this function. */
+
+/* The following two macros define hot and cold assertions. Be sure never to */
+/* call them with arguments with side effects! */
+#define as_cold(e,s) {if (!(e)) as_bomb(s);}
+
+#if AS_DOHOT
+#define as_hot(e,s) {if (!(e)) as_bomb(s);}
+#define AS_HCODE(CODE) {CODE}
+#else
+#define as_hot(e,s) ((void) 0)
+#define AS_HCODE(CODE) ((void) 0)
+#endif
+
+/******************************************************************************/
+
+/* For #ifndef preventing multiple inclusion of the body of this header file. */
+#endif
+
+/******************************************************************************/
+/* AS.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/autoccln.fwi b/web/funnelAC/fwACsrc/autoccln.fwi
new file mode 100644
index 0000000000..6532d05289
--- /dev/null
+++ b/web/funnelAC/fwACsrc/autoccln.fwi
@@ -0,0 +1,45 @@
+@! FUNNNELWEB COPYRIGHT
+@! ====================
+@! FunnelWeb is a literate-programming macro preprocessor.
+@!
+@! Copyright (C) 1992 Ross N. Williams.
+@!
+@! Ross N. Williams
+@! ross@spam.adelaide.edu.au
+@! 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+@!
+@! This program is free software; you can redistribute it and/or modify
+@! it under the terms of Version 2 of the GNU General Public License as
+@! published by the Free Software Foundation.
+@!
+@! This program is distributed WITHOUT ANY WARRANTY; without even the implied
+@! warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+@! See Version 2 of the GNU General Public License for more details.
+@!
+@! You should have received a copy of Version 2 of the GNU General Public
+@! License along with this program. If not, you can FTP the license from
+@! prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+@! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+@!
+@! Section 2a of the license requires that all changes to this file be
+@! recorded prominently in this file. Please record all changes here.
+@!
+@! Programmers:
+@! ABC Anthony B. Coates coates@physics.uq.edu.au
+
+@! Defines a macro "@<line@>" for automatically inserting #line
+@! pragmas into C and C++ code when using the
+@! `@p auto_line_directive_macro = line' pragma.
+
+@! The #line_offset pragma needs to be set to 0 for C/C++.
+@p #line_offset = 0
+
+@! The #line_depth pragma needs to be set to 1 to
+@! work in the manner described above.
+@p #line_depth = 1
+
+@! After all that, here is the definition itself.
+
+@$@<line@>==@{#line @<#line@> "@<#file@>"@}
+
+@! End of autoccln.fwi
diff --git a/web/funnelAC/fwACsrc/ccline.fwi b/web/funnelAC/fwACsrc/ccline.fwi
new file mode 100644
index 0000000000..8b17c718ed
--- /dev/null
+++ b/web/funnelAC/fwACsrc/ccline.fwi
@@ -0,0 +1,74 @@
+@! FUNNNELWEB COPYRIGHT
+@! ====================
+@! FunnelWeb is a literate-programming macro preprocessor.
+@!
+@! Copyright (C) 1992 Ross N. Williams.
+@!
+@! Ross N. Williams
+@! ross@spam.adelaide.edu.au
+@! 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+@!
+@! This program is free software; you can redistribute it and/or modify
+@! it under the terms of Version 2 of the GNU General Public License as
+@! published by the Free Software Foundation.
+@!
+@! This program is distributed WITHOUT ANY WARRANTY; without even the implied
+@! warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+@! See Version 2 of the GNU General Public License for more details.
+@!
+@! You should have received a copy of Version 2 of the GNU General Public
+@! License along with this program. If not, you can FTP the license from
+@! prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+@! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+@!
+@! Section 2a of the license requires that all changes to this file be
+@! recorded prominently in this file. Please record all changes here.
+@!
+@! Programmers:
+@! ABC Anthony B. Coates coates@physics.uq.edu.au
+
+@! Defines a macro "@<line@>" for inserting #line pragmas into C and
+@! C++ code.
+
+@! Here is an example of a (trivial) FunnelWeb file for a C program
+@! with the @<line@> macros added.
+
+@!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+@! @i ccline.fwi @! include the @<line@> definition
+@!
+@! @$@<dummy@>==@{@- @! OK, here is a definition with some C code
+@! @<line@> @! At the start of it, add a @<line@> definition
+@! void dummy(void) {};
+@! @}
+
+@! @O@<tester.cc@>==@{@- @! The main code
+@! @<line@> @! Start with @<line@>
+@! @<dummy@> @! Code for dummy routine
+@! @<line@> @! Call @<line@> again to reset file/line
+@! int main(void) {
+@! } // end main
+@! @}
+@!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+@! i.e. the rules are
+@! (i) call @<line@> at the start of any definition containing
+@! code.
+@! (ii) call @<line@> after any macro call which may itself
+@! contain a @<line@> call.
+
+@! **** These pragmas need to be set at the top of the .fw file.
+@! **** Include this file at the top or set the pragmas there
+@! **** manually.
+
+@! The #line_offset pragma needs to be set to 1 for C/C++.
+@p #line_offset = 1
+
+@! The #line_depth pragma needs to be set to 1 to
+@! work in the manner described above.
+@p #line_depth = 1
+
+@! After all that, here is the definition itself.
+
+@$@<line@>@M==@{#line @<#line@> "@<#file@>"@}
+
+@! End of ccline.fwi
diff --git a/web/funnelAC/fwACsrc/clock.c b/web/funnelAC/fwACsrc/clock.c
new file mode 100644
index 0000000000..886b1bff55
--- /dev/null
+++ b/web/funnelAC/fwACsrc/clock.c
@@ -0,0 +1,125 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* CLOCK.C */
+/******************************************************************************/
+
+#include "style.h"
+
+#include "as.h"
+#include "clock.h"
+#include "machin.h"
+
+/******************************************************************************/
+
+#define MAGIC_HEAD (565854L)
+#define MAGIC_TAIL (256194L)
+
+/******************************************************************************/
+
+LOCAL void ck_check P_((p_ck_t));
+LOCAL void ck_check(p_ck)
+p_ck_t p_ck;
+{
+ as_cold(p_ck!=NULL,"ck_check: Clock pointer is NULL.");
+ as_cold(p_ck->ck_mhead==MAGIC_HEAD,
+ "ck_check: Magic number at head of record is incorrect.");
+ as_cold(p_ck->ck_mtail==MAGIC_TAIL,
+ "ck_check: Magic number at tail of record is incorrect.");
+}
+
+/******************************************************************************/
+
+EXPORT void ck_ini(p_ck)
+p_ck_t p_ck;
+{
+ p_ck->ck_mhead = MAGIC_HEAD;
+ p_ck->ck_run = FALSE;
+ p_ck->ck_csum = 0.0;
+ p_ck->ck_rsum = 0.0;
+ /* ck_csta and ck_rsta are undefined in a stopped clock. */
+ p_ck->ck_mtail = MAGIC_TAIL;
+}
+
+/******************************************************************************/
+
+EXPORT void ck_start(p_ck)
+p_ck_t p_ck;
+{
+ ck_check(p_ck);
+ as_cold(!p_ck->ck_run,"ck_start: Clock is already running!");
+ p_ck->ck_run = TRUE;
+ p_ck->ck_csta = tim_cpu();
+ p_ck->ck_rsta = tim_real();
+}
+
+/******************************************************************************/
+
+EXPORT void ck_stop(p_ck)
+p_ck_t p_ck;
+{
+ ck_check(p_ck);
+ as_cold(p_ck->ck_run,"ck_stop: Clock is already stopped!");
+ p_ck->ck_run = FALSE;
+ p_ck->ck_csum += tim_cpu () - p_ck->ck_csta;
+ p_ck->ck_rsum += tim_real() - p_ck->ck_rsta;
+}
+
+/******************************************************************************/
+
+EXPORT float ck_cpu(p_ck)
+p_ck_t p_ck;
+{
+ ck_check(p_ck);
+ as_cold(!p_ck->ck_run,"ck_cpu: Clock is running.");
+ return p_ck->ck_csum;
+}
+
+/******************************************************************************/
+
+EXPORT float ck_real(p_ck)
+p_ck_t p_ck;
+{
+ ck_check(p_ck);
+ as_cold(!p_ck->ck_run,"ck_real: Clock is running.");
+ return p_ck->ck_rsum;
+}
+
+/******************************************************************************/
+/* End of CLOCK.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/clock.h b/web/funnelAC/fwACsrc/clock.h
new file mode 100644
index 0000000000..906879db1b
--- /dev/null
+++ b/web/funnelAC/fwACsrc/clock.h
@@ -0,0 +1,107 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* CLOCK.H */
+/******************************************************************************/
+/* */
+/* This package implements a clock abstraction that is used to generate */
+/* timing statistics which are useful for performance tuning. The package */
+/* allows the measurement of both real and CPU time. This package gets its */
+/* raw information from the tim_cpu() and tim_real() functions of the machine */
+/* dependent module "machin". */
+/* */
+/******************************************************************************/
+
+/* Ensure that the body of this header file is included at most once. */
+#ifndef DONE_CLOCK
+#define DONE_CLOCK
+
+/******************************************************************************/
+
+#include "style.h"
+
+/******************************************************************************/
+
+/* The following clock type is supposed to be an ADT so don't frob any of its */
+/* fields manually! */
+typedef struct
+ {
+ ulong ck_mhead; /* Magic number helps detect corruptions. */
+ bool ck_run; /* TRUE iff the clock is running. */
+ float ck_csum; /* Accumulated CPU time. */
+ float ck_rsum; /* Accumulated real time. */
+ float ck_csta; /* ck_run => CPU time when clock was started. */
+ float ck_rsta; /* ck_run => Real time when clock was started. */
+ ulong ck_mtail; /* Magic number helps detect corruptions. */
+ } ck_t;
+
+typedef ck_t *p_ck_t;
+
+/******************************************************************************/
+
+EXPORT void ck_ini P_((p_ck_t));
+/* Initializes the clock. After this call, the argument clock will be in the */
+/* STOPPED state and all its registers will be zero. A clock must be */
+/* initialized before any other operations are performed on it. */
+
+EXPORT void ck_start P_((p_ck_t));
+/* Changes the clock from the STOPPED state to the RUNNING state. Starts */
+/* accumulating real time and CPU time on its registers. */
+/* Raises an error if the clock is not in the STOPPED state. */
+
+EXPORT void ck_stop P_((p_ck_t));
+/* Changes the clock from the RUNNING state to the STOPPED state. Stops */
+/* accumulating real time and CPU time on its registers. */
+/* Raises an error if the clock is not in the RUNNING state. */
+
+EXPORT float ck_cpu P_((p_ck_t));
+/* Returns the number of seconds of CPU time accumulated on the clock. */
+/* Raises an error if the clock is not in the STOPPED state. */
+
+EXPORT float ck_real P_((p_ck_t));
+/* Returns the number of seconds of real time accumulated on the clock. */
+/* Raises an error if the clock is not in the STOPPED state. */
+
+/******************************************************************************/
+
+/* For #ifndef preventing multiple inclusion of the body of this header file. */
+#endif
+
+/******************************************************************************/
+/* End of CLOCK.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/command.c b/web/funnelAC/fwACsrc/command.c
new file mode 100644
index 0000000000..e3cdf22b33
--- /dev/null
+++ b/web/funnelAC/fwACsrc/command.c
@@ -0,0 +1,2147 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 16-Sep-1993 ABC Changed all constants *_MAX to *_FWMAX to avoid
+ conflict with some standard UNIX constants.
+ 18-Sep-1994 ABC Changed startup message to reflect my changes.
+ 01-Jan-1995 ABC Modified initial message to reflect first
+ release of FunnelWeb 3.0AC.
+ 20-Jul-1995 ABC Modified initial message to reflect
+ release of FunnelWeb 3.01AC.
+ 08-Aug-1995 ABC Changed include file name from "memory.h"
+ to "fwmem.h" to avoid a clash with the C++
+ standard header file "memory.h".
+ 08-Aug-1995 ABC Modified initial message to reflect
+ release of FunnelWeb 3.02AC.
+ 10-Aug-1995 ABC Modified initial message to reflect
+ release of FunnelWeb 3.03AC.
+ 16-Aug-1995 ABC Added support for `+Qb' batch mode option and
+ matching boolean `batchQ'.
+ 16-Aug-1995 ABC Modified initial message to reflect
+ release of FunnelWeb 3.04AC.
+ 19-Sep-1995 ABC Modified initial message to reflect
+ release of FunnelWeb 3.05AC.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* COMMAND.C */
+/******************************************************************************/
+
+#include <ctype.h>
+#include "style.h"
+
+#include "analyse.h"
+#include "as.h"
+#include "command.h"
+#include "data.h"
+#include "dump.h"
+#include "lister.h"
+#include "fwmem.h"
+#include "mapper.h"
+#include "misc.h"
+#include "option.h"
+#include "parser.h"
+#include "scanner.h"
+#include "tangle.h"
+#include "weave.h"
+
+/******************************************************************************/
+
+/* Because FunnelWeb has so many options ,it is convenient to allow the user */
+/* to construct a startup file. This is its name. */
+#define INITFILE "fwinit.fws"
+
+/******************************************************************************/
+
+/* Three variables hold options information in FunnelWeb. */
+/* 'p_comopt' holds the options conveyed by the original raw command line. */
+/* 'p_defopt' holds the options that are default in the FunnelWeb shell. */
+/* 'option' is global and holds the options that have been specified for the */
+/* current invocation of FunnelWeb proper. */
+/* 'option' is global so here we see only 'p_comopt' and 'p_defopt'. */
+LOCVAR op_t *p_comopt; /* Initial command line options. */
+LOCVAR op_t *p_defopt; /* Default shell options. */
+
+/* The FunnelWeb shell interpreter has many different commands and it is */
+/* worth them sharing the same basic command line scanner. These two */
+/* variables hold the numer of arguments and a pointer to strings holding */
+/* copies of each argument. */
+/* Note: The first argument is placed in arr_arg[0]. */
+#define ARG_FWMAX 5
+LOCVAR uword arg_num;
+LOCVAR char *arg_arr[ARG_FWMAX+1]; /* Is this +1 necessary? */
+
+/* The FunnelWeb command interpreter allows 10 substitution strings. */
+/* These strings are stored in the following array. */
+#define NUM_SUBS (10+26) /* 0..9 and A..Z */
+LOCVAR char *subval[NUM_SUBS];
+
+LOCVAR ulong old_war;
+LOCVAR ulong old_err;
+LOCVAR ulong old_sev;
+
+/* The FunnelWeb script interpreter can echo (trace) each command before it */
+/* executes it. Whether it does is determined by this variable. */
+LOCVAR bool tracing;
+
+/* If this variable is set to true then the interpreter will not abort if the */
+/* very next command (and that one only) generates an error or severe error. */
+LOCVAR bool noabort;
+
+/* If the following boolean is true, the interpreter skips lines until it */
+/* hits the HERE command. */
+LOCVAR bool skipping;
+
+/* The following variables count how many times DIFF is invoked and how many */
+/* times it succeeded. This allows us to output a summary at the end of the */
+/* processing of the test suite. */
+LOCVAR ulong difftotl = 0;
+LOCVAR ulong diffsucc = 0;
+
+/******************************************************************************/
+
+/* Here are the prototypes for recursive or out-of-order functions. */
+LOCAL void interstr P_((char *));
+LOCAL void do_set P_((char *));
+
+/******************************************************************************/
+
+LOCAL char *sing P_((ulong,char *,char *));
+LOCAL char *sing(num,sinstr,plustr)
+/* Return one or other string depending on whether first argument is singular.*/
+ulong num;
+char *sinstr;
+char *plustr;
+{
+ if (num==1)
+ return sinstr;
+ else
+ return plustr;
+}
+
+/******************************************************************************/
+
+LOCAL uword numpos P_((ulong,ulong,ulong));
+LOCAL uword numpos(a,b,c)
+/* Returns the number of its arguments that are positive. */
+ulong a,b,c;
+{
+ uword result=0;
+ if (a>0) result++;
+ if (b>0) result++;
+ if (c>0) result++;
+ return result;
+}
+
+/******************************************************************************/
+
+LOCAL void errsum P_((ulong,ulong,ulong,ulong));
+LOCAL void errsum(fat,sev,err,war)
+/* Supply as arguments, the number of various kinds of diagnostics. */
+/* Places in linet1 a string describing the diagnostics. */
+ulong fat,sev,err,war;
+{
+ char linet2[100];
+
+ if (fat+sev+err+war==0)
+ {strcpy(linet1,"SUCCESS: No diagnostics."); return;}
+
+ strcpy(linet1,"There ");
+
+ /* "Was" or "were" depending on the plurality of highest level diagnostic. */
+ if (fat>0) strcat(linet1,sing(fat,"was","were"));
+ else if (sev>0) strcat(linet1,sing(sev,"was","were"));
+ else if (err>0) strcat(linet1,sing(err,"was","were"));
+ else if (war>0) strcat(linet1,sing(war,"was","were"));
+ else as_bomb("errsum: Error hierarchy failed!");
+
+ strcat(linet1," ");
+
+ /* Fatal errors. */
+ if (fat>0)
+ {
+ sprintf(linet2,"%1lu Fatal error",fat); strcat(linet1,linet2);
+ strcat(linet1,sing(fat,"","s"));
+ }
+
+ /* Joiner stuff. */
+ if (fat>0 && numpos(sev,err,war)>=2) strcat(linet1,", ");
+ if (fat>0 && sev>0 && err==0 && war==0) strcat(linet1," and ");
+
+ /* Severe errors. */
+ if (sev>0)
+ {
+ sprintf(linet2,"%1lu Severe error",sev); strcat(linet1,linet2);
+ strcat(linet1,sing(sev,"","s"));
+ }
+
+ /* Joiner stuff. */
+ if (fat+sev>0 && err>0 && war >0) strcat(linet1,", ");
+ if (fat+sev>0 && err>0 && war==0) strcat(linet1," and ");
+
+ /* Errors. */
+ if (err>0)
+ {
+ sprintf(linet2,"%1lu Error",err); strcat(linet1,linet2);
+ strcat(linet1,sing(err,"","s"));
+ }
+
+ /* Joiner stuff. */
+ if (fat+sev+err>0 && war>0) strcat(linet1," and ");
+
+ /* Warnings. */
+ if (war > 0)
+ {
+ sprintf(linet2,"%1lu Warning",war); strcat(linet1,linet2);
+ strcat(linet1,sing(war,"","s"));
+ }
+
+ /* The final full stop! */
+ strcat(linet1,".");
+}
+
+/******************************************************************************/
+
+LOCAL void allocarg P_((void));
+LOCAL void allocarg()
+/* Some compilers don't allow much room for statics and so it is necessary to */
+/* declare some variables as pointers and allocate them explicitly. This */
+/* function allocates the command line argument array to point to strings. */
+{
+ uword i;
+ for (i=0;i<=ARG_FWMAX;i++)
+ arg_arr[i]=(char *) mm_perm(sizeof(cl_t));
+
+ /* Also initialize the substitution strings. */
+ for (i=0;i<NUM_SUBS;i++)
+ {
+ subval[i]=(char *) mm_perm(sizeof(cl_t));
+ subval[i][0]=EOS;
+ }
+ p_comopt=(p_op_t) mm_perm(sizeof(op_t));
+ p_defopt=(p_op_t) mm_perm(sizeof(op_t));
+}
+
+/******************************************************************************/
+
+LOCAL void zerdia P_((void));
+LOCAL void zerdia()
+{
+ old_war=num_war;
+ old_err=num_err;
+ old_sev=num_sev;
+ num_sev=num_err=num_war=0;
+}
+
+LOCAL void sumdia P_((void));
+LOCAL void sumdia()
+{
+ sum_sev+=num_sev;
+ sum_err+=num_err;
+ sum_war+=num_war;
+}
+
+LOCAL void restdia P_((void));
+LOCAL void restdia()
+{
+ num_sev+=old_sev;
+ num_err+=old_err;
+ num_war+=old_war;
+}
+
+/******************************************************************************/
+
+LOCAL void explode P_((char *));
+LOCAL void explode(p)
+/* Parses the string p into a set of non-blank sequences. Copies each */
+/* distinct run of non-blanks into successive values of arg_arr. Places the */
+/* number of runs of non-blanks into arg_num. DOESN'T generate an error if */
+/* there are too many arguments. */
+char *p;
+{
+ arg_num=0;
+ while (TRUE)
+ {
+ char *x;
+
+ /* Skip to the next argument. */
+ while (*p==' ') p++;
+
+ /* Exit if we have hit the end of the string. */
+ if (*p==EOS) break;
+
+ /* Exit if we are already full up with arguments. */
+ if (arg_num==ARG_FWMAX) break;
+
+ /* Copy the next argument. */
+ x=arg_arr[arg_num];
+ while (*p!=' ' && *p!=EOS) *x++ = *p++;
+ *x=EOS;
+ arg_num++;
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void dollsub P_((char *));
+LOCAL void dollsub(p_comlin)
+/* Assumes that it's string argument is in a command line object. */
+/* Performs dollar substitutions. */
+char *p_comlin;
+{
+ char *p=p_comlin;
+ cl_t cl;
+ char *t;
+
+ t = &cl[0];
+
+ /* Copy the unexpanded command line to the temporary from which we expand it */
+ /* back from whence it came. */
+ strcpy(t,p);
+
+ /* Work through the unexpanded command line expanding. */
+ while (*t != EOS)
+ {
+ /* Complain if there is not room for one more character. */
+ if ((p-p_comlin) == COMLINE_FWMAX) goto toobig;
+
+ /* If no dollar sign, no tricks. Just copy the character over. */
+ if (*t!='$') {*p++ = *t++; continue;}
+
+ /* We have seen a dollar sign. Move onto the next character. */
+ t++;
+
+ /* The only legal escapes are decimal digits, slash, and the dollar sign. */
+ if (!isdigit(*t) && !isupper(*t) && *t!='$' && *t!='/')
+ {
+ wl_sj("S: Illegal dollar subtitution sequence in command line.");
+ wl_sj("Legal sequences are $0..$9, $A..$Z, $/, and $$.");
+ num_sev++;
+ strcpy(p,t);
+ return;
+ }
+
+ /* A dollar escape is easy to process. */
+ if (*t=='$') {*p++ = *t++; continue;}
+
+ /* A slash escape is easy to process. */
+ if (*t=='/') {*p++ = FN_DELIM; t++; continue;}
+
+ /* Substitutions have to be expanded. */
+ if (isdigit(*t) || isupper(*t))
+ {
+ ubyte num;
+ char *q;
+ if (isdigit(*t))
+ num = *t-'0';
+ else
+ num = 10+(*t-'A');
+ as_cold(num<NUM_SUBS,"dollsub: num is too bug!");
+ q=subval[num];
+ if ((p-p_comlin)+strlen(subval[num]) > COMLINE_FWMAX) goto toobig;
+ while (*q!=EOS) *p++ = *q++;
+ t++;
+ }
+ }
+ *p=EOS;
+ return;
+
+ toobig:
+ wl_sj("S: Expanded (i.e. after $1 etc) command line is too long.");
+ num_sev++;
+ strcpy(p,t);
+ return;
+}
+
+/******************************************************************************/
+
+LOCAL void fwonerun P_((void));
+LOCAL void fwonerun()
+/* Performs a single run of FunnelWeb proper, using the global variable */
+/* 'options' as the input command line. */
+{
+ fn_t lisnam;
+
+ /* The following clocks record the time taken by various parts of FunnelWeb. */
+ ck_t mappck;
+ ck_t scanck;
+ ck_t parsck;
+ ck_t analck;
+ ck_t dumpck;
+ ck_t lstrck;
+ ck_t tangck;
+ ck_t weavck;
+ ck_t totlck;
+
+ /* Intialize/zero all the clocks. */
+ ck_ini(&mappck);
+ ck_ini(&scanck);
+ ck_ini(&parsck);
+ ck_ini(&analck);
+ ck_ini(&dumpck);
+ ck_ini(&lstrck);
+ ck_ini(&tangck);
+ ck_ini(&weavck);
+ ck_ini(&totlck);
+
+ /* Start the total time clock ticking. A total time clock is used to gather */
+ /* up the gaps between the invocations of the other clocks. */
+ ck_start(&totlck);
+
+ ck_start(&lstrck);
+
+ /* Establish the listing file output stream. */
+ strcpy(lisnam,""); /* Start with an empty string. */
+ fn_ins(lisnam,option.op_f_s); /* Insert input file name. */
+ fn_ins(lisnam,".lis"); /* Insert constant extension. */
+ fn_ins(lisnam,option.op_l_s); /* Insert command line spec. */
+ wf_ini(&f_l,option.op_l_b); /* Initialize the stream. */
+ wf_ope(&f_l,lisnam); /* Create the file. */
+ if (option.op_l_b && wf_err(&f_l))
+ {
+ sprintf(linet1,"S: Error creating listing file \"%s\".",lisnam);
+ wl_sj(linet1);
+ wl_sj("Aborting...");
+ num_sev++;
+ return;
+ }
+
+ wl_l("FUNNELWEB LISTING FILE");
+ wl_l("======================");
+ wl_l("");
+
+ /* Initialize the lister for this run. */
+ lr_ini();
+
+ ck_stop(&lstrck);
+
+ /* Scanner comes first. */
+ ck_start(&scanck);
+ scanner(&mappck,&scanck);
+ ck_stop(&scanck);
+
+ /* Dump the line and token lists if requested. The scanner supplies sensible */
+ /* lists even if it encounters errors, so there is no danger here. */
+ ck_start(&dumpck);
+ if (option.op_b2_b) dm_lnls(&f_l);
+ if (option.op_b3_b) dm_tkls(&f_l);
+ ck_stop(&dumpck);
+
+ /* Invoke the parser if there were no serious scanner errors. */
+ if (num_sev+num_err==0)
+ {
+ ck_start(&parsck);
+ parser();
+ ck_stop(&parsck);
+ /* Only perform post parser dumps if the parser was run. */
+ ck_start(&dumpck);
+ if (option.op_b4_b) dm_matb(&f_l);
+ if (option.op_b5_b) dm_dcls(&f_l);
+ ck_stop(&dumpck);
+ }
+ else
+ {
+ if (option.op_b4_b)
+ wl_l("Macro table dump skipped (Parser was not invoked).");
+ if (option.op_b5_b)
+ wl_l("Document list dump skipped (Parser was not invoked).");
+ }
+
+ /* Invoke the macro structure analyser if still no errors. */
+ if (num_sev+num_err==0)
+ {
+ ck_start(&analck);
+ analyse();
+ ck_stop(&analck);
+ }
+
+ /* The scanner, parser, and analyser send errors to the lister package. */
+ /* Send sorted listing to the listing file (and screen if desired). */
+ ck_start(&lstrck);
+ if (option.op_l_b) lr_gen(&f_l,option.op_c_i);
+ if (option.op_s_b) lr_gen(&f_s,option.op_s_i);
+ if (option.op_s_b) lr_gen(&f_j,option.op_s_i);
+ ck_stop(&lstrck);
+
+ /* If the first stages went OK, invoke tangle and weave. */
+ if (num_sev+num_err==0)
+ {
+ if (option.op_o_b)
+ {
+ ck_start(&tangck);
+ tangle();
+ ck_stop(&tangck);
+ }
+ if (option.op_t_b)
+ {
+ ck_start(&weavck);
+ weave();
+ ck_stop(&weavck);
+ }
+ /* Leave output lines from Tangle and Weave joined, but separate them */
+ /* from any further output. */
+ if (option.op_t_b || option.op_o_b)
+ wl_sjl("");
+ }
+ else
+ {
+ /* Otherwise tell the user that back-end phases will be skipped. */
+ if ( option.op_o_b || option.op_t_b)
+ {
+ if (num_sev+num_err==1)
+ wr_sjl("Error caused ");
+ else
+ wr_sjl("Errors caused ");
+ }
+ if ( option.op_o_b && option.op_t_b) wr_sjl("tangle and weave phases");
+ if ( option.op_o_b && !option.op_t_b) wr_sjl("tangle phase");
+ if (!option.op_o_b && option.op_t_b) wr_sjl("weave phase");
+ if ( option.op_o_b || option.op_t_b)
+ {wl_sjl(" to be skipped."); wl_sjl("");}
+ }
+
+ ck_stop(&totlck);
+
+ /* If requested write out a summary of the time taken. */
+ if (option.op_b6_b)
+ dm_times(&f_l,
+ &mappck,&scanck,&parsck,&analck,
+ &dumpck,&lstrck,&tangck,&weavck,&totlck);
+
+ /* Write out a line summarizing the diagnostics for this run. */
+ errsum(0L,num_sev,num_err,num_war); wl_sjl(linet1);
+
+ /* Close the listing file. */
+ if (!option.op_l_b) goto finishoff;
+ if (wf_err(&f_l))
+ {
+ wl_sj("S: Error writing to listing file. Aborting...");
+ num_sev++;
+ goto finishoff;
+ }
+ wf_clo(&f_l);
+ if (wf_err(&f_l))
+ {
+ wl_sj("S: Error flushing and closing listing file. Aborting...");
+ num_sev++;
+ }
+
+ finishoff:
+ /* VERY IMPORTANT: Ask the memory management package to free up all the */
+ /* temporary memory (allocated using mm_temp) that has been allocated. This */
+ /* ensures that the memory allocated for this FunnelWeb run will be recycled.*/
+ mm_zapt();
+
+} /* End of fwonerun */
+
+/******************************************************************************/
+
+LOCAL void do_absen P_((void));
+LOCAL void do_absen ()
+{
+ if (arg_num != 2)
+ {
+ wl_sj("S: The ABSENT command requires exactly one argument.");
+ num_sev++;
+ return;
+ }
+ if (fexists(arg_arr[1]))
+ {
+ sprintf(linet1,"S: ABSENT found \"%s\".",arg_arr[1]);
+ wl_sj(linet1);
+ num_sev++;
+ return;
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void do_cody P_((void));
+LOCAL void do_cody ()
+/* The CODIFY command takes an input text file and generates an output text */
+/* file containing C code to write out the input text file. The need for this */
+/* command springs from the weaver. Experience with FunnelWeb showed that use */
+/* of a separate header file, to be included, while apparently sensible, */
+/* caused no end of problems. In particular, problems with portably */
+/* specifying where the header file should be found. In the end, it was */
+/* decided that it would be better to write the header file out with the */
+/* weave output. As the header file is quite long, it is best to automate the */
+/* process of converting the file from text to C code to write out the text. */
+/* That is what the CODIFY command does. */
+{
+ FILE *file1;
+ FILE *file2;
+
+#define MAXHACK 1000
+ char hackline[MAXHACK+1];
+ uword lineno;
+
+ if (arg_num != 3)
+ {
+ wl_sj("S: The CODIFY command requires exactly two arguments.");
+ num_sev++;
+ return;
+ }
+
+ /* Open the input file for text reading. */
+ file1=fopen(arg_arr[1],"r");
+ if (file1 == FOPEN_F)
+ {
+ wl_sj("S: Error opening the input file.");
+ num_sev++;
+ return;
+ }
+ file2=fopen(arg_arr[2],"w");
+ if (file2 == FOPEN_F)
+ {
+ fclose(file1);
+ wl_sj("S: Error creating the output file.");
+ num_sev++;
+ return;
+ }
+
+ lineno=0;
+
+ /* PROCESS A SINGLE LINE PER ITERATION. */
+ while (TRUE)
+ {
+ uword linelength;
+ uword i;
+
+ /* Read in a line of input and terminate loop if there are no more lines. */
+ fgets(hackline,MAXHACK,file1);
+ if (ferror(file1))
+ {wl_sj("S: Error reading the input file.");num_sev++;return;}
+ if (feof(file1)) break;
+ lineno++;
+
+ /* Complain if the input line is too long. */
+ if (strlen(hackline)>81)
+ {
+ sprintf(linet1,"Line %lu of input file is too long.",
+ (ulong) strlen(hackline));
+ wl_sj(linet1);
+ wl_sj("The maximum allowable length is 80 characters.");
+ num_sev++;
+ return;
+ }
+
+ /* Write the start-of-line string. */
+ if (fputs(" WX(\"",file2) == FPUTS_F) goto write_failure;
+
+ /* Write out the line in sanitized form. */
+ linelength=strlen(hackline);
+ for (i=0;i<linelength;i++)
+ {
+ char ch = hackline[i];
+ if (ch==EOL)
+ ; /* Ignore this. */
+ else
+ if (ch=='\"')
+ {if (fputs("\\\"",file2) == FPUTS_F) goto write_failure;}
+ else
+ if (ch=='\\')
+ {if (fputs("\\\\",file2) == FPUTS_F) goto write_failure;}
+ else
+ {if (fputc(ch,file2) == FPUTC_F) goto write_failure;}
+ }
+
+ /* Write the end of line string. */
+ if (fputs("\");\n",file2) == FPUTS_F) goto write_failure;
+ }
+
+ if (fflush(file2) != FFLUSH_S)
+ {wl_sj("S: Error flushing the output file.");num_sev++;return;}
+ if (fclose(file1) == FCLOSE_F)
+ {wl_sj("S: Error closing the input file.");num_sev++;return;}
+ if (fclose(file2) == FCLOSE_F)
+ {wl_sj("S: Error closing the output file.");num_sev++;return;}
+ return;
+
+ write_failure:
+ wl_sj("S: Error writing the output file.");num_sev++;return;
+}
+
+/******************************************************************************/
+
+LOCAL void do_comp P_((void));
+LOCAL void do_comp ()
+/* The compare command should have two arguments being file names. It */
+/* compares the two files and raises a fatal error if they differ. */
+{
+ char *errstr;
+ bool result;
+ if (arg_num != 3)
+ {
+ wl_sj("S: COMPARE command must be given exactly two arguments.");
+ num_sev++;
+ return;
+ }
+ errstr=eq_files(arg_arr[1],arg_arr[2],&result);
+ if (errstr!=NULL)
+ {
+ wl_sj("S: COMPARE command ran into a problem:");
+ wl_sj(errstr);
+ num_sev++;
+ return;
+ }
+ if (!result)
+ {
+ wl_sj("S: A comparison FAILED. Two files compared were not identical!");
+ sprintf(linet1," File1: \"%s\".",arg_arr[1]); wl_sj(linet1);
+ sprintf(linet1," File2: \"%s\".",arg_arr[2]); wl_sj(linet1);
+ wl_sj(" FunnelWeb has just FAILED a regression test.");
+ wl_sj(" You should now inspect the two files to see how the result of");
+ wl_sj(" this run of FunnelWeb differed from the \"correct answer\" in");
+ wl_sj(" the answer directory.");
+ num_sev++;
+ return;
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void do_defin P_((char *));
+LOCAL void do_defin (p_comlin)
+/* The define command associates a string with a $n. */
+char *p_comlin;
+{
+ char *p;
+ ubyte defnum;
+
+ /* p is our scanning pointer and starts at the start of the command line. */
+ p=p_comlin;
+
+ /* Skip past the DEFINE command onto the second argument. */
+ while ((*p!=' ') && (*p!=EOS)) p++;
+ while (*p==' ') p++;
+
+ /* There should be a single digit or upper case letter there. */
+ if (!isdigit(*p) && !isupper(*p))
+ {wl_sj("S: The first argument to DEFINE must be a decimal digit or");
+ wl_sj(" upper case letter.");
+ wl_sj(" Example: define 3 \"A Walrus in Spain is a Walrus in Vain.\"");
+ num_sev++;return;}
+ if (isdigit(*p))
+ defnum = *p-'0';
+ else
+ defnum = 10+(*p-'A');
+ as_cold(defnum<NUM_SUBS,"do_defin: num is too bug!");
+
+ /* Move past the digit. */
+ p++;
+
+ /* Skip blanks to get to the next argument. */
+ while (*p==' ') p++;
+
+ /* Complain if there is no second argument. */
+ if (*p==EOS)
+ {wl_sj("S: The DEFINE command expected a second argument.");
+ num_sev++; return;}
+
+ /* Otherwise make sure that we have a double quoted string. */
+ if (*p!='"' || *(p+1)==EOS || p[strlen(p)-1]!='"')
+ {wl_sj("S: Second argument to DEFINE must be in double quotes.");
+ num_sev++;return;}
+
+ /* All is checked. Now it is safe to copy over the string. */
+ p++;
+ strcpy(subval[defnum],p);
+ subval[defnum][strlen(subval[defnum])-1]=EOS;
+
+ /* TRACE: All the definitions.
+ {
+ ubyte i;
+ for (i=0;i<NUM_SUB;i++)
+ printf("$%u=\"%s\"\n",(unsigned) i,subval[i]);
+ }
+ */
+}
+
+/******************************************************************************/
+
+LOCAL void do_diff P_((void));
+/* COMMAND FORMAT: diff file1 file2 logfile [abort] */
+/* This function/command performs a proper text differences on two files. */
+/* This function is long and messy because of C's lack of nested functions. */
+/* I don't want to create global variables here, and defining subfunctions */
+/* that do not have access to the variables of this function would provoke */
+/* too wide an interface to be worth the trouble. So it's code city. */
+/* How I wish that I had FunnelWeb to help me write this function! */
+LOCAL void do_diff()
+{
+ bool diffabort; /* TRUE iff we should abort if files are different. */
+ bool is_same = FALSE; /* True iff files are proven to be the same. */
+ FILE *logfile; /* File to write result of comparison. */
+ bool badwrite = FALSE; /* TRUE if we couldn't write to the logfile. */
+ char *p_file1; /* Pointer to mapping of first file to compare. */
+ char *p_file2; /* Pointer to mapping of second file to compare. */
+ ulong len_file1; /* Number of bytes in mapping of first file. */
+ ulong len_file2; /* Number of bytes in mapping of second file. */
+ char *mess1; /* Error message from mapper for first file. */
+ char *mess2; /* Error message from mapper for second file. */
+ bool is_image; /* TRUE iff mapped images are identical. */
+ bool anydiff = FALSE; /* TRUE iff any differences detected during loop. */
+
+ /* Check that the number of arguments is correct. */
+ if (arg_num < 4 || arg_num > 5)
+ {
+ wl_sj("S: The DIFF command must be given either 3 or 4 arguments.");
+ wl_sj(" Usage: diff f1 f2 logfile [abort]");
+ num_sev++;
+ return;
+ }
+
+ /* Check that the fourth argument, if present, is legal. */
+ diffabort=FALSE;
+ if (arg_num == 5)
+ if (strcmp(arg_arr[4],"ABORT")==0 || strcmp(arg_arr[4],"abort")==0)
+ diffabort=TRUE;
+ else
+ {
+ wl_sj(
+ "S: The DIFF command's fourth argument, if present, must be ABORT.");
+ wl_sj(" Usage: diff f1 f2 logfile [abort]");
+ num_sev++;
+ return;
+ }
+
+ /* Now open the log file to append result of compare. */
+ logfile=fopen(arg_arr[3],"a");
+ if (logfile == FOPEN_F)
+ {
+ wl_sj("S: DIFF: Error opening the log file (to append result of compare).");
+ num_sev++;
+ return;
+ }
+
+ /* The following define simplifies writing to the log file. */
+#define LOGLINE {if (fputs(linet1,logfile) == FPUTS_F) badwrite=TRUE;}
+#define LOGSTR(STR) {if (fputs((STR),logfile) == FPUTS_F) badwrite=TRUE;}
+#define LOGCHAR(CH) {if (fputc((CH),logfile) == FPUTC_F) badwrite=TRUE;}
+
+ /* Write the header for this comparison to the log file. */
+ sprintf(linet1,"\n\n" ); LOGLINE;
+ sprintf(linet1,"Comparing \"%s\"\n" ,arg_arr[1]); LOGLINE;
+ sprintf(linet1," with \"%s\".\n",arg_arr[2]); LOGLINE;
+
+ /* Now map in the two files to be compared. */
+ /* Once this is done, we MUST do a mm_zapt later or memory will leak. */
+ /* We attempt to map the second file, even if the first mapping has failed */
+ /* as, if the first file is absent, there is a good chance that the second */
+ /* is absent too, and it is useful to the user to know this. */
+ mess1=map_file(arg_arr[1],&p_file1,&len_file1);
+ mess2=map_file(arg_arr[2],&p_file2,&len_file2);
+ if (mess1 != NULL)
+ {
+ sprintf(linet1,"Error mapping \"%s\".\n",arg_arr[1]); LOGLINE;
+ wr_sj("E: DIFF: "); wr_sj(linet1);
+ sprintf(linet1," %s\n",mess1); LOGLINE; wr_sj(linet1);
+ num_err++;
+ }
+ if (mess2 != NULL)
+ {
+ sprintf(linet1,"Error mapping \"%s\".\n",arg_arr[2]); LOGLINE;
+ wr_sj("E: DIFF: "); wr_sj(linet1);
+ sprintf(linet1," %s\n",mess2); LOGLINE; wr_sj(linet1);
+ num_err++;
+ }
+ if ((mess1 != NULL) || (mess2 != NULL))
+ goto frombadmap;
+
+ /* At this point the two files to be compared are sitting in memory and we */
+ /* have a ready-for-writing log file. We are now ready to compare. */
+
+ /* First perform a binary image comparison as a check for later. */
+ /* We could do this later, but it is better to do this now, in case the */
+ /* complicated comparison code somehow corrupts one of the images. */
+ is_image= ((len_file1 == len_file2) &&
+ (memcmp(p_file1,p_file2,(size_t) len_file1) == 0));
+
+ /* This anonymous block performs the actual comparison. */
+ {
+ /* The comparison is performed by scrolling the two input files through two */
+ /* fixed-length line buffers (buf1 and buf2 - see below). To avoid copying, */
+ /* the buffers are made circular. Processing takes place by comparing the */
+ /* first line of each buffer. If the line is the same, the buffers are */
+ /* scrolled by one line. If they are different, then we have encountered a */
+ /* DIFFERENCES SECTION and we have to compare lines near the top of the */
+ /* buffers to find a match. When a match is found, each buffer is scrolled */
+ /* down to its match point and processing continues. */
+
+/* LBUFSIZ is the number of number of lines that each buffer can hold. */
+/* Lines are indexed from [0,LBUFSIZ-1]. */
+/* WARNING: LBUFSIZ must be a power of two corresponding to WRAP(X). */
+/* WARNING: Totally different input files will provoke O(LBUFSIZ^2) */
+/* checksum comparisons per LBUFSIZ input lines. */
+/* WRAP(X) is a macro that performs wraparound of buffer indices. */
+/* GAP is the number of lines that have to match to end a diff section. */
+/* MAXDIST is the maximum "distance" that is tested when matching. */
+#define LBUFSIZ 64
+#define WRAP(X) ((X) & 0x3F)
+#define GAP 3
+#define MAXDIST (LBUFSIZ-GAP)
+
+/* The following macro compares two lines in the buffers. */
+/* The arguments are absolute buffer indices, not relative ones. */
+/* We assume that checksums will mismatch more often than line lengths. */
+#define COMPLINE(INDA,INDB) \
+ ((buf1[INDA].c_line == buf2[INDB].c_line) && \
+ (buf1[INDA].l_line == buf2[INDB].l_line) && \
+ (memcmp(buf1[INDA].p_line,buf2[INDB].p_line, \
+ (size_t) buf1[INDA].l_line)==0))
+
+ /* The two line buffers buf1 and buf2 (see below) don't actually store */
+ /* lines. Instead they store line structures which store pointers to the */
+ /* lines in the mapped images of the files. They also store the length of */
+ /* each line, and a checksum of the line. The checksum is useful for */
+ /* speeding up the comparisons between lines when processing a differences */
+ /* section. */
+ typedef
+ struct
+ {
+ char *p_line; /* Pointer to first byte in the line. */
+ ulong l_line; /* Number of bytes in the line. */
+ uword c_line; /* Checksum of the line. */
+ } line_t;
+
+ char *p_next1 = p_file1; /* Points to next line in file1. */
+ char *p_next2 = p_file2; /* Points to next line in file2. */
+ char *p_post1 = p_file1+len_file1; /* Byte following image of file1. */
+ char *p_post2 = p_file2+len_file2; /* Byte following image of file2. */
+ line_t buf1[LBUFSIZ]; /* Comparison buffer for first file. */
+ line_t buf2[LBUFSIZ]; /* Comparison buffer for second file. */
+ ulong buf1top = 0; /* Index of first line in first buffer. */
+ ulong buf2top = 0; /* Index of first line in second buffer. */
+ ulong buf1fil = 0; /* Number of lines in first buffer. */
+ ulong buf2fil = 0; /* Number of lines in second buffer. */
+ ulong topnum1 = 1; /* Line number of first line of first buffer. */
+ ulong topnum2 = 1; /* Line number of first line of second buffer. */
+
+ /* The following loop compares the line(s) at the top of the two buffers */
+ /* and processes (lines1,lines2) lines of each. */
+ while (TRUE)
+ {
+ ulong lines1; /* Lines of file1 processed during this loop iteration. */
+ ulong lines2; /* Lines of file2 processed during this loop iteration. */
+ ulong d,g; /* Used in comparison loops. */
+
+ /* The first thing we do is to fill each buffer as full as possible. At */
+ /* the end of the next two lumps of code, the only reason that a file's */
+ /* is not full is that we have reached the end of the file. */
+
+ /* Fill the first buffer as full as possible. */
+ while ((buf1fil < LBUFSIZ) && (p_next1 != p_post1))
+ {
+ ulong ind = WRAP(buf1top + buf1fil);
+ ulong len = 0;
+ uword csum = 0;
+ char *p_lin = p_next1;
+ while (TRUE)
+ {
+ if (p_next1 == p_post1) break;
+ len++;
+ csum=(csum+*p_next1++) & 0xFFFF;
+ if (*(p_next1-1) == EOL) break;
+ }
+ buf1[ind].p_line = p_lin;
+ buf1[ind].l_line = len;
+ buf1[ind].c_line = csum;
+ buf1fil++;
+ }
+
+ /* Fill the second buffer as full as possible. */
+ while ((buf2fil < LBUFSIZ) && (p_next2 != p_post2))
+ {
+ ulong ind = WRAP(buf2top + buf2fil);
+ ulong len = 0;
+ uword csum = 0;
+ char *p_lin = p_next2;
+ while (TRUE)
+ {
+ if (p_next2 == p_post2) break;
+ len++;
+ csum=(csum+*p_next2++) & 0xFFFF;
+ if (*(p_next2-1) == EOL) break;
+ }
+ buf2[ind].p_line = p_lin;
+ buf2[ind].l_line = len;
+ buf2[ind].c_line = csum;
+ buf2fil++;
+ }
+
+ /* If the buffers are empty then we must be at the end of each file. */
+ if (buf1fil==0 && buf2fil==0)
+ break;
+
+ /* Try to peel a pair of matching lines off the top of the buffer. */
+ /* If we succeed, zip down to the end of the loop and flush them. */
+ /* We can't integrate this code into the next part because the next part */
+ /* requires GAP matches, whereas here we require just one. */
+ if ((buf1fil>0) && (buf2fil>0) && COMPLINE(buf1top,buf2top))
+ {lines1=lines2=1; goto flushlines;}
+
+ /* At this point, we know we have a differences section. */
+ anydiff=TRUE;
+
+ /* We now compare the top lines of the two buffers for a match. A match */
+ /* is only considered to have been found if we match GAP consecutive */
+ /* lines. The best match minimizes the DISTANCE which is the sum of the */
+ /* offsets (lines1,lines2) (in lines) from the top of each buffer where */
+ /* the match starts. Even better matches minimize abs(lines1-lines2) as */
+ /* well. All these nested loops are to ensure that we search best first. */
+ for (d=1;d<=MAXDIST;d++)
+ {
+ /* Calculate half distance on the high side. */
+ long half = (d/2)+1;
+ long off;
+ long sign_v;
+ /* Explore up and down simultaneously from the halfway mark. */
+ for (off=0;off<=half;off++)
+ for (sign_v= -1;sign_v<2;sign_v+=2)
+ {
+ long x = half + sign_v*off;
+ /* The following test allows the above loops to be sloppy. */
+ if (0<=x && x<=d)
+ {
+ lines1=x;
+ lines2=d-lines1;
+ /* We now know that we want to test at (lines1,lines2). */
+ /* So compare the GAP lines starting at those positions. */
+ /* Note: lines1 and lines2, as well as being the number */
+ /* of lines processed, are also the offset to the first */
+ /* match line in our match gap. */
+ for (g=0;g<GAP;g++)
+ { /* Note: R for relative, A for absolute. */
+ ulong t1r = lines1 + g;
+ ulong t2r = lines2 + g;
+ ulong t1a,t2a;
+
+ /* If both files have run out at this point, it's a match!*/
+ if ((t1r>=buf1fil) && (t2r>=buf2fil)) continue;
+
+ /* If just one of the files has run out it's a mismatch. */
+ if ((t1r>=buf1fil) || (t2r>=buf2fil)) goto gapfail;
+
+ /* We now know that we have two real lines. Compare them. */
+ /* Variables are to avoid big nested macro expansions. */
+ t1a = WRAP(buf1top+t1r);
+ t2a = WRAP(buf2top+t2r);
+ if (!COMPLINE(t1a,t2a)) goto gapfail;
+ }
+ /* If we dropped out of the gap loop, we must have found */
+ /* GAP consecutive matches. So we can run off and write out */
+ /* the difference section. */
+ goto writediff;
+
+ /* Here's where we jump if we found a mismatch during gap */
+ /* looping. All we do is try next pair of offsets. */
+ gapfail:;
+ } /* End sloppy if. */
+ } /* End for sign_v. */
+ } /* End for distance loop. */
+
+ /* If we got to here then we must have dropped out of the search loop */
+ /* which means that there must have been no match at all between the */
+ /* buffers. The only thing to do is to write out what we have as */
+ /* a differences section. */
+ lines1=buf1fil;
+ lines2=buf2fil;
+
+ /* Write out the differences section (lines1,lines2) to the log file. */
+ writediff:
+ { /* Begin writediff */
+ ulong i,j;
+ LOGSTR("\n");
+ LOGSTR(" +-----\n");
+ for (i=0;i<lines1;i++)
+ {
+ ulong nline = WRAP(buf1top+i);
+ sprintf(linet1,"%05lu|",(ulong) topnum1+i); LOGLINE;
+ for (j=0;j<buf1[nline].l_line;j++)
+ LOGCHAR(*(buf1[nline].p_line+j));
+ }
+ LOGSTR(" +-----\n");
+ for (i=0;i<lines2;i++)
+ {
+ ulong nline = WRAP(buf2top+i);
+ sprintf(linet1,"%05lu|",(ulong) topnum2+i); LOGLINE;
+ for (j=0;j<buf2[nline].l_line;j++)
+ LOGCHAR(*(buf2[nline].p_line+j));
+ }
+ LOGSTR(" +-----\n");
+ } /* End writediff. */
+
+ /* Flush from buffer however many lines we ended up processing. */
+ flushlines:
+ buf1top=WRAP(buf1top+lines1); topnum1+=lines1; buf1fil-=lines1;
+ buf2top=WRAP(buf2top+lines2); topnum2+=lines2; buf2fil-=lines2;
+
+ } /* End the while loop that runs through the two files. */
+ } /* End of anonymous block for doing actual comparison. */
+
+ /* The anydiff flag tells us if the loop found any difference sections. */
+ is_same=!anydiff;
+
+ /* Target position if we couldn't map in the input files earlier. */
+ frombadmap:
+
+ /* Release the memory allocated by the mapper for the input files. */
+ /* Failure to do this will result in a memory leak! */
+ mm_zapt();
+
+ /* If the two files are identical, tell the log file. */
+ if (is_same)
+ LOGSTR("The two files are IDENTICAL.\n");
+
+ /* Invalidate this test in the log file, if inconsistent (see later). */
+ if (is_same != is_image)
+ LOGSTR("<<CONSISTENCY FAILURE: ABOVE COMPARISON INVALID>>\n");
+
+ /* If we had problems with the log file at any stage, kick up a fuss now. */
+ if (badwrite)
+ {wl_sj("S: DIFF: Error writing to log file."); num_sev++;}
+
+ /* Close the log file. */
+ if (fclose(logfile) == FCLOSE_F)
+ {wl_sj("S: DIFF: Error closing the log file."); num_sev++;}
+
+ /* The above code is quite tricky and there is a chance that it contains */
+ /* bugs. So, as a safety check we compare the results from the binary memory */
+ /* image comparison performed earlier and the more complicated text */
+ /* comparison above. If they differ, then it's time to go kaboom. */
+ if (is_image && !is_same)
+ as_bomb("do_diff: Image comparison succeeded, but text comparison failed.");
+ if (!is_image && is_same)
+ as_bomb("do_diff: Image comparison failed, but text comparison succeeded.");
+
+ /* If files are non-same and ABORT option is turned on, set severe status. */
+ if (!is_same && diffabort)
+ {
+ wl_sj(
+ "S: DIFF: Files have not been proven identical, and ABORT option is on.");
+ num_sev++;
+ }
+
+ /* Tell the console whether comparison succeeded. */
+ if (is_same)
+ wl_sj("The two files are IDENTICAL.");
+ else
+ wl_sj("The two files are DIFFERENT (see the differences file for the details).");
+
+ /* Increment the difference summary counters. */
+ difftotl++;
+ if (is_same)
+ diffsucc++;
+}
+
+/******************************************************************************/
+
+LOCAL void do_dsum P_((void));
+LOCAL void do_dsum ()
+{
+ sprintf(linet1,"Summary of Differences"); wl_sj(linet1);
+ sprintf(linet1,"----------------------"); wl_sj(linet1);
+ sprintf(linet1,"Identical = %lu.",(ulong) diffsucc); wl_sj(linet1);
+ sprintf(linet1,"Different = %lu.",(ulong) (difftotl-diffsucc)); wl_sj(linet1);
+ sprintf(linet1,"Total = %lu.",(ulong) difftotl); wl_sj(linet1);
+}
+
+/******************************************************************************/
+
+LOCAL void do_dzer P_((void));
+LOCAL void do_dzer ()
+/* Zaps difference counters. */
+{
+ difftotl = 0;
+ diffsucc = 0;
+}
+
+/******************************************************************************/
+
+LOCAL void do_eneo P_((void));
+LOCAL void do_eneo ()
+{
+ if (arg_num != 2)
+ {
+ wl_sj("S: The ENEO command must be given exactly one argument.");
+ num_sev++;
+ return;
+ }
+ if (fexists(arg_arr[1]))
+ if (remove(arg_arr[1]) != REMOVE_S)
+ {
+ sprintf(linet1,"S: ENEO failed to delete \"%s\".",arg_arr[1]);
+ wl_sj(linet1);
+ num_sev++;
+ return;
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void do_exec P_((void));
+LOCAL void do_exec ()
+{
+ uword i;
+
+ if (arg_num < 2)
+ {
+ wl_sj("S: The EXECUTE command requires at least one argument.");
+ num_sev++;
+ return;
+ }
+ if (arg_num > 10)
+ {
+ wl_sj("S: The EXECUTE command can have at most nine arguments.");
+ num_sev++;
+ return;
+ }
+
+ /* Zap all the numeric arguments. */
+ for (i=0; i<10; i++)
+ subval[i][0]=EOS;
+
+ /* Copy the arguments over to the $1 $2 etc substitution variables. */
+ for (i=1;i<arg_num; i++)
+ strcpy(subval[i-1],arg_arr[i]);
+
+ /* Run up a new FunnelWeb shell and interpret the file. */
+ interstr(arg_arr[1]);
+}
+
+/******************************************************************************/
+
+LOCAL void do_exist P_((void));
+LOCAL void do_exist ()
+{
+ if (arg_num != 2)
+ {
+ wl_sj("S: The EXISTS command requires exactly one argument.");
+ num_sev++;
+ return;
+ }
+ if (!fexists(arg_arr[1]))
+ {
+ sprintf(linet1,"S: EXISTS failed to find \"%s\".",arg_arr[1]);
+ wl_sj(linet1);
+ num_sev++;
+ return;
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void do_fix P_((void));
+LOCAL void do_fix ()
+/* When the test suite is moved from one machine to another, it is possible */
+/* that at some stage it will be moved using a BINARY transfer rather than a */
+/* text file transfer. The result is that the test files will contain lines */
+/* terminated with a sequence of control characters that the local buffered */
+/* IO library will not convert to '\n' upon reading in. The are a few */
+/* solutions to this problem, but one of the most direct is to have a command */
+/* such as this one that can convert the file over. */
+/* */
+/* Once we have identified an end of line, it is easy to write it out as we */
+/* can just send a '\n' and the local buffered IO library will write the */
+/* right codes for us. The tricky part is deciding what an EOL is in the */
+/* input stream. Well, I could have made the control characters for the */
+/* remote EOL a parameter of this command, but instead I decided to use a */
+/* simple algorithm that should cover nearly all cases... */
+/* ALGORITHM: Parse the input into alternating blocks of control characters */
+/* and non-control characters. Parse each block of control characters into */
+/* subblocks by parsing it from left to right and starting a new subblock the */
+/* moment a character of the subblock currently being parsed appears again. */
+/* This covers at least the following cases, and probably many more: */
+/* UNIX LF */
+/* MSDOS CR LF */
+/* Macintosh CR */
+{
+ /* Erk! But I found out the hard way, it doesn't work on a VAX! */
+ /* I'm making this do nothing on a VAX rather than generate an error as I */
+ /* want the scripts to work silently on the VAX without modification. */
+#if !VMS
+ FILE *infile; /* File variable for input file. */
+ FILE *tmpfile; /* File variable for temporary output file. */
+ char *p_target; /* Name of final (target) output file. */
+ STAVAR char *p_temp=NULL; /* Name of temporary output file. */
+
+ bool seen[256]; /* TRUE if char is in current control sequence. */
+ char undo[256]; /* undo[0..length-1] contains current control sequence. */
+ uword length; /* Number of control bytes in our buffer. */
+ uword i;
+ int status;
+
+ /* Allocate the temporary file name if not already allocated. */
+ if (p_temp==NULL) p_temp=(p_fn_t) mm_perm(sizeof(fn_t));
+
+ /* We can take one or two arguments. One argument means that we should */
+ /* fix up the input file, leaving the result in the input file. */
+ if (arg_num != 2 && arg_num != 3)
+ {
+ wl_sj("S: The FIXEOLS command requires one or two filename arguments.");
+ num_sev++;
+ return;
+ }
+
+ /* Change to two arguments if the input name is the same as output name. */
+ if (arg_num==3 && strcmp(arg_arr[1],arg_arr[2])==0) arg_num=2;
+
+ /* Work out what the target name is going to be. */
+ p_target=(arg_num==2) ? arg_arr[1] : arg_arr[2];
+
+ /* Generate a temporary filename for the output file. This is tricky because */
+ /* on many machines, one cannot rename across devices or directories. This */
+ /* means that the temporary file has to be created in the same directory as */
+ /* the file that we are going to rename it to later (the target file). */
+ strcpy(p_temp,p_target);
+ fn_ins(p_temp,fn_temp());
+
+ /* Open the input file for BINARY reading. */
+ infile=fopen(arg_arr[1],"rb");
+ if (infile == FOPEN_F)
+ {
+ sprintf(linet1,"S: FIXEOLS: Error opening \"%s\".",arg_arr[1]);
+ wl_sj(linet1);
+ num_sev++;
+ return;
+ }
+
+ /* Create the output file for TEXT writing. */
+ tmpfile=fopen(p_temp,"w");
+ if (tmpfile == FOPEN_F)
+ {
+ fclose(infile);
+ wl_sj("S: FIXEOLS: Error creating the temporary output file.");
+ num_sev++;
+ return;
+ }
+
+ /* Initialialize the control character buffer to empty. */
+ for (i=0;i<256;i++) seen[i]=FALSE;
+ length=0;
+
+ while (TRUE)
+ {
+ /* Read in the next character from the input file. */
+ char ch=getc(infile);
+ if (ferror(infile))
+ {wl_sj("S: FIXEOLS: Error reading the input file.");num_sev++;return;}
+ if (feof(infile)) break;
+
+ /* Does character terminate a non-empty buffer? If so, flush it. */
+ if (length>0 && (isascprn(ch) || seen[ch]))
+ {
+ if (fputc(EOL,tmpfile) == FPUTC_F) goto write_failure;
+ for (i=0;i<length;i++) seen[undo[i]]=FALSE;
+ length=0;
+ }
+
+ /* Now we can approach the character cleanly and freshly. */
+ if (isascprn(ch))
+ {if (fputc(ch,tmpfile) == FPUTC_F) goto write_failure;}
+ else
+ {undo[length++]=ch; seen[ch]=TRUE;}
+ }
+ if (length>0)
+ {if (fputc(EOL,tmpfile) == FPUTC_F) goto write_failure;}
+
+ if (fflush(tmpfile) != FFLUSH_S)
+ {wl_sj("S: FIXEOLS: Error flushing the temporary output file.");num_sev++;return;}
+ if (fclose(infile) == FCLOSE_F)
+ {wl_sj("S: FIXEOLS: Error closing the input file.");num_sev++;return;}
+ if (fclose(tmpfile) == FCLOSE_F)
+ {wl_sj("S: FIXEOLS: Error closing the temporary output file.");num_sev++;return;}
+
+ /* If renaming to the input file, we have to delete the input file first. */
+ if (arg_num==2)
+ {
+ status=remove(arg_arr[1]);
+ if (status != REMOVE_S)
+ {
+ wl_sj("S: FIXEOLS: Error deleting existing input file to replace it");
+ wl_sj(" with the temporary output file. Deleting temporary and aborting...");
+ remove(p_temp);
+ num_sev++;
+ return;
+ }
+ }
+
+ /* Rename the temporary file to the target output file. */
+ status=rename(p_temp,p_target);
+
+ /* Do the error checking. */
+ if (status != RENAME_S)
+ {
+ wl_sjl("S: FIXEOLS: Error renaming temporary output file to output file.");
+ sprintf(linet1,"Temporary file name was \"%s\".",p_temp);
+ wl_sjl(linet1);
+ sprintf(linet1,"Output file name was \"%s\".",p_target);
+ wl_sjl(linet1);
+ wl_sjl("FunnelWeb will leave both files intact so you can look at them.");
+ num_sev++;
+ return;
+ }
+
+ return;
+
+ write_failure:
+ wl_sj("S: FIXEOLS: Error writing the output file.");num_sev++;return;
+#endif
+}
+
+/******************************************************************************/
+
+LOCAL void do_fweb P_((char *));
+LOCAL void do_fweb(p_cl)
+/* This function performs a single run of FunnelWeb proper. */
+char *p_cl;
+{
+ op_t saveop;
+
+ /* Do set can do all the work for us. However, it operates on p_defopt so we */
+ /* have to do some juggling. */
+ ASSIGN(saveop,*p_defopt);
+ do_set(p_cl);
+ ASSIGN(option,*p_defopt);
+ ASSIGN(*p_defopt,saveop);
+ if (num_sev>0) return;
+
+ /* do_set ensures that the user hasn't specified any action parameters such */
+ /* as +X and +K, but it necessarily doesn't check to make sure that the user */
+ /* has actually specified an input file! */
+ if (!option.op_f_b)
+ {
+ wl_sj("S: No input file specified in FW command.");
+ num_sev++;
+ return;
+ }
+ fwonerun();
+}
+
+/******************************************************************************/
+
+LOCAL void do_help P_((void));
+LOCAL void do_help()
+{
+ uword messno;
+
+ if (arg_num == 1)
+ {
+ hel_wri(wr_sj,HL_MEN);
+ return;
+ }
+ if (arg_num > 2)
+ {
+ wl_sj("S: The HELP command takes at most one argument.");
+ num_sev++;
+ return;
+ }
+
+ /* Translate message name to number. */
+
+ messno=hel_num(arg_arr[1]);
+ if (messno == HL_ERR)
+ {
+ wl_sj(
+ "S: Unrecognised help message name. Try just \"help\" for a list of names.");
+ num_sev++;
+ return;
+ }
+
+ hel_wri(wr_sj,messno);
+}
+
+/******************************************************************************/
+
+LOCAL void do_set(p_comlin)
+/* The SET command allows the user to specify default FunnelWeb options. */
+char *p_comlin;
+{
+ op_t tmpopt;
+
+ /* Experiment with temporary options, not the real thing. */
+ ASSIGN(tmpopt,*p_defopt);
+
+ /* Now execute the effect of the command line on 'p_defopt'. */
+ if (!op_add(&tmpopt,p_comlin,wr_sj))
+ {
+ wl_s("This is a severe error (S). Aborting to FunnelWeb shell...");
+ num_sev++;
+ return;
+ }
+
+ /* Now make sure that the user didn't specify an option to do with the */
+ /* entire FunnelWeb run and not just this invocation of FunnelWeb proper. */
+ if (tmpopt.op_j_b)
+ {
+ wl_s("S: You cannot invoke FunnelWeb with +J from the FunnelWeb shell.");
+ wl_s(" To create a journal file, exit FunnelWeb and reinvoke with \"fw +j\".");
+ wl_s("This is a severe error. Aborting to FunnelWeb shell...");
+ num_sev++;
+ return;
+ }
+ if (tmpopt.op_x_b)
+ {
+ wl_s("S: You cannot invoke FunnelWeb with +X from the FunnelWeb shell.");
+ wl_s("Use the interactive command EXECUTE instead.");
+ wl_s("This is a severe error. Aborting to FunnelWeb shell...");
+ num_sev++;
+ return;
+ }
+ if (tmpopt.op_k_b)
+ {
+ wl_s("S: You cannot invoke FunnelWeb with +K from the FunnelWeb shell.");
+ wl_s("This is a severe error. Aborting to FunnelWeb shell...");
+ num_sev++;
+ return;
+ }
+ if (tmpopt.op_h_b)
+ {
+ wl_s("S: You cannot invoke FunnelWeb with +H from the FunnelWeb shell.");
+ wl_s("Use the interactive command HELP instead.");
+ wl_s("This is a severe error. Aborting to FunnelWeb shell...");
+ num_sev++;
+ return;
+ }
+
+ /* If we get to here, the options must be OK so we can set them as default. */
+ ASSIGN(*p_defopt,tmpopt);
+}
+
+/******************************************************************************/
+
+LOCAL void do_show P_((void));
+LOCAL void do_show()
+/* The SHOW command writes out the current options. */
+{
+ if (arg_num != 1)
+ {
+ wl_sj("S: The SHOW command does not take arguments.");
+ num_sev++;
+ return;
+ }
+ wl_sj("Here are the FunnelWeb command line options that are");
+ wl_sj("current in this FunnelWeb session:");
+ op_wri(p_defopt,wr_sj);
+}
+
+/******************************************************************************/
+
+LOCAL void do_stat P_((void));
+LOCAL void do_stat ()
+/* The status command checks the number of diagnostics generated by the run. */
+{
+ uword i;
+ char *thing;
+ ulong cnum;
+
+ if (arg_num<1 || arg_num>4)
+ {
+ wl_sj("S: The STATUS command requires zero to three arguments.");
+ num_sev++;
+ return;
+ }
+
+ /* Zero arguments just means write out status. */
+ if (arg_num == 1)
+ {
+ sprintf(linet1,"Last command: Severes=%lu, Errors=%lu, Warnings=%lu.",
+ (ulong) old_sev, (ulong) old_err, (ulong) old_war);
+ wl_sj(linet1);
+ sprintf(linet1,"Totals : Severes=%lu, Errors=%lu, Warnings=%lu.",
+ (ulong) sum_sev, (ulong) sum_err, (ulong) sum_war);
+ wl_sj(linet1);
+ return;
+ }
+
+ /* More than one argument means CHECK status. */
+ for (i=1;i<arg_num;i++)
+ {
+ char ch=toupper(arg_arr[i][0]);
+ unsigned num;
+ if (ch!='W' && ch!='E' && ch!='S')
+ {
+ sprintf(linet1,
+ "S: Argument %u of STATUS command has bad letter.",
+ (unsigned) i);
+ wl_sj(linet1);
+ wl_sj("Arguments must be of the form ('W'|'E'|'S')<decimalnumber>.");
+ num_sev++;
+ return;
+ }
+ if (sscanf(&arg_arr[i][1],"%u",&num) != 1)
+ {
+ sprintf(linet1,
+ "S: Argument %u of STATUS command has bad number.",
+ (unsigned) i);
+ wl_sj(linet1);
+ wl_sj(" Arguments must be of the form ('W'|'E'|'S')<decimalnumber>.");
+ num_sev++;
+ return;
+ }
+ switch(ch)
+ {
+ case 'W': cnum=old_war; thing="warnings"; break;
+ case 'E': cnum=old_err; thing="errors" ; break;
+ case 'S': cnum=old_sev; thing="severes" ; break;
+ default : as_bomb("do_stat: case defaulted.");
+ }
+ if (cnum != num)
+ {
+ sprintf(linet1,
+ "S: STATUS command detected wrong number of %s.",thing);
+ wl_sj(linet1);
+ sprintf(linet1, "Specifed %s=%u, Actual %s=%u.",
+ thing,(unsigned) num,thing,(unsigned) cnum);
+ wl_sj(linet1);
+ num_sev++;
+ }
+ }
+}
+
+/******************************************************************************/
+
+
+LOCAL void do_trace P_((void));
+LOCAL void do_trace()
+{
+ if (arg_num != 2) goto help;
+ strupper(arg_arr[1]);
+ if (strcmp(arg_arr[1],"OFF") == 0) {tracing=FALSE; return;}
+ if (strcmp(arg_arr[1], "ON") == 0) {tracing=TRUE ; return;}
+
+ help:
+ wl_sj("S: The TRACE command has two forms:");
+ wl_sj(" TRACE OFF");
+ wl_sj(" TRACE ON");
+ num_sev++;
+ return;
+}
+
+/******************************************************************************/
+
+LOCAL void do_write P_((char *));
+LOCAL void do_write(p)
+char *p;
+{
+ uword len;
+
+ /* Skip over the main command and the following blanks. */
+ while (*p!=' ' && *p!=EOS) p++;
+ while (*p==' ') p++;
+
+ /* Now make sure that the remaining string is delimited by double quotes. */
+ len=strlen(p);
+ if ((*p != '\"') || (p[len-1] != '\"') || len<2)
+ {
+ wl_sj("W: The argument to WRITE should be delimited by double quotes.");
+ wl_sj(p);
+ num_war++;
+ return;
+ }
+
+ /* Now temporarily hack out the quotes and write out the string. */
+ p[len-1]=EOS;
+ wl_sj(p+1);
+ p[len-1]='\"';
+}
+
+/******************************************************************************/
+
+LOCAL void do_writu P_((char *));
+LOCAL void do_writu(p)
+char *p;
+{
+ uword len;
+
+ /* Skip over the main command and the following blanks. */
+ while (*p!=' ' && *p!=EOS) p++;
+ while (*p==' ') p++;
+
+ /* Now make sure that the remaining string is delimited by double quotes. */
+ len=strlen(p);
+ if ((*p != '\"') || (p[len-1] != '\"') || len<2)
+ {
+ wl_sj("W: The argument to WRITEU should be delimited by double quotes.");
+ wl_sj(p);
+ num_war++;
+ return;
+ }
+
+ /* Now temporarily hack out the quotes and write out the string. */
+ p[len-1]=EOS;
+ wl_sj(p+1);
+ p[len-1]='\"';
+
+ /* Now write out another line underlining the above. */
+ {uword i; for (i=0;i<len-2;i++) wr_sj("-"); wl_sj("");}
+}
+
+/******************************************************************************/
+
+LOCAL bool do_command P_((char *));
+LOCAL bool do_command(p_command)
+/* Execute a single FunnelWeb shell command. */
+char *p_command;
+{
+ char *v;
+ bool result=FALSE;
+
+ zerdia();
+
+ /* Check the command for non-printables. */
+ {
+ char *s=p_command;
+ while (*s!=EOS)
+ {
+ if (!isascprn(*s))
+ {
+ sprintf(linet1,
+ "S: Command line has non-printable at column %u.",
+ (unsigned) (s-p_command)+1);
+ wl_sj(linet1);
+ num_sev++;
+ goto finished;
+ }
+ s++;
+ }
+ }
+
+ /* Perform substitutions. */
+ dollsub(p_command); if (num_sev>0) goto finished;
+
+ /* Ignore commands consisting entirely of blanks (or empty commands). */
+ {
+ char *s=p_command;
+ while (*s==' ') s++;
+ if (*s==EOS) goto finished;
+ }
+
+ /* Reject command lines beginning with a blank. */
+ if (p_command[0]==' ')
+ {
+ wl_sj("S: Leading blanks are not allowed in command lines.");
+ num_sev++;
+ goto finished;
+ }
+
+ /* Ignore command lines commencing with the comment character. */
+ if (p_command[0]=='!')
+ {restdia(); goto finished;}
+
+ /* Parse the command line into arguments. */
+ explode(p_command);
+
+ /* Complain if there is no command verb. */
+ as_cold(arg_num>0,"do_command: zero arguments!");
+
+ /* It's convenient to have v pointing to verb. */
+ v=arg_arr[0];
+
+ /* Convert the verb to upper case. */
+ strupper(v);
+
+
+ /* Execute the verb. */
+
+ if (strcmp(v,"HERE")==0) skipping=FALSE;
+ else if (!skipping)
+ if (strcmp(v,"ABSENT" )==0) do_absen();
+ else if (strcmp(v,"CODIFY" )==0) do_cody ();
+ else if (strcmp(v,"COMPARE" )==0) do_comp ();
+ else if (strcmp(v,"DEFINE" )==0) do_defin(&p_command[0]);
+ else if (strcmp(v,"DIFF" )==0) do_diff();
+ else if (strcmp(v,"DIFFSUMMARY")==0) do_dsum();
+ else if (strcmp(v,"DIFFZERO" )==0) do_dzer();
+ else if (strcmp(v,"ENEO" )==0) do_eneo ();
+ else if (strcmp(v,"EXECUTE" )==0) do_exec ();
+ else if (strcmp(v,"EXISTS" )==0) do_exist();
+ else if (strcmp(v,"FIXEOLS" )==0) do_fix ();
+ else if (strcmp(v,"FW" )==0) do_fweb (&p_command[0]);
+ else if (strcmp(v,"HELP" )==0) do_help ();
+ else if (strcmp(v,"QUIT" )==0) result=TRUE;
+ else if (strcmp(v,"SET" )==0) do_set (&p_command[0]);
+ else if (strcmp(v,"SHOW" )==0) do_show ();
+ else if (strcmp(v,"SKIPTO" )==0) skipping=TRUE;
+ else if (strcmp(v,"STATUS" )==0) do_stat ();
+ else if (strcmp(v,"TOLERATE" )==0) noabort=TRUE;
+ else if (strcmp(v,"TRACE" )==0) do_trace();
+ else if (strcmp(v,"WRITE" )==0) do_write(&p_command[0]);
+ else if (strcmp(v,"WRITEU" )==0) do_writu(&p_command[0]);
+ else
+ {
+ /* The following trace is likely to confuse beginners. */
+ /* sprintf(linet1,"Expanded command line=\"%s\".",p_command); */
+ /* wl_sj(linet1); */
+ wl_sj("S: Unknown command. Type HELP for a list of commands.");
+ num_sev++;
+ goto finished;
+ }
+
+ finished:
+ sumdia();
+ return result;
+}
+
+/******************************************************************************/
+
+LOCAL void interpret P_((FILE *,char *));
+LOCAL void interpret(p_file,filnam)
+/* p_file must be a file opened for reading. The file's name must be supplied */
+/* in filnam for error reporting reasons. The function reads each line from */
+/* the file and feeds it to the FunnelWeb interpreter command executer. */
+FILE *p_file;
+char *filnam;
+{
+ ulong lineno=0;
+ char *result;
+ bool b;
+ cl_t comline;
+ char *p_comline;
+
+ p_comline = &comline[0];
+
+ while (TRUE)
+ {
+ bool oldnoabort = noabort;
+ noabort=FALSE;
+
+ if (p_file == stdin || tracing)
+ wr_sj("FunnelWeb>");
+
+ result=fgets(p_comline,(int) COMLINE_FWMAX,p_file);
+ if (feof(p_file))
+ {
+ sprintf(linet1,"<End of Script File \"%s\">",filnam);
+ if (p_file == stdin || tracing)
+ wl_sj(linet1);
+ break;
+ }
+ if (ferror(p_file) || (result == FGETS_FE))
+ {
+ sprintf(linet1,"F: Error reading command file \"%s\".",filnam);
+ wl_sj(linet1);
+ wl_sj("Aborting...");
+ sum_fat++;
+ return;
+ }
+ if (p_file == stdin || tracing) wr_j(p_comline);
+ if (p_file != stdin && tracing) wr_s(p_comline);
+
+ lineno++;
+ if (strlen(p_comline)==COMLINE_FWMAX)
+ {
+ sprintf(linet1,"F: Line %lu of command file \"%s\" is too long.",
+ (unsigned long) lineno,filnam);
+ wl_sj(linet1);
+ wl_sj("Aborting...");
+ sum_fat++;
+ return;
+ }
+ as_cold(p_comline[strlen(p_comline)-1]==EOL,"interpret: NO NEWLINE!");
+ p_comline[strlen(p_comline)-1]=EOS;
+ as_cold(strlen(p_comline)<COMLINE_FWMAX,"interpret: Filename too long.");
+
+ b=do_command(p_comline);
+ if (b) break;
+
+ if (sum_fat>0) break;
+ if ((p_file != stdin) && (num_sev+num_err>0) && !oldnoabort)
+ {
+ wl_sj("Error caused termination of FunnelWeb shellscript.");
+ break;
+ }
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void interstr(filnam)
+/* The 'interpret' function (above) interprets each line of a file already */
+/* opened for reading. This function does a little more, opening and closing */
+/* the file before and after calling 'interpret'. */
+char *filnam;
+{
+ FILE *p_file;
+ fn_t fn;
+
+ /* Set up a default of ".fws" as a file extension. */
+ strcpy(&fn[0],".fws");
+
+ /* Inherit the actual filename. */
+ as_cold(strlen(filnam)<=FILENAME_FWMAX,"interstr: Filename blasted.");
+ fn_ins(&fn[0],filnam);
+
+ p_file=fopen(fn,"r");
+ if (p_file == FOPEN_F)
+ {
+ sprintf(linet1,"S: Error opening command file \"%s\".",fn);
+ wl_sj(linet1);
+ sum_sev++;
+ return;
+ }
+
+ interpret(p_file,&fn[0]); if (sum_fat>0) return;
+
+ if (fclose(p_file) == FCLOSE_F)
+ {
+ sprintf(linet1,"F: Error closing command file \"%s\".",fn);
+ wl_sj(linet1);
+ wl_sj("Aborting...");
+ sum_fat++;
+ return;
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void chk_cline P_((void));
+LOCAL void chk_cline()
+/* Checks to make sure that the command line specifies exactly one action. */
+{
+ uword countopt=0;
+
+ /* Count the number of active action options are turned on. */
+ if (p_comopt->op_f_b) countopt++;
+ if (p_comopt->op_x_b) countopt++;
+ if (p_comopt->op_k_b) countopt++;
+ if (p_comopt->op_h_b) countopt++;
+
+ if (countopt == 0)
+ {
+ wl_sj("Your command line does not specify an action.");
+ wl_sj("Here some common ways of invoking FunnelWeb.");
+ wl_sj("");
+ wl_sj(" fw filename Tangle filename.web.");
+ wl_sj(" fw filename +t Tangle and weave filename.web.");
+ wl_sj(" fw +k Enter interactive mode.");
+ wl_sj(" fw +xfilename Execute FunnelWeb shellscript filename.fws.");
+ wl_sj(" fw +h Display help information about FunnelWeb.");
+ wl_sj("");
+ if (countopt == 0)
+ wl_sj("F: Aborting because command line does not specify an action.");
+ sum_fat++;
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void open_j P_((void));
+LOCAL void open_j()
+/* Creates and opens the journal file. Note that the journal output stream is */
+/* established regardless of whether the user requested a journal file. The */
+/* only difference is that if the user did not specify a journal file, the */
+/* stream is created in error mode which means that it never actually writes. */
+{
+ fn_t jname;
+
+ /* Establish the journal file output stream. */
+ strcpy(jname,""); /* Start with an empty string. */
+ fn_ins(jname,p_comopt->op_f_s); /* Insert input file name. */
+ fn_ins(jname,".jrn"); /* Insert file extension. */
+ fn_ins(jname,p_comopt->op_j_s); /* Insert command line spec. */
+ wf_ini(&f_j,p_comopt->op_j_b); /* Initialize the stream. */
+ wf_ope(&f_j,jname); /* Create the file. */
+ if (p_comopt->op_j_b && wf_err(&f_j))
+ {
+ sprintf(linet1,"F: Error creating journal file \"%s\".",jname);
+ wl_s(linet1);
+ wl_s("Aborting...");
+ sum_fat++;
+ return;
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void close_j P_((void));
+LOCAL void close_j()
+/* Closes the journal file. */
+{
+ if (!p_comopt->op_j_b) return;
+ if (wf_err(&f_j))
+ {
+ wl_s("F: Error writing to journal file. Aborting...");
+ sum_fat++;
+ return;
+ }
+ wf_clo(&f_j);
+ if (wf_err(&f_j))
+ {
+ wl_s("F: Error flushing and closing journal file. Aborting...");
+ sum_fat++;
+ return;
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void cl_help P_((void));
+LOCAL void cl_help ()
+{
+ uword messno;
+
+ /* Translate message name to number. This ought to work, as the options */
+ /* package is already have supposed to have cleared this argument as OK. */
+ messno=hel_num(p_comopt->op_h_s);
+ as_cold(messno!=HL_ERR,"cl_help: Unknown help argument.");
+
+ /* Write out the message. */
+ hel_wri(wr_sj,messno);
+}
+
+/******************************************************************************/
+
+EXPORT void command(p_comline)
+/* Execute the top level command line. This is the place where we do all the */
+/* "once per shell" things as opposed to the "once per run" things. */
+/* If a fatal error occurs, the correct course of action here is to increment */
+/* sum_fat and return immediately. The main() function deals with delivering */
+/* the correct return status to the operating system. */
+char *p_comline;
+{
+ old_war=old_err=old_sev=0;
+
+ tracing=FALSE;
+ noabort=FALSE;
+ skipping=FALSE;
+
+ /* Allocate space for command line arguments. */
+ allocarg();
+
+ /* Set up the standard output (stdout) screen (console) output stream. */
+ wf_ini(&f_s,TRUE);
+ wf_att(&f_s,stdout);
+
+ /* Parse the command line and place the information in p_comopt-> */
+ op_ini(p_comopt);
+ if (!op_add(p_comopt,p_comline,wr_s))
+ {wr_s("F: Command line error. Aborting..."); sum_fat++; goto windup;}
+
+ /* If the user asked for some peace and quiet by setting +Q, disable the */
+ /* console stream. Note: FunnelWeb main() always issues a message using a */
+ /* printf if any diagnostics have been generated. */
+ if (p_comopt->op_q_b) wf_ini(&f_s,FALSE);
+
+ /* Create and open the journal file. */
+ open_j(); if (sum_fat>0) goto windup;
+
+ wl_sj("FunnelWeb Version 3.05AC (Oct 1995)");
+ wl_sj("----------------------**-----------");
+ wl_sj("* Differences from FunnelWeb 3.0 are in `sources/README.ABC'.");
+ wl_sj("* No guarantee can be given that all of the features");
+ wl_sj("* of FunnelWeb 3.05AC will appear in Ross Williams'");
+ wl_sj("* next official release of `FunnelWeb'.");
+ wl_sj("-----------------------------------");
+ wl_sj("Copyright (C) Ross Williams 1992.");
+ wl_sj("Copyright (C) Anthony B. Coates 1995. There is ABSOLUTELY NO WARRANTY.");
+ wl_sj("-----------------------------------");
+ wl_sj("Bug reports to `coates@physics.uq.edu.au'.");
+ wl_sj("You are welcome to distribute this software under certain conditions.");
+ /*
+ wl_sj("THIS IS NOT AN APPROVED VERSION OF FUNNELWEB.");
+ wl_sj("USE ONLY AT OWN RISK. [A.B.Coates]");
+ */
+ if (p_comopt->op_k_b)
+ wl_sj("For more information, type HELP.");
+ else
+ wl_sj("For more information, use the +h (help) option (e.g. \"fw +h\").");
+ wl_sj("");
+
+ /* Ensure that the user has specified at least one action. */
+ chk_cline(); if (sum_fat>0) goto windup;
+
+ /* Establish the default options for the shell run (if any). */
+ /* Get rid of any options not to do with a single run of FunnelWeb proper. */
+ ASSIGN(*p_defopt,*p_comopt);
+ p_defopt->op_j_b=FALSE;
+ p_defopt->op_x_b=FALSE;
+ p_defopt->op_k_b=FALSE;
+
+ /* In the absence of everything else, command line options are run options. */
+ ASSIGN(option,*p_comopt);
+
+ /* Execute initialization file if any. */
+ if (fexists(INITFILE))
+ interstr(INITFILE);
+
+ /* Execute the specified actions. */
+ /* ABC { */
+ batchQ = p_comopt->op_q_b && !strcmp(p_comopt->op_q_s, "b");
+ /* } ABC */
+ if (p_comopt->op_x_b) interstr(p_comopt->op_x_s);
+ if (p_comopt->op_f_b) {zerdia(); fwonerun(); sumdia();}
+ if (p_comopt->op_h_b) cl_help();
+ if (p_comopt->op_k_b) interpret(stdin,"standard_input");
+
+ /* If we weren't in onerun mode, give a grand summary of errors. */
+ if (p_comopt->op_k_b || p_comopt->op_x_b)
+ {
+ wr_sj("Final diagnostics totals: ");
+ errsum(sum_fat,sum_sev,sum_err,sum_war);
+ wl_sj(linet1);
+ }
+
+ /* Close the journal file. */
+ close_j(); if (sum_fat>0) goto windup;
+
+ /* Check for errors on the screen stream (standard output). */
+ if (p_comopt->op_s_b && wf_err(&f_s))
+ {
+ /* No point in trying to write a message to the screen! */
+ /* But we can at least register a fatal error. */
+ sum_fat++;
+ }
+
+ windup:
+
+ /* If the user has set +Q to turn off screen output and one or more */
+ /* diagnostics have been generated, we need to break through to warn the */
+ /* user. */
+ {
+ ulong sum_all=sum_fat+sum_sev+sum_err+sum_war;
+ if (p_comopt->op_q_b && sum_all>0)
+ {
+ errsum(sum_fat,sum_sev,sum_err,sum_war);
+ fprintf(stderr,"%s\n",linet1);
+ }
+ }
+}
+
+/******************************************************************************/
+/* End of COMMAND.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/command.h b/web/funnelAC/fwACsrc/command.h
new file mode 100644
index 0000000000..1419a7c8f8
--- /dev/null
+++ b/web/funnelAC/fwACsrc/command.h
@@ -0,0 +1,61 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* COMMAND.H */
+/******************************************************************************/
+/* */
+/* The command package is the mover and shaker of FunnelWeb. It exports a */
+/* single function, whose argument is the command line given to FunnelWeb */
+/* when it is invoked at the operating system level. The command package */
+/* routine examines the command line and executes it, possibly invoking a */
+/* mini-interpreter or calling the different component of FunnelWeb in turn */
+/* (e.g. the parser). */
+/* */
+/******************************************************************************/
+
+#include "style.h"
+#include "machin.h"
+
+/******************************************************************************/
+
+void command P_((p_cl_t));
+/* Executes the command line which is passed as the argument. */
+
+/******************************************************************************/
+/* End of COMMAND.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/data.c b/web/funnelAC/fwACsrc/data.c
new file mode 100644
index 0000000000..7c96c7d566
--- /dev/null
+++ b/web/funnelAC/fwACsrc/data.c
@@ -0,0 +1,50 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* DATA.C */
+/******************************************************************************/
+
+/* The following definition causes the definitions in data.h to be treated */
+/* as real meaty declarations and not wimpy "external" ones. */
+#define EXTERN
+
+#include "data.h"
+
+/******************************************************************************/
+/* End of DATA.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/data.h b/web/funnelAC/fwACsrc/data.h
new file mode 100644
index 0000000000..248102af96
--- /dev/null
+++ b/web/funnelAC/fwACsrc/data.h
@@ -0,0 +1,684 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 24-Aug-1993 ABC Adjusted ps_t and ln_t structures to carry
+ pointers to a file name.
+ Added new token TK_SPEC for special functions
+ (to be recognised by the parser, not by the
+ scanner).
+ Added SF_... tokens for specifying which special
+ function represented by a TK_SPEC token.
+ Added fnam_t and p_fnam_t types for creating a
+ linked list of input file names.
+ 16-Sep-1993 ABC Changed all constants *_MAX to *_FWMAX to avoid
+ conflict with some standard UNIX constants.
+ 30-Dec-1993 ABC Added global variables `lin_off' and `lin_dep'
+ to support internal `#line' macro.
+ 15-Apr-1994 ABC Added hypertext typesetter types
+ TR_HTXT and TR_HTML, which are to HTML hypertext
+ what TR_NONE and TR_TEX are to TeX respectively.
+ 15-Apr-1994 ABC Added doc_incQ flag for inclusion or not of
+ FunnelWeb TeX/HTML header.
+ 10-May-1994 ABC Added DYN_NAMES option to allow macro and
+ section names to be allocated dynamically
+ instead of statically.
+ 20-May-1994 ABC Added raw_namQ flag for allowing or not of
+ raw TeX/HTML in macro/section names.
+ 28-May-1994 ABC Added no_pmrkQ flag for suppressing the inclusion
+ of `<P>' paragraph markups in hypertext or HTML
+ modes.
+ 16-Jul-1994 ABC Added `aldmname' character pointer for the
+ (optional) name of a macro which is called
+ whenever any other macro is invoked in order to
+ generate line directives.
+ 25-Jul-1995 ABC Changed `aldmname' to a pointer to an array of
+ strings, to allow for multiple source types and
+ hence multiple line directive macro types.
+ 25-Jul-1995 ABC Added `xsrctypes' unsigned integer value to hold
+ the number of extra source code types (if any).
+ 25-Jul-1995 ABC Added `xsrcname' char** value to hold
+ the names of extra source code types (if any).
+ 01-Aug-1995 ABC Added automatic line directive macro pointer to
+ macro definition structure.
+ 01-Aug-1995 ABC Changed `xsrctypes' to a boolean `xsrctypesQ'
+ controlling if extra source code types are
+ allowed or not.
+ 03-Aug-1995 ABC Modified the macro definition structure (md_t) by
+ adding a member which records which automatic
+ line insertion macro to use (if required). This
+ member is only valid for macros which are
+ attached to output files.
+ 10-Aug-1995 ABC Added SF_TMS token for @<#timestamp@> internal
+ macro.
+ 16-Aug-1995 ABC Added `batchQ' boolean to denote batch mode -
+ no interaction at all with user.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* DATA.H */
+/******************************************************************************/
+/* */
+/* This package (data.h, data.c) contains ALL of the global variables in */
+/* FunnelWeb. Some of the FunnelWeb packages (e.g. the lister) harbour hidden */
+/* static state variables which could be considered to be a global variable, */
+/* but, these aside, this package contains all the variables that are used */
+/* directly by more than one package. In many programs, it would likely be */
+/* appropriate to have a separate package for each distinct group of shared */
+/* data so that only those packages needing a particular group of data need */
+/* see it. However, in FunnelWeb's case, the variables are so few, and their */
+/* use so widespread that they are clustered here in one package for all to */
+/* see. */
+/* */
+/* This package also contains type definitions for the central FunnelWeb data */
+/* structures. */
+/* */
+/******************************************************************************/
+
+/* Ensure that the body of this header file is included at most once. */
+#ifndef DONE_DATA
+#define DONE_DATA
+
+/******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "style.h"
+#include "clock.h"
+#include "list.h"
+#include "table.h"
+#include "option.h"
+#include "section.h"
+#include "writfile.h"
+
+/******************************************************************************/
+
+/* ABC { */
+/* Set DYN_NAMES to TRUE to make macro and section names
+ * dynamically allocated. Else, set it to false.
+ */
+#define DYN_NAMES TRUE
+/* } ABC */
+
+/******************************************************************************/
+/* */
+/* DATA TYPES */
+/* ========== */
+/* The following section contains all the data types of the global variables. */
+/* */
+/******************************************************************************/
+
+/* ABC { */
+/* The following structure defines a filename, used to */
+/* identify the file to which each token is connected. */
+typedef
+ struct fnam_t_body /* NEVER declare a `fnam_t_body'!! */
+ {
+ char* fnam_name;
+ struct fnam_t_body *fnam_next;
+ } fnam_t;
+
+typedef fnam_t *p_fnam_t;
+/* } ABC */
+
+/******************************************************************************/
+
+/* The following structure defines a position in the global listing of the */
+/* input data by storing a line number and a column number. The line number */
+/* is a global line number meaning that it increases continuously through */
+/* the lines of included files. The first line is line number 1. The first */
+/* (leftmost) column is column number 1. */
+/* A local line-number for the actual source file and the filename for the */
+/* actual source file are also included for use by internal macros. */
+/* The flag ps_declQ defines whether the position actually exists in the */
+/* global source (this should only be false for internally defined macros. */
+typedef
+ struct
+ {
+ ulong ps_line;
+ ulong ps_column;
+ /* ABC { */
+ ulong ps_localno;
+ p_fnam_t ps_fnam;
+ bool ps_declQ;
+ /* } ABC */
+ } ps_t ;
+
+typedef ps_t *p_ps_t; /* A pointer to a position is handy too! */
+
+/******************************************************************************/
+
+/* A macro name is represented simply as a character array. */
+#define NAME_FWMAX 80
+typedef char name_t[NAME_FWMAX+1];
+/* ABC { */
+#if DYN_NAMES
+typedef char *p_name_t;
+#else /* !DYN_NAMES */
+typedef name_t *p_name_t;
+#endif /* DYN_NAMES */
+/* } ABC */
+
+/******************************************************************************/
+
+/* SC stands for SCrap of text. A scrap of text is a contiguous group of */
+/* printable bytes in memory. The following structure defines such a group by */
+/* storing a pointer to the first and last character of the scrap. */
+/* The scrap must contain at least one character (i.e. sc_last>=sc_first). */
+typedef
+ struct
+ {
+ char *sc_first; /* Pointer to the first byte of the scrap. */
+ char *sc_last; /* Pointer to the last byte of the scrap. */
+ bool sc_white; /* TRUE iff the scrap consists entirely of whitespace. */
+ } sc_t;
+
+typedef sc_t *p_sc_t;
+
+/******************************************************************************/
+
+/* LN stands for LiNe. This record holds global and local line numbers as */
+/* well as a scrap that points to the line in question. The scanner (which */
+/* generates this list) guarantees that the last character of the line scrap */
+/* is an EOL. */
+typedef
+ struct
+ {
+ sc_t ln_body; /* Scrap pointing to the line. Line ends in EOL. */
+ ulong ln_global; /* Global line number of this line. */
+ ulong ln_local; /* Local line number of this line. */
+ /* ABC { */
+ p_fnam_t ln_fnam; /* Local file name for this line. */
+ /* } ABC */
+ } ln_t;
+
+/* The global line list is simply a list of lines of the following type. */
+typedef p_ls_t p_lnls_t;
+
+/******************************************************************************/
+
+/* The following enumerated type identifies a font. */
+#define FT_NORM 1
+#define FT_TITL 2
+#define FT_STIT 3
+
+/* The following enumerated type identifies a horizontal alignment. */
+#define LR_LEFT 1
+#define LR_RIGH 2
+#define LR_CENT 3
+
+/* We want to pack a font and an alignment into the tk_gen byte of the token */
+/* record (we could create a new field, but as none of the other token kinds */
+/* require an extra field, we choose to pack instead. The formula is this: */
+/* Packed byte=LRFT_PACK*FONT+ALIGNMENT. */
+#define LRFT_PACK 10
+
+/******************************************************************************/
+
+/* The following enumerated type identifies the kind of a token. */
+#define TK_TEXT 1 /* Text segment. */
+#define TK_NSEC 2 /* @A..New section. */
+#define TK_MDEF 3 /* @$ Macro definition. */
+#define TK_FDEF 4 /* @F File definition. */
+#define TK_ONAM 5 /* @< Open name. */
+#define TK_CNAM 6 /* @> Close name. */
+#define TK_ODEF 7 /* @{ Open definition. */
+#define TK_CDEF 8 /* @} Close definition. */
+#define TK_OPAR 9 /* @( Open parameter list. */
+#define TK_CPAR 10 /* @) Close parameter list. */
+#define TK_COMA 11 /* @, Comma. */
+#define TK_QUOT 12 /* @" Quote. */
+#define TK_PARM 13 /* @1 Parameter. */
+#define TK_ZERO 14 /* @Z Zero calls allowed. */
+#define TK_MANY 15 /* @M Many calls allowed. */
+#define TK_NAME 16 /* @# Self contained name. */
+#define TK_EMPH 17 /* @/ Emphasize text. */
+#define TK_NPAG 18 /* @t..Newpage. */
+#define TK_TOCS 19 /* @t..Table of contents. */
+#define TK_SKIP 20 /* @t..Vertical skip. */
+#define TK_TITL 21 /* @t..Title text. */
+#define TK_EOF 22 /* End of file. */
+typedef ubyte tk_k_t;
+
+/* The following structure conveys all the information about a single token. */
+/* As well as the kind of token, the parser needs to know where the token is */
+/* in the input file and what the text of the token is if it is a text token. */
+/* Some other tokens have a numeric attribute associated with them and the */
+/* tk_gen field provides a place for this. The attributes are: */
+/* TK_PARM - The number of the parameter [1,9]. */
+/* TK_NAME - The number of the character forming the name [0,255]. */
+/* TK_NSEC - The level of the section [0,5]. 0=@*, 1=@A, 2=@B,..,5=@E. */
+/* TK_SKIP - Number of millimetres to skip vertically [0,255]. */
+/* TK_TITL - Font and alignment packed into byte as specified earlier. */
+/* tk_sc is the text to be set as a title. */
+typedef
+ struct
+ {
+ tk_k_t tk_kind; /* Kind of this token. */
+ ps_t tk_ps; /* Position of the first character of this token. */
+ sc_t tk_sc; /* Scrap constituting token. */
+ ubyte tk_gen; /* General token attribute. */
+ } tk_t;
+
+typedef p_ls_t p_tkls_t; /* A list of tokens. */
+
+/******************************************************************************/
+
+typedef p_ls_t p_scls_t; /* List of scraps. */
+typedef p_ls_t p_scll_t; /* List of list of scraps =TEXT. */
+
+typedef p_ls_t p_ells_t; /* List of pointers to elements = EXPRESSION. */
+typedef p_ls_t p_elll_t; /* List of list of pointers to elements. */
+typedef p_ls_t p_ell3_t; /* List of list of list of pointers to elements. */
+
+/******************************************************************************/
+
+/* This structure's signature is BP for Body Part. FunnelWeb macros can */
+/* be defined in a series of "+=" definitions scattered through the input */
+/* file. The definition of the macro is the concatenation of all the parts. */
+/* The contributory part of a part consists of a single expression. */
+/* Throughout the document, body parts (definition parts) are numbered */
+/* sequentially by a sequence number. */
+typedef
+ struct
+ {
+ p_ells_t bp_ex; /* Expression that is logically appended to definition. */
+ ulong bp_seq; /* Sequence number of body part. */
+ ps_t bp_ps; /* Position at which the definition appears. */
+ } bp_t;
+
+typedef bp_t *p_bp_t;
+
+/* A list of body parts constitutes the full body of a macro. */
+typedef p_ls_t p_bpls_t;
+
+/******************************************************************************/
+
+/* The following structure summarizes a macro CALL. Each macro table entry */
+/* contains a field ma_calls which contains a list of these structures. The */
+/* list is used to generate diagnostics (e.g. if a call has the wrong number */
+/* of parameters) and also to give cross reference information in the typeset */
+/* documentation. */
+typedef
+ struct
+ {
+ ulong mc_seq; /* Sequence number of body part containing call. */
+ ps_t mc_ps; /* Position at which the call occurred. */
+ ulong mc_npar; /* Number of parameters in call. */
+ } mc_t;
+
+typedef mc_t *p_mc_t;
+
+/* A list of calls summarizes the entire usage of a macro in a document. */
+typedef p_ls_t p_mcls_t;
+
+/******************************************************************************/
+
+/* ABC { */
+/* The following define a source code type structure and a list *
+ * of the aforesaid. */
+
+typedef struct {
+ /* sourcetype and auto line directive insertion macro name */
+ char *typnam, *lnmac;
+} srcnmac_t, *p_srcnmac_t, **pp_srcnmac_t;
+
+typedef p_ls_t p_srct_t;
+/* } ABC */
+
+/******************************************************************************/
+
+/* This structure stores the definition of a single macro. The first field */
+/* md_isdef indicates whether a definition for this macro has so far been */
+/* seen. If it has, md_isdef=TRUE and the remaining fields are well defined. */
+typedef
+ struct
+ {
+ bool md_isdef; /* TRUE iff the macro is defined. */
+ ps_t md_ps; /* isdef=> Position of first definition part. */
+ ubyte md_npar; /* isdef=> Number of params specified in defn. */
+ bool md_isadd; /* isdef=> TRUE iff additively defined. */
+ bool md_iszer; /* isdef=> TRUE iff zero calls allowed. */
+ bool md_isman; /* isdef=> TRUE iff many calls allowed. */
+ bool md_isfil; /* isdef=> TRUE iff macro is bound to an outp file. */
+ p_bpls_t md_body; /* isdef=> Body of the macro (list of parts). */
+/* ABC { */
+ p_srcnmac_t md_aldm; /* Automatic line insertion macro. */
+/* } ABC */
+ } md_t;
+
+/******************************************************************************/
+
+/* The following structure contains the full information about a macro. */
+typedef
+ struct
+ {
+/* ABC { */
+#if DYN_NAMES
+ p_name_t ma_name; /* Name of the macro. */
+#else /* !DYN_NAMES */
+ name_t ma_name; /* Name of the macro. */
+#endif /* DYN_NAMES */
+/* } ABC */
+ p_mcls_t ma_calls; /* List of calls of this macro in the document. */
+ md_t ma_defn; /* Definition of this macro. */
+ p_ell3_t ma_actn; /* Used by tangle. List of actual parameter lists. */
+ uword ma_level; /* Used by analyser. Depth of deepest call. */
+ } ma_t;
+
+/* A pointer to the comprehensive macro structure defined above is the way */
+/* that FunnelWeb refers to macros internally. */
+typedef ma_t *p_ma_t;
+
+/******************************************************************************/
+
+/* An expression consists of a sequence of ELEMENTS each of which can */
+/* be one of three kinds: */
+/* */
+/* 1. A block of text. */
+/* 2. An invocation of another macro. */
+/* 3. A parameter of the current macro. */
+/* 4. An invocation of an internal function. */
+/* */
+/* The following enumerated type identifies one of these three alternatives. */
+#define EL_TEXT 1
+#define EL_INVC 2
+#define EL_PARM 3
+/* ABC { */
+#define EL_SPEC 4
+/* } ABC */
+
+typedef ubyte el_k_t;
+
+/* ABC { */
+/* The following enumerated type identifies a particular special function. */
+/* This relates to the element type EL_SPEC. */
+#define SF_ERR 0 /* Error value */
+#define SF_LIN 1 /* Insert current local source line value. */
+ /* an offset to this is settable using the */
+ /* pragma `#line_offset'. */
+#define SF_FIL 2 /* Insert current local source file name. */
+#define SF_TMS 3 /* Insert timestamp. */
+
+typedef ubyte sf_k_t;
+/* } ABC */
+
+/* The following rather messy structure contains information about a single */
+/* element. As mentioned above, an element can be one of three kinds and the */
+/* following structure should, strictly speaking, be defined as a C union so */
+/* as to emphasize the mutually exclusive nature of most of its fields. */
+/* At one stage this structure did contain a union, however, it introduced */
+/* more mess than it brought clarity (because of the extra two subnames) and */
+/* was eventually dropped. */
+/* A few fields deserve some explanation: */
+/* el_pretx and el_postx hold the exact whitespace appearing between */
+/* actual parameters in a macro call. This enables the call to be */
+/* formatted properly in the typeset output. */
+/* el_which is part of the macro parameter element (e.g. @1) and points to */
+/* the macro within which the @1 appears. Strictly speaking this should */
+/* not be necessary, but it is convenient for the tangler to have this */
+/* information when it is half way through expanding an expression. */
+typedef
+ struct /* ABC { */ el_t_body /* NEVER use this name!! */ /* } ABC */
+ {
+ el_k_t el_kind; /* Indicates what kind of element structure holds. */
+
+ p_scls_t el_text; /* EL_TEXT => List of scraps forming a text chunk. */
+
+ p_ma_t el_p_mac; /* EL_INVC => Pointer to macro being invoked. */
+ p_elll_t el_parls; /* EL_INVC => List of actual parameters. */
+ p_scll_t el_pretx; /* EL_INVC => Text before each parameter. */
+ p_scll_t el_postx; /* EL_INVC => Text after each parameter. */
+ struct el_t_body
+ *el_p_par; /* EL_INVC/EL_SPEC => Parent invocation. */
+ p_ma_t el_which; /* EL_PARM => Macro in which this element appears. */
+ ubyte el_parno; /* EL_PARM => Parameter number of this actual param. */
+ sf_k_t el_selec; /* EL_SPEC => Identifies which special function. */
+ ps_t el_ps; /* EL_SPEC => Position where function applies. */
+ } el_t;
+
+typedef el_t *p_el_t;
+
+/******************************************************************************/
+
+/* A document component (represented by the DC_ data structures (see below) */
+/* can be one of three things: a lump of text, a typesetter-generic */
+/* typesetting directive, or a macro definition. The second of these consists */
+/* of a whole collection of typesetting commands and so rather than */
+/* cluttering up the dc_ record, they have been separated out here. */
+#define TY_NSEC 1 /* New section. */
+#define TY_OLIT 2 /* Open literal. */
+#define TY_CLIT 3 /* Close literal. */
+#define TY_OEMP 4 /* Open emphasise. */
+#define TY_CEMP 5 /* Close emphasise. */
+#define TY_NPAG 6 /* New page. */
+#define TY_TOCS 7 /* Table of contents. */
+#define TY_SKIP 8 /* Skip vertical. */
+#define TY_TITL 9 /* Title. */
+typedef ubyte ty_k_t;
+
+typedef
+ struct
+ {
+ ty_k_t ty_kind; /* Kind of this typesetting directive. */
+ sn_t ty_sn; /* TY_NSEC=> Hierarchical section number. */
+ bool ty_isnam; /* TY_NSEC=> TRUE iff the section is named. */
+/* ABC { */
+#ifdef DYN_NAMES
+ p_name_t ty_name; /* TY_NSEC=> ty_isnam=> Name of section. */
+#else /* !DYN_NAMES */
+ name_t ty_name; /* TY_NSEC=> ty_isnam=> Name of section. */
+#endif /* DYN_NAMES */
+/* } ABC */
+
+ uword ty_mm; /* TY_SKIP=> Millimetres to skip. */
+
+ ubyte ty_font; /* TY_TITL=> Font in which to write title. */
+ ubyte ty_align; /* TY_TITL=> Alignment with which to write title. */
+ sc_t ty_sc; /* TY_TITL=> Scrap that is title text. */
+ } ty_t;
+
+typedef ty_t *p_ty_t;
+
+/******************************************************************************/
+
+/* The document list contains a representation of the input document in the */
+/* form in which it was fed to FunnelWeb. This structured representation of */
+/* the input is used by the weaver to generate the typeset output. */
+/* Here, a document is represented by a list of DOCUMENT COMPONENTs (DC) each */
+/* of which contains information about a major chunk of the document. The */
+/* following enumerated type dc_k_t (document component kind type) is used to */
+/* indicate which kind of component each list element contains. */
+#define DC_TEXT 1 /* Text component consists of a block of text. */
+#define DC_TYPE 2 /* Typesettting component affecting document typesetting. */
+#define DC_MACR 3 /* A MACRo definition. */
+typedef ubyte dc_k_t;
+
+/* The following structure stores a single document component. Like the el_t */
+/* type, the dc_t type should really be a union type, but a union construct */
+/* has been avoided to make the naming simpler. */
+typedef
+ struct
+ {
+ ps_t dc_ps; /* Position of this component. */
+ dc_k_t dc_kind; /* Kind of this component. */
+
+ p_scls_t dc_text; /* DC_TEXT=> Text segment constituting this compnt. */
+
+ ty_t dc_ty; /* DC_TYPE=> Typesetting object record. */
+
+ p_ma_t dc_p_ma; /* DC_MACR=> Pointer to the macro defined. */
+ ulong dc_part; /* DC_MACR=> Part number of this part of macro defn. */
+ } dc_t;
+
+typedef dc_t *p_dc_t;
+
+/* A list of document components constitutes the global document list */
+/* declared later. */
+typedef p_ls_t p_dcls_t;
+
+/******************************************************************************/
+
+/* This enumerated type identifies a typesetter. */
+/* TR_NONE - No specific typesetter specified. */
+/* TR_TEX - The TeX typesetter. */
+/* ABC { */
+/* TR_HTXT - No specific typesetter, but hypertext. */
+/* TR_HTML - HTML output, for typesetters such as Mosaic. */
+/* } ABC */
+#define TR_NONE 1
+#define TR_TEX 2
+/* ABC { */
+/* TR_HTXT means convert FunnelWeb typesetting to HTML form. */
+#define TR_HTXT 3
+/* TR_HTML means not to use FunnelWeb typesetting, but assume
+ * that the documentation part of the file is in HTML form
+ * already (in the way the TR_TEX assumes that the documentation
+ * part is in (La)TeX form).
+ */
+#define TR_HTML 4
+/* } ABC */
+/* Add more typesetters here later. */
+typedef ubyte tr_k_t;
+
+
+/******************************************************************************/
+/* */
+/* VARIABLES */
+/* ========= */
+/* This section contains external declarations of the global variables. */
+/* The global variables themselves appear in DATA.C. */
+/* */
+/******************************************************************************/
+
+/* This #ifndef is part of a mechanism that makes the following definitions */
+/* visible to other modules declared as "extern", and visible to data.c */
+/* declared as ordinary declarations. This prevents inconsistencies. */
+#ifndef EXTERN
+#define EXTERN extern
+#endif
+
+/* This global options variable holds the options that were transmitted to */
+/* FunnelWeb proper through the command line. */
+EXTERN GLOVAR op_t option;
+
+/* The following option variable is set by the scanner and is used by the */
+/* tangler. It determines whether the tangler will use natural indenting. */
+/* TRUE => Tangler should use space indenting. FALSE=>No indenting. */
+EXTERN GLOVAR bool tgindent;
+
+/* The following option variable is set by the scanner and is used by the */
+/* tangler. It sets a limit on the length of the lines of the product files */
+/* generated by tangle. A value of TGMAXINF indicates that no checking need */
+/* be performed. */
+#define TGMAXINF (ULONG_MAX)
+EXTERN GLOVAR ulong tglinmax;
+
+/* The following variable is written by the scanner and read by weave. It */
+/* stores the typesetter format possibly specified by the user in the input. */
+EXTERN GLOVAR tr_k_t tr_codes;
+
+/* The following five lists and tables constitute the major data structures */
+/* that are communicated between the major components of FunnelWeb. */
+/* The TOKEN_LIST contains a tokenized representation of the input file. */
+/* The LINE_LIST contains a list of the lines of the input file. */
+/* The DOCUMENT_LIST contains a structured representation of the input file. */
+/* The MACRO_TABLE describes the macros defined in the input file. */
+/* The FILE_TABLE identifies macros that are connected to product files. */
+/* Created By Used By */
+/* ---------- ------- */
+EXTERN GLOVAR p_tkls_t token_list; /* Scanner Parser */
+EXTERN GLOVAR p_lnls_t line_list; /* Scanner Lister */
+EXTERN GLOVAR p_dcls_t document_list; /* Parser Weaver */
+EXTERN GLOVAR p_tb_t macro_table; /* Parser Tangler, Weaver */
+EXTERN GLOVAR p_tb_t file_table; /* Parser Tangler, Weaver */
+
+/* Three output streams are accessible globally. */
+/* The SCREEN FILE is connected to standard output (the user screen). */
+/* The JOURNAL FILE logs FunnelWeb command language transactions. */
+/* The LISTING FILE is created by an single invocation of FunnelWeb proper. */
+EXTERN GLOVAR wf_t f_s; /* Screen file. */
+EXTERN GLOVAR wf_t f_j; /* Journal file. */
+EXTERN GLOVAR wf_t f_l; /* Listing file. */
+
+/* Many of the FunnelWeb IO functions accept a single string as a parameter. */
+/* This means that sprintf and a temporary string must be used in order to */
+/* produce parameterized formatted output. Rather than declare temporary */
+/* strings in each local function, we declare them globally. */
+EXTERN GLOVAR char linet1[2000];
+
+/* Definitions of Diagnostic Levels */
+/* -------------------------------- */
+/* A WARNING has no effect except to cause a message to be issued. */
+/* An ERROR causes FunnelWeb to abort to the shell at the end of the phase. */
+/* Example: An error during scanning means that the FunnelWeb run will */
+/* terminate to the shell at the end of the scanning phase. */
+/* A SEVERE ERROR causes FunnelWeb to abort to the shell immediately. */
+/* A FATAL ERROR causes FunnelWeb to abort to the OS immediately. */
+
+/* The following variables count diagnostics over a single FunnelWeb run. */
+EXTERN GLOVAR ulong num_war; /* Number of warnings. */
+EXTERN GLOVAR ulong num_err; /* Number of errors. */
+EXTERN GLOVAR ulong num_sev; /* Number of severe errors. */
+
+/* The following variables count diagnostics over multiple FunnelWeb runs. */
+EXTERN GLOVAR ulong sum_war; /* Number of warnings. */
+EXTERN GLOVAR ulong sum_err; /* Number of errors. */
+EXTERN GLOVAR ulong sum_sev; /* Number of severe errors. */
+EXTERN GLOVAR ulong sum_fat; /* Number of fatal errors. */
+
+/* ABC { */
+/* Whether the TeX or HTML header should be included or not. */
+EXTERN GLOVAR bool doc_incQ; /* Include TeX/HTML header at weave time */
+EXTERN GLOVAR bool raw_namQ; /* Allow raw TeX/HTML in macro/section names */
+EXTERN GLOVAR bool no_pmrkQ; /* Suppress automatic <P> markups (HTML) */
+EXTERN GLOVAR bool xsrctypesQ; /* Are extra source code types to be allowed? */
+EXTERN GLOVAR p_srct_t srctlist; /* Names of the source code types and the */
+ /* corresponding macros to use for automatic */
+ /* line directive insertion. */
+EXTERN GLOVAR word lin_off; /* line offset for @<#line@> internal macro. */
+EXTERN GLOVAR uword lin_dep; /* unwind depth for @<#line@> internal macro. */
+EXTERN GLOVAR bool batchQ; /* Batch mode - no interaction at all? */
+/* } ABC */
+
+/******************************************************************************/
+
+/* For #ifndef preventing multiple inclusion of the body of this header file. */
+#endif
+
+/******************************************************************************/
+/* End of DATA.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/dump.c b/web/funnelAC/fwACsrc/dump.c
new file mode 100644
index 0000000000..9a1687cb80
--- /dev/null
+++ b/web/funnelAC/fwACsrc/dump.c
@@ -0,0 +1,900 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 31-Aug-1993 ABC Added support for EL_SPEC
+ 10-May-1994 ABC Added DYN_NAMES option to allow macro and
+ section names to be allocated dynamically
+ instead of statically.
+ 06-Aug-1995 ABC Modified the macro definition dump to dump
+ information on the automatic line directive
+ macro, if appropriate.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* DUMP.C */
+/******************************************************************************/
+
+#include <ctype.h>
+#include "style.h"
+
+#include "as.h"
+#include "clock.h"
+#include "data.h"
+#include "dump.h"
+#include "misc.h"
+
+/******************************************************************************/
+
+#define DUMP_WIDTH (80)
+
+/******************************************************************************/
+
+/* The following advance declarations are required because of recursion. */
+LOCAL void dm_ex P_((p_wf_t,p_ells_t));
+
+/******************************************************************************/
+
+LOCAL void centerln P_((p_wf_t,uword,int,char *));
+LOCAL void centerln(p_wf,width,ch,s)
+/* Writes string s in a line surrounded by character ch to specified width. */
+/* Example: centerln(*,20,'-',"sloth") would write: "------ sloth -------" */
+p_wf_t p_wf;
+uword width;
+int ch;
+char *s;
+{
+ uword sidebar,i;
+ char linet2[100];
+ /* Warning: linet2 can't be too big, or it will blow the Mac's limited */
+ /* stack space. Perhaps it should be put in the heap with a static pointer. */
+
+ as_cold(width>=5,"centerln: Width is too small.");
+ as_cold(width<=80,"centerln: Width is too large.");
+ as_cold(strlen(s) <= width-4,"centerln: Width is too narrow for string.");
+
+ /* Construct a sidebar string. */
+ sidebar=(width-strlen(s)-2)/2;
+ for (i=0;i<sidebar;i++) linet2[i]=ch;
+ linet2[sidebar]=EOS;
+
+ /* Now construct the result string. */
+ strcpy(linet1,linet2);
+ strcat(linet1," ");
+ strcat(linet1,s);
+ strcat(linet1," ");
+ strcat(linet1,linet2);
+
+ /* If the sidebar division removed a character, and the line is long enough */
+ /* for the user not to notice the imbalance, tack a character on the end. */
+ if (width>40 && strlen(linet1)==width-1)
+ {
+ uword len=strlen(linet1);
+ linet1[len]=ch;
+ linet1[len+1]=EOS;
+ }
+
+ /* Write the result string to the specified stream. */
+ wf_wl(p_wf,linet1);
+}
+
+/******************************************************************************/
+
+LOCAL char * fontname P_((ubyte));
+LOCAL char * fontname(font)
+/* Given a font number, returns a pointer to a static string containing the */
+/* name of the font. */
+ubyte font;
+{
+ switch (font)
+ {
+ case FT_NORM: return "Normal";
+ case FT_TITL: return "Title";
+ case FT_STIT: return "Small Title";
+ default : as_bomb("fontname: Font switch defaulted.");
+ }
+ /* Keep GCC warnings happy. */
+ as_bomb("fontname: Dropped out of switch.");
+ return "Failure";
+}
+
+/******************************************************************************/
+
+LOCAL char * alignname P_((ubyte));
+LOCAL char * alignname(align)
+/* Given an alignment number, returns a pointer to a static string containing */
+/* the name of the alignment. */
+ubyte align;
+{
+ switch (align)
+ {
+ case LR_LEFT: return "Left";
+ case LR_RIGH: return "Right";
+ case LR_CENT: return "Centre";
+ default : as_bomb("alignname: Alignment switch defaulted.");
+ }
+ /* Keep GCC warnings happy. */
+ as_bomb("alignnamename: Dropped out of switch.");
+ return "Failure";
+}
+
+/******************************************************************************/
+
+EXPORT void dm_mem(p_wf,p_mem,length)
+p_wf_t p_wf;
+char *p_mem;
+ulong length;
+{
+ ubyte_ *p_base = (ubyte_ *) p_mem;
+ long len = length;
+
+ wf_wl(p_wf,"");
+ wf_wl(p_wf,"MEMORY DUMP OF MAPPED FILE");
+ wf_wl(p_wf,"==========================");
+ wf_wl(p_wf,"");
+ wf_wr(p_wf,"+-------------------------------------------------+------------------+\n");
+ wf_wr(p_wf,"| 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F | 0123456789ABCDEF |\n");
+ wf_wr(p_wf,"+-------------------------------------------------+------------------+\n");
+
+ while (len>0)
+ {/* Write a single line of 16 bytes per iteration. */
+ uword j;
+ wf_wr(p_wf,"| ");
+ for (j=0;j<16;j++)
+ if (j>=len)
+ wf_wr(p_wf," ");
+ else
+ {
+ char s[10];
+ sprintf(s,"%02X ",(unsigned int) p_base[j]);
+ wf_wr(p_wf,s);
+ }
+ wf_wr(p_wf,"| ");
+ for (j=0;j<16;j++)
+ if (j>=len)
+ wf_chr(p_wf,' ');
+ else
+ {
+ char ch=p_base[j];
+ /* DON'T use library function "isprint" - it is too loose. */
+ /* e.g. The vax "isprint" accepts top bit characters. */
+ if (!isascprn(ch)) ch='.';
+ wf_chr(p_wf,ch);
+ }
+ wf_wr(p_wf," |\n");
+ p_base+=16;
+ len-=16;
+ } /* End while */
+
+ wf_wr(p_wf,"+-------------------------------------------------+------------------+\n");
+ wf_wl(p_wf,"");
+}
+
+/******************************************************************************/
+
+LOCAL void dm_byte P_((p_wf_t,ubyte));
+LOCAL void dm_byte(p_wf,b)
+/* Dumps a text representation of the given byte to the specified stream. */
+p_wf_t p_wf;
+ubyte b;
+{
+ char t[10];
+ /* DON'T use library function "isprint" - it is too loose. */
+ /* e.g. The vax "isprint" accepts top bit characters. */
+ if (isascprn(b))
+ sprintf(t,"%c",(char) b);
+ else
+ sprintf(t,"<%03u>",(unsigned) b);
+ wf_wr(p_wf,t);
+}
+
+/******************************************************************************/
+
+EXPORT void dm_lnls(p_wf)
+p_wf_t p_wf;
+{
+ wf_wl(p_wf,"");
+ centerln(p_wf,DUMP_WIDTH,'=',"Start of LINE LIST DUMP");
+ wf_wl(p_wf,"");
+ /*12345678901234567890123456789012345678901234567890123456789012345678901234567890*/
+ wf_wl(p_wf,"Globl Local| Text");
+ wf_wl(p_wf,"-----------+--------------------------------------------------------------------");
+ ls_fir(line_list);
+ while (TRUE)
+ {
+ ln_t *p_line;
+ char *p;
+ ls_nxt(line_list,PPV &p_line);
+ if (p_line==NULL) break;
+ sprintf(linet1,"%05lu %05lu| ",
+ (ulong) p_line->ln_global,
+ (ulong) p_line->ln_local);
+ wf_wr(p_wf,linet1);
+ for (p=p_line->ln_body.sc_first; p<=p_line->ln_body.sc_last; p++)
+ dm_byte(p_wf,*((ubyte_ *)p));
+ wf_wl(p_wf,"");
+ }
+ wf_wl(p_wf,"-----------+--------------------------------------------------------------------");
+ wf_wl(p_wf,"Globl Local| Text");
+ wf_wl(p_wf,"");
+ centerln(p_wf,DUMP_WIDTH,'=',"End of LINE LIST DUMP");
+ wf_wl(p_wf,"");
+}
+
+/******************************************************************************/
+
+LOCAL void dm_sc P_((p_wf_t,p_sc_t));
+LOCAL void dm_sc(p_wf,p_sc)
+/* Dumps the specified scrap to the specified stream. */
+p_wf_t p_wf;
+p_sc_t p_sc;
+{
+ char *p;
+
+ as_cold(p_sc->sc_first !=NULL,"dm_sc: NULL ptr1.");
+ as_cold(p_sc->sc_last !=NULL,"dm_sc: NULL ptr2.");
+
+ if (p_sc->sc_white)
+ wf_wr(p_wf,"Text scrap[White]=");
+ else
+ wf_wr(p_wf,"Text scrap[Grey]=");
+ wf_wr(p_wf,"\"");
+ for (p=p_sc->sc_first; p<=p_sc->sc_last; p++)
+ {
+ dm_byte(p_wf,*((ubyte_ *) p));
+ if (*p=='\n')
+ wf_wl(p_wf,"");
+ }
+ wf_wl(p_wf,"\"");
+}
+
+/******************************************************************************/
+
+LOCAL void dm_scls P_((p_wf_t,p_scls_t));
+LOCAL void dm_scls(p_wf,p_scls)
+/* Dumps the specified scrap list to the specified stream. */
+p_wf_t p_wf;
+p_scls_t p_scls;
+{
+ wf_wl(p_wf,"");
+ centerln(p_wf,30,'-',"Start of Text Scrap List");
+ ls_fir(p_scls);
+ while (TRUE)
+ {
+ p_sc_t p_sc;
+ ls_nxt(p_scls,PPV &p_sc);
+ if (p_sc==NULL) break;
+ dm_sc(p_wf,p_sc);
+ }
+ centerln(p_wf,30,'-',"End of Text Scrap List");
+ wf_wl(p_wf,"");
+}
+
+/******************************************************************************/
+
+EXPORT void dm_tkls(p_wf)
+p_wf_t p_wf;
+{
+ tk_t *token;
+ char *m;
+ ubyte font;
+ ubyte align;
+
+ wf_wl(p_wf,"");
+ centerln(p_wf,DUMP_WIDTH,'=',"Start of TOKEN LIST DUMP");
+ wf_wl(p_wf,"");
+ sprintf(linet1,"Summary: There are %lu tokens in the token list.",
+ (ulong) ls_len(token_list));
+ wf_wl(p_wf,linet1);
+ wf_wl(p_wf,"");
+ wf_wl(p_wf,"Line[Column]: Token Description");
+ wf_wl(p_wf,"-------------------------------");
+ wf_wl(p_wf,"");
+
+ ls_fir(token_list);
+ ls_nxt(token_list,PPV &token);
+ while (token != NULL)
+ {
+ sprintf(linet1,"%04lu[%02lu]: ",
+ (ulong) token->tk_ps.ps_line,
+ (ulong) token->tk_ps.ps_column);
+ wf_wr(p_wf,linet1);
+ switch (token->tk_kind)
+ {
+ case TK_TEXT: m="Text." ; break;
+ case TK_MDEF: m="@$ Macro defn." ; break;
+ case TK_FDEF: m="@F File defn." ; break;
+ case TK_ONAM: m="@< Open name." ; break;
+ case TK_CNAM: m="@> Close name." ; break;
+ case TK_ODEF: m="@{ Open defn." ; break;
+ case TK_CDEF: m="@} Close defn." ; break;
+ case TK_OPAR: m="@( Open param." ; break;
+ case TK_CPAR: m="@} Close param." ; break;
+ case TK_COMA: m="@, Comma." ; break;
+ case TK_QUOT: m="@\" Quote." ; break;
+ case TK_PARM: m="@n Parameter." ; break;
+ case TK_ZERO: m="@Z Zero calls." ; break;
+ case TK_MANY: m="@M Many calls." ; break;
+ case TK_NAME: m="@# Name." ; break;
+ case TK_EMPH: m="@/ Emphasise." ; break;
+ case TK_NPAG: m="@t.. Newpage." ; break;
+ case TK_TOCS: m="@t.. TOC." ; break;
+ case TK_SKIP: m="@t.. Vertical skip."; break;
+ case TK_TITL: m="@t.. Title." ; break;
+ case TK_EOF : m="End Of File." ; break;
+ case TK_NSEC:
+ switch (token->tk_gen)
+ {
+ case 0: m="@* New section (Level 0)."; break;
+ case 1: m="@A New section (Level 1)."; break;
+ case 2: m="@B New section (Level 2)."; break;
+ case 3: m="@C New section (Level 3)."; break;
+ case 4: m="@D New section (Level 4)."; break;
+ case 5: m="@E New section (Level 5)."; break;
+ default: as_bomb("dmtkls: Level case defaulted.");
+ }
+ break;
+ default: as_bomb("dmtkls: Token case defaulted.");
+ }
+ wf_wr(p_wf,m);
+ wf_wr(p_wf," ");
+ switch (token->tk_kind)
+ {
+ case TK_PARM:
+ sprintf(linet1,"Parameterno=%u.",(unsigned) token->tk_gen);
+ wf_wl(p_wf,linet1);
+ break;
+ case TK_NAME:
+ wf_wr(p_wf,"Character='");
+ dm_byte(p_wf,token->tk_gen);
+ wf_wl(p_wf,"'.");
+ break;
+ case TK_TEXT:
+ dm_sc(p_wf,&token->tk_sc);
+ break;
+ case TK_SKIP:
+ sprintf(linet1,"Vertical space skipped=%lumm.",
+ (ulong) token->tk_gen);
+ wf_wl(p_wf,linet1);
+ break;
+ case TK_TITL:
+ font = token->tk_gen / LRFT_PACK;
+ align = token->tk_gen % LRFT_PACK;
+ wf_wr(p_wf,"Font="); wf_wr(p_wf,fontname(font));
+ wf_wr(p_wf,", Alignment="); wf_wr(p_wf,alignname(align));
+ wf_wl(p_wf,". Title text follows:");
+ dm_sc(p_wf,&token->tk_sc);
+ break;
+ default: wf_wl(p_wf,""); break;
+ }
+ ls_nxt(token_list,PPV &token);
+ } /* End of while loop. */
+
+ centerln(p_wf,DUMP_WIDTH,'=',"End of TOKEN LIST DUMP");
+ wf_wl(p_wf,"");
+}
+
+/******************************************************************************/
+
+LOCAL void dm_eltx P_((p_wf_t,p_el_t));
+LOCAL void dm_eltx (p_wf,p_el)
+/* Dumps the specified text element to the specified stream. */
+p_wf_t p_wf;
+p_el_t p_el;
+{
+ p_sc_t p_sc;
+
+ wf_wl(p_wf,"");
+ centerln(p_wf,30,'-',"Start Text Element");
+
+ ls_fir(p_el->el_text);
+ ls_nxt(p_el->el_text,PPV &p_sc);
+ while (p_sc != NULL)
+ {
+ dm_sc(p_wf,p_sc);
+ ls_nxt(p_el->el_text,PPV &p_sc);
+ }
+ centerln(p_wf,30,'-',"End Text Element");
+ wf_wl(p_wf,"");
+}
+
+/******************************************************************************/
+
+LOCAL void dm_elin P_((p_wf_t,p_el_t));
+LOCAL void dm_elin(p_wf,p_el)
+/* Dumps the specified invocation element to the specified stream. */
+p_wf_t p_wf;
+p_el_t p_el;
+{
+ ulong parno;
+ p_ells_t *pp_ex;
+ p_ells_t p_ex;
+ p_elll_t p_elll = p_el->el_parls;
+
+ wf_wl(p_wf,"");
+ centerln(p_wf,30,'-',"Begin Invocation Element");
+
+/* ABC { */
+ sprintf(
+ linet1,
+ "Invocation of macro @<%s@>",
+ /* ABC { */
+#if DYN_NAMES
+ p_el->el_p_mac->ma_name
+#else /* !DYN_NAMES */
+ &p_el->el_p_mac->ma_name[0]
+#endif /* DYN_NAMES */
+ /* } ABC */
+ );
+/* } ABC */
+ wf_wl(p_wf,linet1);
+
+ if (ls_len(p_elll)==0)
+ wf_wl(p_wf,"No actual parameters.");
+ else
+ {
+ sprintf(linet1,"This invocation has %lu actual parameters.",
+ (ulong) ls_len(p_elll));
+ wf_wl(p_wf,linet1);
+ wf_wl(p_wf,
+ "Actual parameter list follows as a sequence of expressions:");
+ wf_wl(p_wf,"(Text crud before and after parameter has been omitted).");
+ parno=1;
+ ls_fir(p_elll);
+ while (TRUE)
+ {
+ ls_nxt(p_elll,PPV &pp_ex);
+ if (pp_ex==NULL) break;
+ p_ex = *pp_ex;
+ sprintf(linet1,"Expression for parameter number %lu:",(ulong) parno);
+ wf_wl(p_wf,linet1);
+ dm_ex(p_wf,p_ex);
+ parno++;
+ }
+ }
+
+ centerln(p_wf,30,'-',"End Invocation Element");
+ wf_wl(p_wf,"");
+}
+
+/******************************************************************************/
+
+LOCAL void dm_elpr P_((p_wf_t,p_el_t));
+LOCAL void dm_elpr(p_wf,p_el)
+/* Dumps the specified parameter element to the specified stream. */
+p_wf_t p_wf;
+p_el_t p_el;
+{
+ wf_wl(p_wf,"");
+ centerln(p_wf,30,'-',"Start Parameter Element");
+ sprintf(linet1,"Parameter number=%lu.",(ulong) p_el->el_parno);
+ wf_wl(p_wf,linet1);
+ /* ABC { */
+ sprintf(
+ linet1,
+ "Parameter is of macro \"%s\".",
+ /* ABC { */
+#if DYN_NAMES
+ p_el->el_which->ma_name
+#else /* !DYN_NAMES */
+ &p_el->el_which->ma_name[0]
+#endif /* DYN_NAMES */
+ /* } ABC */
+ );
+ /* } ABC */
+ wf_wl(p_wf,linet1);
+ centerln(p_wf,30,'-',"End Parameter Element");
+ wf_wl(p_wf,"");
+}
+
+/* ABC { */
+/******************************************************************************/
+
+LOCAL void dm_elsp P_((p_wf_t,p_el_t));
+LOCAL void dm_elsp (p_wf,p_el)
+/* Dumps the specified special function result to the specified stream. */
+p_wf_t p_wf;
+p_el_t p_el;
+{
+ wf_wl(p_wf,"");
+ centerln(p_wf,30,'-',"Start Special Function");
+
+ centerln(p_wf,30,'-',"End Special Function");
+ wf_wl(p_wf,"");
+}
+
+/* } ABC */
+
+/******************************************************************************/
+
+LOCAL void dm_ex(p_wf,p_ex)
+/* Dumps the specified expression to the specified stream. */
+p_wf_t p_wf;
+p_ells_t p_ex;
+{
+ p_el_t p_el;
+
+ wf_wl(p_wf,"");
+ centerln(p_wf,30,'-',"Start of Expression");
+ ls_fir(p_ex);
+ ls_nxt(p_ex,PPV &p_el);
+ while (p_el != NULL)
+ {
+ switch (p_el->el_kind)
+ {
+ case EL_TEXT: dm_eltx(p_wf,p_el); break;
+ case EL_INVC: dm_elin(p_wf,p_el); break;
+ case EL_PARM: dm_elpr(p_wf,p_el); break;
+ /* ABC { */
+ case EL_SPEC: dm_elsp(p_wf,p_el); break;
+ /* } ABC */
+ default : as_bomb("dm_ex: Case defaulted.");
+ }
+ ls_nxt(p_ex,PPV &p_el);
+ }
+ centerln(p_wf,30,'-',"End of Expression");
+ wf_wl(p_wf,"");
+}
+
+/******************************************************************************/
+
+LOCAL void dm_macro P_((p_wf_t,p_ma_t));
+LOCAL void dm_macro(p_wf,p_ma)
+/* Dump all the information on the specified macro. */
+p_wf_t p_wf;
+p_ma_t p_ma;
+{
+ wf_wl(p_wf,"");
+ centerln(p_wf,DUMP_WIDTH-20,'-',"Start of Macro Dump");
+
+ /* A macro can't exist in the macro table without a name. */
+ sprintf(linet1,"Macro Name : \"%s\"",p_ma->ma_name); wf_wl(p_wf,linet1);
+
+ /* Is the macro defined? */
+ if (!p_ma->ma_defn.md_isdef) wf_wl(p_wf,"Defined? : No.");
+ else wf_wl(p_wf,"Defined? : Yes.");
+
+ /* Defined macros carry lots more information. */
+ if (p_ma->ma_defn.md_isdef)
+ {
+ /* Number of parameters the macro has. */
+ sprintf(linet1,"Parameters : %lu",(ulong) p_ma->ma_defn.md_npar);
+ wf_wl(p_wf,linet1);
+
+ /* Is the macro additive? */
+ if (p_ma->ma_defn.md_isadd) wf_wl(p_wf,"Additive? : Yes.");
+ else wf_wl(p_wf,"Additive? : No.");
+
+ /* Is the macro allowed to be called zero times? */
+ if (p_ma->ma_defn.md_iszer) wf_wl(p_wf,"Zero Calls? : Yes.");
+ else wf_wl(p_wf,"Zero Calls? : No.");
+
+ /* Is the macro allowed to be called many times? */
+ if (p_ma->ma_defn.md_isman) wf_wl(p_wf,"Many Calls? : Yes.");
+ else wf_wl(p_wf,"Many Calls? : No.");
+
+ /* Is the macro connected to an product file? */
+ if (p_ma->ma_defn.md_isfil) wf_wl(p_wf,"Output File?: Yes.");
+ else wf_wl(p_wf,"Output File?: No.");
+
+/* ABC { */
+ /* Is there an automatic line directive macro? */
+ if (p_ma->ma_defn.md_aldm != NULL) {
+ wf_wl(p_wf,"Automatic Line Directive Macro?: Yes.");
+ wf_wr(p_wf," macro name: ");
+ if (p_ma->ma_defn.md_aldm->lnmac == NULL)
+ wf_wr(p_wf, "NULL");
+ else
+ wf_wr(p_wf, p_ma->ma_defn.md_aldm->lnmac);
+ wf_wr(p_wf,", source type: ");
+ if (p_ma->ma_defn.md_aldm->typnam == NULL)
+ wf_wl(p_wf, "NULL");
+ else
+ wf_wl(p_wf, p_ma->ma_defn.md_aldm->typnam);
+ } else {
+ wf_wl(p_wf,"Automatic Line Directive Macro?: No.");
+ } /* end if */
+/* } ABC */
+
+ /* Dump a list of all the calls to the macro. */
+ {
+ p_mc_t p_mc;
+ ulong mcnum;
+ wf_wl(p_wf,"Call list :");
+ ls_fir(p_ma->ma_calls);
+ ls_nxt(p_ma->ma_calls,PPV &p_mc);
+ mcnum=1;
+ while (p_mc != NULL)
+ {
+ sprintf(linet1,
+ " Call %lu: Parameters=%lu, Sequence num=%lu, Position(L,C)=(%lu,%lu).",
+ (ulong) mcnum,
+ (ulong) p_mc->mc_npar,
+ (ulong) p_mc->mc_seq,
+ (ulong) p_mc->mc_ps.ps_line,
+ (ulong) p_mc->mc_ps.ps_column);
+ wf_wl(p_wf,linet1);
+ ls_nxt(p_ma->ma_calls,PPV &p_mc);
+ mcnum++;
+ }
+ }
+
+ /* Dump a list of the body parts of the macro. */
+ {
+ p_bp_t p_bp;
+ ulong bpnum;
+ ulong bptot = ls_len(p_ma->ma_defn.md_body);
+ wf_wl(p_wf,"Macro body :");
+ wf_wl(p_wf,"");
+ wf_wl(p_wf,"--Start of List of Body Parts--");
+ sprintf(linet1,"This macro has %lu body part",(ulong) bptot);
+ if (bptot!=1) strcat(linet1,"s");
+ strcat(linet1,".");
+ wf_wl(p_wf,linet1);
+ bpnum=1;
+ ls_fir(p_ma->ma_defn.md_body);
+ ls_nxt(p_ma->ma_defn.md_body,PPV &p_bp);
+ while (p_bp != NULL)
+ {
+ sprintf(linet1,
+ "Body part %lu: Seqnum=%lu, Pos(L,C)=(%lu,%lu), Expression follows:",
+ (ulong) bpnum,
+ (ulong) p_bp->bp_seq,
+ (ulong) p_bp->bp_ps.ps_line,
+ (ulong) p_bp->bp_ps.ps_column);
+ wf_wl(p_wf,linet1);
+ dm_ex(p_wf,p_bp->bp_ex);
+ ls_nxt(p_ma->ma_defn.md_body,PPV &p_bp);
+ bpnum++;
+ }
+ wf_wl(p_wf,"---End of List of Body Parts---");
+ wf_wl(p_wf,"");
+ }
+
+ } /* End of IF defined. */
+
+ centerln(p_wf,DUMP_WIDTH-20,'-',"End of Macro Dump");
+ wf_wl(p_wf,"");
+}
+
+/******************************************************************************/
+
+EXPORT void dm_matb P_((p_wf_t));
+EXPORT void dm_matb(p_wf)
+p_wf_t p_wf;
+{
+ wf_wl(p_wf,"");
+ centerln(p_wf,DUMP_WIDTH,'=',"Start of MACRO TABLE DUMP");
+ wf_wl(p_wf,"");
+ tb_fir(macro_table);
+ while (TRUE)
+ {
+ name_t name;
+ p_ma_t p_ma;
+ if (!tb_rea(macro_table,PV &name[0],PV &p_ma)) break;
+ dm_macro(p_wf,p_ma);
+ wf_wl(p_wf,"");
+ }
+ wf_wl(p_wf,"");
+ centerln(p_wf,DUMP_WIDTH,'=',"End of MACRO TABLE DUMP");
+ wf_wl(p_wf,"");
+}
+
+/******************************************************************************/
+
+LOCAL void dm_ty P_((p_wf_t,p_ty_t));
+LOCAL void dm_ty(p_wf,p_ty)
+p_wf_t p_wf;
+p_ty_t p_ty;
+{
+ char linet2[200];
+ char linet3[200];
+
+ switch (p_ty->ty_kind)
+ {
+ case TY_NSEC:
+ sn_str(&p_ty->ty_sn,linet2);
+ strcpy(linet3,"<No name>");
+ /* ABC { */
+#if DYN_NAMES
+ if (p_ty->ty_isnam) strcpy(linet3,p_ty->ty_name);
+#else /* !DYN_NAMES */
+ if (p_ty->ty_isnam) strcpy(linet3,&p_ty->ty_name[0]);
+#endif /* DYN_NAMES */
+ /* } ABC */
+ sprintf(linet1," Section \"%s\", Section name=\"%s\".",linet2,linet3);
+ wf_wl(p_wf,"");
+ wf_wl(p_wf,linet1);
+ break;
+ case TY_OLIT: wf_wl(p_wf," Open literal." ); break;
+ case TY_CLIT: wf_wl(p_wf," Close literal." ); break;
+ case TY_OEMP: wf_wl(p_wf," Open emphasise." ); break;
+ case TY_CEMP: wf_wl(p_wf," Close emphasise." ); break;
+ case TY_NPAG: wf_wl(p_wf," New page." ); break;
+ case TY_TOCS: wf_wl(p_wf," Table of contents."); break;
+ case TY_SKIP:
+ sprintf(linet1," Vertical skip by %lu mm.",(ulong) p_ty->ty_mm);
+ wf_wl(p_wf,linet1);
+ break;
+ case TY_TITL:
+ wf_wr(p_wf,"Font="); wf_wr(p_wf,fontname(p_ty->ty_font));
+ wf_wr(p_wf,", Alignment="); wf_wr(p_wf,alignname(p_ty->ty_align));
+ wf_wl(p_wf,". Title text follows:");
+ dm_sc(p_wf,&p_ty->ty_sc);
+ break;
+ default: as_bomb("dm_ty: Typesetter directive switch defaulted.");
+ }
+}
+
+/******************************************************************************/
+
+EXPORT void dm_dcls(p_wf)
+/* Dumps a text representation of the document list to the given stream. */
+p_wf_t p_wf;
+{
+ wf_wl(p_wf,"");
+ centerln(p_wf,DUMP_WIDTH,'=',"Start of DOCUMENT LIST DUMP");
+ wf_wl(p_wf,"");
+
+ ls_fir(document_list);
+ while (TRUE)
+ {
+ p_dc_t p_dc;
+ ls_nxt(document_list,PPV &p_dc);
+ if (p_dc == NULL) break;
+ wf_wl(p_wf,"");
+ sprintf(linet1,"Pos(L,C)=(%lu,%lu). ",
+ p_dc->dc_ps.ps_line,
+ p_dc->dc_ps.ps_column);
+ switch (p_dc->dc_kind)
+ {
+ case DC_TEXT:
+ wf_wr(p_wf,"TEXT COMPONENT: "); wf_wl(p_wf,linet1);
+ dm_scls(p_wf,p_dc->dc_text);
+ break;
+
+ case DC_TYPE:
+ wf_wr(p_wf,"TYPESETTER DIRECTIVE COMPONENT: ");
+ dm_ty(p_wf,&p_dc->dc_ty);
+ break;
+
+ case DC_MACR:
+ wf_wr(p_wf,"MACRO DEFINITION COMPONENT: "); wf_wl(p_wf,linet1);
+ /* ABC { */
+ sprintf(linet1,"Part %lu of macro @<%s@>.",
+ p_dc->dc_part,
+#if DYN_NAMES
+ p_dc->dc_p_ma->ma_name
+#else /* !DYN_NAMES */
+ &p_dc->dc_p_ma->ma_name[0]
+#endif /* DYN_NAMES */
+ );
+ /* } ABC */
+ wf_wl(p_wf,linet1);
+ break;
+
+ default: as_bomb("dm_scls: Case defaulted.");
+ }
+ }
+
+ wf_wl(p_wf,"");
+ centerln(p_wf,DUMP_WIDTH,'=',"End of DOCUMENT LIST DUMP");
+ wf_wl(p_wf,"");
+}
+
+/******************************************************************************/
+
+LOCAL void tm_for P_((p_wf_t,char *,p_ck_t,p_ck_t));
+LOCAL void tm_for(p_wf,s,p_val,p_tot)
+/* This rather ragged function simplifies the formatting in dm_times. */
+p_wf_t p_wf;
+char *s;
+p_ck_t p_val;
+p_ck_t p_tot;
+{
+ sprintf(linet1,"|%s| %3d%% | %8.2f | %8.2f | %3d%% |",
+ s,
+ (int) ((100.0*ck_cpu(p_val))/ck_cpu(p_tot)),
+ (float) ck_cpu(p_val),
+ (float) ck_real(p_val),
+ (int) ((100.0*ck_real(p_val))/ck_real(p_tot))
+ );
+ wf_wl(p_wf,linet1);
+}
+
+/******************************************************************************/
+
+EXPORT void dm_times(p_wf,
+ p_mapp,p_scan,p_pars,p_anal,
+ p_dump,p_lstr,p_tang,p_weav,p_totl)
+p_wf_t p_wf;
+p_ck_t p_mapp;
+p_ck_t p_scan;
+p_ck_t p_pars;
+p_ck_t p_anal;
+p_ck_t p_dump;
+p_ck_t p_lstr;
+p_ck_t p_tang;
+p_ck_t p_weav;
+p_ck_t p_totl;
+{
+ float cputot;
+ float realtot;
+ float cpuerr;
+ float realerr;
+
+ cputot = ck_cpu(p_mapp) + ck_cpu(p_scan) + ck_cpu(p_pars) +
+ ck_cpu(p_anal) + ck_cpu(p_dump) + ck_cpu(p_lstr) +
+ ck_cpu(p_tang) + ck_cpu(p_weav);
+
+ realtot = ck_real(p_mapp) + ck_real(p_scan) + ck_real(p_pars) +
+ ck_real(p_anal) + ck_real(p_dump) + ck_real(p_lstr) +
+ ck_real(p_tang) + ck_real(p_weav);
+
+ cpuerr = ck_cpu (p_totl)-cputot;
+ realerr = ck_real(p_totl)-realtot;
+
+ wf_wl(p_wf,"");
+ wf_wl(p_wf,"Summary of time used by each subsystem of Funnelweb (seconds).");
+ wf_wl(p_wf,"");
+ wf_wl(p_wf, "+------------+------+----------+----------+------+");
+ wf_wl(p_wf, "| Subsystem | CPU% | CPU Time | RealTime | RT% |");
+ wf_wl(p_wf, "+------------+------+----------+----------+------+");
+ tm_for(p_wf," Mapper ",p_mapp,p_totl);
+ tm_for(p_wf," Scanner ",p_scan,p_totl);
+ tm_for(p_wf," Parser ",p_pars,p_totl);
+ tm_for(p_wf," Analyser ",p_anal,p_totl);
+ tm_for(p_wf," Dumper ",p_dump,p_totl);
+ tm_for(p_wf," Lister ",p_lstr,p_totl);
+ tm_for(p_wf," Tangler ",p_tang,p_totl);
+ tm_for(p_wf," Weaver ",p_weav,p_totl);
+ sprintf(linet1,"|%s| %3d%% | %8.2f | %8.2f | %3d%% |",
+ " Clock Err ",
+ (int) ((100.0*cpuerr )/ck_cpu (p_totl)),
+ (float) cpuerr,
+ (float) realerr,
+ (int) ((100.0*realerr)/ck_real(p_totl))
+ );
+ wf_wl(p_wf,linet1);
+
+ wf_wl(p_wf, "+------------+------+----------+----------+------+");
+ tm_for(p_wf," Total ",p_totl,p_totl);
+ wf_wl(p_wf, "+------------+------+----------+----------+------+");
+ wf_wl(p_wf,"");
+}
+
+/******************************************************************************/
+/* End of DUMP.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/dump.h b/web/funnelAC/fwACsrc/dump.h
new file mode 100644
index 0000000000..a02222428f
--- /dev/null
+++ b/web/funnelAC/fwACsrc/dump.h
@@ -0,0 +1,78 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* DUMP.H */
+/******************************************************************************/
+/* */
+/* This package contains functions that dump text representations of */
+/* FunnelWeb data structures. Each function accepts a wf stream on which it */
+/* writes its text representation. These functions are used in testing and */
+/* debugging only and are not used ordinarily in the program. */
+/* */
+/******************************************************************************/
+
+#include "style.h"
+
+#include "clock.h"
+#include "writfile.h"
+
+/******************************************************************************/
+
+EXPORT void dm_mem P_((p_wf_t,char *,ulong));
+/* Writes a hex and ascii dump of the specified block of memory to the */
+/* specified stream. */
+
+EXPORT void dm_lnls P_((p_wf_t));
+/* Dumps a text representation of the global line list to the given stream. */
+
+EXPORT void dm_tkls P_((p_wf_t));
+/* Dumps a text representation of the global token list to the given stream. */
+
+EXPORT void dm_matb P_((p_wf_t));
+/* Dumps a text representation of the macro table to the given stream. */
+
+EXPORT void dm_dcls P_((p_wf_t));
+/* Dumps a text representation of the document list to the given stream. */
+
+EXPORT void dm_times P_((p_wf_t,p_ck_t,p_ck_t,p_ck_t,p_ck_t,
+ p_ck_t,p_ck_t,p_ck_t,p_ck_t,p_ck_t));
+/* Dumps a text representation of the execution times to the given stream. */
+
+/******************************************************************************/
+/* End of DUMP.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/environ.h b/web/funnelAC/fwACsrc/environ.h
new file mode 100644
index 0000000000..daad4f871c
--- /dev/null
+++ b/web/funnelAC/fwACsrc/environ.h
@@ -0,0 +1,316 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+ JMS John Max Skaller maxtal@suphys.physics.su.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 16-Sep-1993 ABC Added machine type OSF64 for a 64-bit processor
+ running OSF/1 (particularly the DEC AXP).
+ 14-Dec-1993 ABC Added machine type OS2 for PCs running OS/2 2.1.
+ 15-Jun-1994 ABC Added machine type LINUX for PCs running
+ LINUX 1.1.8
+ 18-Sep-1994 ABC Added NO_FCASE definition for file systems
+ (like DOS and OS/2) which are case insensitive.
+ 13-Aug-1995 JMS Added PC32 type for 32-bit DOS-extended code.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* ENVIRON.H */
+/******************************************************************************/
+/* */
+/* WARNING: DO NOT ADD ANY PROGRAM-DEPENDENT DEFINITIONS. */
+/* */
+/* This header file environ.h contains definitions and objects whose values */
+/* depends directly on the compilation and execution environment, but are */
+/* otherwise independent of any particular computer program. */
+/* */
+/* This is one of two machine-dependent, program-independent modules. The */
+/* other module is machin (machin.h,machin.c). This "environ" module contains */
+/* definitions and objects that are considered essential. The "machin" module */
+/* contains less essential definitions. Motivation for the division came from */
+/* the fact that style.h (used by almost every module) includes environ.h */
+/* (this file), and from the need for the stuff in style.h by some */
+/* environment-dependent definitions. */
+/* */
+/* There seems to be two ways to organize a module such as this one. The */
+/* first is to have a different version of this module for each target */
+/* environment. The second is to have a single file that uses #defines and */
+/* #ifs to select between code for each target environment. I have chosen the */
+/* latter method as this allows many different environments to share the same */
+/* definitions. */
+/* */
+/******************************************************************************/
+
+/* Ensure that the body of this header file is included at most once. */
+#ifndef DONE_ENVIRON
+#define DONE_ENVIRON
+
+/******************************************************************************/
+
+/* Select An Environment */
+/* --------------------- */
+/* Choose the environment in which the program will be compiled and executed. */
+/* This may be the only change you need to make to get FunnelWeb to compile. */
+/* */
+/* If your exact environment is not listed, try one that is close. */
+/* If problems arise, an attempt should be made to solve them */
+/* without creating a new environment definition. However, if this is not */
+/* possible, define a new environment below and "implement" it by going */
+/* through environ.h and machin.h and machin.c and adding appropriate */
+/* definitions. */
+/* */
+/* The following table lists real/defined environment pairs under which */
+/* FunnelWeb is known to compile cleanly. */
+/* */
+/* Symbol = Processor Machine OS Compiler */
+/* ------ --------- ------- -- -------- */
+/* MAC = 68000 Macintosh-SE Mac THINK-C V4.0.5 */
+/* SUN = SPARC SUN ELC Unix(SunOS) GNUC */
+/* VMS = VAX VAXStation VMS VAXC */
+/* PC = 386 IBM PC Clone MSDOS5.0 Borland C++ */
+/* ABC { */
+/* OSF64 = 64bit e.g. DEC AXP Unix(OSF/1) c89 */
+/* OS2 = 32bit IBM PC Clone OS/2 2.1 GNUC (emx 0.8h) */
+/* LINUX = 32bit IBM PC Clone Linux 1.1.8 GNUC */
+/* } ABC */
+/* JMS { */
+/* PC32 = 32bit IBM PC Clone DOS EXTENDER Borland C++ */
+/* } JMS */
+/* */
+/* Set exactly one of the following environments to 1, the others to 0. */
+
+#define MAC 0
+#define SUN 0
+#define VMS 0
+#define PC 0
+/* ABC { */
+#define OSF64 1
+#define OS2 0
+#define LINUX 0
+/* } ABC */
+/* JMS { */
+#define PC32 0
+/* } JMS */
+/* Ensure that exactly one environment has been selected. */
+/* ABC/JMS { */
+#if MAC+SUN+VMS+PC+OSF64+OS2+LINUX+PC32 != 1
+/* } ABC/JMS */
+ #error Error: You must choose exactly one machine in ENVIRON.H.
+#endif
+
+/******************************************************************************/
+
+/* Establish Presence or Absence of __STDC__ */
+/* ----------------------------------------- */
+/* The __STDC__ symbol is very useful for determining if the compiler is */
+/* ANSI. However, some "nearly ANSI" compilers don't set this symbol, and */
+/* experience shows that things turn out better if it is set. */
+/* This section decides if __STDC__ should be defined. */
+
+/* The Macintosh THINK C compiler seems to be ANSI standard but, strangely */
+/* does not define the standard preprocessor symbol __STDC__ that indicates */
+/* this. Instead it defines THINK_C. Here, we execute the link manually. */
+/* For more information see the THINK C User's Manual, Chapter 57: "Language */
+/* Reference", Section 12.10, p.442. */
+#ifdef THINK_C
+#define __STDC__ 1
+#endif
+
+/* The problem seems to exist with VAX C too. */
+#if VMS
+#define __STDC__ 1
+#endif
+
+/******************************************************************************/
+
+/* Switch From Definedness to Boolean Symbols */
+/* ------------------------------------------ */
+/* Use of the definedness of a preprocessor symbol to detect a condition is */
+/* convenient if it is desired that only one condition be tested at a time. */
+/* However, if we want to OR conditions, it is more convenient to use defined */
+/* symbols that are either 0 or 1. This section contains ifdefs that do this. */
+
+#ifdef __STDC__
+#define STDC 1
+#else
+#define STDC 0
+#endif
+
+/* Note: If THINK_C is predefined, it is predefined to be 1. */
+#ifndef THINK_C
+#define THINK_C 0
+#endif
+
+/******************************************************************************/
+
+/* Void */
+/* ---- */
+/* Define void if necessary and define pointer to void. */
+/* This idea from the book "Portable C", p.41. */
+/* If necessary, add a boolean condition to cover your environment. */
+/* Note: The "| SUN" is a last minute desperate hack. */
+#if STDC | SUN
+typedef void *p_void;
+#else
+typedef int void;
+typedef char *p_void;
+#endif
+
+/* The following function is here solely to act as a first tripping point for */
+/* environments with no "void" so that the users trying to port this code */
+/* will look here first instead of starting to delete voids in the program. */
+extern void test_void();
+
+/******************************************************************************/
+
+/* Const */
+/* ----- */
+/* It's useful to be able to specify that certain objects are constants. */
+/* Unfortunately, the "const" construct is only available in ANSI C and so we */
+/* have to have a macro so as to cope with non-ANSI compilers. */
+/* Note: THINK-C is nearly ANSI, but does not support "const". */
+#if STDC & !THINK_C
+#define CONST const
+#else
+#define CONST
+#endif
+
+/******************************************************************************/
+
+/* Prototypes */
+/* ---------- */
+/* Define a macro to wrap around prototype parameter lists so as to support */
+/* compilers with and without prototypes. */
+/* This idea came from the book "Portable C", S3.1, p.32. */
+#if STDC
+#define P_(A) A
+#else
+#define P_(A) ()
+#endif
+
+/******************************************************************************/
+
+/* Structure Assignments */
+/* --------------------- */
+/* Structure assignments are not supported on some of the older compilers and */
+/* so we use a macro to perform such operations. */
+/* This idea came from the book "Portable C", S8.2.2, p.184. */
+#if STDC
+#define ASSIGN(a,b) ((a)=(b))
+#else
+#define ASSIGN(a,b) (memcpy((char *)&(a),(char *)&(b),sizeof(a)))
+#endif
+
+/******************************************************************************/
+
+/* VMS EXIT STATUS */
+/* --------------- */
+/* The VAX C compiler I used doesn't seem to be ANSI. This means that the */
+/* exit symbols aren't set up properly. Furthermore, the sensible defaults */
+/* in the style.h file don't work for VMS. The upshot is that we have to do */
+/* a special case. Note: The top bit set in a VMS exit status means suppress */
+/* diagnostic message. Even status means failure. Odd means success. */
+#if VMS
+#undef EXIT_SUCCESS
+#undef EXIT_FAILURE
+#define EXIT_SUCCESS 1
+#define EXIT_FAILURE (0x10000002)
+#endif
+
+/******************************************************************************/
+/* ABC { */
+/* MACHINE DEPENDENT TYPEDEFS */
+/* -------------------------- */
+/* These are used in `style.h'. */
+typedef int int_t;
+typedef short short_t;
+#if !OSF64
+/* General types, taken from OSF/1 definitions */
+typedef char char_t;
+typedef long long_t;
+typedef unsigned char uchar_t, uchar;
+#if LINUX
+#include <linux/types.h>
+typedef ushort ushort_t;
+typedef unsigned int uint_t;
+typedef ulong ulong_t;
+#else /* !LINUX */
+typedef unsigned short ushort_t, ushort;
+typedef unsigned int uint_t, uint;
+typedef unsigned long ulong_t, ulong;
+#endif /* LINUX */
+
+#if defined(_LONGLONG)
+typedef long long longlong_t, longlong;
+typedef unsigned long long ulonglong_t, ulonglong;
+#else
+typedef long longlong_t, longlong;
+typedef unsigned long ulonglong_t, ulonglong;
+#endif
+
+typedef void *pointer;
+typedef double double_t;
+typedef float float_t;
+#endif /* !OSF64 */
+/* } ABC */
+
+/******************************************************************************/
+/* ABC { */
+/* Case insensitive filesystems */
+/* ============================ */
+/* Some filesystems, like those of DOS and OS/2, are case *
+ * insensitive (although OS/2 HPFS file systems preserve *
+ * the case of filenames, they consider two file names *
+ * which only differ in case to refer to the same file. *
+ * The NO_FCASE definition tells FunnelWeb to compare *
+ * file macro names in a case-insensitive manner to match *
+ * the way the file system works. */
+
+/* NOTE: case-insensitive filename checking is not yet *
+ * implemented. */
+
+#if PC || PC32 || OS2
+#define NO_FCASE=1
+#endif /* PC || PC32 || OS2 */
+
+/* } ABC */
+
+/******************************************************************************/
+
+/* For #ifndef preventing multiple inclusion of the body of this header file. */
+#endif
+
+/******************************************************************************/
+/* End of ENVIRON.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/err.status b/web/funnelAC/fwACsrc/err.status
new file mode 100644
index 0000000000..aac6d3cb99
--- /dev/null
+++ b/web/funnelAC/fwACsrc/err.status
@@ -0,0 +1 @@
+1 Severe error, 271 Errors and 10 Warnings : Different = 23
diff --git a/web/funnelAC/fwACsrc/fw-latex.sty b/web/funnelAC/fwACsrc/fw-latex.sty
new file mode 100644
index 0000000000..2d35861581
--- /dev/null
+++ b/web/funnelAC/fwACsrc/fw-latex.sty
@@ -0,0 +1,327 @@
+%* Last edited: Apr 8 15:20 1993 (richard)
+%=================== Start of FunnelWeb LaTeX Definitions ====================
+
+
+% Version
+% -------
+% This is FunnelWeb LaTeX Macro Library Version 1.0.
+
+
+% Copyright
+% ---------
+% This set of FunnelWeb LaTeX definitions was written by Richard Walker
+% and Ross Williams and was
+% originally Copyright (C) 1992 Ross N. Williams. It isn't now.
+
+
+% Modification
+% ------------
+% Please record all modifications to these LaTeX definitions here. Unless
+% otherwise specified, all modified definitions fall in the public domain too.
+%
+% Programmers:
+% RNW Ross N. Williams ross@spam.adelaide.edu.au
+% RJW Richard Walker richard@cs.anu.edu.au
+%
+% Changes:
+% 07-May-1992 RNW Prepared this work for public domain release.
+% 6 April 1993 RJW Started work on LaTeX definitions
+%
+
+% Please send bug reports to Richard at the above email address.
+
+
+% General Comments
+% ----------------
+% This set of LaTeX definitions exists for two reasons:
+%
+% 1. To shorten and neaten the FunnelWeb LaTeX output.
+% 2. To allow users to fiddle with the output format in their input files
+% (by inserting redefining "\renewcommand"s) without having to resort to
+% modifying the FunnelWeb code.
+%
+% The user is warned that these definitions may be changed from time to time
+% (but probably not much). The user should not be too sneaky. In particular,
+% users wishing to redefine some of these macros should do so in an explicitly
+% defined section at the top of their input file. This will mean that in the
+% event of problems, that section can simply be deleted or commented out to
+% allow the document to at least be typeset in the default format. Users should
+% limit themselves to redefining these macros in such a section and should
+% refrain from using the macros throughout their documents.
+
+
+% Environment Parameters
+% ----------------------
+% \tolerance tells LaTeX how tolerant it should be about making bad line and
+% page breaks. Here we set it to it's maximum, as
+% 1) Computer programs are likely to cause lots of bad breaks.
+% 2) In most cases the user would probably rather get the LaTeX file through
+% LaTeX without any errors than fiddle with spacings for perfection.
+\tolerance=10000
+
+%% I don't like indentation as it makes the page look more busy. Instead,
+%% paragraphs are separated by a little space (see next).
+\parindent=0pt
+
+% I *do* like indentation. RJW
+
+% In many cases, users will produce documents with long runs of paragraphs.
+% In order to space out these paragraphs, it is convenient to maintain a
+% prevailing non-zero \parskip (end-of-paragaph skip). The only trouble is
+% that the skip becomes a problem in macro definitions which require no skip
+% and so we have to turn the skip on and off. The following two macros
+% simplify this process.
+\newcommand{\fwparskipon}{\parskip=\medskipamount}
+\newcommand{\fwparskipoff}{\parskip=0pt}
+\fwparskipon
+
+% Setting raggedbottom allows LaTeX to leave a bit of space at the
+% bottom of the page in order to better vertically align the rest of
+% the page (e.g. skips won't stretch as much). It also means that
+% headings are less likely to be isolated at the bottom of the page
+% without any following text.
+
+\raggedbottom
+
+
+% Fonts
+% -----
+% Most of the typeset output is set in 10pt roman and 10pt tt font.
+% The major extra font needs spring from titles and headings.
+% For portability's sake we use only the following fonts:
+% cmr10
+% cmbx10
+% cmtt10
+% and some enlargements of them. These fonts are all "standard" fonts
+% in Plain TeX. See The TeXbook p.350.
+\newcommand{\fwfontnote}{\scriptsize}
+
+\newcommand{\fwfontnorm}{\normalsize}
+\newcommand{\fwfontnorma}{\large}
+\newcommand{\fwfontnormb}{\Large}
+
+\newcommand{\fwfontbold}{\normalsize\bf}
+\newcommand{\fwfontbolda}{\large\bf}
+\newcommand{\fwfontboldb}{\Large\bf}
+\newcommand{\fwfontboldc}{\LARGE\bf}
+\newcommand{\fwfontboldd}{\huge\bf}
+
+
+% Macros for Stylistic Details
+% ----------------------------
+% This section contains all the fiddly little macros for setting the details
+% of each macro definition.
+
+% Macro definitions are sandwiched by calls to these macros which can be used
+% to sort out the spacing before and after the macro definition.
+\newcommand{\fwbeginmacro}{\fwparskipoff\bigbreak}
+\newcommand{\fwendmacro}{\fwparskipon\par}
+
+% These macros deal with the macro name and definition line.
+\newcommand{\fwmacroname}[2]{{\sl #1\/}$\lbrack$#2$\rbrack$}
+\newcommand{\fwfilename}[2]{{\bf #1}$\lbrack$#2$\rbrack$}
+\newcommand{\fwzero}[1]{{\bf Z}}
+\newcommand{\fwmany}[1]{{\bf M}}
+\newcommand{\fwequals}{ $\equiv$}
+\newcommand{\fwplusequals}{ $+\equiv$}
+
+% Now for the actual body of the definition. It looks nice to have the tt
+% code indented a little. Again, we use macros instead of writing direct TeX,
+% so as to allow the user to fiddle this stuff to taste without having to
+% modify the FunnelWeb C code.
+\newcommand{\fwodef}{\parindent=15pt\vskip0pt$\lbrace$\parindent=20pt}
+\newcommand{\fwcdef}{$\rbrace$\vskip0pt\parindent=0pt}
+\newcommand{\fwoquote}{`}
+\newcommand{\fwcquote}{'}
+\newcommand{\fwoparen}{$($}
+\newcommand{\fwcomma}{$,$}
+\newcommand{\fwcparen}{$)$}
+\newcommand{\fwparam}[1]{$\diamond #1$}
+\newcommand{\fwparams}[1]{$(\diamond #1)$}
+
+% These macros deal with the notes that are appended at the end of each
+% macro definition. Note that even though \fwisafile,\fwusedin, and \fwseealso
+% have the same definition, they are given different names so as to allow the
+% user to redefine these macros to typeset each kind of information differently
+% if desired.
+\newcommand{\fwbeginmacronotes}{\begingroup\baselineskip=9pt\smallbreak}
+\newcommand{\fwnote}[1]{{\fwfontnote #1}\par}
+\newcommand{\fwisafile}[1]{\fwnote{#1}}
+\newcommand{\fwusedin}[1]{\fwnote{#1}}
+\newcommand{\fwseealso}[1]{\fwnote{#1}}
+\newcommand{\fwendmacronotes}{\endgroup}
+
+
+% Macros to Typeset Program Code Verbatim
+% ---------------------------------------
+% This is by far the hairiest and most difficult part of the typesetting task
+% because we have to turn off most of TeX's natural instincts in order to
+% typeset the program text exactly as it appears in the input file.
+% Two macros are defined to pull this off: \fwbtx and \fwverbatimgobble.
+% Their code was inspired by the following sections of "The TeXbook":
+% Appendix D: Dirty Tricks, 3.Verbatim listing, p.380-382.
+% Appendix E: Example Formats, p.421.
+% The \fwbtx[ (for "FunnelWeb Begin TeXt") macro does most of the hard work.
+% The liberal use of "%" is because I don't understand TeX well enough to
+% understand when an end of line will cause trouble, and I am playing it safe.
+
+% Before defining the main \fwbtx macro, we have to stash away some definitions
+% in the hidden part of TeX's environment. Let's hope that these "hidden"
+% definitions don't affect anything except what is desired to be affected.
+
+% The tt font in which we wish to set the text has two Latin lurking ligatures!
+% These are ?` and !`. To disable them, we define the left quote when ACTIVE
+% to be defined in such a way as to prevent ligatures. The main LaTeX text will
+% normally not be exposed to this definition because normally the leftquote
+% character is not active. The \fwbtx macro temporarily makes the left quote
+% character active thus activating the deactivation of left quote ligatures.
+% See The TeXbook p.381.
+{\catcode`\`=\active \gdef`{\relax\lq}}
+
+% LaTeX is fairly carefree about spaces and so we have to make it more serious.
+% To do so we pull the same trick as above, setting up a definition for active
+% space, but only making space active during the span of the verbatim text.
+% In Plain TeX the active space is defined to be simply a space, but here we
+% define it to be a control space. This ensures that the space cannot
+% be gobbled up by one of TeX's mysterious mechanisms when activated.
+% See The TeXbook, p.381 and p.352.
+{\obeyspaces\global\let =\ }
+
+% Here is the main \fwbtx verbatim text macro.
+% Note: The order in which all these pieces of business have to be done is
+% still a partial mystery to me. Don't fiddle with this stuff unless you
+% think you know what you are doing.
+\def\fwbtx[{%
+%
+% The funnies involved in getting verbatim output are safely housed inside
+% this \begingroup, and the \endgroup in \fwverbatimgobble. Groups are used
+% instead of curly braces because we have to be able to signal the end of
+% this macro with a curly brace.
+\begingroup%
+%
+% \pars at the end of empty lines in the verbatim text won't come out normally
+% because LaTeX is in vertical mode and they get gobbled up. To prevent this,
+% we force \par to exit vertical mode first. See The TeXbook p.381.
+\def\par{\leavevmode\endgraf}%
+%
+% Activate the leftquote character so as to avoid ligatures (see above).
+\catcode`\`=\active%
+%
+% The \obeylines macro simply defines end of line (^M) to be \par. This ensures
+% that LaTeX will treat each verbatim line as a new paragraph.
+\obeylines%
+%
+% To get verbatim output, we have to desex all the special characters. This
+% is explained in detail in The TeXbook p.380.
+\def\do##1{\catcode`##1=12 }\dospecials%
+%
+% Activate the space character so as to make LaTeX treat blanks seriously.
+% This activation invokes an eralier definition (see above).
+\obeyspaces
+%
+% Interparagraph skips do not help the cause.
+% Note: We have to preserve the indentation though, as the code is actually
+% indented in the final output. See \fwodef in an earlier section.
+\parskip=0pt%
+%
+% We typeset the verbatim text in tt font (courier on the Macintosh) for a
+% number of reasons:
+% - tt font has the same horizontal spacing for each character.
+% - tt font covers the ASCII character set.
+% - tt font doesn't have many surprises (e.g. ligatures).
+% - tt font looks much what you might see on a computer terminal screen.
+\tt%
+%
+% Having set up an environment for verbatim, we are ready to use it.
+% By invoking \fwverbatimgobble, this \fwbtx macro gobbles up text verbatim (as
+% part of the parameter of \fwverbatimgobble) until it sees the termination
+% string "]fwetx=" (the "=" was thrown in to add obscurity as this sequence
+% must never occur in the verbatim text).
+\fwverbatimgobble}
+
+% The \fwverbatimgobble macro exists to allow \fwbtx to bracket verbatim text.
+\def\fwverbatimgobble#1]fwetx={#1\endgroup}
+
+
+% Table of Contents
+% -----------------
+% The five levels of table of contents that FunnelWeb supports are identified
+% by the five letters [A..E]. These are used throughout the following macros.
+
+% The following macros are utilities to the TOC macros to follow.
+\newcommand{\fwrule}{\medskip\hrule\medskip}
+\newcommand{\fwqh}{\hskip1.5em\relax}
+\newcommand{\fwbeforesec}{\penalty-200\bigskip\medskip\par}
+
+% The following macros are used to typeset the table of contents.
+\newcommand{\fwtocstart}[1]{\fwrule\leftline{\fwfontbolda Table of Contents}\fwrule}
+\newcommand{\fwtoca}[2]{\leftline{{\bf #1 #2}}}
+\newcommand{\fwtocb}[2]{\leftline{\fwqh #1 #2}}
+\newcommand{\fwtocc}[2]{\leftline{\fwqh\fwqh #1 #2}}
+\newcommand{\fwtocd}[2]{\leftline{\fwqh\fwqh\fwqh #1 #2}}
+\newcommand{\fwtoce}[2]{\leftline{\fwqh\fwqh\fwqh\fwqh #1 #2}}
+\newcommand{\fwtocfinish}[1]{\fwrule}
+
+% The following "library" macros define five different strengths of headings
+% which can be used later in the section macros.
+\newcommand{\fwliba}[2]{\vfill\eject{\fwfontboldc #1 #2}\penalty200\smallskip}
+\newcommand{\fwlibb}[2]{\fwbeforesec{\fwfontboldb #1 #2}\penalty200\smallskip}
+\newcommand{\fwlibc}[2]{\fwbeforesec{\fwfontnormb #1 #2}\penalty200\smallskip}
+\newcommand{\fwlibd}[2]{\fwbeforesec{\bf #1 #2}\penalty200}
+\newcommand{\fwlibe}[2]{\fwbeforesec{\bf #1 #2}}
+
+% Here are the macros that actually typeset the section headings throughout
+% the document. The fwlib system has been employed so as to easily allow the
+% user to redefine the strengths of headings to taste. For example, the
+% user could insert in the input document a similar set of definitions to these
+% but with the b..e headings set to \fwlibc. This would tone down the output.
+\newcommand{\fwseca}[2]{\section{#2}}
+\newcommand{\fwsecb}[2]{\fwlibb{#1}{#2}}
+\newcommand{\fwsecc}[2]{\fwlibc{#1}{#2}}
+\newcommand{\fwsecd}[2]{\fwlibd{#1}{#2}}
+\newcommand{\fwsece}[2]{\fwlibe{#1}{#2}}
+
+
+% Support for Explicit Typesetting
+% --------------------------------
+% FunnelWeb supports pragmas and other constructs that allow
+% typesetter-independent typesetting commands to be given. The
+% following macros support these features.
+
+% The in-text literal @{sloth@} and emphasise @[walrus@] features.
+\newcommand{\fwlit}[1]{{\tt #1}}
+\newcommand{\fwemp}[1]{{\it #1}}
+
+% The "@p new_page" pragma.
+\newcommand{\fwnewpage}{\vfill\eject}
+
+% The "@p vskip Nmm" pragma.
+\newcommand{\fwvskip}[1]{\null\vskip #1mm}
+
+% The "@p title <font> <align> <text>" pragma.
+\newcommand{\fwfontnormal}[1]{{\fwfontnorm {#1}}}
+\newcommand{\fwfonttitle}[1]{{\fwfontboldd {#1}}}
+\newcommand{\fwfontsmalltitle}[1]{{\fwfontboldb {#1}}}
+\newcommand{\fwleftline}[1]{\leftline{#1}}
+\newcommand{\fwcenterline}[1]{\centerline{#1}}
+\newcommand{\fwrightline}[1]{\rightline{#1}}
+
+
+% Support for Old FunnelWeb
+% -------------------------
+% The following macros were used extensively in the first version of
+% FunnelWeb and are retained so that these older input files will still
+% typeset cleanly.
+\newcommand{\p}[1]{{\tt #1}} % P for Program text.
+\newcommand{\flagpage}[2]{
+ \null
+ \vfill
+ \centerline{\fwfontboldd #1}
+ \vskip 1cm
+ \centerline{\fwfontboldd #2}
+ \vfill
+ \null
+ \vfill
+}
+
+%====================== End of FunnelWeb LaTeX Definitions ===================
diff --git a/web/funnelAC/fwACsrc/fw.def b/web/funnelAC/fwACsrc/fw.def
new file mode 100644
index 0000000000..3984db6c35
--- /dev/null
+++ b/web/funnelAC/fwACsrc/fw.def
@@ -0,0 +1,3 @@
+NAME FW WINDOWCOMPAT
+DESCRIPTION 'FunnelWeb Literate Programming Tool'
+STACKSIZE 0x80000
diff --git a/web/funnelAC/fwACsrc/fwmem.c b/web/funnelAC/fwACsrc/fwmem.c
new file mode 100644
index 0000000000..26a8434998
--- /dev/null
+++ b/web/funnelAC/fwACsrc/fwmem.c
@@ -0,0 +1,371 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 10-May-1994 ABC Added MEMTOTALS debugging option.
+ 08-Aug-1995 ABC Changed include file name from "memory.h"
+ to "fwmem.h" to avoid a clash with the C++
+ standard header file "memory.h".
+ Similarly, changed the name of this file to
+ "fwmem.c".
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* FWMEM.C */
+/******************************************************************************/
+/* */
+/* Implementation Overview */
+/* ----------------------- */
+/* One of the tasks of this Memory Management (MM) package is to keep track */
+/* of the memory that it has allocated so that it can all be deallocated */
+/* later, in one go. To do this, the package keeps a linked list whose */
+/* elements describe the blocks allocated. Two linked lists are kept, one for */
+/* temporary blocks and one for permanent blocks. Only the list for the */
+/* temporary blocks is used for deallocation. Permanent blocks are arranged */
+/* in a list so that the code for temporary blocks is also applicable. */
+/* */
+/* In order to avoid many calls to malloc() for small blocks of memory */
+/* (legend has it that some implementations of malloc() are very slow in this */
+/* case), the MM package keeps a spare temporary and permanent block of */
+/* length MM_BLOCK from which it allocates small blocks. Small is defined as */
+/* <=MM_BLOCK/16. A separate malloc call is made for "Large" blocks greater */
+/* than MM_BLOCK bytes. "Large" blocks less than MM_BLOCK bytes may or may */
+/* not be allocated from a buffer block, depending on how much space is */
+/* available. See the code for the full details. */
+/* */
+/******************************************************************************/
+
+#include "style.h"
+
+#include "as.h"
+#include "machin.h"
+#include "fwmem.h"
+
+/******************************************************************************/
+
+/* The environ.h file contains a definition for ALIGN_POWER which is the */
+/* exponent of the power of two corresponding to the machine's alignment */
+/* requirements. The following two constants convert that constant to more */
+/* useful forms. These definitions should never need to be changed. */
+#define ALIGN_SIZE (1L<<ALIGN_POWER)
+#define ALIGN_MASK (ALIGN_SIZE-1)
+
+/* Because standard malloc() can be slow on some systems for large numbers of */
+/* calls requesting small blocks of memory, FunnelWeb's memory management */
+/* package MM_* allocates memory in sizeable blocks and then allocates */
+/* smaller blocks from these big blocks without reference to malloc(). The */
+/* following #define tells the MM package how big the sizeable allocated */
+/* blocks should be. The rule is then: if the requested block is greater than */
+/* MM_BLOCK/16, allocate it directly using malloc(), otherwise peel off some */
+/* memory from the latest sizeable block allocated. */
+/* In practice, MM_BLOCK should be chosen to be about 1/10 to 1/20 of the */
+/* memory available to FunnelWeb. The disadvantage of making it big is that */
+/* when memory is tight, MM will be unable to allocate a full block and about */
+/* half a block of memory will be unusable. The disadvantage of making it too */
+/* small is that the linked lists tracking memory allocations will grow long */
+/* and it will take a long time to free up memory between invocations of */
+/* FunnelWeb proper. The value is not critical. A value of 31K should work */
+/* well on most systems. 31K is chosen instead of 32K just to be on the safe */
+/* side of 16 bits (so who's paranoid?). */
+#define MM_BLOCK (31L*1024L)
+
+/* This definition provides the definition of the size of a "big" block; that */
+/* is, one that should possibly be treated differently from the others. */
+/* The rule we use is that a big block is 1/16 of the standard block size. */
+/* This results in a maximum memory wastage of 1/16 or about 7%. */
+#define MM_BIG (MM_BLOCK >> 4)
+
+/* Magic numbers help us to detect corruptions. */
+#define MAGIC_HEAD (83716343L)
+#define MAGIC_TAIL (11172363L)
+
+/* Set MEMTRACE to TRUE to trace all memory operations. */
+#define MEMTRACE FALSE
+
+/* ABC { */
+#if MEMTRACE
+#define MEMTOTALS TRUE
+#else /* !MEMTRACE */
+/* Set MEMTOTALS to TRUE to see block memory allocations and total */
+#define MEMTOTALS FALSE
+#endif /* MEMTRACE */
+/* } ABC */
+
+/******************************************************************************/
+
+/* The following structures define a type for the linked lists that keep */
+/* track of the allocated blocks. */
+typedef struct mm_t_
+ {
+ ulong mm_mhead; /* Magic number protecting beginning of record. */
+ ubyte_ *mm_pblok; /* Pointer to the allocated block. */
+ ubyte_ *mm_pfree; /* Pointer to next free byte in block (ALIGNED). */
+ ulong mm_nfree; /* Number of unused bytes available in the block. */
+ struct mm_t_ *mm_pnext; /* Pointer to the header for the next block. */
+ ulong mm_mtail; /* Magic number protecting end of record. */
+ } mm_t;
+
+typedef mm_t *p_mm_t; /* Handy to have a pointer type too. */
+
+/* The following two local variables point to the head of the temporary and */
+/* permanent block lists. The first block in each list is that list's buffer. */
+LOCVAR p_mm_t p_perm = NULL;
+LOCVAR p_mm_t p_temp = NULL;
+
+/******************************************************************************/
+
+LOCAL void mm_check P_((p_mm_t));
+LOCAL void mm_check(p_mm)
+/* Checks the magic numbers in the specified block header object. */
+p_mm_t p_mm;
+{
+ as_cold(p_mm!=NULL,"mm_check: Null pointer.");
+ as_cold(p_mm->mm_mhead==MAGIC_HEAD,"mm_check: Corrupted header.");
+ as_cold(p_mm->mm_mtail==MAGIC_TAIL,"mm_check: Corrupted trailer.");
+}
+
+/******************************************************************************/
+
+LOCAL void mm_align P_((p_mm_t));
+LOCAL void mm_align(p_mm)
+/* Some machines are very fussy about the memory alignment of allocated */
+/* objects. To solve this problem, the mm_pfree pointer is always kept at an */
+/* "aligned" address. This function accepts a pointer to the header of a */
+/* block whose mm_pfree pointer is possibly unaligned and consumes bytes */
+/* until mm_pfree is aligned. */
+p_mm_t p_mm;
+{
+ ubyte bump;
+ ubyte consume;
+
+ mm_check(p_mm);
+
+ /* Work out how many bytes are sticking out over the alignment boundary. */
+ bump = ((ulong) p_mm->mm_pfree) & ALIGN_MASK;
+
+ /* Return if the block is already aligned. */
+ if (bump==0) return;
+
+ /* Otherwise work out how many bytes we have to consume to become realigned. */
+ consume=ALIGN_SIZE-bump;
+
+ /* If there are not enough bytes left in the block to allow the free pointer */
+ /* to be aligned, then simply set the available bytes to zero and return. It */
+ /* doesn't matter if we don't achieve alignment in this case as if */
+ /* mm_nfree==0, nothing can ever be allocated at the misaligned address. */
+ if (consume>p_mm->mm_nfree) {p_mm->mm_nfree=0; return;}
+
+ /* Consume the bytes required to align the free pointer. */
+ p_mm->mm_pfree += consume;
+ p_mm->mm_nfree -= consume;
+
+ /* Check that we have properly aligned the free pointer. */
+ as_cold((((ulong) p_mm->mm_pfree) & ALIGN_MASK)==0,
+ "mm_align: Failed to align.");
+}
+
+/******************************************************************************/
+
+LOCAL p_mm_t mm_newblk P_((size_t));
+LOCAL p_mm_t mm_newblk(blk_len)
+/* Creates a new block containing (after alignment) at least blk_len bytes. */
+/* Returns a pointer to the header for the block. */
+size_t blk_len;
+{
+ p_mm_t p_mm;
+ ubyte_ *p_bl;
+#if MEMTOTALS
+ STAVAR ulong total_mem = 0;
+ ulong alloc_size;
+#endif /* MEMTOTALS */
+
+ /* Allocate the header and the block itself. Because we are guaranteeing */
+ /* that the resultant block will have at least blk_len bytes free, we have */
+ /* to take into account alignment and add in ALIGN_SIZE when requesting mem. */
+ p_mm=(p_mm_t ) malloc((size_t) sizeof(mm_t));
+ p_bl=(ubyte_ *) malloc((size_t) (blk_len+ALIGN_SIZE));
+ if (p_mm==NULL || p_bl==NULL)
+ {
+ fprintf(stderr,"mm_newblk: Out of memory!\n");
+ fprintf(stderr,"FunnelWeb doesn't cope well when it runs out of memory.\n");
+ fprintf(stderr,"It falls in a heap just as it is about to now.\n");
+ as_bomb("Stand by for an ungraceful termination!");
+ }
+
+ /* Fill in the fields of the block header. */
+ p_mm->mm_mhead = MAGIC_HEAD;
+ p_mm->mm_pblok = p_bl;
+ p_mm->mm_pfree = p_bl;
+ p_mm->mm_nfree = blk_len+ALIGN_SIZE;
+ p_mm->mm_pnext = NULL;
+ p_mm->mm_mtail = MAGIC_TAIL;
+
+ /* Align the free pointer in the header block. */
+ mm_align(p_mm);
+
+#if MEMTOTALS
+ alloc_size = sizeof(mm_t)+blk_len+ALIGN_SIZE;
+ printf(
+ "TRACE: mm_newblk: Allocated %lu bytes of memory.\n",
+ alloc_size
+ );
+ total_mem += alloc_size;
+ printf(
+ "TRACE: mm_newblk: Total allocated: %lu bytes.\n",
+ total_mem
+ );
+#endif /* MEMTOTALS */
+
+ /* Return a pointer to the header block we created. */
+ return p_mm;
+}
+
+/******************************************************************************/
+
+LOCAL p_void mm_alloc P_((p_mm_t *,size_t));
+LOCAL p_void mm_alloc(pp_mm,bytes)
+/* 'pp_mm' must be a pointer to either p_perm or p_temp. */
+/* 'bytes' is the number of bytes required. */
+/* Allocates the required memory and returns an aligned pointer to it. */
+/* Bombs the program if the memory is not available. */
+p_mm_t *pp_mm;
+size_t bytes;
+{
+ p_mm_t p_from; /* Pointer to header for block from which we finally alloc.*/
+ ubyte_ *p_result; /* The result pointer returned to the caller. */
+
+ /* If the list is empty, create a "buffer block" and put it in the list. */
+ if (*pp_mm==NULL) *pp_mm=mm_newblk((size_t) MM_BLOCK);
+
+ /* If there is room in the current buffer block, we can allocate directly. */
+ /* Note that we may be allocating a "big" block here, but as long as it fits */
+ /* into the free space of the current buffer block, we don't care. */
+ if ((*pp_mm)->mm_nfree >= bytes) {p_from = *pp_mm; goto dole_out;}
+
+ /* At this point we know that there is not enough space in the current */
+ /* buffer block. This could mean that we have an extra big allocation on our */
+ /* hands in which case, we should malloc up a block specially for this */
+ /* request. It could also mean that we are running out of space in our */
+ /* buffer block in which case a new one must be allocated. */
+ if (bytes >= MM_BIG)
+ {
+ /* If the request is BIG, allocate a special block for it and insert the */
+ /* block in the block list just after the buffer block, leaving the */
+ /* buffer block the first in the block list. */
+ p_mm_t p_tmp=mm_newblk(bytes);
+ p_tmp->mm_pnext=(*pp_mm)->mm_pnext;
+ (*pp_mm)->mm_pnext=p_tmp;
+ p_from=p_tmp;
+ }
+ else
+ {
+ /* If the request is not big, our buffer block is probably too empty and */
+ /* so it is time to create a new one. Allocate a new buffer block and */
+ /* make it the new head of this block list. Note that by giving up on the */
+ /* previous buffer, we waste at most 1/16 of the block we are giving up */
+ /* on. This cost is reasonable in exchange for all the speed this gives. */
+ p_mm_t p_tmp=mm_newblk((size_t) MM_BLOCK);
+ p_tmp->mm_pnext=(*pp_mm);
+ (*pp_mm)=p_tmp;
+ p_from=p_tmp;
+ }
+
+ dole_out:
+ /* Jump here to dole out 'bytes' bytes from block 'p_from'. */
+ p_result=p_from->mm_pfree;
+ p_from->mm_pfree += bytes;
+ p_from->mm_nfree -= bytes;
+ mm_align(p_from);
+
+ /* Ensure that the pointer being returned is properly aligned. */
+ as_cold((((ulong) p_result) & ALIGN_MASK)==0,
+ "mm_alloc: Result is misaligned.");
+
+ /* Return the result. */
+ return (p_void) p_result;
+}
+
+/******************************************************************************/
+
+EXPORT p_void mm_perm(bytes)
+size_t bytes;
+{
+#if MEMTRACE
+ printf("TRACE: mm_perm: Allocating %lu bytes of permanent memory.\n",
+(ulong) bytes);
+#endif
+ return mm_alloc(&p_perm,bytes);
+}
+
+/******************************************************************************/
+
+EXPORT p_void mm_temp(bytes)
+size_t bytes;
+{
+#if MEMTRACE
+ printf("TRACE: mm_temp: Allocating %lu bytes of temporary memory.\n",
+(ulong) bytes);
+#endif
+ return mm_alloc(&p_temp,bytes);
+}
+
+/******************************************************************************/
+
+EXPORT void mm_zapt()
+/* This function frees all the memory blocks recorded in the temporary */
+/* memory list. We choose to free them rather than merely re-using them */
+/* directly because they may not all be the same size, and we want to give */
+/* the built-in memory manager a chance to smooth out the heap. */
+{
+#if MEMTRACE
+ printf("TRACE: mm_zapt: Attempting to release all temporary memory.\n");
+#endif
+
+ while (p_temp != NULL)
+ {
+ p_mm_t p_mm=p_temp;
+ mm_check(p_temp);
+#if MEMTRACE
+ printf("TRACE: mm_zapt: Deallocating a big chunk of temporary memory.\n");
+#endif
+ free(p_temp->mm_pblok);
+ p_temp=p_temp->mm_pnext;
+ free(p_mm);
+ }
+}
+
+/******************************************************************************/
+/* End of FWMEM.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/fwmem.h b/web/funnelAC/fwACsrc/fwmem.h
new file mode 100644
index 0000000000..44dd8615c7
--- /dev/null
+++ b/web/funnelAC/fwACsrc/fwmem.h
@@ -0,0 +1,116 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 08-Aug-1995 ABC Changed the file name from "memory.h"
+ to "fwmem.h" to avoid a clash with the C++
+ standard header file "memory.h".
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* FWMEM.H */
+/******************************************************************************/
+/* */
+/* Introduction */
+/* ------------ */
+/* This package provides a memory management facility for FunnelWeb. */
+/* The conventional MALLOC does not suit the needs of FunnelWeb. The */
+/* following notes give an idea of why: */
+/* */
+/* 1. At the times where FunnelWeb requires memory, it is nearly always */
+/* the case that failure to provide the memory should result in a bomb. */
+/* It therefore makes sense to wrap MALLOC up inside another function */
+/* that, at the very least, checks the status from malloc and bombs */
+/* the program if the requested memory is not available. */
+/* */
+/* 2. Because FunnelWeb proper can be invoked an indefinite number of */
+/* times from the FunnelWeb command interpreter, it is very important */
+/* to reclaim all the memory used by each invocation. This could be */
+/* done by explicitly tearing apart the data structures constructed */
+/* for each run. However, this is very messy, requiring detailed */
+/* knowledge of the data structures. A far simpler, safer scheme is to */
+/* arrange for a memory manager to keep track of all the memory that it */
+/* allocates and to provide a single call to free it all. This facility */
+/* is provided by this package. */
+/* */
+/* 3. In addition to the TEMPORARY memory allocations described in (2) above, */
+/* it should also be possible to make permanent allocations. */
+/* */
+/* 4. FunnelWeb uses linked lists a lot and hence will make many requests */
+/* for small chunks of memory (e.g 10 bytes). Legend has it that some */
+/* malloc libraries are very inefficient in this case, and that it is */
+/* better to use malloc to allocate a large chunk of memory and dole it */
+/* out yourself. This package does this too. */
+/* */
+/* For all these reasons, FunnelWeb memory management has been handed over to */
+/* this package which provides services that satisfy the conditions outlined */
+/* above. */
+/* */
+/******************************************************************************/
+
+/* Ensure that the body of this header file is included at most once. */
+#ifndef DONE_MEMORY
+#define DONE_MEMORY
+
+/******************************************************************************/
+
+#include "style.h"
+
+/******************************************************************************/
+
+EXPORT p_void mm_perm P_((size_t));
+/* Allocates a block of memory of the specified size (specified in bytes) and */
+/* returns a pointer to the new block of memory. Bombs the program if the */
+/* memory is not available. Memory allocated using mm_perm is permanently */
+/* allocated and cannot be freed. */
+
+EXPORT p_void mm_temp P_((size_t));
+/* Allocates a block of memory of the specified size (specified in bytes) and */
+/* returns a pointer to the new block of memory. Bombs the program if the */
+/* memory is not available. Memory allocated using this function can later be */
+/* freed in its entirely by making a call to mm_zapt. */
+
+EXPORT void mm_zapt P_((void));
+/* This function can be called at any time. Its effect is to free up all the */
+/* memory allocated using mm_temp since the last call to mm_zapt or the start */
+/* of the program, whichever is the more recent. */
+
+/******************************************************************************/
+
+/* For #ifndef preventing multiple inclusion of the body of this header file. */
+#endif
+
+/******************************************************************************/
+/* End of FWMEM.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/fwtest.cmd b/web/funnelAC/fwACsrc/fwtest.cmd
new file mode 100644
index 0000000000..007a1231d5
--- /dev/null
+++ b/web/funnelAC/fwACsrc/fwtest.cmd
@@ -0,0 +1,5 @@
+@echo off
+rem FunnelWeb test sequence
+cd ..\scripts
+..\fwACsrc\fw +xmaster
+cd ..\fwACsrc
diff --git a/web/funnelAC/fwACsrc/help.c b/web/funnelAC/fwACsrc/help.c
new file mode 100644
index 0000000000..f4e554790d
--- /dev/null
+++ b/web/funnelAC/fwACsrc/help.c
@@ -0,0 +1,631 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 16-Sep-1993 ABC Changed all constants *_MAX to *_FWMAX to avoid
+ conflict with some standard UNIX constants.
+ 20-Jul-1995 ABC Modified program name to reflect
+ release of FunnelWeb 3.01AC.
+ 08-Aug-1995 ABC Modified program name to reflect
+ release of FunnelWeb 3.02AC.
+ 10-Aug-1995 ABC Modified program name to reflect
+ release of FunnelWeb 3.03AC.
+ 16-Aug-1995 ABC Added support for batch mode (no interaction
+ with user) via `+Qb' command switch.
+ 16-Aug-1995 ABC Modified program name to reflect
+ release of FunnelWeb 3.04AC.
+ 19-Sep-1995 ABC Modified program name to reflect
+ release of FunnelWeb 3.05AC.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* HELP.C */
+/******************************************************************************/
+/* */
+/* REPRESENTING MESSAGES AS C CODE */
+/* =============================== */
+/* Experience has shown that it is much more reliable to code text messages */
+/* into a program than to expect the program to track down text files */
+/* containing the messages at run time. Worthwhile for smallish files (such */
+/* as these help messages) at least. For this reason, most the messages in */
+/* this module are represented by code (e.g. as in printf statements). */
+/* */
+/* The only exception is the 18K Gnu license message which is a bit too big */
+/* to be done by hand. It has been moved to the help_gnu module. */
+/* */
+/******************************************************************************/
+
+#include <ctype.h>
+#include "style.h"
+
+#include "as.h"
+#include "help.h"
+#include "help_gnu.h"
+#include "misc.h"
+#include "option.h"
+
+/******************************************************************************/
+
+/* This module contains many many output statements that call an output */
+/* function. To neaten up all these calls, we define a global variable to */
+/* hold a pointer to the function and simple macro to write output using */
+/* the function. */
+LOCVAR void (*pf) P_((char *));
+
+#define WX(STR) (*pf)(STR)
+
+/******************************************************************************/
+
+LOCAL void hel_men P_((void));
+LOCAL void hel_men ()
+{
+ WX("\n");
+ WX("FunnelWeb Help Messages\n");
+ WX("-----------------------\n");
+ WX("Introduction - Introduction to FunnelWeb.\n");
+ WX("DOcumentation - How to obtain FunnelWeb documentation.\n");
+ WX("Options - Command line options.\n");
+ WX("DEfoptions - Default command line options.\n");
+ WX("COMmands - Interactive commands.\n");
+ WX("Registration - How to register as an \"official\" FunnelWeb user.\n");
+ WX("Support - How you can help support FunnelWeb development.\n");
+ WX("COPyright - Copyright notice.\n");
+ WX("License - The license under which this software is distributed (long).\n");
+ WX("Nowarranty - Extract from the GNU license concerning lack of warranty.\n");
+ WX("DIstribution - Extract from the GNU license concerning distribution.\n");
+ WX("MOdification - Read this message if you intend to modify FunnelWeb.\n");
+ WX("Versions - A list of existing versions of FunnelWeb.\n");
+ WX("Acknowledge - Thanks to people who helped with FunnelWeb development.\n");
+ WX("MEnu - The message you are reading (the default help message).\n");
+ WX("\n");
+ WX("To display a message, give its (optionally abbreviated) name in a help command.\n");
+ WX("To capture a message to a file, add +J<filename> to the fw command. Examples:\n");
+ WX("\n");
+ WX(" fw +Hintroduction +Jintro.txt -- From the operating system level.\n");
+ WX(" help introduction -- From FunnelWeb interactive mode.\n");
+}
+
+/******************************************************************************/
+
+LOCAL void hel_int P_((void));
+LOCAL void hel_int ()
+{
+ WX("\n");
+ WX("FunnelWeb Introduction\n");
+ WX("----------------------\n");
+ WX("Welcome to FunnelWeb, a literate-programming macro preprocessor.\n");
+ WX("\n");
+ WX("Traditional computer programs are primarily written for computers and consist\n");
+ WX("of code laced with comments. In contrast, literate programs are primarily\n");
+ WX("written for humans and consist of comments laced with code. While simple, the\n");
+ WX("effect of this inversion can be so profound as to change one's whole approach\n");
+ WX("to programming. The literate programmer focuses on conveying meaning to other\n");
+ WX("intelligent beings rather than merely convincing the computer to behave in a\n");
+ WX("particular way. It is the difference between performing and exposing a magic\n");
+ WX("trick.\n");
+ WX("\n");
+ WX("FunnelWeb is a production-quality literate-programming tool that emphasises\n");
+ WX("simplicity and reliability. It provides a macro facility, and assists in the\n");
+ WX("production of typeset documentation. FunnelWeb runs on most popular machines\n");
+ WX("(Sun, VAX, Mac, PC) and its highly portable source code in C is freely\n");
+ WX("available under a GNU license.\n");
+ WX("\n");
+ WX("To get started with FunnelWeb, obtain a printed copy of the \"FunnelWeb User's\n");
+ WX("Manual\" (see the \"DOCUMENTATION\" help message). Read the introduction and work\n");
+ WX("through the tutorial. The manual contains an overview of FunnelWeb, an\n");
+ WX("introductory tutorial, and a comprehensive reference manual. Try it!\n");
+}
+
+/******************************************************************************/
+
+LOCAL void hel_opt P_((void));
+LOCAL void hel_opt ()
+{
+ WX("\n");
+ WX("FunnelWeb Command Line Options\n");
+ WX("------------------------------\n");
+ WX("Options are of the form (\"+\" | \"=\" | \"-\") <letter> [<string>].\n");
+ WX("+ turns on an option. - turns it off. = doesn't affect it's onoffedness.\n");
+ WX("The case (e.g. upper or lower) of <letter> does not matter.\n");
+ WX("<string> is usually a filename or directory, but sometimes a number.\n");
+ WX("Convention: f=filename, n=decimal number, h=help message name.\n");
+ WX("\n");
+ WX("Example: fw sloth +L +Jaardvark.xxx +W80 -Q =Twalrus.tex\n");
+ WX("\n");
+ WX("Action options: (choose at least one when you invoke FunnelWeb from the OS).\n");
+ WX("If you choose more than one, they will be executed in the order given here.\n");
+ WX(" +Xf Execute specified Funnelweb script.\n");
+ WX(" +Ff Process specified input file.\n");
+ WX(" +Hh Display specified help message.\n");
+ WX(" +K Invoke FunnelWeb's interative mode.\n");
+ WX("\n");
+ WX("Other options:\n");
+ WX(" +B1 Diagnostic: Dump image of input file to listing file.\n");
+ WX(" +B2 Diagnostic: Dump scanner's line list to listing file.\n");
+ WX(" +B3 Diagnostic: Dump scanner's token list to listing file.\n");
+ WX(" +B4 Diagnostic: Dump parser's macro table to listing file.\n");
+ WX(" +B5 Diagnostic: Dump parser's document list to listing file.\n");
+ WX(" +B6 Diagnostic: Dump time breakdown report to listing file.\n");
+ WX(" +B7 Diagnostic: Suppress non-deterministic output.\n");
+ WX(" +Cn Number of lines of context around diagnostics in listing file.\n");
+ WX(" +D Delete each output file identical to its previous version.\n");
+ WX(" +If Default file specification for include files.\n");
+ WX(" +Jf Generate journal file. Default file specification.\n");
+ WX(" +Lf Generate listing file. Default file specification.\n");
+ WX(" +Of Generate product files. Default file specification.\n");
+ WX(" +Q Quiet mode. Only really important messages displayed on console.\n");
+ /* ABC { */
+ WX(" +Qb Batch mode. No interaction with user via console.\n");
+ /* } ABC */
+ WX(" +Tf Generate typesetter file. Default file specification.\n");
+ WX(" +Sn Send errors to console with specified number of lines of context.\n");
+ WX(" +Wn Set maximum length of lines in product files.\n");
+ WX("\n");
+ WX("If an option appears more than once, the rightmost one dominates.\n");
+ WX("For more detailed information, refer to the FunnelWeb User's Manual.\n");
+ WX("For default values refer to the \"DEFOPTIONS\" help message.\n");
+}
+
+/******************************************************************************/
+
+LOCAL void hel_dop P_((void));
+LOCAL void hel_dop ()
+{
+ op_t defop;
+
+ WX("\n");
+ WX("FunnelWeb Default Option Settings\n");
+ WX("---------------------------------\n");
+ WX("These are the settings FunnelWeb STARTS UP with.\n");
+ op_ini(&defop);
+ WX("\n");
+ op_wri(&defop,pf);
+ WX("\n");
+ WX("See the OPTIONS help message for a brief description of these options.\n");
+ WX("For more detailed information, refer to the FunnelWeb User's Manual.\n");
+}
+
+/******************************************************************************/
+
+LOCAL void hel_com P_((void));
+LOCAL void hel_com ()
+{
+ WX("\n");
+ WX("FunnelWeb Interactive Commands\n");
+ WX("------------------------------\n");
+ WX(" ! - Comment. Ignores the whole line. \n");
+ WX(" ABSENT fn - Aborts if specified file exists. \n");
+ WX(" CODIFY ftext fC - Convert text file into C code to write text. \n");
+ WX(" COMPARE f1 f2 - Aborts if two files are different. \n");
+ WX(" DEFINE n \"text\" - Defines $n to translate to text. \n");
+ WX(" DIFF f1 f2 logf [ABORT] - Writes differences between f1 and f2 to logf.\n");
+ WX(" - Severe if different and ABORT is present. \n");
+ WX(" DIFFSUMMARY - Summary of differences done since DIFFZERO. \n");
+ WX(" DIFFZERO - Zeros differences counters. \n");
+ WX(" ENEO fn - Establish Non Existence Of file. \n");
+ WX(" EXECUTE fn - Execute commands in specified file. \n");
+ WX(" EXISTS fn - Aborts if file does not exist. \n");
+ WX(" FIXEOLS fn [outf] - Fixes up EOL markers in specified file. \n");
+ WX(" FW options - Invoke FunnelWeb-proper once. \n");
+ WX(" HELP [name] - Displays specified help message. \n");
+ WX(" HERE - Terminates effect of SKIPTO command. \n");
+ WX(" QUIT - Quits FunnelWeb. \n");
+ WX(" SET options - Sets options. \n");
+ WX(" SHOW - Displays currently active options. \n");
+ WX(" SKIPTO - Ignore commands until HERE command. \n");
+ WX(" STATUS - Write out status and diagnostic counts. \n");
+ WX(" STATUS [Sn] [En] [Wn] - Aborts if status is not as specified. \n");
+ WX(" TOLERATE - Don't abort script if next commmand gens err.\n");
+ WX(" TRACE ON | OFF - Turns command tracing ON or OFF. \n");
+ WX(" WRITE \"text\" - Writes specified text to screen and journal. \n");
+ WX(" WRITEU \"text\" - Same as WRITE but underlines text. \n");
+ WX("\n");
+ WX("More detailed information can be found in the FunnelWeb User's Manual.\n");
+ WX("\n");
+ WX("Most of these commands were created to support regression testing and\n");
+ WX("can be ignored by most users. In fact most users will never need to invoke\n");
+ WX("FunnelWeb's interactive mode at all. If you are just getting started\n");
+ WX("with FunnelWeb, it's probably best to run FunnelWeb directly from your\n");
+ WX("command interface and ignore the +K command line option for now.\n");
+}
+
+/******************************************************************************/
+
+LOCAL void hel_doc P_((void));
+LOCAL void hel_doc ()
+{
+ WX("\n");
+ WX("FunnelWeb Documentation\n");
+ WX("-----------------------\n");
+ WX("The following FunnelWeb documentation is available:\n");
+ WX("\n");
+ WX(" \"FunnelWeb User's Manual\": Tutorial, Hints, Reference Manual.\n");
+ WX(" \"FunnelWeb Hacker's Manual\": Notes on Design and Implementation.\n");
+ WX("\n");
+ WX("Everyone involved with FunnelWeb should read the User's Manual.\n");
+ WX("It contains everything you need to learn how to use FunnelWeb.\n");
+ WX("\n");
+ WX("The Hacker's Manual is for those who want to install, modify, fix,\n");
+ WX("fiddle with, and generally hack the FunnelWeb C source code.\n");
+ WX("\n");
+ WX("Both of these manuals are shipped with the FunnelWeb distribution\n");
+ WX("kit, and should be available on your machine in the form of LaTeX text\n");
+ WX("files. If you cannot find them, you can obtain them by FTP from:\n");
+ WX("\n");
+ WX(" Machine : sirius.itd.adelaide.edu.au [IP=129.127.40.3].\n");
+ WX(" Directory: ~pub/funnelweb/ (or a directory of similar name).\n");
+ WX("\n");
+}
+
+/******************************************************************************/
+
+LOCAL void hel_reg P_((void));
+LOCAL void hel_reg ()
+{
+ WX("FunnelWeb Registration\n");
+ WX("----------------------\n");
+ WX("If you install or use FunnelWeb, please fill in and return this form:\n");
+ WX("\n");
+ WX(" +----------------------FunnelWeb Registration Form----------------------+\n");
+ WX(" | 1. Date: |\n");
+ WX(" | 2. Title and name: |\n");
+ WX(" | 3. Internet email address: |\n");
+ WX(" | 4. Snail mail address: |\n");
+ WX(" | 5. Work phone number (country,area,number): |\n");
+ WX(" | 6. Which category of FunnelWeb user best describes you? |\n");
+ WX(" | Latent - Installed FunnelWeb, but don't intend to use it. |\n");
+ WX(" | Beginner - Haven't used FunnelWeb much yet; have an open mind. |\n");
+ WX(" | Casual - Use FunnelWeb occasionally. |\n");
+ WX(" | Convert - Use FunnelWeb to do most programming. |\n");
+ WX(" | Fanatic - FunnelWeb has become a way of life. |\n");
+ WX(" | 7. What changes or new features would you like to see in FunnelWeb? |\n");
+ WX(" | 8. Do you want to be kept informed of new FunnelWeb developments? |\n");
+ WX(" | 9. Email this form to \"ross@spam.adelaide.edu.au\", OR snail mail to |\n");
+ WX(" | Ross Williams, 16 Lerwick Avenue, Hazelwood Park 5066, Australia. |\n");
+ WX(" +-----------------------------------------------------------------------+\n");
+ WX("To write this form to a file, use \"fw +hreg +jregform.txt\".\n");
+ WX("You may wish to make a contribution when you register. See SUPPORT.\n");
+}
+
+/******************************************************************************/
+
+LOCAL void hel_cop P_((void));
+LOCAL void hel_cop ()
+{
+ WX("\n");
+ WX("FunnelWeb Copyright\n");
+ WX("-------------------\n");
+ WX("Copyright (C) 1992 Ross Williams.\n");
+ WX("\n");
+ WX("However, FunnelWeb has been released by the author and copyright owner Ross\n");
+ WX("Williams (ross@spam.adelaide.edu.au) under Version 2 of the GNU General Public\n");
+ WX("License published by the Free Software Foundation. This means that you can\n");
+ WX("redistribute FunnelWeb and/or modify it under the terms of the license.\n");
+ WX("\n");
+ WX("Note: This program is distributed WITHOUT ANY WARRANTY; without even the\n");
+ WX("implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
+ WX("\n");
+ WX("The following help messages provide further information:\n");
+ WX("\n");
+ WX(" License - The license under which this software is distributed (long).\n");
+ WX(" DIstribution - Extract from the GNU license concerning distribution.\n");
+ WX(" Nowarranty - Extract from the GNU license concerning lack of warranty.\n");
+ WX(" MOdification - Read this message if you intend to modify FunnelWeb.\n");
+ WX(" Registration - How to register as an \"official\" FunnelWeb user.\n");
+ WX("\n");
+}
+
+/******************************************************************************/
+
+LOCAL void hel_now P_((void));
+LOCAL void hel_now ()
+{
+ WX("\n");
+ WX("FunnelWeb Comes With No Warranty\n");
+ WX("--------------------------------\n");
+ WX("Here is an extract from the GNU General Public License Version 2, under which\n");
+ WX("FunnelWeb is distributed. See help message \"LICENSE\" for the full license.\n");
+ WX("\n");
+ WX(" 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n");
+ WX(" FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n");
+ WX(" OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n");
+ WX(" PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n");
+ WX(" OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n");
+ WX(" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n");
+ WX(" TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n");
+ WX(" PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n");
+ WX(" REPAIR OR CORRECTION.\n");
+ WX("\n");
+ WX(" 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n");
+ WX(" WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n");
+ WX(" REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n");
+ WX(" INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n");
+ WX(" OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n");
+ WX(" TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n");
+ WX(" YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n");
+ WX(" PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n");
+ WX(" POSSIBILITY OF SUCH DAMAGES.\n");
+}
+
+/******************************************************************************/
+
+LOCAL void hel_dis P_((void));
+LOCAL void hel_dis ()
+{
+ WX("\n");
+ WX("FunnelWeb Distribution\n");
+ WX("----------------------\n");
+ WX("The following is an extract from the GNU General Public License Version 2,\n");
+ WX("under which FunnelWeb is distributed.\n");
+ WX("\n");
+ WX(" 1. You may copy and distribute verbatim copies of the Program's\n");
+ WX(" source code as you receive it, in any medium, provided that you\n");
+ WX(" conspicuously and appropriately publish on each copy an appropriate\n");
+ WX(" copyright notice and disclaimer of warranty; keep intact all the\n");
+ WX(" notices that refer to this License and to the absence of any warranty;\n");
+ WX(" and give any other recipients of the Program a copy of this License\n");
+ WX(" along with the Program.\n");
+ WX("\n");
+ WX(" You may charge a fee for the physical act of transferring a copy, and\n");
+ WX(" you may at your option offer warranty protection in exchange for a fee.\n");
+ WX("\n");
+ WX("The license also allows you other freedoms. For more information refer\n");
+ WX("to the full text of the license in the help message \"LICENSE\".\n");
+}
+
+/******************************************************************************/
+
+LOCAL void hel_ack P_((void));
+LOCAL void hel_ack ()
+{
+ WX("\n");
+ WX("FunnelWeb Acknowledgements\n");
+ WX("--------------------------\n");
+ WX("The following people assisted with the preparation of FunnelWeb V3.0.\n");
+ WX("\n");
+ WX("Many thanks go to DAVID HULSE (dave@cs.adelaide.edu.au) who translated the 1986\n");
+ WX("version of FunnelWeb (V1) written in Ada into a public domain C version (V2).\n");
+ WX("The C code written by David formed the basis of V3 of FunnelWeb, but was\n");
+ WX("entirely rewritten during the intensive refinement and feature-injection\n");
+ WX("period leading up to this release (V3 is about 3 times the size of V2).\n");
+ WX("\n");
+ WX("Thanks go to SIMON HACKETT (simon@internode.com.au) of Internode Systems\n");
+ WX("Pty Ltd for the use of his Sun, Mac, and PC, for assistance in porting\n");
+ WX("FunnelWeb to the Sun and PC, and for helpful discussions.\n");
+ WX("\n");
+ WX("Thanks go to JEREMY BEGG (jeremy@vsm.com.au) of VSM Software Services\n");
+ WX("for the use of his VAX, and for assistance with the VMS-specific code.\n");
+ WX("\n");
+ WX("Ross Williams (ross@spam.adelaide.edu.au), 12 May 1992.\n");
+}
+
+/******************************************************************************/
+
+LOCAL void hel_ver P_((void));
+LOCAL void hel_ver ()
+{
+ WX("\n");
+ WX("FunnelWeb Versions\n");
+ WX("------------------\n");
+ WX("FunnelWeb was created in 1986 and was used extensively by Ross Williams\n");
+ WX("(ross@spam.adelaide.edu.au) for three years. However, Version 1.0 was written\n");
+ WX("in Ada and was not very portable (it was fairly VAX/VMS specific). David Hulse\n");
+ WX("(dave@cs.adelaide.edu.au) took the first step towards a release by translating\n");
+ WX("the Ada code into C. Ross Williams then extensively reworked the C code, making\n");
+ WX("it robust and portable, adding new features, and polishing it to its current\n");
+ WX("form.\n");
+ WX("\n");
+ WX("Vers Lang Created Released Author Copyright Licensing \n");
+ WX("---- ---- ------- -------- -------------- ------------- --------- \n");
+ WX("V1.0 Ada 1986 Never Ross Williams Ross Williams \n");
+ WX("V2.0 C 1989 Never David Hulse Public domain No restriction.\n");
+ WX("V3.0 C 1992 May-1992 Ross Williams Ross Williams GNU release. \n");
+ WX("V3.0AC C 1994 Sep-1994 A.B.Coates RW and ABC GNU release. \n");
+ WX("V3.01AC C 1995 Never A.B.Coates RW and ABC GNU release. \n");
+ WX("V3.02AC C 1995 Never A.B.Coates RW and ABC GNU release. \n");
+ WX("V3.03AC C 1995 Never A.B.Coates RW and ABC GNU release. \n");
+ WX("V3.04AC C 1995 Never A.B.Coates RW and ABC GNU release. \n");
+ WX("V3.05AC C 1995 Oct-1995 A.B.Coates RW and ABC GNU release. \n");
+ WX("\n");
+ WX("This is FunnelWeb Version 3.05AC. Unless otherwise specified, all references\n");
+ WX("in this release to \"FunnelWeb\" refer either to the abstract identity\n");
+ WX("of FunnelWeb, or to this version, FunnelWeb Version 3.05AC.\n");
+}
+
+/******************************************************************************/
+
+LOCAL void hel_sup P_((void));
+LOCAL void hel_sup ()
+{
+ WX("\n");
+ WX("FunnelWeb Support\n");
+ WX("-----------------\n");
+ WX("FunnelWeb is released \"as is\" under a GNU license, and no formal support\n");
+ WX("is available. You have the right to make changes to FunnelWeb and to use\n");
+ WX("the modified versions created by random programmers. However, this is\n");
+ WX("discouraged (see the MODIFICATION help message).\n");
+ WX("\n");
+ WX("In fact the support that is most needed is your financial support for the\n");
+ WX("FunnelWeb developers! It has taken MONTHS of full-time UNPAID work to bring\n");
+ WX("FunnelWeb to you in its current form. I don't want to inconvenience users\n");
+ WX("who install FunnelWeb, play with it, and then hardly ever use it. If you are\n");
+ WX("in this category, please register, but don't bother contributing. However,\n");
+ WX("if you find that FunnelWeb has become a useful programming tool, a contribution\n");
+ WX("of some positive multiple of US$50 would be appreciated.\n");
+ WX("\n");
+ WX("To make a contribution, send payment with a completed registration form\n");
+ WX("(see the REGISTRATION help message) to:\n");
+ WX("\n");
+ WX(" Renaissance Software Pty Ltd\n");
+ WX(" Email: ross@spam.adelaide.edu.au\n");
+ WX(" Snail: 16 Lerwick Avenue, Hazelwood Park 5066, Australia.\n");
+ WX("\n");
+ WX("Payment can be by personal or bank cheque to any bank in the world or by\n");
+ WX("Visa or Mastercard. Please give the card name, number, expiry date, and\n");
+ WX("the amount to be paid in US dollars. All contributions will be appreciated\n");
+ WX("and will encourage further FunnelWeb development. However, no undertaking\n");
+ WX("is made whatsoever about how the money will be used.\n");
+ WX("\n");
+ WX("Ross Williams (ross@spam.adelaide.edu.au), 12 May 1992.\n");
+}
+
+/******************************************************************************/
+
+LOCAL void hel_mod P_((void));
+LOCAL void hel_mod ()
+{
+ WX("\n");
+ WX("FunnelWeb Modifications\n");
+ WX("-----------------------\n");
+ WX("FunnelWeb is distributed under a GNU license, and you are free to modify the\n");
+ WX("source code and distribute modified copies (see the help message LICENSE).\n");
+ WX("However, there are good reasons why you should avoid doing this.\n");
+ WX("\n");
+ WX(" 1) If you distribute modified versions of FunnelWeb, you run the risk of\n");
+ WX(" creating a version that will diverge from the \"official\" version of\n");
+ WX(" FunnelWeb which I intend to maintain.\n");
+ WX("\n");
+ WX(" 2) If you release a version of FunnelWeb with a changed input language,\n");
+ WX(" users of your modified version will create source files that will no\n");
+ WX(" longer work on other versions of FunnelWeb. The result will be chaos.\n");
+ WX("\n");
+ WX("For these reasons I request that you do not distribute modified versions of\n");
+ WX("FunnelWeb, particularly versions with a modified language. However, if you must\n");
+ WX("distribute a version with a modified language, PLEASE CHANGE ITS NAME (i.e.\n");
+ WX("from \"FunnelWeb\" to something else). Please also allocate a new file extension\n");
+ WX("to replace \".fw\" as the extension for source files written in the modified\n");
+ WX("language. For more information, refer to the FunnelWeb Hacker's Manual.\n");
+ WX("\n");
+ WX("Ross Williams (ross@spam.adelaide.edu.au), 12 May 1992.\n");
+}
+
+/******************************************************************************/
+
+LOCAL bool prefeq P_((char *,char *));
+LOCAL bool prefeq (p_pref,p_target)
+/* Returns TRUE iff string p_pref is a case insensitive prefix of p_target. */
+char *p_pref;
+char *p_target;
+{
+ char *p,*q;
+
+ if (strlen(p_pref) > strlen(p_target))
+ return FALSE;
+
+ p=p_pref;
+ q=p_target;
+ while (*p != EOS)
+ {
+ if (toupper(*p) != toupper(*q)) return FALSE;
+ p++;
+ q++;
+ }
+ return TRUE;
+}
+
+/******************************************************************************/
+
+EXPORT uword hel_num (p_name)
+char *p_name;
+{
+ uword matches = 0;
+ uword messnum;
+
+ /* We want to be fairly lenient on the user here as the user is trying to */
+ /* obtain help and will probably get annoyed and give up if it doesn't work, */
+ /* so we perform case insensitive prefix matching. However, we don't want */
+ /* to match if the user inputs a prefix that matches two message names. This */
+ /* means we can't just return when we find a match; we have to see if there */
+ /* are any others as well. */
+
+ if (prefeq(p_name,"MENU" )) {messnum=HL_MEN; matches++;}
+ if (prefeq(p_name,"INTRODUCTION" )) {messnum=HL_INT; matches++;}
+ if (prefeq(p_name,"OPTIONS" )) {messnum=HL_OPT; matches++;}
+ if (prefeq(p_name,"DEFOPTIONS" )) {messnum=HL_DOP; matches++;}
+ if (prefeq(p_name,"COMMANDS" )) {messnum=HL_COM; matches++;}
+ if (prefeq(p_name,"DOCUMENTATION")) {messnum=HL_DOC; matches++;}
+ if (prefeq(p_name,"REGISTRATION" )) {messnum=HL_REG; matches++;}
+ if (prefeq(p_name,"LICENSE" )) {messnum=HL_GNU; matches++;}
+ if (prefeq(p_name,"COPYRIGHT" )) {messnum=HL_COP; matches++;}
+ if (prefeq(p_name,"NOWARRANTY" )) {messnum=HL_NOW; matches++;}
+ if (prefeq(p_name,"DISTRIBUTION" )) {messnum=HL_DIS; matches++;}
+ if (prefeq(p_name,"ACKNOWLEDGE" )) {messnum=HL_ACK; matches++;}
+ if (prefeq(p_name,"VERSIONS" )) {messnum=HL_VER; matches++;}
+ if (prefeq(p_name,"SUPPORT" )) {messnum=HL_SUP; matches++;}
+ if (prefeq(p_name,"MODIFICATION" )) {messnum=HL_MOD; matches++;}
+
+ if (matches != 1) return HL_ERR;
+
+ return messnum;
+}
+
+/******************************************************************************/
+
+EXPORT void hel_wri (p_outf,messno)
+void (*p_outf) P_((char *));
+uword messno;
+{
+ as_cold(1 <= messno,
+ "hel_wri: Message number is zero.");
+ as_cold(messno <= HL_FWMAX,
+ "hel_wri: Message number is greater than HL_FWMAX.");
+
+ /* Set the global output function pointer. */
+ pf=p_outf;
+
+ switch(messno)
+ {
+ case HL_MEN: hel_men(); break;
+ case HL_INT: hel_int(); break;
+ case HL_OPT: hel_opt(); break;
+ case HL_DOP: hel_dop(); break;
+ case HL_COM: hel_com(); break;
+ case HL_DOC: hel_doc(); break;
+ case HL_REG: hel_reg(); break;
+ case HL_GNU: hel_gnu(p_outf); break; /* Calling another module. */
+ case HL_COP: hel_cop(); break;
+ case HL_NOW: hel_now(); break;
+ case HL_DIS: hel_dis(); break;
+ case HL_ACK: hel_ack(); break;
+ case HL_VER: hel_ver(); break;
+ case HL_SUP: hel_sup(); break;
+ case HL_MOD: hel_mod(); break;
+ default : as_bomb("hel_wri: switch defaulted.");
+ }
+}
+
+/******************************************************************************/
+/* End of HELP.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/help.h b/web/funnelAC/fwACsrc/help.h
new file mode 100644
index 0000000000..d51690f8e3
--- /dev/null
+++ b/web/funnelAC/fwACsrc/help.h
@@ -0,0 +1,164 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 16-Sep-1993 ABC Changed all constants *_MAX to *_FWMAX to avoid
+ conflict with some standard UNIX constants.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* HELP.H */
+/******************************************************************************/
+/* */
+/* HELP PACKAGE */
+/* ============ */
+/* As I came closer and closer to completing the release version of */
+/* FunnelWeb, I noticed that the online help was a bit of a mess. I had */
+/* random commands and command line options here and there to provide bits of */
+/* information. After a close look and some thought, I decided to centralize */
+/* all of FunnelWeb's help messages into one module, and provide a clean and */
+/* consistent interface to the help messages, both in the command line, and */
+/* in interactive mode. */
+/* */
+/* The result is that all of the help messages have been moved to */
+/* this module. Each help message has a name consisting of a string. One */
+/* particular message has the name "MENU" and is the root help message (the */
+/* "menu message"). It contains a list of all the help messages available and */
+/* their names. */
+/* */
+/* The command line connects to help by providing a single command line */
+/* option called +Hx which has the effect of displaying the help message */
+/* called x. The default is -Hmenu. The "-" means that help is not invoked by */
+/* default, but that if the user specifies +H, the menu message will be */
+/* printed. If the user specifies (say) +Hsloth, message SLOTH will be */
+/* displayed. The menu message is printed if the user invokes FunnelWeb with */
+/* no actions. The +H option is classified as an action option. */
+/* */
+/* Interactive mode connects to help through the HELP command. In the spirit */
+/* of the command line interface, if no argument is given, the menu message */
+/* is displayed. If an argument is given, the specified message is written */
+/* out. */
+/* */
+/* This module contributes two things to this process: */
+/* 1) Provides a mapping from message names to messages. */
+/* 2) Acts as a repository for the messages themselves. */
+/* */
+/******************************************************************************/
+
+/* Ensure that the body of this header file is included at most once. */
+#ifndef DONE_HELP
+#define DONE_HELP
+
+/******************************************************************************/
+
+#include "style.h"
+
+/******************************************************************************/
+
+/* Place a bound on help name length, and define an array type to hold them. */
+#define HL_NMLEN 20
+typedef char hn_t[HL_NMLEN+1];
+
+/******************************************************************************/
+
+/* Each of the messages has a unique symbol and number. The reason for */
+/* defining these symbols instead of just using the message names in the code */
+/* is that doing it this way allows us to change the exact message names */
+/* without having to track down all their occurences in the code, or getting */
+/* nasty surprises later down the track at run time (the compiler will tell */
+/* you in a call containing HL_SLT that the symbol doesn't exist, but it */
+/* won't complain about a string argument that just happens not to be the */
+/* name of a message anymore). */
+
+/* HL_ERR is the non-existent message. */
+#define HL_ERR 0
+
+/* HL_MEN - Help messages. */
+/* HL_INT - Introduction to FunnelWeb. */
+/* HL_OPT - Command line options. */
+/* HL_DOP - Option defaults. */
+/* HL_COM - Interactive commands. */
+/* HL_DOC - Documentation. */
+/* HL_REG - Registration. */
+/* HL_LIC - The GNU License. */
+/* HL_COP - Copyright notice. */
+/* HL_NOW - No Warranty notice. */
+/* HL_DIS - Distribution notice. */
+/* HL_ACK - Acknowledgements. */
+/* HL_VER - Versions. */
+/* HL_SUP - Support. */
+/* HL_MOD - Modifications. */
+#define HL_MEN 1
+#define HL_INT 2
+#define HL_OPT 3
+#define HL_DOP 4
+#define HL_COM 5
+#define HL_DOC 6
+#define HL_REG 7
+#define HL_GNU 8
+#define HL_COP 9
+#define HL_NOW 10
+#define HL_DIS 11
+#define HL_ACK 12
+#define HL_VER 13
+#define HL_SUP 14
+#define HL_MOD 15
+
+/* The following symbol does not represent a message. It is the number of */
+/* messages. This is useful for range checking and possibly in for loops. */
+#define HL_FWMAX 15
+
+/******************************************************************************/
+
+EXPORT uword hel_num P_((char *));
+/* Accepts a character string that is supposed to be the name of a message */
+/* and returns the number of the message, or HL_ERR if the string does not */
+/* correspond to any defined message. A match will occur if the argument */
+/* string is the same (with case independent matching) as the prefix (of */
+/* corresponding length) of exactly one message name. */
+
+EXPORT void hel_wri P_((void (*)(char *),uword));
+/* Accepts a message number and writes the message using the function */
+/* provided in the first argument. Bombs the program if the message number in */
+/* the second argument is not in the range [1,HL_FWMAX]. */
+
+/******************************************************************************/
+
+/* For #ifndef preventing multiple inclusion of the body of this header file. */
+#endif
+
+/******************************************************************************/
+/* End of HELP.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/help_gnu.c b/web/funnelAC/fwACsrc/help_gnu.c
new file mode 100644
index 0000000000..20555d3b14
--- /dev/null
+++ b/web/funnelAC/fwACsrc/help_gnu.c
@@ -0,0 +1,105 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* HELP_GNU.C */
+/******************************************************************************/
+/* */
+/* REPRESENTING MESSAGES AS C CODE */
+/* =============================== */
+/* Experience has shown that it is much more reliable to code text messages */
+/* into a program than to expect the program to track down text files */
+/* containing the messages at run time. Worthwhile for smallish files (such */
+/* as these help messages) at least. For this reason, all the messages in */
+/* this module are represented by code (e.g. as in printf statements). */
+/* */
+/* There is no difficulty turning a short message into code; simply place it */
+/* in output statements. However, large messages (e.g. the GNU license) are */
+/* more tedious, and also present more of a problem if it is necessary to */
+/* change them substantially at a later date. This problem has been solved in */
+/* FunnelWeb by writing a small program that reads a text file and writes out */
+/* C code that writes the text file. The files involved are: */
+/* */
+/* help_gnu.mes - The original message. */
+/* help_gnu.c - C code to write out the original message. */
+/* */
+/* To turn help_gnu.mes into help_gnu.c, give the following command in */
+/* FunnelWeb interactive mode: codify help_gnu.txt help_gnu.c */
+/* */
+/******************************************************************************/
+
+#include "style.h"
+
+#include "help_gnu.h"
+
+/******************************************************************************/
+
+/* This module contains many many output statements that call an output */
+/* function. To neaten up all these calls, we define a global variable to */
+/* hold a pointer to the function and simple macro to write output using */
+/* the function. */
+LOCVAR void (*pf) P_((char *));
+
+#define WX(STR) (*pf)(STR);(*pf)("\n")
+#define WY(STR) (*pf)(STR)
+
+/******************************************************************************/
+
+EXPORT void hel_gnu (p_outf)
+void (*p_outf) P_((char *));
+{
+ pf=p_outf;
+ WY("\n");
+ WY("FunnelWeb License\n");
+ WY("-----------------\n");
+ WY("FunnelWeb is distributed under the following license.\n");
+ WY("\n");
+ WY("--<Start of GNU License>--\n");
+#include "help_gnu.ctx"
+ WY("--<End of GNU License>--\n");
+ WY("\n");
+ WY("If all that scrolled off your screen too quickly, don't worry. You can\n");
+ WY("capture this message (or any other FunnelWeb output) in a file by\n");
+ WY("specifying the +J option when you invoke FunnelWeb. For example:\n");
+ WY("\n");
+ WY(" fw +hlicense +jresult.txt\n");
+ WY("\n");
+}
+
+/******************************************************************************/
+/* End of HELP_GNU.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/help_gnu.ctx b/web/funnelAC/fwACsrc/help_gnu.ctx
new file mode 100644
index 0000000000..34af6039b0
--- /dev/null
+++ b/web/funnelAC/fwACsrc/help_gnu.ctx
@@ -0,0 +1,339 @@
+ WX(" GNU GENERAL PUBLIC LICENSE");
+ WX(" Version 2, June 1991");
+ WX("");
+ WX(" Copyright (C) 1989, 1991 Free Software Foundation, Inc.");
+ WX(" 675 Mass Ave, Cambridge, MA 02139, USA");
+ WX(" Everyone is permitted to copy and distribute verbatim copies");
+ WX(" of this license document, but changing it is not allowed.");
+ WX("");
+ WX(" Preamble");
+ WX("");
+ WX(" The licenses for most software are designed to take away your");
+ WX("freedom to share and change it. By contrast, the GNU General Public");
+ WX("License is intended to guarantee your freedom to share and change free");
+ WX("software--to make sure the software is free for all its users. This");
+ WX("General Public License applies to most of the Free Software");
+ WX("Foundation's software and to any other program whose authors commit to");
+ WX("using it. (Some other Free Software Foundation software is covered by");
+ WX("the GNU Library General Public License instead.) You can apply it to");
+ WX("your programs, too.");
+ WX("");
+ WX(" When we speak of free software, we are referring to freedom, not");
+ WX("price. Our General Public Licenses are designed to make sure that you");
+ WX("have the freedom to distribute copies of free software (and charge for");
+ WX("this service if you wish), that you receive source code or can get it");
+ WX("if you want it, that you can change the software or use pieces of it");
+ WX("in new free programs; and that you know you can do these things.");
+ WX("");
+ WX(" To protect your rights, we need to make restrictions that forbid");
+ WX("anyone to deny you these rights or to ask you to surrender the rights.");
+ WX("These restrictions translate to certain responsibilities for you if you");
+ WX("distribute copies of the software, or if you modify it.");
+ WX("");
+ WX(" For example, if you distribute copies of such a program, whether");
+ WX("gratis or for a fee, you must give the recipients all the rights that");
+ WX("you have. You must make sure that they, too, receive or can get the");
+ WX("source code. And you must show them these terms so they know their");
+ WX("rights.");
+ WX("");
+ WX(" We protect your rights with two steps: (1) copyright the software, and");
+ WX("(2) offer you this license which gives you legal permission to copy,");
+ WX("distribute and/or modify the software.");
+ WX("");
+ WX(" Also, for each author's protection and ours, we want to make certain");
+ WX("that everyone understands that there is no warranty for this free");
+ WX("software. If the software is modified by someone else and passed on, we");
+ WX("want its recipients to know that what they have is not the original, so");
+ WX("that any problems introduced by others will not reflect on the original");
+ WX("authors' reputations.");
+ WX("");
+ WX(" Finally, any free program is threatened constantly by software");
+ WX("patents. We wish to avoid the danger that redistributors of a free");
+ WX("program will individually obtain patent licenses, in effect making the");
+ WX("program proprietary. To prevent this, we have made it clear that any");
+ WX("patent must be licensed for everyone's free use or not licensed at all.");
+ WX("");
+ WX(" The precise terms and conditions for copying, distribution and");
+ WX("modification follow.");
+ WX("");
+ WX(" GNU GENERAL PUBLIC LICENSE");
+ WX(" TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION");
+ WX("");
+ WX(" 0. This License applies to any program or other work which contains");
+ WX("a notice placed by the copyright holder saying it may be distributed");
+ WX("under the terms of this General Public License. The \"Program\", below,");
+ WX("refers to any such program or work, and a \"work based on the Program\"");
+ WX("means either the Program or any derivative work under copyright law:");
+ WX("that is to say, a work containing the Program or a portion of it,");
+ WX("either verbatim or with modifications and/or translated into another");
+ WX("language. (Hereinafter, translation is included without limitation in");
+ WX("the term \"modification\".) Each licensee is addressed as \"you\".");
+ WX("");
+ WX("Activities other than copying, distribution and modification are not");
+ WX("covered by this License; they are outside its scope. The act of");
+ WX("running the Program is not restricted, and the output from the Program");
+ WX("is covered only if its contents constitute a work based on the");
+ WX("Program (independent of having been made by running the Program).");
+ WX("Whether that is true depends on what the Program does.");
+ WX("");
+ WX(" 1. You may copy and distribute verbatim copies of the Program's");
+ WX("source code as you receive it, in any medium, provided that you");
+ WX("conspicuously and appropriately publish on each copy an appropriate");
+ WX("copyright notice and disclaimer of warranty; keep intact all the");
+ WX("notices that refer to this License and to the absence of any warranty;");
+ WX("and give any other recipients of the Program a copy of this License");
+ WX("along with the Program.");
+ WX("");
+ WX("You may charge a fee for the physical act of transferring a copy, and");
+ WX("you may at your option offer warranty protection in exchange for a fee.");
+ WX("");
+ WX(" 2. You may modify your copy or copies of the Program or any portion");
+ WX("of it, thus forming a work based on the Program, and copy and");
+ WX("distribute such modifications or work under the terms of Section 1");
+ WX("above, provided that you also meet all of these conditions:");
+ WX("");
+ WX(" a) You must cause the modified files to carry prominent notices");
+ WX(" stating that you changed the files and the date of any change.");
+ WX("");
+ WX(" b) You must cause any work that you distribute or publish, that in");
+ WX(" whole or in part contains or is derived from the Program or any");
+ WX(" part thereof, to be licensed as a whole at no charge to all third");
+ WX(" parties under the terms of this License.");
+ WX("");
+ WX(" c) If the modified program normally reads commands interactively");
+ WX(" when run, you must cause it, when started running for such");
+ WX(" interactive use in the most ordinary way, to print or display an");
+ WX(" announcement including an appropriate copyright notice and a");
+ WX(" notice that there is no warranty (or else, saying that you provide");
+ WX(" a warranty) and that users may redistribute the program under");
+ WX(" these conditions, and telling the user how to view a copy of this");
+ WX(" License. (Exception: if the Program itself is interactive but");
+ WX(" does not normally print such an announcement, your work based on");
+ WX(" the Program is not required to print an announcement.)");
+ WX("");
+ WX("These requirements apply to the modified work as a whole. If");
+ WX("identifiable sections of that work are not derived from the Program,");
+ WX("and can be reasonably considered independent and separate works in");
+ WX("themselves, then this License, and its terms, do not apply to those");
+ WX("sections when you distribute them as separate works. But when you");
+ WX("distribute the same sections as part of a whole which is a work based");
+ WX("on the Program, the distribution of the whole must be on the terms of");
+ WX("this License, whose permissions for other licensees extend to the");
+ WX("entire whole, and thus to each and every part regardless of who wrote it.");
+ WX("");
+ WX("Thus, it is not the intent of this section to claim rights or contest");
+ WX("your rights to work written entirely by you; rather, the intent is to");
+ WX("exercise the right to control the distribution of derivative or");
+ WX("collective works based on the Program.");
+ WX("");
+ WX("In addition, mere aggregation of another work not based on the Program");
+ WX("with the Program (or with a work based on the Program) on a volume of");
+ WX("a storage or distribution medium does not bring the other work under");
+ WX("the scope of this License.");
+ WX("");
+ WX(" 3. You may copy and distribute the Program (or a work based on it,");
+ WX("under Section 2) in object code or executable form under the terms of");
+ WX("Sections 1 and 2 above provided that you also do one of the following:");
+ WX("");
+ WX(" a) Accompany it with the complete corresponding machine-readable");
+ WX(" source code, which must be distributed under the terms of Sections");
+ WX(" 1 and 2 above on a medium customarily used for software interchange; or,");
+ WX("");
+ WX(" b) Accompany it with a written offer, valid for at least three");
+ WX(" years, to give any third party, for a charge no more than your");
+ WX(" cost of physically performing source distribution, a complete");
+ WX(" machine-readable copy of the corresponding source code, to be");
+ WX(" distributed under the terms of Sections 1 and 2 above on a medium");
+ WX(" customarily used for software interchange; or,");
+ WX("");
+ WX(" c) Accompany it with the information you received as to the offer");
+ WX(" to distribute corresponding source code. (This alternative is");
+ WX(" allowed only for noncommercial distribution and only if you");
+ WX(" received the program in object code or executable form with such");
+ WX(" an offer, in accord with Subsection b above.)");
+ WX("");
+ WX("The source code for a work means the preferred form of the work for");
+ WX("making modifications to it. For an executable work, complete source");
+ WX("code means all the source code for all modules it contains, plus any");
+ WX("associated interface definition files, plus the scripts used to");
+ WX("control compilation and installation of the executable. However, as a");
+ WX("special exception, the source code distributed need not include");
+ WX("anything that is normally distributed (in either source or binary");
+ WX("form) with the major components (compiler, kernel, and so on) of the");
+ WX("operating system on which the executable runs, unless that component");
+ WX("itself accompanies the executable.");
+ WX("");
+ WX("If distribution of executable or object code is made by offering");
+ WX("access to copy from a designated place, then offering equivalent");
+ WX("access to copy the source code from the same place counts as");
+ WX("distribution of the source code, even though third parties are not");
+ WX("compelled to copy the source along with the object code.");
+ WX("");
+ WX(" 4. You may not copy, modify, sublicense, or distribute the Program");
+ WX("except as expressly provided under this License. Any attempt");
+ WX("otherwise to copy, modify, sublicense or distribute the Program is");
+ WX("void, and will automatically terminate your rights under this License.");
+ WX("However, parties who have received copies, or rights, from you under");
+ WX("this License will not have their licenses terminated so long as such");
+ WX("parties remain in full compliance.");
+ WX("");
+ WX(" 5. You are not required to accept this License, since you have not");
+ WX("signed it. However, nothing else grants you permission to modify or");
+ WX("distribute the Program or its derivative works. These actions are");
+ WX("prohibited by law if you do not accept this License. Therefore, by");
+ WX("modifying or distributing the Program (or any work based on the");
+ WX("Program), you indicate your acceptance of this License to do so, and");
+ WX("all its terms and conditions for copying, distributing or modifying");
+ WX("the Program or works based on it.");
+ WX("");
+ WX(" 6. Each time you redistribute the Program (or any work based on the");
+ WX("Program), the recipient automatically receives a license from the");
+ WX("original licensor to copy, distribute or modify the Program subject to");
+ WX("these terms and conditions. You may not impose any further");
+ WX("restrictions on the recipients' exercise of the rights granted herein.");
+ WX("You are not responsible for enforcing compliance by third parties to");
+ WX("this License.");
+ WX("");
+ WX(" 7. If, as a consequence of a court judgment or allegation of patent");
+ WX("infringement or for any other reason (not limited to patent issues),");
+ WX("conditions are imposed on you (whether by court order, agreement or");
+ WX("otherwise) that contradict the conditions of this License, they do not");
+ WX("excuse you from the conditions of this License. If you cannot");
+ WX("distribute so as to satisfy simultaneously your obligations under this");
+ WX("License and any other pertinent obligations, then as a consequence you");
+ WX("may not distribute the Program at all. For example, if a patent");
+ WX("license would not permit royalty-free redistribution of the Program by");
+ WX("all those who receive copies directly or indirectly through you, then");
+ WX("the only way you could satisfy both it and this License would be to");
+ WX("refrain entirely from distribution of the Program.");
+ WX("");
+ WX("If any portion of this section is held invalid or unenforceable under");
+ WX("any particular circumstance, the balance of the section is intended to");
+ WX("apply and the section as a whole is intended to apply in other");
+ WX("circumstances.");
+ WX("");
+ WX("It is not the purpose of this section to induce you to infringe any");
+ WX("patents or other property right claims or to contest validity of any");
+ WX("such claims; this section has the sole purpose of protecting the");
+ WX("integrity of the free software distribution system, which is");
+ WX("implemented by public license practices. Many people have made");
+ WX("generous contributions to the wide range of software distributed");
+ WX("through that system in reliance on consistent application of that");
+ WX("system; it is up to the author/donor to decide if he or she is willing");
+ WX("to distribute software through any other system and a licensee cannot");
+ WX("impose that choice.");
+ WX("");
+ WX("This section is intended to make thoroughly clear what is believed to");
+ WX("be a consequence of the rest of this License.");
+ WX("");
+ WX(" 8. If the distribution and/or use of the Program is restricted in");
+ WX("certain countries either by patents or by copyrighted interfaces, the");
+ WX("original copyright holder who places the Program under this License");
+ WX("may add an explicit geographical distribution limitation excluding");
+ WX("those countries, so that distribution is permitted only in or among");
+ WX("countries not thus excluded. In such case, this License incorporates");
+ WX("the limitation as if written in the body of this License.");
+ WX("");
+ WX(" 9. The Free Software Foundation may publish revised and/or new versions");
+ WX("of the General Public License from time to time. Such new versions will");
+ WX("be similar in spirit to the present version, but may differ in detail to");
+ WX("address new problems or concerns.");
+ WX("");
+ WX("Each version is given a distinguishing version number. If the Program");
+ WX("specifies a version number of this License which applies to it and \"any");
+ WX("later version\", you have the option of following the terms and conditions");
+ WX("either of that version or of any later version published by the Free");
+ WX("Software Foundation. If the Program does not specify a version number of");
+ WX("this License, you may choose any version ever published by the Free Software");
+ WX("Foundation.");
+ WX("");
+ WX(" 10. If you wish to incorporate parts of the Program into other free");
+ WX("programs whose distribution conditions are different, write to the author");
+ WX("to ask for permission. For software which is copyrighted by the Free");
+ WX("Software Foundation, write to the Free Software Foundation; we sometimes");
+ WX("make exceptions for this. Our decision will be guided by the two goals");
+ WX("of preserving the free status of all derivatives of our free software and");
+ WX("of promoting the sharing and reuse of software generally.");
+ WX("");
+ WX(" NO WARRANTY");
+ WX("");
+ WX(" 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY");
+ WX("FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN");
+ WX("OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES");
+ WX("PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED");
+ WX("OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF");
+ WX("MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS");
+ WX("TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE");
+ WX("PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,");
+ WX("REPAIR OR CORRECTION.");
+ WX("");
+ WX(" 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING");
+ WX("WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR");
+ WX("REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,");
+ WX("INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING");
+ WX("OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED");
+ WX("TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY");
+ WX("YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER");
+ WX("PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE");
+ WX("POSSIBILITY OF SUCH DAMAGES.");
+ WX("");
+ WX(" END OF TERMS AND CONDITIONS");
+ WX("");
+ WX(" Appendix: How to Apply These Terms to Your New Programs");
+ WX("");
+ WX(" If you develop a new program, and you want it to be of the greatest");
+ WX("possible use to the public, the best way to achieve this is to make it");
+ WX("free software which everyone can redistribute and change under these terms.");
+ WX("");
+ WX(" To do so, attach the following notices to the program. It is safest");
+ WX("to attach them to the start of each source file to most effectively");
+ WX("convey the exclusion of warranty; and each file should have at least");
+ WX("the \"copyright\" line and a pointer to where the full notice is found.");
+ WX("");
+ WX(" <one line to give the program's name and a brief idea of what it does.>");
+ WX(" Copyright (C) 19yy <name of author>");
+ WX("");
+ WX(" This program is free software; you can redistribute it and/or modify");
+ WX(" it under the terms of the GNU General Public License as published by");
+ WX(" the Free Software Foundation; either version 2 of the License, or");
+ WX(" (at your option) any later version.");
+ WX("");
+ WX(" This program is distributed in the hope that it will be useful,");
+ WX(" but WITHOUT ANY WARRANTY; without even the implied warranty of");
+ WX(" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the");
+ WX(" GNU General Public License for more details.");
+ WX("");
+ WX(" You should have received a copy of the GNU General Public License");
+ WX(" along with this program; if not, write to the Free Software");
+ WX(" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.");
+ WX("");
+ WX("Also add information on how to contact you by electronic and paper mail.");
+ WX("");
+ WX("If the program is interactive, make it output a short notice like this");
+ WX("when it starts in an interactive mode:");
+ WX("");
+ WX(" Gnomovision version 69, Copyright (C) 19yy name of author");
+ WX(" Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.");
+ WX(" This is free software, and you are welcome to redistribute it");
+ WX(" under certain conditions; type `show c' for details.");
+ WX("");
+ WX("The hypothetical commands `show w' and `show c' should show the appropriate");
+ WX("parts of the General Public License. Of course, the commands you use may");
+ WX("be called something other than `show w' and `show c'; they could even be");
+ WX("mouse-clicks or menu items--whatever suits your program.");
+ WX("");
+ WX("You should also get your employer (if you work as a programmer) or your");
+ WX("school, if any, to sign a \"copyright disclaimer\" for the program, if");
+ WX("necessary. Here is a sample; alter the names:");
+ WX("");
+ WX(" Yoyodyne, Inc., hereby disclaims all copyright interest in the program");
+ WX(" `Gnomovision' (which makes passes at compilers) written by James Hacker.");
+ WX("");
+ WX(" <signature of Ty Coon>, 1 April 1989");
+ WX(" Ty Coon, President of Vice");
+ WX("");
+ WX("This General Public License does not permit incorporating your program into");
+ WX("proprietary programs. If your program is a subroutine library, you may");
+ WX("consider it more useful to permit linking proprietary applications with the");
+ WX("library. If this is what you want to do, use the GNU Library General");
+ WX("Public License instead of this License.");
diff --git a/web/funnelAC/fwACsrc/help_gnu.h b/web/funnelAC/fwACsrc/help_gnu.h
new file mode 100644
index 0000000000..8844e1463a
--- /dev/null
+++ b/web/funnelAC/fwACsrc/help_gnu.h
@@ -0,0 +1,58 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* HELP_GNU.H */
+/******************************************************************************/
+/* */
+/* This module is used solely by the help module, and is really part of the */
+/* help module, but has been separated out because THINK C on the Macintosh */
+/* couldn't cope with more than 32K of code in one module. */
+/* */
+/******************************************************************************/
+
+#include "style.h"
+
+/******************************************************************************/
+
+EXPORT void hel_gnu P_((void (*)(char *)));
+/* Writes out the GNU General Public License Version 2 using the specified */
+/* output function. */
+
+/******************************************************************************/
+/* End of HELP_GNU.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/help_gnu.txt b/web/funnelAC/fwACsrc/help_gnu.txt
new file mode 100644
index 0000000000..b8cf3a1ab2
--- /dev/null
+++ b/web/funnelAC/fwACsrc/help_gnu.txt
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/web/funnelAC/fwACsrc/htmlhead.c b/web/funnelAC/fwACsrc/htmlhead.c
new file mode 100644
index 0000000000..1af2e9524f
--- /dev/null
+++ b/web/funnelAC/fwACsrc/htmlhead.c
@@ -0,0 +1,112 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 15-Apr-1994 ABC Created this file by modifying `texhead.c'
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* HTMLHEAD.C */
+/******************************************************************************/
+/* */
+/* HTML HEADER PACKAGE */
+/* ================== */
+/* This package contains a single function that writes the HTML header */
+/* (containing all the Weave macros) to the specified stream. The package */
+/* consists of: */
+/* */
+/* htmlhead.htm - The header file ("source code" for htmlhead.cht). */
+/* htmlhead.cht - Automatically generated C code based on htmlhead.htm. */
+/* htmlhead.h - Exported header file containing function definition. */
+/* htmlhead.c - Contains the function body and the codified header file. */
+/* */
+/* WARNING: THE ONLY FILE THAT SHOULD EVER BE MODIFIED BY HAND IS */
+/* HTMLHEAD.HTM. */
+/* From this can be generated a new version of htmlhead.cht. Here's how: */
+/* 1. Edit htmlhead.htm as desired. */
+/* 2. Fire up the FunnelWeb shell and give the command: */
+/* codify htmlhead.htm htmlhead.cht */
+/* */
+/******************************************************************************/
+
+#include "style.h"
+
+#include "htmlhead.h"
+#include "writfile.h"
+
+/******************************************************************************/
+
+EXPORT void html_head(p_wf)
+p_wf_t p_wf;
+/* Writes the FunnelWeb HTML header block to the argument stream. */
+{
+
+ /*#############################################################################
+ IMPORTANT COPYRIGHT NOTICE
+ --------------------------
+ The set of FunnelWeb HTML definitions, embodied in C code in the file
+ included by the #include directive below, is a public domain work.
+
+ Notwithstanding the fact that the public domain set of FunnelWeb HTML
+ definitions is represented in the form of strings in C code #included by the
+ FunnelWeb literate-programming preprocessor program released under GNU General
+ Public License Version 2, the set of HTML definitions themselves do not fall
+ under GNU license. Instead, the set of FunnelWeb HTML definitions is classified
+ as a public domain work that is distributed with FunnelWeb as a "separate
+ work". The set of definitions is included as strings in the FunnelWeb code for
+ the sole reason that this organization avoids FunnelWeb having to locate the
+ file at run time. Thus, when FunnelWeb writes the set of HTML definitions to a
+ .htm output file, it is not generating a work based on itself, but is merely
+ copying a public domain file (which it happened to represent in the form of
+ code rather than data) into the output file.
+
+ The motivation for rigorously clarifying the status of the set of
+ FunnelWeb HTML definitions is that it will appear in HTML output files
+ generated by FunnelWeb, and I do not want any output files generated by
+ FunnelWeb to be under any copyright restrictions.
+
+ -- Ross N. Williams, 5:42pm 07-May-1992, Adelaide, Australia.
+ -- A.B.Coates, 5:55pm 15-Apr-1994, Brisbane, Australia.
+
+ #############################################################################*/
+
+#define WX(STR) wf_wl(p_wf,STR)
+
+#include "htmlhead.cht"
+}
+
+/******************************************************************************/
+/* End of HTMLHEAD.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/htmlhead.cht b/web/funnelAC/fwACsrc/htmlhead.cht
new file mode 100644
index 0000000000..25e78253b1
--- /dev/null
+++ b/web/funnelAC/fwACsrc/htmlhead.cht
@@ -0,0 +1,42 @@
+ WX("<!--============ Start of FunnelWeb HTML Definitions ============-->");
+ WX("");
+ WX("<!-- Version -->");
+ WX("<!-- ------- -->");
+ WX("<!-- This is FunnelWeb HTML Macro Library Version 1.0. -->");
+ WX("");
+ WX("<!-- Copyright -->");
+ WX("<!-- --------- -->");
+ WX("<!-- This set of FunnelWeb HTML definitions was written by -->");
+ WX("<!-- Anthony Coates and is Copyright (C) 1994 Anthony B. Coates. -->");
+ WX("<!-- However, I, Anthony Coates, hereby forego any claim to -->");
+ WX("<!-- Copyright in this set of FunnelWeb HTML definitions and -->");
+ WX("<!-- hereby authorize that the set of HTML definitions pass -->");
+ WX("<!-- into the public domain. -->");
+ WX("<!-- Anthony B. Coates, 6:25pm 15-Apr-1994, Brisbane, Australia. -->");
+ WX("");
+ WX("<!-- Modification -->");
+ WX("<!-- ------------ -->");
+ WX("<!-- Please record all modifications to these HTML definitions -->");
+ WX("<!-- here. Unless otherwise specified, all modified definitions -->");
+ WX("<!-- fall in the public domain too. -->");
+ WX("");
+ WX("<!-- Programmers: -->");
+ WX("<!-- ABC Anthony B. Coates coates@physics.uq.edu.au -->");
+ WX("");
+ WX("<!-- Changes: -->");
+ WX("<!-- 23-Apr-1994 ABC Prepared this work for -->");
+ WX("<!-- public domain release. -->");
+ WX("");
+ WX("<!-- General Comments -->");
+ WX("<!-- ---------------- -->");
+ WX("<!-- Where possible, definitions here will be used to reflect -->");
+ WX("<!-- existing FunnelWeb TeX definitions. -->");
+ WX("");
+ WX("<!-- The ISO-Latin-1 character set does not have the bullet -->");
+ WX("<!-- character that FunnelWeb uses for unprintable characters in -->");
+ WX("<!-- TeX output, so an inverted question mark (a Spanish -->");
+ WX("<!-- character used at the start of questions) is used instead. -->");
+ WX("");
+ WX("<!-- THERE ARE CURRENTLY NO DEFINITIONS IN THIS HEADER FILE. -->");
+ WX("");
+ WX("<!--============= End of FunnelWeb HTML Definitions =============-->");
diff --git a/web/funnelAC/fwACsrc/htmlhead.h b/web/funnelAC/fwACsrc/htmlhead.h
new file mode 100644
index 0000000000..09ea08e6a6
--- /dev/null
+++ b/web/funnelAC/fwACsrc/htmlhead.h
@@ -0,0 +1,125 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 15-Apr-1994 ABC Created this file by modifying `texhead.h'
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* HTMLHEAD.H */
+/******************************************************************************/
+/* */
+/* HTML HEADER PACKAGE */
+/* ================== */
+/* This package contains a single function that writes the HTML header */
+/* (containing all the Weave macros) to the specified stream. The package */
+/* consists of: */
+/* */
+/* htmlhead.htm - The header file ("source code" for htmlhead.cht). */
+/* htmlhead.cht - C code automatically generated by htmlhead.htm. */
+/* htmlhead.h - This file, containing a function definition. */
+/* htmlhead.c - Contains a function body. */
+/* */
+/* The first version of FunnelWeb (1986) generated TeX output files that used */
+/* a collection of macros to neaten and simplify the bulk of the TeX output */
+/* file. For example, the macro \fwbtx provided a simple way to specify */
+/* verbatim text. This system worked extremely well, the only inconvenience */
+/* being that each FunnelWeb TeX output file had to "\input" the TeX header */
+/* file containing all the macros. At the time, this seemed a sensible */
+/* factorization of the macros, and, within the limited environment in which */
+/* FunnelWeb was operating, worked well. */
+/* */
+/* In NEW, IMPROVED FunnelWeb, "\input"ing the header file has the potential */
+/* to cause lots of problems, the major ones being: */
+/* */
+/* - The header file would have to be installed as part of the FunnelWeb */
+/* system. Currently this means that it would be the ONLY other file */
+/* necessary apart from the FunnelWeb executable. It would be far more */
+/* desirable to avoid having to install the header file. */
+/* */
+/* - The header file would have to be referred to somehow by the TeX file. */
+/* As it makes sense to have only one copy of the header file on a machine, */
+/* TeX files would have to refer to that copy. This would require one of a */
+/* number of messy machine-specific mechanisms such as (VMS) logical name */
+/* translation or environment variable translation. */
+/* */
+/* - TeX files could not be easily moved to other machines (particularly */
+/* those not running FunnelWeb themselves) without also sending the header */
+/* file. */
+/* */
+/* - If FunnelWeb and the header file were ever jointly modified, the dynamic */
+/* binding of old TeX files would mean that they may no longer be printable.*/
+/* */
+/* For all these reasons, the decision was made to write the library of TeX */
+/* macros at the start of each TeX output file, thus making each TeX output */
+/* file entirely self-contained. To do this, the header file had to be */
+/* converted into a sequence of C output statments. To this end, a new */
+/* FunnelWeb shell command CODIFY was added that performs this transformation.*/
+/* CODIFY could have been a separate utility program, but if it was, it might */
+/* somehow be separated from the rest of FunnelWeb during distribution. By */
+/* building CODIFY into FunnelWeb itself, this possibility is eliminated. */
+/* */
+/* This package encapsulates the automatically generated C code. This header */
+/* file defines a function that writes it to a specified stream. The package */
+/* body htmlhead.c contains the body of the function which consists mainly of */
+/* a #include of the automatically generated C code in htmlhead.cht. */
+/* */
+/******************************************************************************/
+
+/* Ensure that the body of this header file is included at most once. */
+#ifndef DONE_HTMLH
+#define DONE_HTMLH
+
+/******************************************************************************/
+
+/* Define NO_HEADER to suppress inclusion of the FunnelWeb HTML header */
+
+#include "style.h"
+
+#include "writfile.h"
+
+/******************************************************************************/
+
+EXPORT void html_head P_((p_wf_t));
+/* Writes the FunnelWeb HTML header block to the argument stream. */
+
+/******************************************************************************/
+
+/* For #ifndef preventing multiple inclusion of the body of this header file. */
+#endif
+
+/******************************************************************************/
+/* End of HTMLHEAD.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/htmlhead.htm b/web/funnelAC/fwACsrc/htmlhead.htm
new file mode 100644
index 0000000000..95bd531d66
--- /dev/null
+++ b/web/funnelAC/fwACsrc/htmlhead.htm
@@ -0,0 +1,42 @@
+<!--============ Start of FunnelWeb HTML Definitions ============-->
+
+<!-- Version -->
+<!-- ------- -->
+<!-- This is FunnelWeb HTML Macro Library Version 1.0. -->
+
+<!-- Copyright -->
+<!-- --------- -->
+<!-- This set of FunnelWeb HTML definitions was written by -->
+<!-- Anthony Coates and is Copyright (C) 1994 Anthony B. Coates. -->
+<!-- However, I, Anthony Coates, hereby forego any claim to -->
+<!-- Copyright in this set of FunnelWeb HTML definitions and -->
+<!-- hereby authorize that the set of HTML definitions pass -->
+<!-- into the public domain. -->
+<!-- Anthony B. Coates, 6:25pm 15-Apr-1994, Brisbane, Australia. -->
+
+<!-- Modification -->
+<!-- ------------ -->
+<!-- Please record all modifications to these HTML definitions -->
+<!-- here. Unless otherwise specified, all modified definitions -->
+<!-- fall in the public domain too. -->
+
+<!-- Programmers: -->
+<!-- ABC Anthony B. Coates coates@physics.uq.edu.au -->
+
+<!-- Changes: -->
+<!-- 23-Apr-1994 ABC Prepared this work for -->
+<!-- public domain release. -->
+
+<!-- General Comments -->
+<!-- ---------------- -->
+<!-- Where possible, definitions here will be used to reflect -->
+<!-- existing FunnelWeb TeX definitions. -->
+
+<!-- The ISO-Latin-1 character set does not have the bullet -->
+<!-- character that FunnelWeb uses for unprintable characters in -->
+<!-- TeX output, so an inverted question mark (a Spanish -->
+<!-- character used at the start of questions) is used instead. -->
+
+<!-- THERE ARE CURRENTLY NO DEFINITIONS IN THIS HEADER FILE. -->
+
+<!--============= End of FunnelWeb HTML Definitions =============-->
diff --git a/web/funnelAC/fwACsrc/list.c b/web/funnelAC/fwACsrc/list.c
new file mode 100644
index 0000000000..6585904214
--- /dev/null
+++ b/web/funnelAC/fwACsrc/list.c
@@ -0,0 +1,328 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 08-Aug-1995 ABC Changed include file name from "memory.h"
+ to "fwmem.h" to avoid a clash with the C++
+ standard header file "memory.h".
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* LIST.C */
+/******************************************************************************/
+
+#include "style.h"
+
+#include "as.h"
+#include "machin.h"
+#include "fwmem.h"
+
+/******************************************************************************/
+
+/* In order to catch uninitialized and corrupted lists, the first and last */
+/* fields of legitimate list objects contain magic numbers. The following */
+/* #defines give the values of these numbers. The first thing that each */
+/* function of this package does is to check the two magic number fields of */
+/* the list it has just been passed, and bomb the package if the fields have */
+/* the wrong values. This technique is likely to pick uninitialized lists, */
+/* as well as lists that have been partially overwritten. */
+#define MAGIC_HEAD_VALUE (97673812L)
+#define MAGIC_TAIL_VALUE (49357294L)
+
+/******************************************************************************/
+
+typedef struct node_t_ /* Structure used to compose the list proper. */
+ {
+ struct node_t_ *p_prev; /* Points to adjacent node closer to head. */
+ struct node_t_ *p_next; /* Points to adjacent node closer to tail. */
+ p_void p_data; /* Points to data in heap for this element. */
+ }
+ node_t;
+
+typedef node_t *p_node_t; /* Pointer to node type. */
+
+typedef struct /* Main list object containing all the goodies. */
+ {
+ ulong magic_head; /* Helpful in catching list object corruptions. */
+ p_node_t p_head; /* Points to the head of the list (or NULL). */
+ p_node_t p_tail; /* Points to the tail of the list (or NULL). */
+ p_node_t p_mark; /* Points to the marked element (or NULL). */
+ size_t data_bytes; /* Number of bytes in this list's data elements. */
+ ulong length; /* Number of elements in this list. */
+ ulong magic_tail; /* Helpful in catching list object corruptions. */
+ }
+ ls_t;
+
+typedef ls_t *p_ls_t; /* Main list view type. */
+
+typedef p_void p_lsel_t; /* Escalating pointers to data elements! */
+typedef p_lsel_t *pp_lsel_t;
+
+/* We need the function prototypes from list.h. The #define ensures that the */
+/* abstract exported definition of a list is not visible to us here. */
+#define INLISTC
+#include "list.h"
+
+/******************************************************************************/
+
+LOCAL void ls_check P_((p_ls_t));
+LOCAL void ls_check(p_ls)
+/* Accepts a pointer to a list and performs a series of checks to make sure */
+/* that the list has not been corrupted in some way. */
+/* This function is the sort of function that is normally turned off in */
+/* production versions. However, we are too scared to in FunnelWeb because */
+/* lists are not typesafe and are used throughout the program. */
+p_ls_t p_ls;
+{
+ as_cold(p_ls!=NULL,"ls_check: List pointer is NULL.");
+ as_cold(p_ls->magic_head==MAGIC_HEAD_VALUE,
+ "ls_check: Magic number at head of record is incorrect.");
+ as_cold(p_ls->magic_tail==MAGIC_TAIL_VALUE,
+ "ls_check: Magic number at tail of record is incorrect.");
+}
+
+/******************************************************************************/
+
+EXPORT p_ls_t ls_cre (data_bytes)
+size_t data_bytes;
+{
+ p_ls_t p_ls;
+
+ p_ls=(p_ls_t) mm_temp(sizeof(ls_t));
+ p_ls->magic_head = MAGIC_HEAD_VALUE;
+ p_ls->p_head = NULL;
+ p_ls->p_tail = NULL;
+ p_ls->p_mark = NULL;
+ p_ls->data_bytes = data_bytes;
+ p_ls->length = 0;
+ p_ls->magic_tail = MAGIC_TAIL_VALUE;
+ return p_ls;
+}
+
+/******************************************************************************/
+
+EXPORT void ls_add(p_ls,p_lsel)
+p_ls_t p_ls;
+p_void p_lsel;
+{
+ p_node_t p_node;
+
+ AS_HCODE(ls_check(p_ls);)
+
+ /* Create the list node and the data node hanging off it. Copy the data in. */
+ p_node =(p_node_t) mm_temp(sizeof(node_t));
+ p_node->p_data=(p_void) mm_temp(p_ls->data_bytes);
+ memcpy(p_node->p_data,p_lsel,p_ls->data_bytes);
+
+ /* Attach the new node to the tail of the list. */
+
+ p_node->p_prev=p_ls->p_tail; /* Pointers in the new node itself. */
+ p_node->p_next=NULL;
+
+ if (p_ls->p_head == NULL) /* Headside pointer pointing to new node. */
+ p_ls->p_head=p_node;
+ else
+ p_ls->p_tail->p_next=p_node;
+
+ p_ls->p_tail=p_node; /* Tailside pointer pointing to new node. */
+
+ /* Inc the length. */
+ p_ls->length++;
+}
+
+/******************************************************************************/
+
+EXPORT void ls_lop(p_ls)
+p_ls_t p_ls;
+{
+ /* p_node_t p_targ; ONLY NEEDED IF DEALLOCATING */
+
+ AS_HCODE(ls_check(p_ls);)
+
+ as_cold(p_ls->length>0,"ls_lop: List is empty.");
+
+ /* Make a note of the node being deleted. */
+ /* p_targ=p_ls->p_tail; ONLY NEEDED IF DEALLOCATED. */
+
+ /* If the target node was the only node, stitch up the ends of the list. */
+ if (--p_ls->length==0)
+ {
+ p_ls->p_head=NULL;
+ p_ls->p_tail=NULL;
+ }
+ else
+ { /* Unhook node from tail of list. */
+ p_ls->p_tail = p_ls->p_tail->p_prev;
+ p_ls->p_tail->p_next = NULL;
+ }
+
+ /* The following two commented calls show what we WOULD have to do to */
+ /* deallocate the list node. However, in FunnelWeb, all list items are */
+ /* allocated under the mm package watermark system using mm_temp calls so */
+ /* there is no need to free up the memory here. */
+ /* DEALLOCATE(PV p_targ->p_data); */
+ /* DEALLOCATE(PV p_targ); */
+}
+
+/******************************************************************************/
+
+EXPORT ulong ls_len(p_ls)
+p_ls_t p_ls;
+{
+ AS_HCODE(ls_check(p_ls);)
+ return p_ls->length;
+}
+
+/******************************************************************************/
+
+EXPORT void ls_fir(p_ls)
+p_ls_t p_ls;
+{
+ ls_check(p_ls);
+ p_ls->p_mark=p_ls->p_head;
+}
+
+/******************************************************************************/
+
+EXPORT void ls_nxt(p_ls,pp_lsel)
+p_ls_t p_ls;
+pp_lsel_t pp_lsel;
+{
+ AS_HCODE(ls_check(p_ls);)
+
+ if (p_ls->p_mark==NULL)
+ {*pp_lsel=NULL; return;}
+ *pp_lsel=p_ls->p_mark->p_data;
+ p_ls->p_mark=p_ls->p_mark->p_next;
+}
+
+/******************************************************************************/
+
+EXPORT void ls_loo(p_ls,index,pp_lsel)
+p_ls_t p_ls;
+ulong index;
+pp_lsel_t pp_lsel;
+{
+ p_node_t p;
+ ulong i;
+
+ AS_HCODE(ls_check(p_ls);)
+
+ p=p_ls->p_head;
+ as_cold(p!=NULL,"is_loo: List is empty.");
+ for(i=1;i<index;i++)
+ {
+ p=p->p_next;
+ as_cold(p!=NULL,"is_loo: Index is too high for this list.");
+ }
+ *pp_lsel=p->p_data;
+}
+
+/******************************************************************************/
+
+EXPORT void ls_tai(p_ls,pp_lsel)
+p_ls_t p_ls;
+pp_lsel_t pp_lsel;
+{
+ AS_HCODE(ls_check(p_ls);)
+
+ as_cold(p_ls->p_tail!=NULL,"ls_tai: List is empty.");
+ *pp_lsel=p_ls->p_tail->p_data;
+}
+
+/******************************************************************************/
+
+EXPORT void ls_emp(p_ls)
+p_ls_t p_ls;
+{
+ AS_HCODE(ls_check(p_ls);)
+
+ /* The following loop WOULD be required if we had to deallocate the list */
+ /* elements explicitly. However, as all list elements are allocated using */
+ /* mm_temp, it is possible to claim them later as a block. So here, we just */
+ /* let the list items drift off into the sunset. */
+ /* p_node_t p_curr; */
+ /* p_curr=p_ls->p_head; */
+ /* while (p_curr != NULL) */
+ /* { */
+ /* p_node_t p_targ=p_curr; */
+ /* p_curr=p_curr->p_next; */
+ /* my_free(PV p_targ->p_data); */
+ /* my_free(PV p_targ); */
+ /* } */
+
+ p_ls->p_head=NULL;
+ p_ls->p_tail=NULL;
+ p_ls->p_mark=NULL;
+ p_ls->length=0;
+}
+
+/******************************************************************************/
+
+EXPORT void ls_des(p_ls)
+p_ls_t p_ls;
+{
+ ls_check(p_ls);
+
+ ls_emp(p_ls);
+ p_ls->magic_head=0; /* Zap the magic numbers in case memory is reused. */
+ p_ls->magic_tail=0;
+
+ /* The following call WOULD be required if it wasn't for the MM watermark */
+ /* system of memory allocation. */
+ /* my_free(PV p_ls); */
+}
+
+/******************************************************************************/
+
+EXPORT p_void ls_mar (p_ls)
+p_ls_t p_ls;
+{
+ AS_HCODE(ls_check(p_ls);)
+ return PV p_ls->p_mark;
+}
+
+/******************************************************************************/
+
+EXPORT void ls_set(p_ls,p_m)
+p_ls_t p_ls;
+p_void p_m;
+{
+ AS_HCODE(ls_check(p_ls);)
+ p_ls->p_mark=(p_node_t) p_m;
+}
+
+/******************************************************************************/
+/* End of LIST.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/list.h b/web/funnelAC/fwACsrc/list.h
new file mode 100644
index 0000000000..f7cadf90a7
--- /dev/null
+++ b/web/funnelAC/fwACsrc/list.h
@@ -0,0 +1,207 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* LIST.H */
+/******************************************************************************/
+/* */
+/* Introduction */
+/* ------------ */
+/* This list package (list.h and list.c) implements a list abstraction. */
+/* */
+/* Facts about Lists */
+/* ----------------- */
+/* - A LIST stores zero or more LIST ELEMENTS. */
+/* - The user decides the type of element to be stored in each list. */
+/* - Each list stores only one type of list element; lists are homogeneous. */
+/* - Lists store copies of elements rather than pointers to elements. */
+/* - Each list can hold from zero to about 2^31 elements. */
+/* - Each list has a HEAD end and a TAIL end. */
+/* - Elements can be appended and deleted only at the tail of the list. */
+/* - The elements of a list can be read sequentially from head to tail. */
+/* - A MARKER stores the current position in the list for sequential reading. */
+/* - Upon list creation, the marker is positioned at the tail of the list. */
+/* - In a list of n elements, elements are numbered from 1 to n. */
+/* - Element 1 is at the head of the list. Element n is at the tail. */
+/* - The identifier "ls" is used as an abbreviation for "list". */
+/* - The identifier "el" is used as an abbreviation for "element". */
+/* - Longer names are desirable, but shorter ones have been used so as to */
+/* enhance the portability of the package. */
+/* - IMPORTANT: Lists get all their memory using mm_temp calls. */
+/* */
+/* How To Use This List Package */
+/* ---------------------------- */
+/* 1. Include this .H file in your program file. */
+/* 2. Identify the type of elements to be placed in the list. */
+/* 3. Define a variable of type p_ls as a view to a list. */
+/* 4. Use the ls_* functions to perform the desired operations. */
+/* Start with a call to ls_cre and (optionally) end with a call to ls_des. */
+/* */
+/******************************************************************************/
+
+/* Ensure that the body of this header file is included at most once. */
+#ifndef DONE_LIST
+#define DONE_LIST
+
+/******************************************************************************/
+
+#include "style.h"
+
+/******************************************************************************/
+
+/* Users manipulate lists through pointers to lists (p_ls_t). The following */
+/* declaration serves the list user of the package while hiding the */
+/* implementation details (which appear in a similar declaration in list.c). */
+/* The #ifndef stops list.c from seeing these public declarations. */
+#ifndef INLISTC
+typedef struct {word NEVER_USE_THIS_FIELD_UQJTKC;} ls_yqwx; /* Don't use! */
+typedef ls_yqwx *p_ls_t;
+typedef p_void p_lsel_t;
+typedef p_lsel_t *pp_lsel_t;
+#endif
+
+/******************************************************************************/
+/* */
+/* General Notes About These Functions */
+/* ----------------------------------- */
+/* - All lists and elements are passed by pointer. Whether a parameter is */
+/* read or written is determined by it's function's description. */
+/* - Each function (except ls_cre) accepts a single pointer to a list and */
+/* each function's description is assumed to be referring to the list. */
+/* - "Raising an error" means calling the external function "error" to */
+/* write out a message and bomb the program. */
+/* - You must create a list using ls_cre before performing any operations */
+/* upon it. A list function will usually raise an error if it is */
+/* handed a pointer that does not point to a properly CREated list. */
+/* */
+/* WARNING: This package copies values into its internal data structures */
+/* (through ls_add), but returns only POINTERS to elements when asked to */
+/* retrieve them. These pointers are valid only so long as the element */
+/* that they point to remains in the list. If the element is deleted somehow, */
+/* the pointer points to garbage and becomes dangerous. */
+/* So, if you have been handed a pointer to an element in a list (ls_nxt, */
+/* ls_loo), do not subsequently delete the element (ls_lop, ls_emp, ls_des) */
+/* and then attempt to access the element through the pointer. */
+/* One sure way to avoid the problem is always to use the pointer handed back */
+/* by ls_nxt or ls_loo to copy the element immediately. */
+
+/* The Functions */
+/* ------------- */
+EXPORT p_ls_t ls_cre P_((size_t));
+/* CREate. Creates a new list and returns a pointer to the new list. The user */
+/* must specify in the parameter the size of elements that are to be stored */
+/* in the list. Specify the size of elements in bytes (usually using sizeof). */
+/* The sequential reading marker is set to position n+1=1=tail of the list. */
+
+EXPORT void ls_add P_((p_ls_t,p_lsel_t));
+/* ADD. Adds a new element onto the tail of the list (at position n+1). */
+/* The user must supply in the second parameter a pointer to the element to */
+/* be added. ls_add takes a copy of the element (it knows from the earlier */
+/* call to ls_cre how many bytes to copy) and stores the copy in its own */
+/* internal data structures. */
+
+EXPORT void ls_lop P_((p_ls_t));
+/* LOP. Removes (lops) element n from the tail of the list. */
+/* Raises an error if the list is empty. */
+
+EXPORT ulong ls_len P_((p_ls_t));
+/* LENgth. Returns the number of elements in the list (n). */
+
+EXPORT void ls_fir P_((p_ls_t));
+/* FIRst. Sets the sequential reading marker to element 1. */
+/* If the list is empty (n=0) the marker is placed at the tail of the list */
+/* and subsequent calls to ls_add will leave it there until the next call to */
+/* ls_fir. */
+
+EXPORT void ls_nxt P_((p_ls_t,pp_lsel_t));
+/* NeXT. Returns the list element under the marker and advances the marker */
+/* one position towards the tail of the list. */
+/* The method of returning the list element is a little messy. The user */
+/* supplies a pointer to a pointer in the second parameter, and the function */
+/* writes the address of the element in the list into the pointer. */
+/* If the marker is at position n+1 upon entry to ls_nxt, the marker position */
+/* doesn't change and NULL is written to the argument pointer. */
+
+EXPORT void ls_loo P_((p_ls_t,ulong,pp_lsel_t));
+/* LOOkup. Returns (using the same mechanism as ls_nxt) the k'th element of */
+/* the specified list where k is the second (ulong) parameter and the first */
+/* element (at the head of the list) is numbered number one (1). */
+/* Raises an error if the index k is out of the range [1,n]. */
+
+EXPORT void ls_tai P_((p_ls_t,pp_lsel_t));
+/* Lookup TAIl. Returns (using the same mechanism as ls_nxt) the tail element */
+/* of the specified list. */
+/* Raises an error if the list is empty. */
+
+EXPORT void ls_emp P_((p_ls_t));
+/* EMPty. Empties the specified list, deallocating all the space used by the */
+/* list elements. Upon completion, the list will be empty and the list marker */
+/* will be positioned at the tail of the list. */
+
+EXPORT void ls_des P_((p_ls_t));
+/* DEStroy. Destroys a list, destroying all its elements and deallocating all */
+/* the memory used by the list. */
+
+/* Marker Functions */
+/* ---------------- */
+/* The following two functions ls_mar and ls_set were hacked in to this list */
+/* package when it was discovered that the tangler sometimes needs to run */
+/* more than one context down a list at the same time. The two new functions */
+/* allow the list package user to save and restore the current mark. */
+/* These functions are not tightly controlled and so care must be taken in */
+/* their use. */
+
+EXPORT p_void ls_mar P_((p_ls_t));
+/* Returns a representation of the current list marker. */
+
+EXPORT void ls_set P_((p_ls_t,p_void));
+/* Sets the position of the marker to an earlier saved position. */
+/* Calls to this function should satisfy the following conditions: */
+/* 1. The marker argument (p_void) must be the result of an earlier call */
+/* to ls_mar with the same list as an argument. */
+/* 2. No part of the list should have been modified in the interim. In */
+/* particular, this means that no calls to ls_add, ls_lop, ls_emp or */
+/* ls_des can be made between linked calls to ls_mar and ls_set. */
+
+/******************************************************************************/
+
+/* For #ifndef preventing multiple inclusion of the body of this header file. */
+#endif
+
+/******************************************************************************/
+/* End of LIST.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/lister.c b/web/funnelAC/fwACsrc/lister.c
new file mode 100644
index 0000000000..659f199045
--- /dev/null
+++ b/web/funnelAC/fwACsrc/lister.c
@@ -0,0 +1,370 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 11-Jan-1994 ABC Increased MAXLINES to 100000.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* LISTER.C */
+/******************************************************************************/
+
+#include "style.h"
+
+#include "as.h"
+#include "data.h"
+#include "list.h"
+#include "lister.h"
+#include "machin.h"
+#include "misc.h"
+#include "table.h"
+#include "writfile.h"
+
+/******************************************************************************/
+
+#define LISTWIDTH 80 /* Nominal width of listing file. Can be wider. */
+#define INDENTQ 3 /* Indentation quantum for include files. */
+#define MESSMAXCH 200 /* Maximum number of characters in a message. */
+#define CTXINF 100 /* Special value that signals infinite context. */
+#define MAXLINES 100000 /* Maximum number of lines in input file. */
+
+/******************************************************************************/
+
+/* The following #defines and typedef define an enumerated type for message */
+/* kinds. There are four kinds of message, and we need a type for storing */
+/* this information. mess_k_t stands for message_kind_type. */
+/* We use #defines instead of enums as enums are not portable enough. */
+#define MESS_MES 1
+#define MESS_WAR 2
+#define MESS_ERR 3
+#define MESS_SEV 4
+typedef ubyte mess_k_t;
+
+/* We wish to store messages in a table with message positions as keys. */
+/* However, the table package will not tolerate duplicate keys. To solve this */
+/* problem, we create a new type 'unqpos_t' (unique position type) which has */
+/* not only a position but a serial number as well. */
+typedef struct
+ {
+ ps_t up_pos;
+ ulong up_serial;
+ } unqpos_t;
+
+/* The following structure stores a single message. As we are storing COPIES */
+/* of the messages, we impose a maximum limit (MESSMAXCH) to their length. */
+typedef struct
+ {
+ mess_k_t ms_kind;
+ char ms_text[MESSMAXCH+1];
+ } mess_t;
+
+/******************************************************************************/
+
+LOCVAR p_tb_t p_msgtab; /* The message table storing diagnostics. */
+LOCVAR ulong serial_next; /* Serial number for numbering messages. */
+
+/******************************************************************************/
+
+LOCAL int cmpuqpos P_((unqpos_t *,unqpos_t *));
+LOCAL int cmpuqpos(p1,p2)
+/* Compare two unique positions for the table package and returns [-1,0,1]. */
+unqpos_t *p1;
+unqpos_t *p2;
+{
+ long diff;
+ ubyte i;
+
+ for (i=1; i<=3; i++)
+ {
+ switch (i)
+ {
+ case 1: diff= p1->up_pos.ps_line - p2->up_pos.ps_line; break;
+ case 2: diff= p1->up_pos.ps_column - p2->up_pos.ps_column; break;
+ case 3: diff= p1->up_serial - p2->up_serial; break;
+ default: as_bomb("cmpuqpos: Case defaulted.");
+ }
+ if (diff<0)
+ return -1;
+ else
+ if (diff>0)
+ return 1;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+/* Converts a value of message kind type into a representative string. */
+/* This routine unused at present.
+LOCAL char *mess_let P_((mess_k_t));
+LOCAL char *mess_let (mess_k)
+mess_k_t mess_k;
+{
+ switch (mess_k)
+ {
+ case MESS_MES : return "M";
+ case MESS_WAR : return "W";
+ case MESS_ERR : return "E";
+ case MESS_SEV : return "S";
+ default: as_bomb("mess_let: Case defaulted.");
+ }
+ as_bomb("mess_let: Switch dropped out.");
+ return "Failure";
+}
+*/
+
+/******************************************************************************/
+
+#define DUPMAX 200
+
+LOCAL char *dup P_((int,uword));
+LOCAL char *dup(ch,count)
+/* Returns a pointer to a STAVAR string containing 'count' copies of 'ch'. */
+/* Count must be in the range [0,DUPMAX]. The pointer returned always points */
+/* to the same address which is a 'STAVAR' inside this function. */
+int ch;
+uword count;
+{
+ STAVAR char buffer[DUPMAX+1];
+
+ as_cold(count<DUPMAX,"lister.dup: count>=DUPMAX");
+ /* The IF in the following is just in case 'memset' is brain damaged. */
+ if (count>0) memset(&buffer[0],ch,(size_t) count);
+ buffer[count]=EOS;
+ return &buffer[0];
+}
+
+/******************************************************************************/
+
+LOCAL void mess_wri P_((p_wf_t,mess_t *,uword,uword));
+LOCAL void mess_wri(p_wf,p_mess,indent,column)
+/* Writes message p_mess to file p_wf indented by INDENTQ*indent+column. */
+p_wf_t p_wf;
+mess_t *p_mess;
+uword indent;
+uword column;
+{
+ switch (p_mess->ms_kind)
+ {
+ case MESS_MES : wf_wr(p_wf," "); break;
+ case MESS_WAR : wf_wr(p_wf," Warning"); break;
+ case MESS_ERR : wf_wr(p_wf," Error"); break;
+ case MESS_SEV : wf_wr(p_wf," Severe"); break;
+ default: as_bomb("mess_let: Case defaulted.");
+ }
+ wf_wr(p_wf,"|.");
+ wf_wr(p_wf,dup('.',indent*INDENTQ));
+ wf_wr(p_wf,dup('.',column-1));
+ wf_wr(p_wf,"^");
+ wf_wr(p_wf,&p_mess->ms_text[0]);
+ wf_wr(p_wf,"\n");
+}
+
+/******************************************************************************/
+
+LOCAL void line_wri P_((p_wf_t,ln_t *));
+LOCAL void line_wri(p_wf,p_line)
+/* Writes the given line to the given output stream. */
+p_wf_t p_wf;
+ln_t *p_line;
+{
+ char buffer[100];
+
+ /* The last line of the line list is the EOF marker line and to indicate */
+ /* that it is not really part of the input file, we omit it's line number. */
+ if (p_line->ln_global==ls_len(line_list))
+ /*" 12345 12345| "*/
+ sprintf(buffer," | ");
+ else
+ sprintf(buffer," %5lu %5lu| ",
+ (unsigned long) p_line->ln_global,
+ (unsigned long) p_line->ln_local);
+ wf_wr(p_wf,buffer);
+ wf_blk(p_wf,p_line->ln_body.sc_first,(size_t)
+ (p_line->ln_body.sc_last-p_line->ln_body.sc_first+1));
+}
+
+/******************************************************************************/
+
+LOCAL void add_mess P_((ps_t *,mess_k_t,char *));
+LOCAL void add_mess(p_pos,messkind,p_string)
+/* Creates a message record and places the message information in the */
+/* argument into the record. Inserts the record into the message table. */
+ps_t *p_pos;
+mess_k_t messkind;
+char *p_string;
+{
+ mess_t tempmess;
+ unqpos_t unqpos;
+
+ tempmess.ms_kind=messkind;
+ as_cold(strlen(p_string)<=MESSMAXCH,
+ "lister.add_mess: Parameter message is too long.");
+ strcpy(tempmess.ms_text,p_string);
+ ASSIGN(unqpos.up_pos,*p_pos);
+ unqpos.up_serial=serial_next++;
+ tb_ins(p_msgtab,PV &unqpos,PV &tempmess);
+}
+
+/******************************************************************************/
+
+EXPORT void lr_ini P_((void))
+{
+ /* Create a brand new empty message table. */
+ p_msgtab=tb_cre(sizeof(unqpos_t),sizeof(mess_t),(p_kycm_t) cmpuqpos);
+
+ /* Start the serial numbers at zero again. */
+ serial_next=0;
+}
+
+/******************************************************************************/
+
+EXPORT void lr_mes(p_pos,s)
+ps_t *p_pos;
+char *s;
+{
+ add_mess(p_pos,MESS_MES,s);
+}
+
+/******************************************************************************/
+
+EXPORT void lr_war(p_pos,s)
+ps_t *p_pos;
+char *s;
+{
+ add_mess(p_pos,MESS_WAR,s);
+ num_war++;
+}
+
+/******************************************************************************/
+
+EXPORT void lr_err(p_pos,s)
+ps_t *p_pos;
+char *s;
+{
+ add_mess(p_pos,MESS_ERR,s);
+ num_err++;
+}
+
+/******************************************************************************/
+
+EXPORT void lr_sev(p_pos,s)
+ps_t *p_pos;
+char *s;
+{
+ add_mess(p_pos,MESS_SEV,s);
+ num_sev++;
+}
+
+/******************************************************************************/
+
+EXPORT void lr_gen(p_wf,ctx)
+p_wf_t p_wf;
+uword ctx;
+{
+ unqpos_t next_pos; /* Position of next message. */
+ mess_t next_mes; /* Content of next message. */
+ long prev_no; /* Global line number of previous message. */
+ long next_no; /* Global line number of next message. */
+ bool ingap; /* Controls issuance of gap markers in the listing. */
+ long context=ctx; /* Signed version of the parameter. */
+
+ /* A context of CTXINF signals an infinite context. */
+ if (context==CTXINF) context=MAXLINES;
+
+ /* Write listing header. */
+ wf_wr(p_wf,"\nGlobal Local| Input File\n");
+ wf_wr(p_wf,dup('-',12));wf_wr(p_wf,"+");
+ wf_wr(p_wf,dup('-',LISTWIDTH-13));wf_wr(p_wf,"\n");
+
+ /* Reset the line list and message table for reading. */
+ ls_fir(line_list);
+ tb_fir(p_msgtab);
+
+ /* Prime the variables ingap, prev_no, next_no, next_pos, and next_mes. */
+ ingap=FALSE; prev_no = -(context+1);
+ if (tb_rea(p_msgtab,PV &next_pos,PV &next_mes))
+ next_no=next_pos.up_pos.ps_line;
+ else
+ next_no=MAXLINES+context+1;
+
+ while (TRUE)
+ {/* Process a single line per iteration. */
+ ln_t *p_line;
+
+ /* Grab the next line from the line list. */
+ ls_nxt(line_list,PPV &p_line);
+ if (p_line==NULL) break;
+
+ /* List the line if it is within context range of prev or next message. */
+ if ((((long) p_line->ln_global) <= prev_no+context) ||
+ (((long) p_line->ln_global) >= next_no-context))
+ {line_wri(p_wf,p_line);ingap=FALSE;}
+ else
+ if (!ingap)
+ {wf_wr(p_wf,".................\n");ingap=TRUE;}
+
+ /* Issue any messages that are about this line. */
+ while (next_no == p_line->ln_global)
+ {
+ /* Write the current message. */
+ mess_wri(p_wf,&next_mes,(uword) 0,
+ (uword) next_pos.up_pos.ps_column);
+
+ /* Read the next message from the table. */
+ prev_no=next_no;
+ if (tb_rea(p_msgtab,PV &next_pos,PV &next_mes))
+ next_no=next_pos.up_pos.ps_line;
+ else
+ next_no=MAXLINES+context+1;
+ }
+ } /* End while */
+
+ /* Make sure that we have read to the end of the message table. */
+ {bool result;
+ result=tb_rea(p_msgtab,PV &next_pos,PV &next_mes);
+ as_cold(!result,
+ "lr_gen: Messages remaining in message table after listing.");
+ }
+
+ /* Write listing trailer. */
+ wf_wr(p_wf,dup('-',12));wf_wr(p_wf,"+");
+ wf_wr(p_wf,dup('-',LISTWIDTH-13));wf_wr(p_wf,"\n");
+ wf_wl(p_wf,"");
+}
+
+/******************************************************************************/
+/* End of LISTER.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/lister.h b/web/funnelAC/fwACsrc/lister.h
new file mode 100644
index 0000000000..829acce655
--- /dev/null
+++ b/web/funnelAC/fwACsrc/lister.h
@@ -0,0 +1,75 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* LISTER.H */
+/******************************************************************************/
+
+#include "style.h"
+
+#include "data.h"
+
+/******************************************************************************/
+
+EXPORT void lr_ini P_((void));
+/* Initialize the lister. Calling this function destroys all the lister */
+/* package's old internal data structures and sets them to a well-defined */
+/* initial state (empty) and prepares the lister for the incoming messages. */
+/* This function may be called at any time and many times. */
+
+EXPORT void lr_mes P_((ps_t *,char *));
+EXPORT void lr_war P_((ps_t *,char *));
+EXPORT void lr_err P_((ps_t *,char *));
+EXPORT void lr_sev P_((ps_t *,char *));
+/* The functions above allow the user to record four different kinds of */
+/* messages and to specify exactly where in the listing each message is to */
+/* appear. */
+
+EXPORT void lr_gen P_((p_wf_t,uword));
+/* Merges the global structure line_list with the message table stored by the */
+/* lister package and writes the resultant listing to the p_wf_t stream. */
+/* The second parameter is the number of lines of context around each */
+/* diagnostic. The lister does not write the entire input file out. It only */
+/* writes input lines near a diagnostic. The context argument specifies the */
+/* number of lines that should be written around each diagnostic. */
+/* Note: A context of 100 is special and means that no lines should be */
+/* omitted in between diagnostics. */
+
+/******************************************************************************/
+/* End of LISTER.H */
+/******************************************************************************/
+
diff --git a/web/funnelAC/fwACsrc/machin.c b/web/funnelAC/fwACsrc/machin.c
new file mode 100644
index 0000000000..1692ca6bf3
--- /dev/null
+++ b/web/funnelAC/fwACsrc/machin.c
@@ -0,0 +1,355 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+ JMS John Max Skaller maxtal@suphys.physics.su.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 16-Sep-1993 ABC Added machine type OSF64 for a 64-bit processor
+ running OSF/1 (particularly the DEC AXP).
+ 16-Sep-1993 ABC Changed all constants *_MAX to *_FWMAX to avoid
+ conflict with some standard UNIX constants.
+ 14-Dec-1993 ABC Added machine type OS2 for PCs running OS/2 2.1.
+ 15-Jun-1994 ABC Added machine type LINUX for PCs running
+ LINUX 1.1.8
+ 13-Aug-1995 JMS Added PC32 type for 32-bit DOS-extended code.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* MACHIN.C */
+/******************************************************************************/
+/* */
+/* WARNING: DO NOT ADD ANY PROGRAM DEPENDENT DEFINITIONS. */
+/* */
+/* This file contains machine-dependent, program-independent stuff that */
+/* implements the functionality promised in MACHIN.H. */
+/* */
+/* Note: As usual, the full definitions of functions in the .H file are not */
+/* repeated here. */
+/* */
+/******************************************************************************/
+
+#include <time.h>
+#include "style.h"
+
+#include "as.h"
+#include "machin.h"
+
+/* The Macintosh's doesn't have a command language, and so we have to prompt */
+/* for a command line. This requires a special package. */
+#if MAC
+#include <console.h>
+#endif
+
+/* Under VMS, we need RMS to get at stuff to do with filenames. */
+#if VMS
+#include RMS
+#endif
+
+/******************************************************************************/
+/* LOCAL FUNCTIONS */
+/******************************************************************************/
+
+LOCAL void mconcat P_((int,char **,char *));
+LOCAL void mconcat(argc,argv,result)
+/* Given argc and argv, as passed to main(), this function appends all the */
+/* arguments together (separated by spaces) into the string "result". */
+/* This function assists in reconstructing the command line. */
+/* This function is actually portable, so you shouldn't have to change it. */
+/* Note: "mconcat" stands for Multiple CONCATenation. */
+int argc;
+char **argv;
+char *result;
+{
+ uword i;
+ strcpy(&result[0],argv[0]);
+ for (i=1;i<argc;i++)
+ {
+ strcat(&result[0]," " );
+ strcat(&result[0],argv[i]);
+ }
+}
+
+/******************************************************************************/
+
+#if MAC | SUN | PC | PC32 | OSF64 | OS2 | LINUX
+LOCAL void fn_split P_((p_fn_t,p_fn_t,p_fn_t,p_fn_t));
+LOCAL void fn_split(p_fn,p_path,p_name,p_ext)
+/* Accepts a filename in p_fn and writes the path, name, and extension */
+/* components of the filename to the strings p_path, p_name, and p_ext. */
+p_fn_t p_fn;
+p_fn_t p_path;
+p_fn_t p_name;
+p_fn_t p_ext;
+{
+ char *p,*q;
+
+ /* Make sure that the input filename is a sensible length. */
+ as_cold(strlen(p_fn)<=FILENAME_FWMAX,"fn_split: Filename is too long.");
+
+ /* Extract the path from the input string by searching for the last */
+ /* occurrance of the special character used for directories. */
+
+ /* Find the last directory/filename separator. */
+ p=strrchr(p_fn,FN_DELIM);
+ if (p==NULL)
+ {strcpy(p_path,""); p=p_fn;}
+ else
+ {
+ memcpy(p_path,p_fn,(size_t) (p-p_fn+1));
+ p_path[(size_t) (p-p_fn+1)]=EOS;
+ p++;
+ }
+
+ /* Assert: p now points to the first character of the name field. */
+
+ /* Now locate the file extension. */
+ q=strrchr(p_fn,'.');
+ if (q==NULL)
+ {strcpy(p_ext,""); q = &p_fn[strlen(p_fn)];}
+ else
+ {strcpy(p_ext,q);}
+
+ /* Assert: q now points to the '.' preceding the extension field. */
+
+ /* Now anything between p and q must be the filename proper. */
+ for (;p<q;p++)
+ *p_name++ = *p;
+ *p_name=EOS;
+}
+#endif
+
+/******************************************************************************/
+
+#if MAC | SUN | PC | PC32 | OSF64 | OS2 | LINUX
+LOCAL void fn_join P_((p_fn_t,p_fn_t,p_fn_t,p_fn_t));
+LOCAL void fn_join(p_fn,p_path,p_name,p_ext)
+/* This function sets p_fn to the empty string and then successively appends */
+/* p_path, p_name, and p_ext. Before doing this, it checks to make sure that */
+/* there will be enough room and bombs the program if there isn't. */
+p_fn_t p_fn;
+p_fn_t p_path;
+p_fn_t p_name;
+p_fn_t p_ext;
+{
+ as_cold(strlen(p_path)+strlen(p_name)+strlen(p_ext) <= FILENAME_FWMAX,
+ "fn_join: Constructed filename is too long.");
+ strcpy(p_fn,p_path);
+ strcat(p_fn,p_name);
+ strcat(p_fn,p_ext);
+}
+#endif
+
+/******************************************************************************/
+/* EXPORTED FUNCTIONS */
+/******************************************************************************/
+
+#if MAC | SUN | PC | PC32 | OSF64 | OS2 | LINUX
+EXPORT void fn_ins(p_cur,p_add)
+p_fn_t p_cur;
+p_fn_t p_add;
+{
+ fn_t cur_path, add_path;
+ fn_t cur_name, add_name;
+ fn_t cur_extn, add_extn;
+
+ /* Split the argument file names into their component parts. */
+ fn_split(p_cur,cur_path,cur_name,cur_extn);
+ fn_split(p_add,add_path,add_name,add_extn);
+
+ /* Perform the inheriting on a field by field basis. */
+ if (strlen(add_path) > 0) strcpy(cur_path,add_path);
+ if (strlen(add_name) > 0) strcpy(cur_name,add_name);
+ if (strlen(add_extn) > 0) strcpy(cur_extn,add_extn);
+
+ /* Put the fields back together again to yield the final result. */
+ fn_join(p_cur,cur_path,cur_name,cur_extn);
+}
+#endif
+
+#if VMS
+EXPORT void fn_ins(p_cur,p_add)
+/* This VMS version of fn_ins was written with the assistance of: */
+/* Jeremy Begg (jeremy@vsm.com.au) of VSM Software Services. Thanks! */
+/* The VMS version is messy because VMS has highly structured filenames and */
+/* highly ingrained rituals for manipulating them. */
+p_fn_t p_cur;
+p_fn_t p_add;
+{
+ struct FAB cur_fab; /* FAB for SYS$PARSE */
+ struct NAM cur_nam; /* NAM for SYS$PARSE */
+ fn_t expanded; /* Result of SYS$PARSE */
+ long rms_status; /* Status of SYS$PARSE */
+
+ /*
+ printf("\nTRACE: Call of fn_ins(...).\n");
+ printf(" Current spec = \"%s\".\n",p_cur);
+ printf(" Add spec = \"%s\".\n",p_add);
+ */
+
+ /* Initialize the FAB and NAM block to something sensible. */
+ cur_fab = cc$rms_fab;
+ cur_nam = cc$rms_nam;
+
+ /* (fna,fns) is address and size of input file spec in FAB block. */
+ cur_fab.fab$l_fna = p_add;
+ cur_fab.fab$b_fns = strlen(p_add);
+
+ /* (dna,dns) is address and size of default file spec in FAB block. */
+ cur_fab.fab$l_dna = p_cur;
+ cur_fab.fab$b_dns = strlen(p_cur);
+
+ /* Connect the NAM block to the FAB block. */
+ cur_fab.fab$l_nam = &cur_nam;
+
+ /* Point the NAM block's target name fields to the target namechar array. */
+ cur_nam.nam$l_esa = &expanded;
+ cur_nam.nam$b_ess = FILENAME_FWMAX; /* Reserve last char for NULL terminator */
+
+ /* PWD => put the password from a DECnet Access Control String in the filespec
+ * SYNCHK => check syntax only, don't search for the file on disk
+ */
+ cur_nam.nam$b_nop = NAM$M_PWD + NAM$M_SYNCHK;
+
+ /* Perform the parse. */
+ rms_status = sys$parse(&cur_fab);
+ if (rms_status & 1)
+ {
+ expanded[cur_nam.nam$b_esl]=EOS; /* Terminate VMS string. */
+ strcpy(p_cur,expanded);
+ }
+ else
+ {
+ printf("Note: RMS parse failed. Could be a syntax error, could be a bug!\n");
+ }
+
+ /* TRACE printf(" Result spec = \"%s\".",p_cur); */
+}
+#endif
+
+/******************************************************************************/
+
+EXPORT void getcline(argc,argv,p_comline)
+/* Given, argc and argv, writes a command line string in p_comline. */
+/* See machin.h for a thorough definition of this function. */
+int argc;
+char **argv;
+char *p_comline;
+{
+ int argc2;
+ char **argv2;
+
+#if MAC
+ /* On the Macintosh there is no command language and therefore no command */
+ /* line. Therefore we cannot trust the argc and argv handed to us by main() */
+ /* and have to obtain a command line from other sources. */
+ /* The "ccommand" function comes from <console.h> of the THINK C libraries. */
+ argc2=ccommand(&argv2);
+#endif
+
+/* The other systems work like Unix. */
+#if SUN | VMS | PC | PC32 | OSF64 | OS2 | LINUX
+argc2=argc;
+argv2=argv;
+#endif
+
+ /* The command line is currently in pieces. Reassemble it. That's all! */
+ mconcat(argc2,argv2,p_comline);
+}
+
+/******************************************************************************/
+
+EXPORT float tim_real()
+{
+ STAVAR bool init=FALSE;
+ STAVAR time_t base;
+
+ /* The first time this routine is called, we establish a base real time */
+ /* from which real time differences are calculated. There are two reasons */
+ /* for doing this. The first is that difftime seems to be the only way to */
+ /* get ANSI C to hand over a calibrated arithmetic type holding the real */
+ /* time. The second is that we don't want to have to deal with large */
+ /* absolute times anyway. */
+ if (!init)
+ {
+ /* Returns -1 if the time is not available (ANSI 7.12.2.4). */
+ base=time(NULL);
+ init=TRUE;
+ }
+
+ /* Return the elapsed time since the base time. */
+
+/* Macintosh, VMS, and PC have difftime. */
+#if MAC | VMS | PC | PC32 | OSF64 | OS2
+ if (base == -1)
+ return 0.0;
+ else
+ return (float) difftime(time(NULL),base);
+#endif
+
+/* Sun does not have difftime; neither does LINUX */
+#if SUN | LINUX
+ return 0.0;
+#endif
+
+/* The timing functions are only used to generate performance statistics and */
+/* are not critical to FunnelWeb. There is not much harm in returning 0.0. */
+}
+
+/******************************************************************************/
+
+EXPORT float tim_cpu()
+{
+ clock_t t=clock();
+
+/* Make sure that we have a definition for CLOCKS_PER_SEC. */
+#ifndef CLOCKS_PER_SEC
+#ifdef CLK_TCK
+#define CLOCKS_PER_SEC CLK_TCK
+#else
+/* Assume one million ticks per second. */
+#define CLOCKS_PER_SEC (1000000L)
+#endif
+#endif
+
+ /* The clock() function returns -1 if the CPU time is not available. */
+ /* Otherwise it returns the number of "clocks" since power-up. */
+ if (t == -1)
+ return 0.0;
+ else
+ return ((float) t) / ((float) CLOCKS_PER_SEC);
+}
+
+/******************************************************************************/
+/* End of MACHIN.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/machin.h b/web/funnelAC/fwACsrc/machin.h
new file mode 100644
index 0000000000..d9e48aca62
--- /dev/null
+++ b/web/funnelAC/fwACsrc/machin.h
@@ -0,0 +1,342 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+ JMS John Max Skaller maxtal@suphys.physics.su.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 16-Sep-1993 ABC Added machine type OSF64 for a 64-bit processor
+ running OSF/1 (particularly the DEC AXP).
+ 16-Sep-1993 ABC Changed all constants *_MAX to *_FWMAX to avoid
+ conflict with some standard UNIX constants.
+ 14-Dec-1993 ABC Added machine type OS2 for PCs running OS/2 2.1.
+ 15-Jun-1994 ABC Added machine type LINUX for PCs running LINUX 1.1.8
+ 13-Aug-1995 JMS Added PC32 type for 32-bit DOS-extended code.
+ 19-Sep-1995 ABC Set UNIX_EOL to 1 for Unix systems (having
+ removed dependency on this from `mapper.c'.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* MACHIN.H */
+/******************************************************************************/
+/* */
+/* WARNING: DO NOT ADD ANY PROGRAM DEPENDENT DEFINITIONS. */
+/* */
+/* This module (machin.h and machin.c) contains definitions and objects */
+/* whose values depends directly on the compilation and execution */
+/* environment, but are otherwise independent from any particular computer */
+/* program. */
+/* */
+/* The only difference between the purpose of this module and the "environ" */
+/* module is that the "environ" module contains the "essentials" whereas this */
+/* module contains extra machine specific definitions and objects that will */
+/* not be required by most user modules. */
+/* */
+/******************************************************************************/
+
+/* Ensure that the body of this header file is included at most once. */
+#ifndef DONE_MACHIN
+#define DONE_MACHIN
+
+/******************************************************************************/
+
+#include <time.h>
+#include "style.h"
+
+/******************************************************************************/
+
+/* Machine Alignment Constraints */
+/* ----------------------------- */
+/* Some machines require that objects of particular lengths be aligned in */
+/* memory. For example, the 68000 will trap any attempt to access a word */
+/* (16 bits or an int in THINK C) at an odd address. It is important that C */
+/* programs that deal with memory at a low level be aware of such */
+/* constraints. As the constraints are always at a power of two, we defined */
+/* ALIGN_POWER to be the minimum power of two at which it is both safe and */
+/* efficient to operate. */
+
+/* The Macintosh requires words and longs to be aligned on word boundaries. */
+/* The PC is not fussy about alignment, but operates more efficiently at word */
+/* boundaries. */
+#if MAC | PC
+#define ALIGN_POWER (1L)
+#endif
+
+/* The Sun requires objects to be aligned on longword boundaries (=2^2). */
+/* The VMS VAX doesn't care about alignment, but operates more efficiently on */
+/* longword boundaries. */
+/* OS2, LINUX, and 32-bit DOS code should work better with 32 bit boundaries */
+/* as well [ABC]. */
+#if SUN | VMS | PC32 | OS2 | LINUX
+#define ALIGN_POWER (2L)
+#endif
+
+/* ABC { */
+/* 64 bit processors, such as the DEC AXP, require objects to be aligned on */
+/* 64bit boundaries (=2^4). */
+#if OSF64
+#define ALIGN_POWER (4L)
+#endif
+/* } ABC */
+
+/******************************************************************************/
+
+/* Filenames */
+/* --------- */
+/* The length and structure of filenames varies from machine to machine. The */
+/* differences addressed here are: */
+/* 1) The character used to separate directory specs from filenames. */
+/* 2) The maximum length of a filename. */
+
+/* FN_DELIM must contain the character that separates directory specs from */
+/* filenames. Notice that in the VMS case, it is "]", not "." */
+
+#if MAC
+#define FN_DELIM ':'
+#endif
+
+#if SUN | OSF64 | LINUX
+#define FN_DELIM '/'
+#endif
+
+#if VAX
+#define FN_DELIM ']'
+#endif
+
+#if PC | PC32 | OS2
+#define FN_DELIM '\\'
+#endif
+
+/* The rest of this section shouldn't have to be changed, unless you */
+/* encounter a funny with your system's definition of FILENAME_FWMAX. */
+
+/* FILENAME_FWMAX tells the maximum number of characters allowed in a filename */
+/* on the target machine. The symbol FILENAME_MAX is supposed to be defined */
+/* in stdio.h (ANSI S7.9.1) so we don't want to override that. However, if it */
+/* isn't, we need to define a safe default length. */
+/* ABC { */
+/* Note that with SysV Unix, `FILENAME_MAX' is the maximum length of the */
+/* filename alone (same as VAX definition mentioned below), without the */
+/* directory path prepended. The full filename including the directory, has */
+/* a maximum length `PATH_MAX'. */
+#ifdef PATH_MAX
+#define FILENAME_FWMAX PATH_MAX
+#else /* !PATH_MAX */
+#ifdef FILENAME_MAX
+#define FILENAME_FWMAX FILENAME_MAX
+#else /* !FILENAME_MAX */
+#define FILENAME_FWMAX 300
+#endif /* FILENAME_MAX */
+#endif /* PATH_MAX */
+/* } ABC */
+
+/* Some VAX compilers define FILENAME_MAX to be 39, which is the maximum */
+/* length of the NAME part of a VMS filename. This is not appropriate, so we */
+/* override it. */
+#if VMS
+#undef FILENAME_FWMAX
+#define FILENAME_FWMAX 255 /* Should really be NAM$C_MAXRSS */
+#endif
+
+/* ABC { */
+/* OS/2 has a 256 character file-name limit (I think). */
+#if OS2
+#undef FILENAME_FWMAX
+#define FILENAME_FWMAX 255
+#endif /* OS2 */
+/* } ABC */
+
+/* Now we can use the constant to define a filename type. */
+/* Note: For a while I defined "typedef fn_t *p_fn_t". However, this is a */
+/* pointer to an array rather than (char *) and it caused no end of problems. */
+typedef char fn_t[FILENAME_FWMAX+1];
+typedef char *p_fn_t;
+
+/******************************************************************************/
+
+/* Command Lines */
+/* ------------- */
+/* The maximum length of command line varies from machine to machine and we */
+/* define symbols to reflect this. The reason why we don't just set this to a */
+/* high value and forget about it is that FunnelWeb sometimes places */
+/* command line variables on the stack, and some machines (e.g. MAC under */
+/* THINK-C don't provide much stack space. So we have to minimize this */
+/* variable on those machines. */
+
+/* We choose a small maximum command line on the Macintosh so as to avoid */
+/* chewing up stack space when command lines have to be pushed. */
+#if MAC
+#define COMLINE_FWMAX 300
+#endif
+
+/* On the Sun, OSF/1, or LINUX machine, 1024 is a normal command line and */
+/* 2048 is safe. */
+#if SUN | OSF64 | LINUX
+#define COMLINE_FWMAX 2048
+#endif
+
+/* On the VMS, 1024 is usually adequate. */
+#if VMS
+#define COMLINE_FWMAX 1024
+#endif
+
+/* On a PC and for OS/2, we assume this is enough. */
+#if PC | PC32 | OS2
+#define COMLINE_FWMAX 300
+#endif
+
+/* Make sure that the value is not too low. */
+/* The value 300 is guaranteed by the command interpreter. */
+#if COMLINE_FWMAX < 300
+ #error COMLINE_FWMAX must be at least 300.
+#endif
+
+/* Now define a type for command lines. */
+/* Note: For a while I defined "typedef cl_t *p_cl_t". However, this is a */
+/* pointer to an array rather than (char *) and it caused no end of problems. */
+typedef char cl_t[COMLINE_FWMAX+1];
+typedef char *p_cl_t;
+
+/******************************************************************************/
+
+/* Line Termination */
+/* ---------------- */
+
+/* FunnelWeb has special-case code to make reading input files faster on */
+/* machines where the format of text files corresponds to the internal C */
+/* text stream model. The UNIX_EOL #define should be activated if and only */
+/* the host environment has text files consisting of a stream of bytes with */
+/* a single LF (ASCII,decimal-10,hex-0A) character being used to terminate */
+/* each line, and no special character to indicate end of file. */
+/* This is the same format as is used in the Unix operating system. */
+/* If you are in doubt about this, play it safe and define your environment */
+/* to be non-Unix, as non-Unix will work on ALL systems (including Unix). */
+
+#if MAC | VMS | PC | PC32 | OS2
+/* These systems do NOT use Unix EOLs. */
+#define UNIX_EOL 0
+#endif
+
+#if SUN | OSF64 | LINUX
+/* ABC { */
+#define UNIX_EOL 1
+/* } ABC */
+#endif
+
+/******************************************************************************/
+
+/* Missing Prototypes */
+/* ---------------- */
+/* Compilers that are fussy about prototypes sometimes complain about calls */
+/* to the standard libraries. These declarations solve this problem. */
+
+#if SUN
+int fclose P_((FILE *stream));
+int fputs P_((const char *s, FILE *stream));
+int fputc P_((int c, FILE *stream));
+int fflush P_((FILE *stream));
+int remove P_((const char *filename));
+int rename P_((const char *oldname, const char *newname));
+int toupper P_((int));
+int sscanf P_(());
+int fprintf P_(());
+int _filbuf P_(());
+void *memcpy P_((void *s1, void *s2, size_t n));
+void *memset P_((void *s, int c, size_t n));
+int memcmp P_((void *s1, void *s2, size_t n));
+size_t fread P_((void *ptr, size_t size, size_t nobj, FILE *stream));
+size_t fwrite P_((const void *ptr, size_t size, size_t nobj, FILE *stream));
+clock_t clock P_((void));
+time_t time P_((time_t *tp));
+int printf P_(());
+#endif /* SUN */
+
+/******************************************************************************/
+
+EXPORT void fn_ins P_((p_fn_t,char *));
+/* - The name stands for FileName INSert. */
+/* - The first argument must be a pointer to an object of type fn_t */
+/* (containing an ordinary C character string). */
+/* - The second argument must be a pointer to an ordinary C character string. */
+/* - Both arguments must contain a full, partial, or empty filename spec. */
+/* - We will refer to the arguments as f1 and f2. */
+/* - If there is a syntax error in either spec, fn_ins does nothing. */
+/* - Otherwise, it: */
+/* 1. Analyses the two filename specifications into filename field . */
+/* 2. Replaces each field in f1 by the corresponding field in f2, but */
+/* only if the corresponding field in f2 is non-empty. */
+/* 3. Optionally [concession to VMS] it may then replace blank fields */
+/* in the resulting file spec in f1 by fields from the current */
+/* global "default" directory spec. */
+/* The structure and fields of filenames will vary from machine to machine */
+/* and so this is not important. However, every implementation must structure */
+/* the filename so that it will at least RECOGNISE a file extension */
+/* (e.g. ".lis") field. */
+
+/******************************************************************************/
+
+EXPORT void getcline P_((int,char **,char *));
+/* Operating system environments vary a lot in the way in which their command */
+/* language interfaces are set up. The approach taken in FunnelWeb is to */
+/* define a "standard" Unix-like command line syntax and then insist that */
+/* other environments deliver such a command line as a single string. */
+/* This function getcline must extract such a standard command line from its */
+/* environment and copy it as a single string of not more than COMLINE_FWMAX */
+/* characters into its third argument. A description of the "standard" */
+/* command line can be found in the options package. */
+/* The first argument is given to getcline and is argc from main(). */
+/* The second argument is given to getcline and is argv from main(). */
+/* These two arguments are given in case getcline needs them to assemble the */
+/* command line (as opposed to calling e.g. VMS CLI routines). */
+/* The third argument is the string into which the result should be placed. */
+
+/******************************************************************************/
+
+EXPORT float tim_real P_((void));
+/* Returns the number of seconds between the present and an unspecified, but */
+/* statically fixed time in the past. */
+/* Returns 0.0 if this information is unavailable */
+
+EXPORT float tim_cpu P_((void));
+/* Returns the number of CPU seconds consumed between the present and an */
+/* unspecified, but statically fixed time in the past. */
+/* Returns 0.0 if this information is unavailable */
+
+/******************************************************************************/
+
+/* For #ifndef preventing multiple inclusion of the body of this header file. */
+#endif
+
+/******************************************************************************/
+/* End of MACHIN.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/main.c b/web/funnelAC/fwACsrc/main.c
new file mode 100644
index 0000000000..1707220994
--- /dev/null
+++ b/web/funnelAC/fwACsrc/main.c
@@ -0,0 +1,115 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 16-Sep-1993 ABC Changed all constants *_MAX to *_FWMAX to avoid
+ conflict with some standard UNIX constants.
+ 08-Aug-1995 ABC Changed include file name from "memory.h"
+ to "fwmem.h" to avoid a clash with the C++
+ standard header file "memory.h".
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* MAIN.C */
+/******************************************************************************/
+
+#include "style.h"
+
+#include "as.h"
+#include "command.h"
+#include "data.h"
+#include "machin.h"
+#include "fwmem.h"
+
+/******************************************************************************/
+
+/* The following variables should really be local to main. However, some */
+/* compilers have a problem with this and so it has been declared here. */
+LOCVAR char *p_comline;
+LOCVAR ulong sum_all;
+
+/******************************************************************************/
+
+LOCAL void minimain P_((int,char **));
+LOCAL void minimain(argc,argv)
+/* Some compilers generate buggy code for main() and so this minimain */
+/* function has been created to take the heat off main(). */
+int argc;
+char **argv;
+{
+ /* The principal concern of this main() function is to execute FunnelWeb and */
+ /* to ensure that the correct return status is returned to the OS. So it */
+ /* seems appropriate to zero all the global diagnostic counters here. */
+ sum_fat=sum_sev=sum_err=sum_war=0;
+
+ /* Some compilers place a low limit on the total amount of statics. So we */
+ /* have to allocate space for a command line. */
+ p_comline=(char *) mm_perm((size_t) COMLINE_FWMAX+1);
+
+ /* Obtaining the command line is highly machine specific and so it has been */
+ /* delegated to a function in the non-portable "machin". Just in case argc */
+ /* and argv are to be used, we hand them in too. The result of all this is a */
+ /* standard FunnelWeb command line string in the variable 'comline'. */
+ getcline(argc,argv,p_comline);
+
+ /* Execute the command line. */
+ command(p_comline);
+
+ /* Exit to the operating system with an appropriate status code. */
+ sum_all=sum_war+sum_err+sum_sev+sum_fat;
+ if (sum_all>0)
+ exit(EXIT_FAILURE);
+ else
+ exit(EXIT_SUCCESS);
+}
+
+/******************************************************************************/
+
+int main(argc,argv)
+int argc;
+char *argv[];
+{
+ /* We don't put anything into the function main() because some compilers */
+ /* generate incorrect code for main, especially with local variables. */
+ minimain(argc,argv);
+
+ /* Keep GCC warnings happy. */
+ as_bomb("Main program dropped through.");
+ return 0;
+}
+
+/******************************************************************************/
+/* End of MAIN.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/mapper.c b/web/funnelAC/fwACsrc/mapper.c
new file mode 100644
index 0000000000..fa4c7c67a8
--- /dev/null
+++ b/web/funnelAC/fwACsrc/mapper.c
@@ -0,0 +1,343 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 08-Aug-1995 ABC Changed include file name from "memory.h"
+ to "fwmem.h" to avoid a clash with the C++
+ standard header file "memory.h".
+ 16-Aug-1995 ABC Noted existence of new `PC32' type without
+ 64K block restriction.
+ 19-Sep-1995 ABC Removed UNIX_EOL #ifdef support and instead
+ modified `stan_map' to remove non-printable
+ whitespace (not space or tab) from the end of
+ lines. This should hopefully allow FunnelWeb
+ sources files to be moved between Unix and DOS
+ without complaints about the CR characters used
+ by DOS.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* MAPPER.C */
+/******************************************************************************/
+
+#include <limits.h>
+#include "style.h"
+
+#include "as.h"
+#include "machin.h"
+#include "mapper.h"
+#include "fwmem.h"
+
+/******************************************************************************/
+
+/* When we allocate a block of memory for a mapped file, we have to allocate */
+/* a little more than the official length of the file. Here are some reasons: */
+/* */
+/* - We may wish to append an EOF character later on in the program. */
+/* - fgets, when requested to fetch n characters, fetches n characters and */
+/* then puts an EOS on the end of them. */
+/* - It is conceivable that fgets will insert a "\n" at the end of the */
+/* block if it doesn't see a "\n" just before the end of file. */
+/* */
+/* For all these reasons, we allocate a little more memory than we need. How */
+/* much more is determined by BLK_FUDGE which is set to be on the safe side. */
+#define BLK_FUDGE (20)
+
+/* The following fudge is useful for avoiding the limits of types. */
+#define LIM_FUDGE (10)
+
+/* On PCs, size_t is 16 bits and malloc cannot allocate contiguous chunks of */
+/* memory of more than about 64K. This really stuffs up FunnelWeb's capacity */
+/* map in files of length greater than 64K. I didn't think of this problem */
+/* when I designed FunnelWeb because I was thinking of the VOLUME of memory */
+/* available nowadays, rather than its organization on small computers. */
+/* Anyway, this problem should really be fixed by allowing files to be read */
+/* in in segments. Perhaps the mapper should hand over a linked list of */
+/* chunks rather than a single chunk. Unfortunately, I don't have the time to */
+/* do this now, so users of the PC version of FunnelWeb will have to be */
+/* content with an (approx) 64K limit to input files. This isn't as bad as it */
+/* sounds, as large input files can be split using the include facility. */
+/* 63K is chosen instead of 64K so as to be paranoid. */
+/* ABC { */
+/* Note that this is unnecessary for the 32-bit `PC32' type. */
+/* } ABC */
+#define PCFILEMX (63L*1024L)
+
+/******************************************************************************/
+/* */
+/* Error Strings */
+/* ------------- */
+/* Routines in this package return pointers to error strings. These pointers */
+/* are subsequently bandied about by other packages. Therefore, they must be */
+/* pointers to constant strings. The trick of returning a pointer to a static */
+/* character array containing a specific sprintf message will backfire here */
+/* if there is an error opening more than one input file. Using mm_* to */
+/* create space for each error string would work though. */
+/* STOP PRESS: Now that the lister copies error messages, there may no longer */
+/* be a problem here. */
+/* */
+/******************************************************************************/
+
+/* Finding The Length of a File */
+/* ---------------------------- */
+/* We have to be able to find out the length of a file before reading it in */
+/* because, in this version of FunnelWeb, the entire file must be read into */
+/* one contiguous block of memory. */
+/* */
+/* As it turns out, finding the length of a file in portable C turns out to */
+/* be a very hard problem. Here are some possible solutions: */
+/* */
+/* 1. Read the entire file in and see how long it is. */
+/* 2. Use fseek to move to the end of the file and then use ftell. */
+/* 3. Use the Unix 'stat' call. */
+/* */
+/* Of these, only the first is portable. The second alternative is */
+/* non-portable because some environments do not support the SEEK_END symbol */
+/* required to perform a seek to the end of file. */
+/* Alternatives to needing the length are as follows: */
+/* */
+/* 4. Read the file/allocate memory in 64K blocks. */
+/* 5. Read the file in 64K blocks and then copy them to a contiguous one. */
+/* */
+/* Perhaps options 4 or 5 could be implemented later. However, right now I */
+/* haven't got the time to do anything except strive for portability, so */
+/* option 1 it is. */
+
+LOCAL char *file_len P_((char *,ulong *));
+LOCAL char *file_len (p_name,p_length)
+/* Given a filename (in 'p_name'), returns the length of the binary image of */
+/* the file in *p_length. Returns NULL upon success or a pointer to a string */
+/* describing an error upon failure. The length is measured in bytes. */
+char *p_name;
+ulong *p_length;
+{
+ FILE *infile;
+ STAVAR char *p_buf = NULL;
+
+/* The length of the buffer handed to fgets is non-critical. However, it */
+/* mustn't be bigger than 15 bits, as we are passing it as an int to fgets. */
+#define LENBUFLEN (1024L)
+#if LENBUFLEN > 30000L
+ #error "mapper.c: LENBUFLEN must be less than 15 bits."
+#endif
+
+ /* Allocate the buffer if it has not already been allocated. */
+ if (p_buf == NULL)
+ p_buf=mm_perm((size_t) LENBUFLEN);
+
+ /* Open for TEXT reading. Earlier, I tried this using a binary read, but */
+ /* I had problems with this on the VAX (I forget what the problems were) and */
+ /* so I have switched back to a text read which is slower, but more reliable.*/
+ infile=fopen(p_name,"r");
+ if (infile == FOPEN_F)
+ return "Error fopen()ing input file (to determine its length).";
+
+ /* Start with a zero length. */
+ *p_length=0;
+
+ /* Read the file as text and count the number of bytes it contains. */
+ while (!feof(infile))
+ {
+ /* Set the buffer to the empty string so it is valid even if fgets fails. */
+ p_buf[0]=EOS;
+
+ /* Read in a whole lot of bytes. */
+ fgets(p_buf,LENBUFLEN,infile);
+
+ /* If there is an error, abort. */
+ if (ferror(infile))
+ {
+ fclose(infile);
+ return "Error fgets()ing input file (as part of determining its length).";
+ }
+
+ /* Count the bytes that we have got. If EOF occurred above AND no bytes */
+ /* were read, the EOS we planted earlier saves us. */
+ (*p_length)+=strlen(p_buf);
+ }
+
+ if (fclose(infile) == FCLOSE_F)
+ return "Error fclose()ing input file (as part of determining its length).";
+
+ return NULL;
+}
+
+/******************************************************************************/
+
+LOCAL char *stan_map P_((char *,char **,ulong *));
+LOCAL char *stan_map(p_name,pp_mem,p_length)
+/* Maps in a file using refined text stream IO calls. */
+char *p_name;
+char **pp_mem;
+ulong *p_length;
+{
+ ulong file_length; /* Number of bytes in the target input file. */
+ char *p_err; /* Temporary to store pointer to error message. */
+ FILE *infile; /* The file variable for the input file we are reading. */
+ ulong num_bytes; /* Number of bytes actually read in (may be different). */
+ char *p_bytes; /* Pointer to the memory block where all the action is. */
+ char *p_curr; /* Pointer to current position in memory block. */
+ long bytes_left; /* Number of bytes still left to read. */
+
+ /* Obtain the length of the file we are about to map in. */
+ p_err=file_len(p_name,&file_length);
+ if (p_err != NULL)
+ return p_err;
+
+ /* Complain on the PC if the file is too big to fit in one 64K segment. */
+#if PC
+ if (file_length+BLK_FUDGE > PCFILEMX)
+ return
+ "Error: Input file too big for PC FunnelWeb. Split using include files.";
+#endif
+
+ /* TRACE printf("MAPPER: LENGTH OF INPUT FILE=%lu\n",file_length); */
+
+ /* Allocate memory to hold the mapped file. */
+ /* Note: The memory allocation package bombs if there is no more memory. */
+ /* Note: As Unix stream format (the format to which we are converting) uses */
+ /* just one byte to mark the end of file, it seems highly unlikely */
+ /* that the file read in will be longer than the binary image. */
+ p_bytes=(char *) mm_temp((size_t) file_length+BLK_FUDGE);
+
+ /* If the file is of zero length, we already know its contents! */
+ /* This is probably not strictly necessary, but why pressure the code below? */
+ if (file_length==0)
+ {
+ *pp_mem = p_bytes;
+ *p_length = 0;
+ return NULL;
+ }
+
+ /* Open the file afresh in TEXT mode for portable reading. */
+ infile=fopen(p_name,"r");
+ if (infile==FOPEN_F)
+ return "Error fopen()ing input file (for reading).";
+
+ /* Read in as much of the file as we can without actually overflowing the */
+ /* buffer. If the file finished before the buffer, things have probably gone */
+ /* OK. If the buffer finishes before the file, we have a problem. */
+ /* Note: bytes_left = file_length+1 because in the following loop, we might */
+ /* read exactly up to the EOF and then be unable to actually trigger the EOF */
+ /* condition without another read. So we add one on to allow this extra read */
+ /* to take place. I don't know if this is necessary, but I certainly can't */
+ /* find anything in all my C books that will tell me. Anyway, it doesn't */
+ /* matter because we fudged in a few extra bytes earlier. */
+
+ p_curr = p_bytes; /* p_curr runs through the memory. */
+ bytes_left = file_length+1; /* Bytes left in memory allocated to hold file. */
+
+ /* ABC { */
+ num_bytes = 0;
+ /* } ABC */
+ while (!feof(infile))
+ {
+ int bytes_try;
+ int bytes_read;
+
+ /* Try to read as much as we possibly can, but not more than the integer */
+ /* limit (which can be as low as 15 bits). */
+ bytes_try = bytes_left >= ((ulong) (INT_MAX-LIM_FUDGE)) ?
+ (int) INT_MAX-LIM_FUDGE : (int) bytes_left;
+
+ /* Plan an EOS to cover the EOF case. */
+ *p_curr=EOS;
+
+ /* Attempt to read bytes_try bytes. +1 is because fgets reads n-1 bytes. */
+ fgets(p_curr,bytes_try+1,infile);
+ if (ferror(infile))
+ {
+ fclose(infile);
+ return "Error fgets()ing the input file.";
+ }
+
+ /* fgets doesn't return a length so we have to hobble behind with strlen. */
+ /* It's still probably better than using lots of fgetc calls. */
+ /* If we hit EOF and no bytes were read, the EOS we planted saves us. */
+ bytes_read = strlen(p_curr);
+ p_curr += bytes_read;
+ bytes_left -= bytes_read;
+
+ /* ABC { */
+ /* Remove non-printing whitespace from the end of the bytes which have */
+ /* been read. */
+ if ((bytes_read > 0) && !isascprn(p_curr[-1])) {
+ while ((bytes_read > 0) && !isascprn(p_curr[-1])) {
+ *(--p_curr) = EOS;
+ bytes_read--;
+ } /* end while */
+ /* } ABC */
+ *(p_curr++) = EOL;
+ num_bytes += bytes_read+1; /* +1 for EOL */
+ *p_curr = EOS;
+ } /* end if */
+ /* } ABC */
+
+ /* If we have run out of bytes in our allocated memory zone, then the */
+ /* file is longer than the length reported earlier. This is a bad thing. */
+ as_cold(bytes_left >=0,
+ "stan_map: Text representation was longer than binary rep.");
+ }
+
+ /* ABC {
+ num_bytes=(file_length+1)-bytes_left;
+ } ABC */ /* See earlier to undserstand +1. */
+
+ /* Note: We can't get fussy here and check the read in length with the */
+ /* official length, as the read-in length is the text representation which */
+ /* is allowed to be shorter than the physical (binary) length of the file. */
+
+ if (fclose(infile) == FCLOSE_F)
+ return "Error fclose()ing input file.";
+
+ /* Success. We got through the IO calls. Now fill in the blanks and go home. */
+ *pp_mem = p_bytes;
+ *p_length = num_bytes;
+ return NULL;
+}
+
+/******************************************************************************/
+
+EXPORT char *map_file(p_name,pp_mem,p_length)
+char *p_name;
+char **pp_mem;
+ulong *p_length;
+{
+ return stan_map(p_name,pp_mem,p_length);
+}
+
+/******************************************************************************/
+/* End of MAPPER.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/mapper.h b/web/funnelAC/fwACsrc/mapper.h
new file mode 100644
index 0000000000..6210206df6
--- /dev/null
+++ b/web/funnelAC/fwACsrc/mapper.h
@@ -0,0 +1,69 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* MAPPER.H */
+/******************************************************************************/
+/* */
+/* The mapper is the first of FunnelWeb's four front end processors: (mapper, */
+/* scanner, parser, analyser). The sole task of the mapper is, given the */
+/* name of a file, to create an image of that file in memory. This approach */
+/* is not wasteful of memory at all because FunnelWeb requires random access */
+/* to each input file at all times anyway so it can scramble the text around. */
+/* */
+/******************************************************************************/
+
+#include "style.h"
+
+/******************************************************************************/
+
+EXPORT char *map_file P_((char *,char **,ulong *));
+/* Allocates a block of memory and places a Unix text stream representation */
+/* (with EOL marking end of line and no character marking end of file) of the */
+/* file 'p_name' in the block of memory. Returns a pointer to the address and */
+/* len of the file in the mem block in the parameters (pp_mem and p_length). */
+/* Returns NULL upon success or a pointer to an error message string upon */
+/* failure. Note: Parameters are: p_name, pp_mem, p_length. */
+/* Note: Allocates enough memory so that there is guaranteed to be at least */
+/* two extra bytes of spare memory at the end of the mapped file. The */
+/* scanner uses this space to put EOL and EOF characters. */
+/* Note: The mapper grabs its memory using mm_temp, so it can be recycled */
+/* as part of a call to mm_zapt. */
+
+/******************************************************************************/
+/* End of MAPPER.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/misc.c b/web/funnelAC/fwACsrc/misc.c
new file mode 100644
index 0000000000..ab1a2db9d0
--- /dev/null
+++ b/web/funnelAC/fwACsrc/misc.c
@@ -0,0 +1,235 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 08-Aug-1995 ABC Changed include file name from "memory.h"
+ to "fwmem.h" to avoid a clash with the C++
+ standard header file "memory.h".
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* MISC.C */
+/******************************************************************************/
+
+#include <ctype.h>
+#include "style.h"
+
+#include "as.h"
+#include "data.h"
+#include "fwmem.h"
+#include "misc.h"
+#include "writfile.h"
+
+/******************************************************************************/
+
+EXPORT void wr_s (s) char *s; {wf_wr(&f_s,s);}
+EXPORT void wr_j (s) char *s; {wf_wr(&f_j,s);}
+EXPORT void wr_l (s) char *s; {wf_wr(&f_l,s);}
+
+EXPORT void wl_s (s) char *s; {wf_wr(&f_s,s); wf_wr(&f_s,"\n");}
+EXPORT void wl_j (s) char *s; {wf_wr(&f_j,s); wf_wr(&f_j,"\n");}
+EXPORT void wl_l (s) char *s; {wf_wr(&f_l,s); wf_wr(&f_l,"\n");}
+
+EXPORT void wr_sj (s) char *s; {wr_s(s); wr_j(s);}
+EXPORT void wl_sj (s) char *s; {wl_s(s); wl_j(s);}
+
+EXPORT void wr_sjl(s) char *s; {wr_s(s); wr_j(s); wr_l(s);}
+EXPORT void wl_sjl(s) char *s; {wl_s(s); wl_j(s); wl_l(s);}
+
+/******************************************************************************/
+
+EXPORT char *chabbrev(ch)
+int ch;
+{
+ switch (ch)
+ {
+ case 0: return "NUL";
+ case 1: return "SOH";
+ case 2: return "STX";
+ case 3: return "ETX";
+ case 4: return "EOT";
+ case 5: return "ENQ";
+ case 6: return "ACK";
+ case 7: return "BEL";
+ case 8: return "BS";
+ case 9: return "HT";
+ case 10: return "LF";
+ case 11: return "VT";
+ case 12: return "FF";
+ case 13: return "CR";
+ case 14: return "SO";
+ case 15: return "SI";
+ case 16: return "DLE";
+ case 17: return "DC1";
+ case 18: return "DC2";
+ case 19: return "DC3";
+ case 20: return "DC4";
+ case 21: return "NAK";
+ case 22: return "SYN";
+ case 23: return "ETB";
+ case 24: return "CAN";
+ case 25: return "EM";
+ case 26: return "SUB";
+ case 27: return "ESC";
+ case 28: return "FS";
+ case 29: return "GS";
+ case 30: return "RS";
+ case 31: return "US";
+ case 127:return "DEL";
+ default: return "";
+ }
+}
+
+/******************************************************************************/
+
+EXPORT sign signof(n)
+long n;
+{
+ if (n<0) return -1;
+ if (n>0) return 1;
+ return 0;
+}
+
+/******************************************************************************/
+
+EXPORT char * eq_files(name1,name2,p_result)
+char *name1;
+char *name2;
+bool *p_result;
+{
+ FILE *file1;
+ FILE *file2;
+
+ /* The following three lines define two comparison buffers. The next part of */
+ /* the two files being compared are read into these buffers and compared. */
+ /* Using the buffers allows bulk reads, which speeds things up considerably. */
+#define CMPBUFSIZ 16384
+ STAVAR ubyte_ *buf1 = NULL;
+ STAVAR ubyte_ *buf2 = NULL;
+
+ /* Set the default result to be FALSE (no match). */
+ *p_result=FALSE;
+
+ /* Allocate the comparison buffers if they are not already allocated. */
+ if (buf1 == NULL)
+ {
+ buf1=(ubyte_ *) mm_perm((size_t) CMPBUFSIZ);
+ buf2=(ubyte_ *) mm_perm((size_t) CMPBUFSIZ);
+ }
+
+ /* Open, for binary reading, the two files to be compared. */
+ file1=fopen(name1,"rb");
+ if (file1 == FOPEN_F)
+ return "Error opening the first file.";
+ file2=fopen(name2,"rb");
+ if (file2 == FOPEN_F)
+ {fclose(file1);return "Error opening the second file.";}
+
+ while (TRUE)
+ { /* Compare a chunk. */
+ size_t len1;
+ size_t len2;
+
+ /* Read a chunk from each file. */
+ len1=fread(buf1,(size_t) 1,(size_t) CMPBUFSIZ,file1);
+ len2=fread(buf2,(size_t) 1,(size_t) CMPBUFSIZ,file2);
+ if (ferror(file1))
+ return "Compare: Error reading the first file.";
+ if (ferror(file2))
+ return "Compare: Error reading the second file.";
+
+ /* Compare the two chunks. */
+ if (len1 != len2) break;
+ if (len1 == 0) {*p_result=TRUE; break;}
+ if (memcmp(buf1,buf2,(size_t) len1) != 0) break;
+ }
+
+ if (fclose(file1) == FCLOSE_F)
+ {*p_result=FALSE; return "Error closing the first file.";}
+ if (fclose(file2) == FCLOSE_F)
+ {*p_result=FALSE; return "Error closing the second file.";}
+
+ /* If we have reached this point, we can be sure that no errors occurred. */
+ return NULL;
+}
+
+/******************************************************************************/
+
+EXPORT bool fexists(fn)
+char *fn;
+{
+ FILE *file;
+ bool success;
+
+ file=fopen(fn,"rb");
+ if (file==NULL)
+ return FALSE;
+
+ success= (fclose(file) != FCLOSE_F);
+ as_cold(success,
+ "fexists: Error closing file whose existence is being tested!");
+
+ return TRUE;
+}
+
+/******************************************************************************/
+
+EXPORT char *fn_temp()
+{
+ STAVAR uword filnum=1;
+ STAVAR fn_t fn;
+ do
+ {
+ sprintf(fn,"fwtf%04lu.tmp",(ulong) filnum);
+ filnum++;
+ }
+ while (fexists(fn));
+ return fn;
+}
+
+/******************************************************************************/
+
+EXPORT void strupper(s)
+char *s;
+{
+ while (*s != EOS)
+ {
+ *s=toupper(*s);
+ s++;
+ }
+}
+
+/******************************************************************************/
+/* End of MISC.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/misc.h b/web/funnelAC/fwACsrc/misc.h
new file mode 100644
index 0000000000..aa98dbb2f0
--- /dev/null
+++ b/web/funnelAC/fwACsrc/misc.h
@@ -0,0 +1,126 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* MISC.H */
+/******************************************************************************/
+/* */
+/* This package contains a ragbag of FunnelWeb-specific functions that didn't */
+/* seem to have a home anywhere else. */
+/* */
+/******************************************************************************/
+
+#include "style.h"
+
+#include "data.h"
+
+/******************************************************************************/
+
+/* The following functions each write a string to one or more output streams. */
+/* The code is as follows: */
+/* wr - means write the string only. */
+/* wl - means write the string followed by a '\n'. */
+/* s - The f_s output stream (the console/screen). */
+/* j - The f_j output stream (the journal file). */
+/* l - The f_l output stream (the listing file). */
+/* These functions are hard wired to the f_s, f_j, and f_l global variables. */
+
+EXPORT void wr_s P_((char *));
+EXPORT void wr_j P_((char *));
+EXPORT void wr_l P_((char *));
+
+EXPORT void wl_s P_((char *));
+EXPORT void wl_j P_((char *));
+EXPORT void wl_l P_((char *));
+
+EXPORT void wr_sj P_((char *));
+EXPORT void wl_sj P_((char *));
+
+EXPORT void wr_sjl P_((char *));
+EXPORT void wl_sjl P_((char *));
+
+/******************************************************************************/
+
+EXPORT char *chabbrev P_((int));
+/* If the argument is non-printable in the range [0,127], returns a pointer */
+/* to a constant string containing the mnemonic abbreviation for the */
+/* character (e.g. 10="LF"). Otherwise returns the empty string. */
+
+/******************************************************************************/
+
+EXPORT sign signof P_((long));
+/* Returns -1 if its argument is negative. */
+/* Returns 0 if its argument is zero. */
+/* Returns 1 if its argument is positive. */
+
+/******************************************************************************/
+
+EXPORT char * eq_files P_((char *,char *,bool *));
+/* Performs an exact binary comparison of the files named name1 and name2. */
+/* If there is no error during the comparison, returns NULL and the boolean */
+/* parameter carries the result of the comparison with TRUE=>Files identical. */
+/* If there is an error during the comparison, the boolean parameter is set */
+/* to FALSE and the function returns a pointer to a string describing the */
+/* error in terms of "the first file" and "the second file". */
+
+/******************************************************************************/
+
+EXPORT bool fexists P_((char *));
+/* Returns TRUE iff a file of the name given in the parameter exists. */
+/* (Does this by attempting to open the file. If it succeeds, it closes it */
+/* again). */
+
+/******************************************************************************/
+
+EXPORT char *fn_temp P_((void));
+/* Creates a filename (not containing a directory component) for which there */
+/* is no corresponding file in the current directory. */
+/* Returns a pointer to a static array containing the filename. */
+/* Each time this function is called, the new filename overwrites the old. */
+/* This function was created after it was discovered that, on some systems, */
+/* the standard library function "tmpnam" returns the name of a file in the */
+/* /tmp partition. This would not be a problem were it not for the fact that */
+/* generally, files cannot be renamed across partitions! */
+
+/******************************************************************************/
+
+EXPORT void strupper P_((char *));
+/* Converts all lower case letters in the argument string to upper case. */
+
+/******************************************************************************/
+/* End of MISC.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/option.c b/web/funnelAC/fwACsrc/option.c
new file mode 100644
index 0000000000..3211ae18a7
--- /dev/null
+++ b/web/funnelAC/fwACsrc/option.c
@@ -0,0 +1,454 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 16-Sep-1993 ABC Changed all constants *_MAX to *_FWMAX to avoid
+ conflict with some standard UNIX constants.
+ 16-Aug-1995 ABC Added `+Qb' command line option to suppress all
+ requests for user input in case of errors, so
+ that FunnelWeb can run in a genuine batch mode.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* OPTION.C */
+/******************************************************************************/
+
+#include <ctype.h>
+#include "style.h"
+
+#include "as.h"
+#include "data.h"
+#include "machin.h"
+#include "misc.h"
+#include "option.h"
+
+/******************************************************************************/
+
+LOCAL void wl_caret P_((ulong,void (*)(char *)));
+LOCAL void wl_caret(n,p_outf)
+/* Writes a caret at position n of an otherwise blank line. */
+ulong n;
+void (*p_outf) P_((char *));
+{
+ as_cold(n<1000,"wl_caret: Argument is out of range.");
+ while (--n > 0)
+ (*p_outf)(" ");
+ (*p_outf)("^\n");
+}
+
+/******************************************************************************/
+
+EXPORT void op_ini(p_op)
+p_op_t p_op;
+{
+ p_op->op_f_b=FALSE;
+ strcpy(&p_op->op_f_s[0],"");
+
+ p_op->op_j_b=FALSE;
+ strcpy(&p_op->op_j_s[0],"");
+
+ strcpy(&p_op->op_i_s[0],"");
+
+ p_op->op_o_b=TRUE;
+ strcpy(&p_op->op_o_s[0],"");
+
+ p_op->op_t_b=FALSE;
+ strcpy(&p_op->op_t_s[0],"");
+
+ p_op->op_l_b=TRUE;
+ strcpy(&p_op->op_l_s[0],"");
+
+ p_op->op_d_b=FALSE;
+
+ p_op->op_c_i=2;
+
+ p_op->op_q_b=FALSE;
+ strcpy(&p_op->op_q_s[0],"");
+
+ p_op->op_s_b=FALSE;
+ p_op->op_s_i=1;
+
+ p_op->op_w_b=FALSE;
+ p_op->op_w_i=80;
+
+ p_op->op_x_b=FALSE;
+ strcpy(&p_op->op_x_s[0],"");
+
+ p_op->op_k_b=FALSE;
+
+ p_op->op_b1_b=FALSE;
+ p_op->op_b2_b=FALSE;
+ p_op->op_b3_b=FALSE;
+ p_op->op_b4_b=FALSE;
+ p_op->op_b5_b=FALSE;
+ p_op->op_b6_b=FALSE;
+ p_op->op_b7_b=FALSE;
+
+ p_op->op_h_b=FALSE;
+ strcpy(&p_op->op_h_s[0],"menu");
+}
+
+/******************************************************************************/
+
+EXPORT bool op_add(p_op,p_cl,p_outf)
+p_op_t p_op;
+p_cl_t p_cl;
+void (*p_outf) P_((char *));
+{
+ op_t op_save; /* Saves *p_op so it can be restored later. */
+ char *comline = (char *) p_cl; /* Pointer to the command line to be parsed. */
+ char *p; /* Handy parsing pointer. */
+ bool seen_error = FALSE; /* TRUE iff one or more errors seen. */
+
+#define ECHO_CL {if (!seen_error)\
+ {(*p_outf)(comline);(*p_outf)("\n"); seen_error=TRUE;}}
+
+ /* Save the parameter option structure so that we can restore it */
+ /* if an error occurs later on. */
+ ASSIGN(op_save,*p_op);
+
+ /* Check to make sure that the command line is not too long. */
+ /* This error should really never occur. */
+ p=comline;
+ while (*p++ != EOS)
+ if ((p-comline) > COMLINE_FWMAX)
+ {
+ (*p_outf)("FunnelWeb command line syntax error.\n");
+ (*p_outf)("The entire command line is too long.\n");
+ sprintf(linet1,"The maximum command line length is %u characters.\n",
+ (unsigned) COMLINE_FWMAX);
+ (*p_outf)(linet1);
+ goto failure;
+ }
+
+ /* Check that the command line contains only printables. */
+ p=comline;
+ while (*p != EOS)
+ {
+ if (!isascprn(*p))
+ {
+ (*p_outf)("FunnelWeb command line syntax error.\n");
+ (*p_outf)("Command line contains one or more non-printables.\n");
+ sprintf(linet1,"The first is at column %u.\n",(unsigned) (1+p-comline));
+ (*p_outf)(linet1);
+ goto failure;
+ }
+ p++;
+ }
+
+ /* Now parse each option. */
+ p=comline;
+ while (TRUE)
+ {/* This loop processes one command line parameter (option) per iteration. */
+ char *p_startopt; /* Points to the start of the parameter. */
+ bool opsign; /* The sign of the current option (+=TRUE). */
+ bool opsign_active; /* TRUE => (+ or -). FALSE => (=). */
+ char letter; /* Letter of current option. */
+ cl_t cl_temp; /* Parameter string of the current option. */
+ fn_t fn_temp; /* Parameter string of the current option. */
+ int i; /* Handy int used to feed sscanf. */
+
+ /* Skip first parameter or rest of previous parameter after syntax error. */
+ while ((*p!=' ') && (*p!=EOS)) p++;
+
+ /* Skip blanks between parameters. */
+ while (*p==' ') p++;
+
+ /* At this point we are either at the start of a parameter or at EOS. */
+ /* Finish if we are at the EOS. */
+ if (*p==EOS) break;
+
+ /* p now points to the next parameter (option). Make a note of its start. */
+ p_startopt=p;
+
+ /* This switch statement parses the sign and letter characters. */
+ switch (*p)
+ {
+ case '-': opsign=FALSE; opsign_active=TRUE; p++; goto parse_letter;
+ case '+': opsign=TRUE; opsign_active=TRUE; p++; goto parse_letter;
+ case '=': opsign_active=FALSE; p++; goto parse_letter;
+ parse_letter:
+ /* We have seen a sign. There should be a following letter. */
+ letter = *p;
+ if (!isalpha(letter))
+ {
+ ECHO_CL; wl_caret(p-comline,p_outf);
+ (*p_outf)("FunnelWeb command line syntax error.\n");
+ (*p_outf)("Option letter expected here.\n");
+ continue; /* Skip to the next parameter. */
+ }
+ p++;
+ break;
+ default: /* If no sign the option is a NAME option and defaults to +F. */
+ opsign=TRUE; opsign_active=TRUE; letter='F'; break;
+ } /* End switch */
+
+ /* Assert: p points to the parameter string of the option. */
+ /* Copy the parameter string into the holding variable cl_temp. */
+ {char *q;
+ q = &cl_temp[0];
+ while ((*p!=EOS) && (*p!=' '))
+ *q++ = *p++;
+ *q=EOS;
+ }
+
+ /* As COMLINE_FWMAX can be greater than FILENAME_FWMAX, we have to be careful */
+ /* that the user is not about to blow our filename buffer. */
+ if (strlen(cl_temp) > FILENAME_FWMAX)
+ {
+ ECHO_CL; wl_caret(p_startopt-comline,p_outf);
+ (*p_outf)("FunnelWeb command line syntax error.\n");
+ (*p_outf)("Option parameter string is too long.\n");
+ sprintf(linet1,"The maximum option parameter length is %u characters.\n",
+ (unsigned) FILENAME_FWMAX);
+ (*p_outf)(linet1);
+ continue; /* Skip to next parameter. */
+ }
+
+ /* Now that we know that the parameter is not too big, we can copy it */
+ /* into a temporary variable of filename type. */
+ strcpy(&fn_temp[0],&cl_temp[0]);
+
+ /* At this point p points to the character following the option that */
+ /* we have just scanned. This is either a blank or an EOS. */
+ /* The current option is held in (opsign,opsign_active,letter,fn_temp). */
+ /* Now we apply the option to the option record. */
+ switch (toupper(letter))
+ {
+ case 'F':
+ if (opsign_active) p_op->op_f_b=opsign;
+ strcpy(&p_op->op_f_s[0],&fn_temp[0]);
+ break;
+ case 'J':
+ if (opsign_active) p_op->op_j_b=opsign;
+ strcpy(&p_op->op_j_s[0],&fn_temp[0]);
+ break;
+ case 'I':
+ strcpy(&p_op->op_i_s[0],&fn_temp[0]);
+ break;
+ case 'O':
+ if (opsign_active) p_op->op_o_b=opsign;
+ strcpy(&p_op->op_o_s[0],&fn_temp[0]);
+ break;
+ case 'T':
+ if (opsign_active) p_op->op_t_b=opsign;
+ strcpy(&p_op->op_t_s[0],&fn_temp[0]);
+ break;
+ case 'L':
+ if (opsign_active) p_op->op_l_b=opsign;
+ strcpy(&p_op->op_l_s[0],&fn_temp[0]);
+ break;
+ case 'D':
+ if (opsign_active) p_op->op_d_b=opsign;
+ if (strlen(fn_temp)>0)
+ {
+ ECHO_CL; wl_caret(3+p_startopt-comline,p_outf);
+ (*p_outf)("FunnelWeb command line syntax error.\n");
+ (*p_outf)("The D option does not take an argument.\n");
+ }
+ break;
+ case 'C':
+ if ((sscanf(&fn_temp[0],"%d",&i) != 1) || (i<0) || (100<i))
+ {
+ ECHO_CL; wl_caret(3+p_startopt-comline,p_outf);
+ (*p_outf)("FunnelWeb command line syntax error.\n");
+ (*p_outf)("Numeric argument to C option invalid. It must\n");
+ (*p_outf)("be an unsigned decimal integer in the range [0,100].\n");
+ }
+ else
+ p_op->op_c_i=i;
+ break;
+ case 'Q':
+ if (opsign_active) p_op->op_q_b=opsign;
+ if (strlen(fn_temp)>0) {
+ /* ABC { */
+ if (!strcmp(fn_temp, "b")) {
+ strcpy(&p_op->op_q_s[0],&fn_temp[0]);
+ } else {
+ ECHO_CL; wl_caret(2+p_startopt-comline+(1+i),p_outf);
+ (*p_outf)("FunnelWeb command line syntax error.\n");
+ (*p_outf)("Error: Character in Q argument must be 'b'.\n");
+ } /* end if */
+ /* } ABC */
+ } /* end if */
+ break;
+ case 'S':
+ if (opsign_active) p_op->op_s_b=opsign;
+ if (strlen(fn_temp)==0) break;
+ if ((sscanf(&fn_temp[0],"%d",&i) != 1) || (i<0) || (100<i))
+ {
+ ECHO_CL; wl_caret(2+p_startopt-comline,p_outf);
+ (*p_outf)("FunnelWeb command line syntax error.\n");
+ (*p_outf)("Numeric argument to S option invalid. It must\n");
+ (*p_outf)("be an unsigned decimal integer in the range [0,100].\n");
+ }
+ else
+ p_op->op_s_i=i;
+ break;
+ case 'W':
+ if (opsign_active) p_op->op_w_b=opsign;
+ if (strlen(fn_temp)==0) break;
+ if ((sscanf(&fn_temp[0],"%d",&i) != 1) || (i<0) || (1000<i))
+ {
+ ECHO_CL; wl_caret(2+p_startopt-comline,p_outf);
+ (*p_outf)("FunnelWeb command line syntax error.\n");
+ (*p_outf)("Error: Numeric argument to W option invalid. It must\n");
+ (*p_outf)("be an unsigned decimal integer in the range [0,1000].\n");
+ }
+ else
+ p_op->op_w_i=i;
+ break;
+ case 'X':
+ if (opsign_active) p_op->op_x_b=opsign;
+ strcpy(&p_op->op_x_s[0],&fn_temp[0]);
+ break;
+ case 'K':
+ if (opsign_active) p_op->op_k_b=opsign;
+ if (strlen(fn_temp)>0)
+ {
+ ECHO_CL; wl_caret(3+p_startopt-comline,p_outf);
+ (*p_outf)("FunnelWeb command line syntax error.\n");
+ (*p_outf)("The K option does not take an argument.\n");
+ }
+ break;
+ case 'H':
+ if (opsign_active) p_op->op_h_b=opsign;
+ if (strlen(&fn_temp[0])>0)
+ if (strlen(&fn_temp[0]) > HL_NMLEN)
+ {
+ ECHO_CL; wl_caret(3+p_startopt-comline,p_outf);
+ (*p_outf)("FunnelWeb command line syntax error.\n");
+ (*p_outf)("The H option string argument is too long.\n");
+ (*p_outf)("Try +Hmenu for a list of help message names.\n");
+ }
+ else
+ if (hel_num(&fn_temp[0]) == HL_ERR)
+ {
+ ECHO_CL; wl_caret(3+p_startopt-comline,p_outf);
+ (*p_outf)("FunnelWeb command line syntax error.\n");
+ (*p_outf)("Unrecognised message name in argument to H option.\n");
+ (*p_outf)("Try +Hmenu for a list of help message names.\n");
+ }
+ else
+ strcpy(&p_op->op_h_s[0],&fn_temp[0]);
+ break;
+ case 'B':
+ {
+ uword i;
+ if (strlen(fn_temp)==0)
+ {
+ ECHO_CL; wl_caret(3+p_startopt-comline,p_outf);
+ (*p_outf)("FunnelWeb command line syntax error.\n");
+ (*p_outf)("The B option must be followed by one or more digits.\n");
+ (*p_outf)("The digits must be in the range 1..7.\n");
+ break;
+ }
+ for (i=0;i<strlen(fn_temp);i++)
+ if (fn_temp[i]<'1' || fn_temp[i]>'7')
+ {
+
+ECHO_CL; wl_caret(2+p_startopt-comline+(1+i),p_outf);
+ (*p_outf)("FunnelWeb command line syntax error.\n");
+ (*p_outf)("Error: Characters in B argument must be '1'..'7'.\n");
+ goto endbop;
+ }
+ if (opsign_active)
+ for (i=0;i<strlen(fn_temp);i++)
+ switch (fn_temp[i])
+ {
+ case '1': p_op->op_b1_b=opsign; break;
+ case '2': p_op->op_b2_b=opsign; break;
+ case '3': p_op->op_b3_b=opsign; break;
+ case '4': p_op->op_b4_b=opsign; break;
+ case '5': p_op->op_b5_b=opsign; break;
+ case '6': p_op->op_b6_b=opsign; break;
+ case '7': p_op->op_b7_b=opsign; break;
+ default: as_bomb("op_add: b option case defaulted.");
+ }
+ endbop:
+ break;
+ }
+ default:
+ ECHO_CL; wl_caret(2+p_startopt-comline,p_outf);
+ (*p_outf)("FunnelWeb command line syntax error.\n");
+ (*p_outf)("Error: Unknown option letter.\n");
+ (*p_outf)("Legal option letters are FIOTLCSWPXZ.\n");
+ (*p_outf)("(Note: But P is not yet implemented!)\n");
+ break;
+ }
+ } /* End while. */
+ if (seen_error) goto failure;
+ return TRUE;
+
+ failure: ASSIGN(*p_op,op_save); return FALSE;
+ }
+
+/******************************************************************************/
+
+EXPORT void op_wri(p_op,p_outf)
+p_op_t p_op;
+void (*p_outf) P_((char *));
+{
+#define STC(BOOLV) ((BOOLV)?'+':'-')
+ sprintf(linet1," %cB1 %cB2 %cB3 %cB4 %cB5 %cB6 %cB7\n",
+ STC(p_op->op_b1_b),
+ STC(p_op->op_b2_b),
+ STC(p_op->op_b3_b),
+ STC(p_op->op_b4_b),
+ STC(p_op->op_b5_b),
+ STC(p_op->op_b6_b),
+ STC(p_op->op_b7_b));(*p_outf)(linet1);
+ sprintf(linet1," +C%u\n" , (unsigned) p_op->op_c_i );(*p_outf)(linet1);
+ sprintf(linet1," %cD\n" , STC(p_op->op_d_b) );(*p_outf)(linet1);
+ sprintf(linet1," %cF%s\n", STC(p_op->op_f_b), p_op->op_f_s );(*p_outf)(linet1);
+ sprintf(linet1," %cH%s\n", STC(p_op->op_h_b), p_op->op_h_s );(*p_outf)(linet1);
+ sprintf(linet1," +I%s\n" , p_op->op_i_s );(*p_outf)(linet1);
+ sprintf(linet1," %cJ%s\n", STC(p_op->op_j_b), p_op->op_j_s );(*p_outf)(linet1);
+ sprintf(linet1," %cK\n" , STC(p_op->op_k_b) );(*p_outf)(linet1);
+ sprintf(linet1," %cL%s\n", STC(p_op->op_l_b), p_op->op_l_s );(*p_outf)(linet1);
+ sprintf(linet1," %cO%s\n", STC(p_op->op_o_b), p_op->op_o_s );(*p_outf)(linet1);
+ /* ABC { */
+ sprintf(linet1," %cQ%s\n", STC(p_op->op_q_b), p_op->op_q_s );(*p_outf)(linet1);
+ /* } ABC */
+ sprintf(linet1," %cS%u\n", STC(p_op->op_s_b), (unsigned) p_op->op_s_i );(*p_outf)(linet1);
+ sprintf(linet1," %cT%s\n", STC(p_op->op_t_b), p_op->op_t_s );(*p_outf)(linet1);
+ sprintf(linet1," %cW%u\n", STC(p_op->op_w_b), (unsigned) p_op->op_w_i );(*p_outf)(linet1);
+ sprintf(linet1," %cX%s\n", STC(p_op->op_x_b), p_op->op_x_s );(*p_outf)(linet1);
+}
+
+/******************************************************************************/
+/* End of OPTION.C */
+/******************************************************************************/
+
diff --git a/web/funnelAC/fwACsrc/option.h b/web/funnelAC/fwACsrc/option.h
new file mode 100644
index 0000000000..b0b57e90b0
--- /dev/null
+++ b/web/funnelAC/fwACsrc/option.h
@@ -0,0 +1,180 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 16-Aug-1995 ABC Added `op_q_s' string to `op_t' structure to
+ accomodate the addition of a `+Qb' batch mode
+ command line switch.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* OPTION.H */
+/******************************************************************************/
+
+/* Ensure that the body of this header file is included at most once. */
+#ifndef DONE_OPTION
+#define DONE_OPTION
+
+/******************************************************************************/
+
+#include "style.h"
+
+#include "machin.h"
+#include "help.h"
+
+/******************************************************************************/
+
+/* THE B7 OPTION */
+/* ------------- */
+/* When FunnelWeb was first ported to different machines and the regression */
+/* testing was activated, a most irritating occurance was the failure of the */
+/* results of tests on different machines to compare, because of minor */
+/* differences in implementation. For example, error messages that contained */
+/* file names would differ because the directory name on different machines */
+/* was different. Another example was error messages that quoted */
+/* implementation limits. This problem was solved by creating the B7 option */
+/* which instructs FunnelWeb to suppress all output that is */
+/* non-deterministic, machine specific, or which in any other way would cause */
+/* an unncessary failure of the test suite. */
+
+/* The following symbol provides a simple replacement for filenames in error */
+/* messages. */
+#define SUPPNAME "<<Suppressed>>"
+#define SUPPVAL "<<Suppressed>>"
+
+/******************************************************************************/
+
+/* The following structure stores all the information that can be */
+/* communicated in one or more command lines. An important aspect of the */
+/* structure is that it is totally self contained; it does not contain any */
+/* pointers to outside structures such as command lines. */
+/* The rather strange field names are explained as follows: */
+/* 1) Local names must be distinct to 8 characters (for portability). */
+/* 2) All structure field names should be unique (for portability). */
+/* Some of the older compilers use a single field structure name space. */
+/* 3) The op_ is used as a prefix for entities in this whole package. */
+/* 4) The next letter is the option letter itself. It is not intended that */
+/* the command line option names be tightly bound to the internal */
+/* identifier names -- the command line names are just convenient. */
+/* 5) The next letter gives the type: [B]oolean, [S]tring, [I]nteger. */
+
+typedef struct
+ {
+ bool op_f_b; /* The input file. */
+ fn_t op_f_s;
+
+ bool op_j_b; /* The journal file. */
+ fn_t op_j_s;
+
+ fn_t op_i_s; /* Include file (default). */
+
+ bool op_o_b; /* Product files (default). */
+ fn_t op_o_s;
+
+ bool op_t_b; /* Typeset file (default). */
+ fn_t op_t_s;
+
+ bool op_l_b; /* Listing file (default). */
+ fn_t op_l_s;
+
+ bool op_d_b; /* Delete output files that have not changed? */
+
+ uword op_c_i; /* Lines of error context in listing file. */
+
+ bool op_q_b; /* Quiet mode. Console chatter suppressed if turned on. */
+ /* ABC { */
+ fn_t op_q_s;
+ /* } ABC */
+
+ bool op_s_b; /* Send errors to the screen with specified context. */
+ uword op_s_i;
+
+ bool op_w_b; /* Set maximum line length of product files. */
+ uword op_w_i;
+
+ bool op_x_b; /* Execute specified file in FunnelWeb shell. */
+ fn_t op_x_s;
+
+ bool op_k_b; /* Interactive (keyboard) mode. */
+
+ /* Dump flags: */
+ bool op_b1_b; /* Dump input file image. */
+ bool op_b2_b; /* Dump line list. */
+ bool op_b3_b; /* Dump token list. */
+ bool op_b4_b; /* Dump macro table. */
+ bool op_b5_b; /* Dump document list. */
+ bool op_b6_b; /* Dump time summary. */
+ bool op_b7_b; /* Don't write anything non-deterministic or machine */
+ /* specific. This option is designed to assist in */
+ /* regression testing. */
+
+ bool op_h_b; /* Help messages. */
+ hn_t op_h_s;
+ } op_t;
+
+typedef op_t *p_op_t;
+
+/******************************************************************************/
+
+EXPORT void op_ini P_((p_op_t));
+/* Initializes the specified options structure with default values. */
+/* This includes ALL the fields of the structure. If, for example, the */
+/* default value of op_l_b is FALSE, op_l_s will be set to the empty string. */
+
+EXPORT bool op_add P_((p_op_t,p_cl_t,void (*)(char *)));
+/* Parses the specified command line and places the information given in the */
+/* command line into specific fields of the options structure. The options */
+/* structure should be entirely defined upon entry, as this parsing function */
+/* only ADDS information present in the command line. Call op_ini if you */
+/* don't want to initialize all the fields manually. */
+/* The comline string should start with the leading command (e.g. "fw"). */
+/* However, he leading command is ignored. */
+/* Returns FALSE: One or more syntax errors have been detected. One or error */
+/* messages have been written using the funtion argument. */
+/* *p_op unchanged. */
+/* Returns TRUE : No syntax errors. Comline information placed in *p_op. */
+
+EXPORT void op_wri P_((p_op_t,void (*)(char *)));
+/* Writes a text representation of the specified options record using the */
+/* function argument. */
+
+/******************************************************************************/
+
+/* For #ifndef preventing multiple inclusion of the body of this header file. */
+#endif
+
+/******************************************************************************/
+/* End of OPTION.H */
+/******************************************************************************/
+
diff --git a/web/funnelAC/fwACsrc/parser.c b/web/funnelAC/fwACsrc/parser.c
new file mode 100644
index 0000000000..d34d7c122b
--- /dev/null
+++ b/web/funnelAC/fwACsrc/parser.c
@@ -0,0 +1,1476 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 31-Aug-1993 ABC Added support for EL_SPEC
+ 31-Aug-1993 ABC Added internal macros @<#line@>, @<#file@>.
+ 16-Sep-1993 ABC Changed all constants *_MAX to *_FWMAX to avoid
+ conflict with some standard UNIX constants.
+ 10-May-1994 ABC Added DYN_NAMES option to allow macro and
+ section names to be allocated dynamically
+ instead of statically.
+ 16-Jul-1994 ABC Added support for automatic insertion of #line
+ directives by supporting automatic calling of
+ of a macro (such as @<line@>).
+ 06-Aug-1995 ABC Added support for extra language types when
+ the `allow_source_code_typing' pragma is used.
+ 06-Aug-1995 ABC Modified `pr_name' to check for a source code
+ type as will for macros attached to files.
+ 08-Aug-1995 ABC Changed include file name from "memory.h"
+ to "fwmem.h" to avoid a clash with the C++
+ standard header file "memory.h".
+ 10-Aug-1995 ABC Added internal macro @<#timestamp@>
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* PARSER.C */
+/******************************************************************************/
+
+#include <setjmp.h>
+#include "style.h"
+
+#include "as.h"
+#include "data.h"
+#include "lister.h"
+#include "machin.h"
+#include "mapper.h"
+#include "fwmem.h"
+#include "misc.h"
+#include "parser.h"
+#include "section.h"
+#include "table.h"
+
+/******************************************************************************/
+
+#define DUMMYINT 0 /* It doesn't matter what this value is!!! */
+#define TKPS &(p_tk->tk_ps) /* A commonly used construct. */
+
+/******************************************************************************/
+
+/* The following variables look after sections. */
+LOCVAR sn_t last_sn; /* Hierarchical section number of last section. */
+LOCVAR ps_t pssection; /* Position of last section. */
+LOCVAR p_dc_t p_secdc; /* Pointer to current section document component. */
+LOCVAR tk_t *p_tk; /* Pointer to the current token (a structure). */
+LOCVAR ulong sequence; /* Current sequence number. */
+LOCVAR jmp_buf jmp_pos; /* Setjmp() position of main parsing loop. */
+
+
+/******************************************************************************/
+/* Comparison Functions */
+/******************************************************************************/
+
+LOCAL sign cm_name P_((name_t *,name_t *));
+LOCAL sign cm_name(name1,name2)
+/* Compares two names and returns: */
+/* -1 if name1 < name2 */
+/* 0 if name1 = name2 */
+/* 1 if name1 > name2 */
+/* Provides a full ordering on the set of names. */
+name_t *name1;
+name_t *name2;
+{
+ return signof(strcmp(&(*name1)[0],&(*name2)[0]));
+}
+
+/******************************************************************************/
+
+LOCAL sign eq_txst P_((p_scls_t,char *));
+LOCAL sign eq_txst(p_scls,p_str)
+/* The first argument is a list of text scraps. */
+/* The second argument is an ordinary string. */
+/* Returns TRUE iff the two are identical. Otherwise FALSE. */
+p_scls_t p_scls;
+char *p_str;
+{
+ /* To compare the scrap list with the string, we run through the scrap list */
+ /* comparing the bytes its scraps yield progressively with the string. */
+ /* The two scanning groups are (p_scls,p_sc,p_ch) and p_str. */
+ sc_t *p_sc;
+
+ ls_fir(p_scls);
+ ls_nxt(p_scls,PPV &p_sc);
+ while (p_sc!=NULL)
+ {
+ /* The loop body compares a single scrap pointed to by p_sc. */
+ char *p_ch;
+ for (p_ch=p_sc->sc_first; p_ch<=p_sc->sc_last; p_ch++)
+ {
+ if (*p_str==EOS || *p_str != *p_ch) return FALSE;
+ p_str++;
+ }
+ ls_nxt(p_scls,PPV &p_sc);
+ }
+ return *p_str==EOS;
+}
+
+/******************************************************************************/
+/* Parsing Primitives */
+/******************************************************************************/
+/* The following functions provide the basic parsing primitives used by the */
+/* main parsing routines. */
+/******************************************************************************/
+
+LOCAL void next_tk P_((bool));
+LOCAL void next_tk(iseoferr)
+/* This function reads the next token from the token list and places a */
+/* pointer to the token (structure) in the global variable "token". */
+/* The "iseoferr" determines whether a fuss should be made if the next token */
+/* fetched is TK_EOF. If iseoferr==TRUE and the next token is TK_EOF, next_tk */
+/* jumps to the main parsing loop. */
+bool iseoferr;
+{
+ ls_nxt(token_list,PPV &p_tk);
+ as_cold(p_tk!=NULL,"next_tk: Attempted to read next token at EOF.");
+ if (iseoferr && p_tk->tk_kind==TK_EOF)
+ {
+ lr_err(TKPS,"Ouch! High velocity encounter with end of file.");
+ lr_mes(TKPS,"FunnelWeb expected something else when it hit the EOF.");
+ longjmp(jmp_pos,DUMMYINT); /* Jump up to the main parsing loop. */
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void recover P_((void));
+LOCAL void recover()
+/* Parsing functions call this function at points where a syntax error has */
+/* has occurred that it is unlikely that the particular parsing function will */
+/* be able to recover from on its own. In these situations, the parser */
+/* resorts to a course grained syntactic error-recovery implemented by this */
+/* function. The goal of the error recovery system is to skip tokens until */
+/* the next major outer-level-syntax structure is encountered. These are: */
+/* - A new section (@A etc.). */
+/* - A macro definition (@$ or @O). */
+/* - End of file. */
+/* Once one of these three is found, "recover" raises the syntax exception */
+/* which sends control to the main parsing loop which is the correct place */
+/* to deal with a new, major syntactic construct. */
+{
+ lr_mes(TKPS,"Skipping after error to the next major construct...");
+
+ /* Skip to one of TK_NSEC,... */
+ while (TRUE)
+ {
+ tk_k_t k = p_tk->tk_kind;
+ if (k==TK_NSEC || k==TK_MDEF || k==TK_FDEF || k==TK_EOF) break;
+ next_tk(FALSE);
+ }
+
+ /* Keep the user informed. */
+ lr_mes(TKPS,"...skipped to here after the error.");
+
+ /* Jump up to the main parsing loop. */
+ longjmp(jmp_pos,DUMMYINT);
+}
+
+/******************************************************************************/
+
+LOCAL void genexerr P_((tk_k_t));
+LOCAL void genexerr(tk_kind)
+/* Genexerr stands for GENerate EXpecting ERRor. */
+/* Given a token kind, genexerr issues an error saying that the specified */
+/* kind of token was expected. It then invokes recover() for error recovery. */
+tk_k_t tk_kind;
+{
+ switch (tk_kind)
+ {
+ /* Note: Not all token kinds are listed here. Only those token kinds that */
+ /* are passed to pr_token and check_tk by the main parsing routines are */
+ /* included here. There are some tokens that one never expects! */
+ case TK_NSEC: lr_err(TKPS,"Expecting '@*'."); break;
+ case TK_ONAM: lr_err(TKPS,"Expecting '@<'."); break;
+ case TK_ODEF: lr_err(TKPS,"Expecting '@{'."); break;
+ case TK_CDEF: lr_err(TKPS,"Expecting '@}'."); break;
+ case TK_EMPH: lr_err(TKPS,"Expecting '@/'."); break;
+ case TK_CPAR: lr_err(TKPS,"Expecting '@)'."); break;
+ case TK_QUOT: lr_err(TKPS,"Expecting '@\"'."); break;
+ case TK_PARM: lr_err(TKPS,"Expecting one of [@1..@9]." ); break;
+ case TK_TEXT: lr_err(TKPS,"Expecting a text character."); break;
+ default: as_bomb("genexerr: Case defaulted.");
+ }
+ recover();
+}
+
+/******************************************************************************/
+
+LOCAL void pr_token P_((tk_k_t));
+LOCAL void pr_token(tk_kind)
+/* Parses a single token of the specified kind. */
+/* If the token is of the specified kind, gets the next token. */
+/* If the token is not of the specified kind, generates an "expecting" error. */
+tk_k_t tk_kind;
+{
+ if (p_tk->tk_kind != tk_kind)
+ genexerr(tk_kind);
+ next_tk(TRUE);
+}
+
+/******************************************************************************/
+
+LOCAL void check_tk P_((tk_k_t));
+LOCAL void check_tk(tk_kind)
+/* Same as pr_token, but only checks that the token is OK. Does not move on. */
+tk_k_t tk_kind;
+{
+ if (p_tk->tk_kind != tk_kind)
+ genexerr(tk_kind);
+}
+
+/******************************************************************************/
+
+LOCAL void ass_tk P_((tk_k_t));
+LOCAL void ass_tk(tk_kind)
+/* Aborts the program if the current token is not of the specified kind. */
+/* This function is intended to perform internal consistency checks, and */
+/* should not be considered to be part of the parsing operation. */
+tk_k_t tk_kind;
+{
+ as_cold(p_tk->tk_kind==tk_kind,"Parser.ass_tk: Incorrect token.");
+}
+
+/******************************************************************************/
+
+LOCAL void ass_tks P_((tk_k_t,tk_k_t));
+LOCAL void ass_tks(tk_kind1,tk_kind2)
+/* Same as ass_tk except it allows a choice of two token kinds. */
+tk_k_t tk_kind1;
+tk_k_t tk_kind2;
+{
+ as_cold((p_tk->tk_kind == tk_kind1) || (p_tk->tk_kind == tk_kind2),
+ "Parser.ass_tks: Token is neither of two allowables.");
+}
+
+/******************************************************************************/
+/* Main Parsing Functions */
+/******************************************************************************/
+
+/* The parse expression procedures are the only procedures for which forward */
+/* declarations are required. This is a product of the recursive definition */
+/* of a FunnelWeb expression. */
+LOCAL void pr_exp P_((p_ells_t *,p_ma_t));
+
+/******************************************************************************/
+
+LOCAL void pr_text P_((p_scls_t *,bool *));
+LOCAL void pr_text(pp_scls,p_white)
+/* This function parses a sequence of zero or more text tokens (until it runs */
+/* into a non-text token) and constructs a list of scraps containing the text */
+/* pointed to by the tokens. In addition the function writes TRUE to its */
+/* second argument iff all of the text scraps are whitespace. */
+p_scls_t *pp_scls;
+bool *p_white;
+{
+ *pp_scls=ls_cre(sizeof(sc_t));
+ *p_white=TRUE;
+
+ while (p_tk->tk_kind==TK_TEXT)
+ {
+ *p_white = *p_white && p_tk->tk_sc.sc_white;
+ ls_add(*pp_scls,PV &p_tk->tk_sc);
+ next_tk(FALSE);
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void pr_white P_((p_scls_t *));
+LOCAL void pr_white(pp_scls)
+/* Same as pr_text, but generates an error if the text is non-white. */
+p_scls_t *pp_scls;
+{
+ bool iswhite;
+ ps_t ps;
+ ASSIGN(ps,p_tk->tk_ps);
+ pr_text(pp_scls,&iswhite);
+ if (!iswhite)
+ lr_err(&ps,"Expecting whitespace text.");
+}
+
+/******************************************************************************/
+
+LOCAL void pr_name P_((char *,char *));
+LOCAL void pr_name(p_name,p_srctnam)
+/* Parses a single FunnelWeb name (e.g. "@<Sloth@>" and "@#K"). */
+char *p_name; /* Really should be of type p_name_t but this caused trouble. */
+/* ABC { */
+char *p_srctnam;
+/* } ABC */
+{
+ uword namelen = 0;
+/* ABC { */
+char *p_curr_str; /* current string being parsed */
+/* } ABC */
+
+ /* Deal with the special case of a token name. */
+ if (p_tk->tk_kind==TK_NAME)
+ {
+ p_name[0]=p_tk->tk_gen;
+ p_name[1]=EOS;
+ p_srctnam[0]=EOS;
+ next_tk(TRUE);
+ return;
+ }
+
+ ass_tk(TK_ONAM);
+ next_tk(TRUE);
+ p_curr_str = p_name;
+ p_srctnam[0] = EOS;
+
+ while (TRUE)
+ switch (p_tk->tk_kind)
+ {
+ case TK_TEXT:
+ {
+ /* Copy the text token to the name array, checking all the time. */
+ char *p;
+ for (p=p_tk->tk_sc.sc_first; p<=p_tk->tk_sc.sc_last; p++)
+ {
+ if (*p==EOL)
+ {
+ lr_err(TKPS,"Names cannot cross lines.");
+ recover();
+ }
+ namelen++;
+ if (namelen>NAME_FWMAX)
+ {
+ lr_err(TKPS,"Name is too long.");
+ sprintf(linet1,
+ "The maximum length of a legal name is %lu characters.",
+ (unsigned long) NAME_FWMAX);
+ lr_mes(TKPS,linet1);
+ recover();
+ }
+ p_curr_str[namelen-1] = *p;
+ }
+ next_tk(TRUE);
+ break;
+ }
+/* ABC { */
+ case TK_COMA:
+ /* A source type name has been supplied. */
+ p_curr_str[namelen]=EOS;
+ next_tk(TRUE);
+ namelen = 0;
+ p_curr_str = p_srctnam;
+ break;
+/* } ABC */
+ case TK_CNAM:
+ /* We finish successfully if we hit a close name token "@>". */
+ p_curr_str[namelen]=EOS;
+ next_tk(TRUE);
+ return;
+ default:
+ lr_err(TKPS,"Illegal character or symbol in name.");
+ recover();
+ } /* End switch */
+}
+
+/******************************************************************************/
+
+LOCAL void pr_dctxt P_((void));
+LOCAL void pr_dctxt()
+/* Parse a major text chunk. */
+{
+ dc_t dc;
+ bool dummybool;
+ ps_t pstext;
+
+ ass_tk(TK_TEXT);
+
+ ASSIGN(pstext,p_tk->tk_ps);
+ pr_text(&dc.dc_text,&dummybool);
+ ASSIGN(dc.dc_ps,pstext);
+ dc.dc_kind=DC_TEXT;
+ ls_add(document_list,PV &dc);
+}
+
+/******************************************************************************/
+
+LOCAL void sendtype P_((ty_k_t));
+LOCAL void sendtype(ty_kind)
+/* Send a document component of kind typesetter directive with no attributes. */
+ty_k_t ty_kind;
+{
+ dc_t dc;
+ ASSIGN(dc.dc_ps,p_tk->tk_ps);
+ dc.dc_kind = DC_TYPE;
+ dc.dc_ty.ty_kind=ty_kind;
+ ls_add(document_list,PV &dc);
+}
+
+/******************************************************************************/
+
+LOCAL void pr_lit P_((void));
+LOCAL void pr_lit()
+/* Parse a string delimited by literal typeset directives e.g. @{sloth@}. */
+{
+ /* Check and get past opening directive. */
+ ass_tk(TK_ODEF);
+ sendtype(TY_OLIT);
+
+ /* Move past the opening directive and parse the sandwich text. */
+ next_tk(TRUE);
+ if (p_tk->tk_kind!=TK_TEXT)
+ {
+ lr_err(TKPS,"Text expected after open literal token \"@{\".");
+ if (p_tk->tk_kind==TK_CDEF)
+ lr_mes(TKPS,"Sorry, empty literal strings are not allowed.");
+ recover();
+ }
+ pr_dctxt();
+
+ /* Check and parse the closing directive. */
+ pr_token(TK_CDEF);
+ sendtype(TY_CLIT);
+}
+
+/******************************************************************************/
+
+LOCAL void pr_emp P_((void));
+LOCAL void pr_emp()
+/* Parse a string delimited by emphasis typeset directives e.g. @/sloth@/. */
+{
+ /* Check and get past opening directive. */
+ ass_tk(TK_EMPH);
+ sendtype(TY_OEMP);
+
+ /* Move past the opening directive and parse the sandwich text. */
+ next_tk(TRUE);
+ if (p_tk->tk_kind!=TK_TEXT)
+ {
+ lr_err(TKPS,"Text expected after open emphasise token \"@/\".");
+ if (p_tk->tk_kind==TK_EMPH)
+ lr_mes(TKPS,"Sorry, empty emphasised strings are not allowed.");
+ recover();
+ }
+ pr_dctxt();
+
+ /* Check and parse the closing directive. */
+ pr_token(TK_EMPH);
+ sendtype(TY_CEMP);
+}
+
+/******************************************************************************/
+
+LOCAL void pr_npag P_((void));
+LOCAL void pr_npag()
+/* Parse a newpage token. */
+{
+ ass_tk(TK_NPAG);
+ sendtype(TY_NPAG);
+ pr_token(TK_NPAG);
+}
+
+/******************************************************************************/
+
+LOCAL void pr_tocs P_((void));
+LOCAL void pr_tocs()
+/* Parse a table of contents token. */
+{
+ ass_tk(TK_TOCS);
+ sendtype(TY_TOCS);
+ pr_token(TK_TOCS);
+}
+
+/******************************************************************************/
+
+LOCAL void pr_skip P_((void));
+LOCAL void pr_skip()
+/* Parse a skip token. */
+{
+ dc_t dc;
+ ass_tk(TK_SKIP);
+ ASSIGN(dc.dc_ps,p_tk->tk_ps);
+ dc.dc_kind = DC_TYPE;
+ dc.dc_ty.ty_kind=TY_SKIP;
+ dc.dc_ty.ty_mm=p_tk->tk_gen;
+ ls_add(document_list,PV &dc);
+ pr_token(TK_SKIP);
+}
+
+/******************************************************************************/
+
+LOCAL void pr_titl P_((void));
+LOCAL void pr_titl()
+/* Parse a title token. Bascially moving bones from one grave to another. */
+{
+ dc_t dc;
+ ass_tk(TK_TITL);
+ ASSIGN(dc.dc_ps,p_tk->tk_ps);
+ dc.dc_kind = DC_TYPE;
+ dc.dc_ty.ty_kind = TY_TITL;
+ dc.dc_ty.ty_font = p_tk->tk_gen / LRFT_PACK;
+ dc.dc_ty.ty_align = p_tk->tk_gen % LRFT_PACK;
+ ASSIGN(dc.dc_ty.ty_sc,p_tk->tk_sc);
+ ls_add(document_list,PV &dc);
+ pr_token(TK_TITL);
+}
+
+/******************************************************************************/
+
+LOCAL void pr_sec P_((void));
+LOCAL void pr_sec()
+/* Parse a new section marker ("@A.. and @*") and its optional name. */
+{
+ ps_t secps; /* Position of this new section. */
+ ubyte level; /* Level number of new section. */
+ bool has_name; /* Set to TRUE iff the section has a name. */
+ name_t name; /* Name of the section (if it has a name). */
+ /* ABC { */
+ name_t srctnam; /* Name of the source code type (if any). */
+ /* } ABC */
+
+ /* If called, a new section marker must have been seen. */
+ ass_tk(TK_NSEC);
+
+ /* Grab a copy of the position of the start of the section. */
+ ASSIGN(secps,p_tk->tk_ps);
+
+ /* Grab the level number of the section marker. Move to the next token. */
+ level=p_tk->tk_gen;
+ next_tk(TRUE);
+
+ /* Check for a discontinuity in level. */
+ if (level>sn_lev(&last_sn)+1)
+ {
+ if (sn_lev(&last_sn)==0)
+ lr_err(&secps,"The first section in a document must be an @A section.");
+ else
+ {
+ sprintf(linet1,"The next section (at line %lu) is too deep.",
+ (unsigned long) secps.ps_line);
+ lr_mes(&pssection,linet1);
+ lr_err(&secps,"This section is more than one level deeper than the last");
+ sprintf(linet1,"section (at line %lu). Example: @B followed by @D is not allowed.",
+ (unsigned long) pssection.ps_line);
+ lr_mes(&secps,linet1);
+ }
+ /* At this point we know that the section structure of the document is */
+ /* faulty and that the weaver will never be invoked. As such the */
+ /* principal concern becomes that of error recovery. The best we can do */
+ /* there is to set to the specified level regardless of how silly it is. */
+ /* This ensures that we generate section errors only relative to the */
+ /* previous section. Thus, we avoid cascades of errors, if, for example */
+ /* the user mistypes an @A at the beginning of a FunnelWeb document. */
+ /* Once an error has occurred we don't care about the actual numbers. */
+ sn_set(&last_sn,level);
+ }
+
+ /* Actually increment the section number at the specified level. */
+ sn_inc(&last_sn,level);
+
+ /* Record the position. */
+ ASSIGN(pssection,secps);
+
+ /* Parse optional name (e.g. "@<Sloth@>"). */
+ if (p_tk->tk_kind==TK_ONAM || p_tk->tk_kind==TK_NAME)
+ {
+ pr_name(name,srctnam);
+ if (strlen(srctnam) > 0)
+ as_bomb("pr_sec: Sections cannot have source code types.");
+ has_name=TRUE;
+ }
+ else
+ {
+ strcpy(name,"No name given");
+ has_name=FALSE;
+ }
+
+ /* Place all the information we have into a document component structure */
+ /* and add it to the document list. */
+ {
+ dc_t dc;
+ ASSIGN(dc.dc_ps,secps);
+ dc.dc_kind = DC_TYPE;
+ dc.dc_ty.ty_kind=TY_NSEC;
+ ASSIGN(dc.dc_ty.ty_sn,last_sn);
+ dc.dc_ty.ty_isnam = has_name;
+/* ABC { */
+#if DYN_NAMES
+ dc.dc_ty.ty_name = (char*)mm_temp((strlen(name)+1)*sizeof(char));
+ strcpy(dc.dc_ty.ty_name,&name[0]);
+#else /* !DYN_NAMES */
+ strcpy(&dc.dc_ty.ty_name[0],&name[0]);
+#endif /* DYN_NAMES */
+/* } ABC */
+ ls_add(document_list,PV &dc);
+ ls_tai(document_list,PPV &p_secdc);
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void rem_name P_((char *));
+LOCAL void rem_name(p_name)
+/* rem_name stands for REMember NAME. rem_name accepts a pointer to a name. */
+/* It looks up the name in the global macro table, and if the name is in the */
+/* table performs no action. If the name isn't in the table, it creates a new */
+/* entry for the name, filling the entry's fields with "blank" values. */
+/* The rem_name function should not be seen as recording the definition of a */
+/* macro. This is handled by the md_isdef field. Instead the rem_name macro */
+/* should be viewed as just creating the space in the table for the info. */
+char * p_name; /* Really should be of type p_name_t but this caused trouble. */
+{
+ if (!tb_itb(macro_table,PV p_name))
+ {
+ p_ma_t p_macro=(p_ma_t) mm_temp(sizeof(ma_t));
+ /* ABC { */
+#if DYN_NAMES
+ p_macro->ma_name =
+ (char*)mm_temp((strlen(p_name)+1)*sizeof(char));
+ strcpy(p_macro->ma_name,&p_name[0]);
+#else /* !DYN_NAMES */
+ strcpy(&p_macro->ma_name[0],&p_name[0]);
+#endif /* DYN_NAMES */
+ /* } ABC */
+ p_macro->ma_calls = ls_cre(sizeof(mc_t));
+ p_macro->ma_defn.md_isdef = FALSE;
+ /* ABC { */
+ p_macro->ma_defn.md_aldm = NULL;
+ /* } ABC */
+ p_macro->ma_actn = ls_cre(sizeof(p_elll_t));
+ tb_ins(macro_table,PV p_name,PV &p_macro);
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void chk_whex P_((p_ps_t,p_ells_t,p_scls_t *));
+LOCAL void chk_whex(p_ps,p_ex,pp_white)
+/* This function should really be a subfunction of pr_plist. However, C */
+/* doesn't allow nested functions so we have to put it here. This function is */
+/* called after pr_plist has just parsed an opening expression followed by */
+/* @". This means that the expression should consist of whitespace crud. Our */
+/* mission here is to check that it really does contain only whitespace crud */
+/* and return a text list containing the crud. If, on the other hand, it */
+/* contains meatier items, we have to call recover(). */
+p_ps_t p_ps; /* Position of the start of the expression. */
+p_ells_t p_ex; /* The expression that we have to check out. */
+p_scls_t *pp_white; /* The place to put the resultant whitespace list. */
+{
+ p_el_t p_el;
+
+ /* If the expression is empty, we can return an empty list. */
+ if (ls_len(p_ex)==0)
+ {
+ *pp_white=ls_cre(sizeof(sc_t));
+ return;
+ }
+
+ /* If there is more than one element, there is ...trouble. */
+ if (ls_len(p_ex) > 1) goto trouble;
+
+ /* Extract the first element of the list. */
+ ls_fir(p_ex); ls_nxt(p_ex,PPV &p_el);
+
+ /* If it's not text, there is ...trouble. */
+ if (p_el->el_kind != EL_TEXT) goto trouble;
+
+ /* If the text isn't lilly white, there is ...trouble. */
+ {
+ p_scls_t p_scls = p_el->el_text;
+ p_sc_t p_sc;
+ ls_fir(p_scls);
+ while (TRUE)
+ {
+ ls_nxt(p_scls,PPV &p_sc);
+ if (p_sc==NULL) break;
+ if (!p_sc->sc_white) goto trouble;
+ }
+ /* If we got this far, we know that the expression contains a single */
+ /* element and that that element is a text list and that that text */
+ /* list consists entirely of whitespace. We can now return it. */
+ *pp_white=p_scls;
+ return;
+ }
+
+ /* We COULD start dissecting the expression and issuing detailed specific */
+ /* error messages. However, the general approach is cleaner and so a general */
+ /* error message is used. */
+ trouble:
+ lr_err( p_ps,"Everything from here...");
+ lr_mes(TKPS,"...to here should be whitespace.");
+ lr_mes(TKPS,"Use of @\" to delimit macro parameters is optional, but");
+ lr_mes(TKPS,"if they are used, any surrounding text must be white.");
+ recover();
+}
+
+/******************************************************************************/
+
+LOCAL void pr_plist P_((p_elll_t *, p_scll_t *, p_scll_t *,p_ma_t));
+LOCAL void pr_plist(pp_plist,p_before,p_after,p_curmac)
+/* This function parses an optional parameter list. If the current token is */
+/* not TK_OPAR, then it is assumed that no list is present and no tokens are */
+/* consumed and empty lists are returned. */
+/* The three lists returned are: */
+/* A list of parameters each being a pointer to a list of elements. */
+/* A list of whitespace blocks being the space before each parameter. */
+/* A list of whitespace blocks being the space after each parameter. */
+/* The last parameter p_curmac should be supplied by the caller and should */
+/* contain a pointer to the macro currently being parsed. */
+p_elll_t *pp_plist;
+p_scll_t *p_before;
+p_scll_t *p_after;
+p_ma_t p_curmac;
+{
+ /* Initialize all the result lists to empty. */
+ *pp_plist = ls_cre(sizeof(p_ells_t));
+ *p_before = ls_cre(sizeof(p_scls_t));
+ *p_after = ls_cre(sizeof(p_scls_t));
+
+ /* The parameter list is optional. If it isn't there we assume a null one. */
+ if (p_tk->tk_kind!=TK_OPAR)
+ return;
+ next_tk(TRUE);
+
+ /* Now parse the parameter list, one parameter during each iteration. */
+ while (TRUE)
+ {
+ ps_t exp_ps;
+ p_ells_t p_ex;
+ p_scls_t p_white;
+
+ /* Things get a little tricky here because the double quotes around */
+ /* parameters are optional (per parameter). Thus the following calls are */
+ /* all legal (and functionally identical): */
+ /* @<Sloth@>@( @"walrus@" @, @"aardvark@" @) */
+ /* @<Sloth@>@(walrus@, @"aardvark@" @) */
+ /* @<Sloth@>@(walrus@,aardvark@) */
+
+ /* Note the position of the start of this parameter slot. */
+ ASSIGN(exp_ps,p_tk->tk_ps);
+
+ /* Because we face either crud text or an expression, we parse an exp. */
+ pr_exp(&p_ex,p_curmac);
+
+ /* Now take a look at the next token. If it is @" we know that we have */
+ /* been parsing whitespace crud. If it is @, or @) we know that we have */
+ /* been parsing the parameter expression itself. */
+ if (p_tk->tk_kind==TK_COMA || p_tk->tk_kind==TK_CPAR)
+ {
+ p_scls_t p_scls = ls_cre(sizeof(sc_t));
+ ls_add(*p_before,PV &p_scls); /* Add empty whitespace to crud list. */
+ ls_add(*pp_plist,PV &p_ex); /* Add expression to parameter list. */
+ ls_add(*p_after ,PV &p_scls); /* Add empty whitespace to crud list. */
+ }
+ else
+ if (p_tk->tk_kind==TK_QUOT)
+ {
+ /* After parsing the expression we hit a @". This means that the */
+ /* expression just parsed SHOULD turn out to contain a single */
+ /* element consisting of a white space text list. */
+ chk_whex(&exp_ps,p_ex,&p_white);
+ ls_add(*p_before,PV &p_white);
+
+ /* Get past the quote. */
+ next_tk(TRUE);
+
+ /* Parse the expression and add it to the parameter list. */
+ pr_exp(&p_ex,p_curmac); ls_add(*pp_plist,PV &p_ex);
+
+ /* Parse the quote to move onto the whitespace. */
+ pr_token(TK_QUOT);
+
+ /* Parse the whitespace after the parameter. */
+ {p_scls_t p_white; pr_white(&p_white); ls_add(*p_after,PV &p_white);}
+ }
+ else
+ {lr_err(TKPS,"Expecting @\" or @, or @)."); recover();}
+
+ /* The parameter list can now end (TK_CPAR) or continue (TK_COMA). */
+ if (p_tk->tk_kind==TK_COMA)
+ next_tk(TRUE);
+ else
+ if (p_tk->tk_kind==TK_CPAR)
+ {next_tk(TRUE);return;}
+ else
+ {lr_err(TKPS,"Expecting @, or @)."); recover();}
+ } /* End while */
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void pr_invelt P_((p_ells_t,p_el_t,p_ma_t));
+LOCAL void pr_invelt(ex,p_el,p_curmac)
+/* } ABC */
+/* Parses an "invocation element" which is just FunnelWebSpeak for "macro */
+/* call". Upon entry the current token must be TK_ONAM or TK_NAME which */
+/* presumably is the start of a macro call. Returns a pointer to an element */
+/* object describing the call. Does some other macro table stuff too. */
+/* p_curmac should be supplied by the caller and should be a pointer to the */
+/* macro currently being parsed. */
+p_ells_t ex;
+p_el_t p_el;
+p_ma_t p_curmac;
+{
+ name_t name; /* Name of the macro being invoked. */
+/* ABC { */
+ name_t srctnam; /* Name of the source code type. */
+/* } ABC */
+ ps_t mc_ps; /* Position of the start of the macro invocation. */
+ mc_t mc; /* Macro call object that describes the invocation. */
+ p_ma_t p_callee; /* Pointer to the macro object of the target macro. */
+ p_elll_t parlist; /* The parameter list of the invocation. */
+ p_scll_t before; /* Whitespace before each parameter in the param list. */
+ p_scll_t after; /* Whitespace after each parameter in the param list. */
+
+ /* We shouldn't have been called unless we have seen the start of a name. */
+ ass_tks(TK_ONAM,TK_NAME);
+
+ /* Note the position of the start of the invocation. */
+ mc_ps=p_tk->tk_ps;
+
+ /* Parse the invocation (name and optional parameter list). */
+ pr_name(name,srctnam);
+ if (strlen(srctnam) > 0)
+ as_bomb("pr_invelt: Macro invocations cannot have source code types.");
+ pr_plist(&parlist,&before,&after,p_curmac);
+
+ /* Ensure that there is an entry for this macro name in the macro table. */
+ rem_name(name);
+
+ /* Construct a macro call object describing the call and add it to the */
+ /* callee macro's call list. */
+ /* Note: The +1 in sequence+1 is because the sequence number is incremented */
+ /* at the end of each macro definition and we are only halfway here. */
+ mc.mc_seq = sequence + 1;
+ mc.mc_ps = mc_ps;
+ mc.mc_npar = ls_len(parlist);
+ tb_loo(macro_table,PV name,PV &p_callee);
+ ls_add(p_callee->ma_calls,PV &mc);
+
+ /* Write an invocation element describing the call to the parameter. */
+ p_el->el_kind = EL_INVC;
+ p_el->el_p_mac = p_callee;
+ p_el->el_parls = parlist;
+ p_el->el_pretx = before;
+ p_el->el_postx = after;
+ /* ABC { */
+ p_el->el_ps = mc_ps;
+ /* } ABC */
+}
+
+/******************************************************************************/
+
+LOCAL void pr_txtelt P_((p_el_t));
+LOCAL void pr_txtelt(p_el)
+/* Parses a text element. Upon entry, the current token must be of type */
+/* TK_TEXT. Writes a text element into its parameter. */
+p_el_t p_el;
+{
+ p_scls_t p_scls;
+ bool dummy;
+ ass_tk(TK_TEXT);
+ /* ABC { */
+ p_el->el_ps = p_tk->tk_ps;
+ /* } ABC */
+ pr_text(&p_scls,&dummy);
+ p_el->el_kind = EL_TEXT;
+ p_el->el_text = p_scls;
+}
+
+/******************************************************************************/
+
+LOCAL void pr_parelt P_((p_el_t,p_ma_t));
+LOCAL void pr_parelt(p_el,p_curmac)
+/* Parses a parameter element (e.g. @5). Writes the resultant parameter */
+/* element object to the first parameter. The second parameter should be */
+/* supplied by the caller and should be a pointer to the macro being parsed. */
+p_el_t p_el;
+p_ma_t p_curmac;
+{
+ /* We have to be sitting on a parameter token. */
+ ass_tk(TK_PARM);
+
+ /* Complain if the parameter does not exist. */
+ if (p_tk->tk_gen > p_curmac->ma_defn.md_npar)
+ {
+ sprintf(linet1,"Macro being defined has only %lu parameter%s.",
+ (unsigned long) p_curmac->ma_defn.md_npar,
+ p_curmac->ma_defn.md_npar==1 ? "" : "s");
+ lr_err(TKPS,linet1);
+ }
+
+ /* Write a parameter element to the function parameter. */
+ p_el->el_kind = EL_PARM;
+ p_el->el_parno = p_tk->tk_gen;
+ p_el->el_which = p_curmac;
+
+ /* Move on to the token following the parameter token. */
+ next_tk(TRUE);
+}
+
+/******************************************************************************/
+
+LOCAL void pr_exp(p_ex,p_curmac)
+/* Parses an expression and writes an expression list to the first parameter. */
+/* The second parameter should be supplied by the user and should be a */
+/* pointer to the macro currently being parsed. */
+p_ells_t *p_ex;
+p_ma_t p_curmac;
+{
+ p_ells_t ex = ls_cre(sizeof(el_t));
+
+ while (TRUE)
+ {
+ el_t el;
+ switch (p_tk->tk_kind)
+ {
+ case TK_TEXT: pr_txtelt(&el); break;
+ case TK_NAME:
+ case TK_ONAM: pr_invelt(ex,&el,p_curmac); break;
+ case TK_PARM: pr_parelt(&el,p_curmac); break;
+ default : *p_ex=ex; return;
+ }
+ ls_add(ex,PV &el);
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void pr_formal P_((uword *,p_ps_t));
+LOCAL void pr_formal(p_numpar,p_ps)
+/* A FunnelWeb formal parameter list looks something like this: "@(@5@)". */
+/* This function parses a parameter list if present and returns the number of */
+/* parameters in the formal parameter list. The function also returns the */
+/* position the parameter list. */
+uword *p_numpar;
+p_ps_t p_ps;
+{
+ /* If the parameter list is absent, we default to having zero parameters and */
+ /* making the position of the parameter list the position of the next token. */
+ *p_numpar = 0;
+ *p_ps = p_tk->tk_ps;
+
+ /* Parse the parameter list only if one is present. */
+ if (p_tk->tk_kind==TK_OPAR)
+ {
+ /* Move to the parameter token and get its number and position. */
+ next_tk(TRUE);
+ check_tk(TK_PARM);
+ *p_numpar=p_tk->tk_gen;
+ *p_ps=p_tk->tk_ps;
+
+ /* Parse the end of the formal parameter list. */
+ next_tk(TRUE);
+ pr_token(TK_CPAR);
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void pr_number P_((bool *,bool *));
+LOCAL void pr_number(p_iszer,p_isman)
+/* Parses optional @Z@M after parameter list. */
+bool *p_iszer;
+bool *p_isman;
+{
+ *p_iszer=FALSE;
+ *p_isman=FALSE;
+
+ /* The following parse allows zero, one or both of @Z@M, but in order. */
+
+ /* Grab an @Z if it is there. */
+ if (p_tk->tk_kind==TK_ZERO)
+ {
+ next_tk(TRUE);
+ *p_iszer=TRUE;
+ }
+
+ /* Grab an @M too if it is there. */
+ if (p_tk->tk_kind==TK_MANY)
+ {
+ next_tk(TRUE);
+ *p_isman=TRUE;
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void pr_equals P_((bool *,p_ps_t));
+LOCAL void pr_equals(isadd,p_ps)
+/* Parses optional "==" or "+=". Sets *isadd==TRUE iff "+=" parsed else FALSE.*/
+/* Sets *p_ps to the position of the equals. */
+bool *isadd;
+p_ps_t p_ps;
+{
+ p_scls_t p_scls;
+ bool dummy;
+
+ /* Grab a copy of the position of the equals (even if it is not there) . */
+ ASSIGN(*p_ps,p_tk->tk_ps);
+
+ /* If the equals isn't there, we default to FALSE. */
+ *isadd=FALSE;
+ if (p_tk->tk_kind!=TK_TEXT) return;
+
+ /* Parse text tokens producing a text list. */
+ pr_text(&p_scls,&dummy);
+
+ /* Compare the text list with the assignment constant strings. */
+ if (eq_txst(p_scls,"==")) {*isadd=FALSE; ls_des(p_scls); return;}
+ if (eq_txst(p_scls,"+=")) {*isadd=TRUE; ls_des(p_scls); return;}
+
+ lr_err(p_ps,"Expecting \"==@{\" or \"+=@{\" or just \"@{\".");
+ lr_mes(p_ps,"(or @Z or @M if they have not already appeared).");
+ lr_mes(p_ps,"Note: FunnelWeb is intolerant of spaces at this point.");
+ ls_des(p_scls);
+ recover();
+}
+
+/******************************************************************************/
+
+LOCAL bool checkdef P_((p_ma_t,bool,ulong,bool,bool,bool,
+ p_ps_t,p_ps_t,p_ps_t,p_ps_t));
+LOCAL bool checkdef (p_ma,is_file,numpar,iszer,isman,isadd,
+ p_psnam,p_psfor,p_pseql,p_psnum)
+/* This function performs all sorts of checks on a macro definition. */
+/* If there is anything wrong, it generates and error and calls recover(). */
+/* This would be best as a local function but because C doesn't have local */
+/* functions we have to use millions of parameters instead. */
+p_ma_t p_ma;
+bool is_file;
+ulong numpar;
+bool iszer;
+bool isman;
+bool isadd;
+p_ps_t p_psnam;
+p_ps_t p_psfor;
+p_ps_t p_pseql;
+p_ps_t p_psnum;
+{
+ bool semerr = FALSE;
+
+ /* CHECK INTERNAL INCONSISTENCIES */
+ /* ------------------------------ */
+ /* Complain if a file macro has a parameter list. */
+ if (is_file && numpar>0)
+ {
+ lr_err(p_psfor,"Macros attached to output files cannot be parameterized.");
+ lr_mes(p_psfor,"Reason: No actual parameters would be available during");
+ lr_mes(p_psfor," output file generation.");
+ semerr=TRUE;
+ }
+
+ /* Complain if a file macro is declared additive. */
+ if (is_file && isadd)
+ {
+ lr_err(p_pseql,"Macros attached to output files cannot be additive.");
+ lr_mes(p_pseql,"Reason: Preventing this makes it easy to find output");
+ lr_mes(p_pseql,"file macros later, because there will be exactly one");
+ lr_mes(p_pseql,"@O declaration in the input file for each output file.");
+ lr_mes(p_pseql,"To do what you are trying to do, just create an additive");
+ lr_mes(p_pseql,"bridging macro, like this:");
+ lr_mes(p_pseql," @O@<prog.c@>@{@<Bridge@>@}");
+ lr_mes(p_pseql," @$@<Bridge@>+=@{void stringhack()...@}");
+ lr_mes(p_pseql," @$@<Bridge@>+=@{main()...@}");
+ semerr=TRUE;
+ }
+
+ /* Complain if a file macro has a name that is too long. */
+ /* ABC { */
+#if DYN_NAMES
+ if (is_file && strlen(p_ma->ma_name)>FILENAME_FWMAX)
+#else /* !DYN_NAMES */
+ if (is_file && strlen(&p_ma->ma_name[0])>FILENAME_FWMAX)
+#endif /* DYN_NAMES */
+ /* } ABC */
+ {
+ lr_err(p_psnam,
+ "File macro's name is longer than the maximum permissible filename length.");
+ sprintf(linet1,"Maximum filename length is %lu characters.",
+ (unsigned long) FILENAME_FWMAX);
+ lr_mes(p_psnam,linet1);
+ semerr=TRUE;
+ }
+
+ /* Complain if a file macro has "zero" or "many" attributes. */
+ if (is_file && (iszer || isman))
+ {
+ lr_err(p_psnum,"Macros attached to output files cannot have @Z or @M.");
+ lr_mes(p_psnum,"Reason: They are always called once to generate their");
+ lr_mes(p_psnum,"output file and they cannot be called from other macros.");
+ lr_mes(p_psnum,"Hence they are always called exactly once and so there");
+ lr_mes(p_psnum,"can be no need for @Z or @M in their declarations.");
+ semerr=TRUE;
+ }
+
+ /* COMPARE WITH EARLIER DEFINITIONS */
+ /* -------------------------------- */
+ /* Don't do this section if no previous definition exists. */
+ if (!p_ma->ma_defn.md_isdef) goto finish;
+
+ /* Assert: An earlier definition of this macro exists. */
+
+ /* Old definition is a full definition, not admitting partial ones now. */
+ if (!p_ma->ma_defn.md_isadd)
+ {
+ if (isadd)
+ {
+ sprintf(linet1,"A full definition of this macro appears at line %lu.",
+ (ulong) p_ma->ma_defn.md_ps.ps_line);
+ lr_err(p_psnam,linet1);
+ lr_mes(p_psnam,"Full and additive definitions of the same macro cannot coexist.");
+ }
+ else
+ {
+ sprintf(linet1,"This macro is already fully defined (at line %lu).",
+ (ulong) p_ma->ma_defn.md_ps.ps_line);
+ lr_err(p_psnam,linet1);
+ }
+ semerr=TRUE;
+ }
+
+ /* Old definition is partial but new definition is full. */
+ if (p_ma->ma_defn.md_isadd && !isadd)
+ {
+ sprintf(linet1,"An additive definition of this macro appears at line %lu.",
+ (ulong) p_ma->ma_defn.md_ps.ps_line);
+ lr_err(p_psnam,linet1);
+ lr_mes(p_psnam,"Full and additive definitions of the same macro cannot coexist.");
+ semerr=TRUE;
+ }
+
+ /* Make sure that non-first body parts of additive macros do not have params.*/
+ if (isadd && (numpar>0))
+ {
+ lr_err(p_psfor,"The formal parameter list of an additive macro");
+ lr_mes(p_psfor,"must be placed only in the first definition part.");
+ sprintf(linet1,"The first part of this macro appears at line %lu.",
+ (ulong) p_ma->ma_defn.md_ps.ps_line);
+ lr_mes(p_psfor,linet1);
+ semerr=TRUE;
+ }
+
+ /* Complain if number attributes are being attached to an additive. */
+ if (isadd && (iszer || isman))
+ {
+ lr_err(p_psnum,"@Z and @M modifiers for additive macros must");
+ lr_mes(p_psnum,"be placed only in the first definition part.");
+ sprintf(linet1,"The first part of this macro appears at line %lu.",
+ (ulong) p_ma->ma_defn.md_ps.ps_line);
+ lr_mes(p_psnum,linet1);
+ semerr=TRUE;
+ }
+
+ finish:
+ if (semerr)
+ {
+ lr_mes(p_psnam,"Macro definition ignored.");
+ recover();
+ }
+ return TRUE;
+}
+
+/******************************************************************************/
+
+LOCAL void pr_macro P_((void));
+LOCAL void pr_macro()
+/* This function parses a single macro definition. Upon entry, the current */
+/* token must be either TK_MDEF or TK_FDEF. */
+{
+ ps_t ps_mac; /* Position of start of the macro definition. */
+ bool is_file; /* TRUE iff definition starts with @O instead of @$. */
+ name_t name; /* The macro name appearing in this definition. */
+/* ABC { */
+ name_t srctname; /* The name of the source code type, if applicable. */
+/* } ABC */
+ p_ma_t p_ma; /* Pointer to the macro record corresponding to 'name'. */
+ ps_t ps_name; /* Position of the macro name. */
+ ps_t ps_form; /* Position of the formal parameter list. */
+ ps_t ps_equal; /* Position of the equals. */
+ ps_t ps_num; /* Position of number attributes. */
+ uword numpar; /* Number of parameters in formal parameter list. */
+ bool iszer; /* TRUE iff macro is allowed to be called zero times. */
+ bool isman; /* TRUE iff macro is allowed to be called more than once. */
+ bool isadd; /* TRUE iff equals parsed here is "+=" not "==". */
+ p_ells_t ex; /* Expression constituting this macro body part. */
+ bool hasname; /* TRUE iff current section already has a name. */
+/* ABC { */
+ p_srcnmac_t p_srctype; /* Pointer to a source code type structure. */
+/* } ABC */
+
+ /* We should not have got in here without seeing a definition token. */
+ ass_tks(TK_MDEF,TK_FDEF);
+
+ /* Grab a copy of the position of the start of the macro. */
+ ASSIGN(ps_mac,p_tk->tk_ps);
+
+ /* If we have seen a macro definition token then it means that the user is */
+ /* TRYING to define a macro. The macro may or may not provoke errors. In */
+ /* either case though we do not want to hassle the user with errors about */
+ /* nameless sections not containing macros if it is obvious that an attempt */
+ /* to define a macro has been made. So here we set the name flag after */
+ /* having a look at it so we can use its value later. */
+ if (sn_lev(&last_sn)>0)
+ {
+ as_cold(p_secdc->dc_kind==DC_TYPE,"pr_macro: section processing error (1).");
+ as_cold(p_secdc->dc_ty.ty_kind==TY_NSEC,"pr_macro: section processing error (2).");
+ hasname=p_secdc->dc_ty.ty_isnam;
+ p_secdc->dc_ty.ty_isnam=TRUE;
+ }
+
+ /* Record whether the macro is attached to an product file. */
+ is_file= (p_tk->tk_kind==TK_FDEF);
+
+ /* Parse the macro name. Record its position. Ensure that there is an entry */
+ /* in the macro table for this macro name (i.e. create one if not there). */
+ next_tk(TRUE);
+ if (p_tk->tk_kind!=TK_ONAM && p_tk->tk_kind!=TK_NAME)
+ {
+ lr_err(TKPS,"Macro name expected (@<...@> or @#c).");
+ recover();
+ }
+ ps_name=p_tk->tk_ps;
+ pr_name(name, srctname);
+ if (!xsrctypesQ && (strlen(srctname) > 0))
+ as_bomb("pr_macro: A pragma is needed to allow source code typing.");
+ rem_name(name);
+ tb_loo(macro_table,PV name,PV &p_ma);
+
+ /* Parse the optional formal parameter list and the equals. */
+ /* Extract positioning and other information. */
+ pr_formal(&numpar,&ps_form );
+ ASSIGN(ps_num,p_tk->tk_ps);
+ pr_number(&iszer, &isman);
+ pr_equals(&isadd ,&ps_equal);
+
+ /* Perform semantic checks on whether this definition is valid. */
+ checkdef(p_ma,is_file,numpar,iszer,isman,isadd,
+ &ps_name,&ps_form,&ps_equal,&ps_num);
+
+ /* If we have got this far, we know that we have parsed a valid macro */
+ /* definition except possibly for the actual expression body. */
+ /* If this is the first definition of this macro, establish its definition. */
+ if (!p_ma->ma_defn.md_isdef)
+ {
+ p_ma->ma_defn.md_isdef = TRUE;
+ ASSIGN(p_ma->ma_defn.md_ps,ps_mac);
+ p_ma->ma_defn.md_npar = numpar;
+ p_ma->ma_defn.md_isadd = isadd;
+ p_ma->ma_defn.md_iszer = iszer;
+ p_ma->ma_defn.md_isman = isman;
+ p_ma->ma_defn.md_isfil = is_file;
+/* ABC { */
+ if (p_ma->ma_defn.md_isfil) {
+ ls_fir(srctlist);
+ for (;;) { /* forever */
+ ls_nxt(srctlist, (pp_lsel_t)&p_srctype);
+ if (p_srctype == NULL) break;
+ if (p_srctype->typnam == NULL) {
+ if (strlen(srctname) == 0) break;
+ } else {
+ if (!strcmp(srctname, p_srctype->typnam)) break;
+ } /* end if */
+ } /* end forever */
+ p_ma->ma_defn.md_aldm = p_srctype;
+ } else {
+ p_ma->ma_defn.md_aldm = NULL;
+ } /* end if */
+/* } ABC */
+ p_ma->ma_defn.md_body = ls_cre(sizeof(bp_t));
+ if (is_file) tb_ins(file_table,PV name,PV &p_ma);
+ }
+
+ /* Parse the body of this macro definition. */
+ pr_token(TK_ODEF); pr_exp(&ex,p_ma); pr_token(TK_CDEF);
+
+ /* We are now clear to execute the effects of the macro on our tables. */
+ /* First we bump up the sequence number. */
+ sequence++;
+
+ {
+ /* Construct a body part object containing the information in this */
+ /* definition and append it to the list of body parts in the macro record. */
+ bp_t bp;
+ bp.bp_ex = ex;
+ bp.bp_seq = sequence;
+ bp.bp_ps = ps_name;
+ ls_add(p_ma->ma_defn.md_body,PV &bp);
+ }
+
+ {
+ /* Construct a document component object for this definition and append it */
+ /* to the global document component list. */
+ dc_t dc;
+ ASSIGN(dc.dc_ps,ps_mac);
+ dc.dc_kind = DC_MACR;
+ dc.dc_p_ma = p_ma;
+ dc.dc_part = ls_len(p_ma->ma_defn.md_body);
+ ls_add(document_list,PV &dc);
+ }
+
+ /* Sections without names inherit the name of their first macro. */
+ if (sn_lev(&last_sn)>0 && !hasname) {
+ /* ABC { */
+#if DYN_NAMES
+ p_secdc->dc_ty.ty_name =
+ (char*)mm_temp((strlen(name)+1)*sizeof(char));
+ strcpy(p_secdc->dc_ty.ty_name,name);
+#else /* !DYN_NAMES */
+ strcpy(&p_secdc->dc_ty.ty_name[0],name);
+#endif /* DYN_NAMES */
+ /* } ABC */
+ } /* end if */
+}
+
+/* ABC { */
+/******************************************************************************/
+
+LOCAL void pr_spinit P_((char*, sf_k_t));
+LOCAL void pr_spinit(p_name, selection)
+/* Initialises a single internal macro, associating the given name with *
+ * a value describing the actual function selected. */
+char *p_name;
+sf_k_t selection;
+{
+ p_ma_t p_macro;
+ bp_t bp;
+ el_t el;
+
+ p_macro = (p_ma_t)mm_temp(sizeof(ma_t));
+#if DYN_NAMES
+ p_macro->ma_name = (char*)mm_temp((strlen(p_name)+1)*sizeof(char));
+#endif /* DYN_NAMES */
+ strcpy(p_macro->ma_name, p_name);
+ p_macro->ma_calls = ls_cre(sizeof(mc_t));
+ p_macro->ma_actn = ls_cre(sizeof(p_elll_t));
+
+ p_macro->ma_defn.md_isdef = TRUE; /* Yes, being pre-defined */
+ p_macro->ma_defn.md_ps.ps_declQ = FALSE;
+ /* Not explicitly declared */
+ p_macro->ma_defn.md_npar = 0; /* No parameters */
+ p_macro->ma_defn.md_isadd = FALSE; /* Can't add to definition */
+ p_macro->ma_defn.md_iszer = TRUE; /* Doesn't have to be called */
+ p_macro->ma_defn.md_isman = TRUE; /* Can be called many times */
+ p_macro->ma_defn.md_isfil = FALSE; /* Not attached to a file */
+ p_macro->ma_defn.md_aldm = NULL; /* Not a file macro */
+
+ p_macro->ma_defn.md_body = ls_cre(sizeof(bp_t));
+ bp.bp_seq = 0; /* Not really valid here, just a definite value */
+ bp.bp_ps.ps_declQ = FALSE; /* Not explicitly declared */
+ bp.bp_ex = ls_cre(sizeof(el_t));
+
+ el.el_kind = EL_SPEC; /* Special function */
+ el.el_selec = selection; /* Particular function */
+
+ ls_add(bp.bp_ex, PV &el);
+ ls_add(p_macro->ma_defn.md_body, PV &bp);
+
+ tb_ins(macro_table,PV p_name,PV &p_macro);
+}
+
+/******************************************************************************/
+
+LOCAL void pr_intern P_((void));
+LOCAL void pr_intern()
+/* This routine initialises the document with a set of standard internal */
+/* macros which give access to such things as the line number and file name */
+/* for a given position in the FunnelWeb source. */
+{
+ STAVAR char lineMacroName[] = "#line";
+ STAVAR char fileMacroName[] = "#file";
+ STAVAR char tstampMacroName[] = "#timestamp";
+ /* EL_SPEC && SF_LIN : source line macro @<#line@> */
+ pr_spinit(lineMacroName, SF_LIN);
+ /* EL_SPEC && SF_FIL : source line macro @<#file@> */
+ pr_spinit(fileMacroName, SF_FIL);
+ /* EL_SPEC && SF_TMS : source line macro @<#timestamp@> */
+ pr_spinit(tstampMacroName, SF_TMS);
+}
+/* } ABC */
+
+/******************************************************************************/
+
+EXPORT void parser()
+/* This is the main parser function. This function contains parser */
+/* initialization as well as the main parsing loop to which control is */
+/* returned (by recover()) when an error occurs. */
+{
+ /* Create the lists and tables generated by the parser. */
+ macro_table = tb_cre (sizeof(name_t),sizeof(p_ma_t),(p_kycm_t) cm_name);
+ file_table = tb_cre (sizeof(name_t),sizeof(p_ma_t),(p_kycm_t) cm_name);
+ document_list= ls_cre (sizeof(dc_t));
+
+ /* Initialize the section number counter. */
+ sequence = 0;
+ sn_ini(&last_sn);
+ p_secdc = NULL;
+
+ /* Prime the scanning of the token list. */
+ ls_fir(token_list);
+ next_tk(FALSE);
+
+ /* ABC { */
+ /* Initialise the internal macros. */
+ pr_intern();
+ /* } ABC */
+
+ /* This is where we longjmp back to after hitting a nasty syntax error. */
+ /* We don't actually have to test dummyint, as our control state is no */
+ /* different after a syntax error has occurred. Example: We try to parse */
+ /* a macro but there is a syntax error. So we skip to the start of the */
+ /* next macro and then longjmp back to here ready to parse the next */
+ /* macro. Thus, there is no need to a fork test. */
+ (void) setjmp(jmp_pos);
+
+ /* This is the main parser loop which parses major syntactic chunks. */
+ while (p_tk->tk_kind != TK_EOF)
+ switch (p_tk->tk_kind)
+ {
+ case TK_NSEC: pr_sec (); break;
+ case TK_TEXT: pr_dctxt(); break;
+ case TK_MDEF: pr_macro(); break;
+ case TK_FDEF: pr_macro(); break;
+ case TK_ODEF: pr_lit (); break;
+ case TK_EMPH: pr_emp (); break;
+ case TK_NPAG: pr_npag (); break;
+ case TK_TOCS: pr_tocs (); break;
+ case TK_SKIP: pr_skip (); break;
+ case TK_TITL: pr_titl (); break;
+ default:
+ lr_err(TKPS,"The parser was at the top level and was expecting");
+ lr_mes(TKPS,"one of: {Directive, Text, Macro definition, EOF}.");
+ next_tk(FALSE);
+ break;
+ }
+
+}
+
+/******************************************************************************/
+/* End of PARSER.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/parser.h b/web/funnelAC/fwACsrc/parser.h
new file mode 100644
index 0000000000..687a5bbf23
--- /dev/null
+++ b/web/funnelAC/fwACsrc/parser.h
@@ -0,0 +1,65 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* PARSER.H */
+/******************************************************************************/
+/* */
+/* The FunnelWeb parser parses the tokens in the global token list and */
+/* constructs a macro table and a document list. These two data structures */
+/* give structured views of the input document which are used later by tangle */
+/* and weave. If the parser detects any errors it sends them to the lister */
+/* package. If any errors have occurred, the output of the parser should not */
+/* be used. */
+/* */
+/* IN : token_list - List of tokens to be parsed. */
+/* OUT: macro_table - Table of macros parsed. */
+/* file_table - Table indicating which macros are attached to files. */
+/* document_list - List giving a structured view of the document. */
+/* Also sends diagnostic messages to the lister. */
+/* */
+/******************************************************************************/
+
+#include "style.h"
+
+/******************************************************************************/
+
+EXPORT void parser P_((void));
+
+/******************************************************************************/
+/* End of PARSER.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/scanner.c b/web/funnelAC/fwACsrc/scanner.c
new file mode 100644
index 0000000000..c80f2258c0
--- /dev/null
+++ b/web/funnelAC/fwACsrc/scanner.c
@@ -0,0 +1,2559 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 24-Aug-1993 ABC Added support for file name inclusion in tokens.
+ 16-Sep-1993 ABC Changed all constants *_MAX to *_FWMAX to avoid
+ conflict with some standard UNIX constants.
+ 30-Dec-1993 ABC Added the `#line_offset' and `#line_depth'
+ pragmas to support the internal `#line' macro.
+ 15-Apr-1994 ABC Added hypertext typesetter types
+ TR_HTXT and TR_HTML, which are to HTML hypertext
+ what TR_NONE and TR_TEX are to TeX respectively.
+ 15-Apr-1994 ABC Added no_doc_header pragma to suppress inclusion
+ of the TeX header (not needed for LaTeX) or HTML
+ header at weave time. Also suppresses addition
+ of "\bye" at end of TeX files, and suppresses
+ <HTML>...</HTML> markup around HTML files.
+ 15-Apr-1994 ABC Added doc_incQ flag for inclusion or not of
+ FunnelWeb TeX/HTML header.
+ 20-May-1994 ABC Added raw_macro_and_section_names pragma for
+ allowing or not of raw TeX/HTML in macro/section
+ names.
+ 20-May-1994 ABC Added raw_namQ flag for allowing or not of
+ raw TeX/HTML in macro/section names.
+ 27-May-1994 ABC Added ignore_text_after_special_minus flag to
+ cause text on a line after `@-' (assuming `@' is
+ the special character) to be ignored as a
+ comment. This is to aid in embedding text to
+ set the proper mode in an emacs buffer.
+ 28-May-1994 ABC Added no_paragraph_markups pragma which inhibits
+ the automatic insertion of `<P>' paragraph
+ markups for hypertext and HTML modes.
+ 16-Jul-1994 ABC Added automatic_line_directive_macro pragma to
+ allow the nomination of a macro which should
+ be called at each macro invocation in order
+ to generate line directives.
+ 25-Jul-1995 ABC Replaced `aldmname' with a list of structures
+ containing a source code type name (or NULL)
+ and a corresponding automatic line directive
+ insertion macro name.
+ 30-Jul-1995 ABC Added declare_source_code_type pragma to support
+ multiple source code types.
+ 30-Jul-1995 ABC Modified the automatic_line_directive_macro
+ pragma to accept an optional source code type.
+ 08-Aug-1995 ABC Changed include file name from "memory.h"
+ to "fwmem.h" to avoid a clash with the C++
+ standard header file "memory.h".
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* SCANNER.C */
+/******************************************************************************/
+/* */
+/* Introduction */
+/* ------------ */
+/* The FunnelWeb scanner is a little messy because it deals with two */
+/* structures at the same time while attempting to be efficient. On the one */
+/* hand it is busy constructing the line list. This means that it has to keep */
+/* an eye out for end of line characters ('\n'=EOL) so that it can add a line */
+/* record whenever it sees one. On the other hand, it has to scan the input */
+/* file into a token stream consisting of text tokens and special tokens */
+/* which usually have no regard for end of lines. It is tempting to divide */
+/* these two functions up (into perhaps a LINER and a TOKENIZER). However, */
+/* the presence of the include file facility would make this messy. Also, the */
+/* tokenizer has to count end of line markers so that it can generate */
+/* correctly positioned diagnostics. */
+/* */
+/* The long and short of it all is that the best way to do the scanning seems */
+/* to be to run a liner and a tokenizer as parallel layers. The liner */
+/* extracts characters from the input file and hands them to the tokenizer. */
+/* It also keeps an eye out for newline characters, sending a line record off */
+/* whenever it sees one, and counting lines. The tokenizer receives the */
+/* characters from the liner and performs the tokenize operation. */
+/* */
+/* Notes */
+/* ----- */
+/* - Currently FunnelWeb recognises only two characters as whitespace. */
+/* These are ' ' and EOL. */
+/* */
+/******************************************************************************/
+
+#include <ctype.h>
+#include <limits.h>
+#include "style.h"
+
+#include "as.h"
+#include "clock.h"
+#include "data.h"
+#include "dump.h"
+#include "list.h"
+#include "lister.h"
+#include "machin.h"
+#include "mapper.h"
+#include "fwmem.h"
+#include "misc.h"
+#include "option.h"
+#include "scanner.h"
+
+/******************************************************************************/
+
+/* The "special" character is the character that is used to introduce a */
+/* "special sequence". FunnelWeb allows the user to change this character so */
+/* as to cater for documents where the "default" character is common. This */
+/* definition defines what the default character is. */
+#define CH_DSPE ('@')
+
+/* FunnelWeb allows include files which are handled by the scanner by placing */
+/* recursive calls to scan_file. A maximum is placed on the level of nested */
+/* includes. This acts as a good sanity check as well as catching recursive */
+/* include files which are never a sensible construct in FunnelWeb as */
+/* FunnelWeb does not provide any conditional construct. */
+#define MAX_INCL (10)
+
+/* FunnelWeb is very conservative about what characters it will allow in its */
+/* input and output files. Currently the only characters allowed are */
+/* printables and end of lines. When FunnelWeb does spot an illegal character */
+/* it needs to be able to draw the user's attention to the character. The */
+/* best way to do this is to point to it in the listing file. However, if the */
+/* character is banned, it cannot appear in the listing file! The problem is */
+/* solved by having the scanner replace all illegal characters in each mapped */
+/* file by the following character. This eliminates further problems. */
+#define CENSORCH ('?')
+
+/* Following the Unix convention, mapped in files are not terminated with an */
+/* end-of-file character. However, the presence of such a character at the */
+/* end of the mapped file simplifies scanning and so we add one. This */
+/* definition defines what the character is to be. It doesn't matter what the */
+/* character is, so long as it cannot legally appear in the file. A control */
+/* character is a good choice as these are filtered out by the liner (see */
+/* above). */
+/* We undef EOF (from <stdio.h>) because it is too dangerously close to EOFCH.*/
+/* (EOF wasn't redefined as that might confuse readers used to <stdio.h>. */
+/* However, we still use EOF as an acronym for End Of File. */
+#define EOFCH (26)
+#undef EOF
+
+/* Tokens have a field for a general attribute which has meaning for some */
+/* token kinds. For other kinds, it has no meaning. This constant is used to */
+/* indicate a "don't care" value. */
+#define DONTCARE 0
+
+/* A nominal maximum value for the maximum length of an input line. */
+#define INMAXINF (ULONG_MAX)
+
+/******************************************************************************/
+
+/* The following type is used in the suite of pragma routines for parsing. */
+typedef
+ struct
+ {
+ ps_t pt_ps; /* Position of the start of this argument. */
+ char *pt_pstr; /* Pointer to a string containing the argument. */
+ char *pt_pinl; /* Pointer to first byte of the argument in commndline. */
+ } pt_t;
+typedef pt_t *p_pt_t;
+
+/******************************************************************************/
+
+ /* Variables Instantiated Over The Entire Scan */
+ /* ------------------------------------------- */
+LOCVAR p_ck_t p_mapp; /* Pointer to mapper's clock. */
+LOCVAR p_ck_t p_scan; /* Pointer to scanner's clock. */
+LOCVAR ulong globalno; /* Global line number of line being scanned. */
+LOCVAR ulong inclevel; /* Include level of current file. Top file is zero. */
+LOCVAR bool seenind; /* TRUE iff we have seen an indentation pragma. */
+LOCVAR ps_t ps_ind; /* seenind==TRUE => ps_ind is position of pragma. */
+LOCVAR bool seentyp; /* TRUE iff we have seen a typesetter pragma. */
+LOCVAR ps_t ps_typ; /* seentyp==TRUE => ps_typ is position of pragma. */
+LOCVAR bool seenlimo; /* TRUE iff we have seen an out lin len limit pragma. */
+LOCVAR ps_t ps_limo; /* seenlimo==TRUE => ps_limo is position of pragma. */
+
+ /* Variables Instantiated Over The Current File */
+ /* -------------------------------------------- */
+LOCVAR ulong inln_max; /* Maximum permitted length of an input line. */
+LOCVAR char specialch; /* Current special (escape) character. */
+LOCVAR char *p_eof; /* Pointer to EOFCH byte at the end of current file. */
+LOCVAR ulong localno; /* Local line number of line being scanned. */
+
+ /* Variables Instantiated Over The Current Line */
+ /* -------------------------------------------- */
+LOCVAR char *p_sol; /* Pointer to Start (first char) Of current Line. */
+LOCVAR char *p_ch; /* Pointer to current character in current line. */
+LOCVAR char ch; /* *p_ch. */
+/* ABC { */
+LOCVAR p_fnam_t src_1st; /* Start of list of all source filenames. */
+LOCVAR p_fnam_t src_cur; /* current filename. */
+LOCVAR bool igntxtQ; /* whether to ignore text on a line after `@-'. */
+/* } ABC */
+
+/******************************************************************************/
+/* Line Processing Layer */
+/******************************************************************************/
+/* */
+/* This mini-section contains the two routines (prepline and NEXTCH) that */
+/* take care of the line based-scanning and feed characters to the */
+/* token-based scanner routines which have the top level of control. */
+/* After mapping in a file to be read, place a call to prepline passing the */
+/* address of the first byte of the mapped file as an argument. At that */
+/* point the current position will be the first byte on the first line and */
+/* the "variables instantiated over the current line" will be well defined. */
+/* Calls to NEXTCH then move the position through the mapped file one byte at */
+/* a time, stopping at the end of file at which point calls will not move the */
+/* marker which will point to the EOF character. */
+/* */
+/******************************************************************************/
+
+LOCAL void prepline P_((char *));
+LOCAL void prepline(p_line)
+/* This function should be called at the end of each line to prepare the next */
+/* line for scanning. The user of the liner mini-package should place a */
+/* single call to this function at the start of scanning a mapped file. */
+/* The user should then place calls to NEXTCH (which calls prepline when */
+/* necessary). */
+/* This function serves two purposes: */
+/* 1. It looks at the next line and converts all non-printables into */
+/* CENSORCH and issues errors for each non-printable. */
+/* 2. It initializes the line scanning variables for the next line. */
+/* The argument is a pointer to the first byte of the next line. */
+char *p_line;
+{
+ char *p; /* Scans through the line and winds up sitting on the EOL. */
+
+ /* Test to see if the "line" we have been given is the end of file marker. */
+ /* We have to be careful here because the byte we are using to mark the end */
+ /* of file could appear as an illegal unprintable. This is the reason for */
+ /* the test p_line==p_eof. */
+ if (*p_line==EOFCH && p_line==p_eof)
+ {
+ /* The line we have to process is in fact the end of file marker. */
+ p_sol = p_line;
+ p_ch = p_line;
+ ch = EOFCH;
+ return;
+ }
+
+ /* At this point we know that we are faced with a run of bytes terminated by */
+ /* an EOL character (we know this cos we put an EOL before EOF earlier on). */
+ /* We know that we have a line, so we can now bump up the line counters. */
+ globalno++;
+ localno++;
+
+ /* Run through the line checking for non-printables and issuing errors. */
+ p = p_line;
+ while (*p != EOL)
+ {
+ /* The following test tests to see if the character is a printable in */
+ /* seven bit ascii. FunnelWeb is not currently designed to work with */
+ /* any character set other than seven-bit ascii and so we flag and */
+ /* convert all out-of-range characters here before they are exposed to */
+ /* the rest of the scanner code which assumes that each line that it is */
+ /* handed consists entirely of printables except for the EOL char on the */
+ /* end and possibly an EOF char at the "Start" of a line. */
+ /* In particular, the NEXTCH macro will fail on machines with siged */
+ /* chars if non-printables are not removed. It goes into an infinite */
+ /* loop. */
+ /* Note: I don't use library function "isprint" here because on the vax */
+ /* it's definition is too loose (seems to accept characters with the top */
+ /* bit set as printable). */
+ if (!isascprn(*p)) /* If not a printable character. */
+ {
+ ps_t ps;
+ char c = *p;
+ ubyte_ uc = *((ubyte_ *) p);
+ ps.ps_line = globalno;
+ ps.ps_column = p-p_line+1;
+ /* ABC { */
+ ps.ps_localno = localno;
+ ps.ps_fnam = src_cur;
+ ps.ps_declQ = TRUE;
+ /* } ABC */
+ if (strlen(chabbrev(c))==0)
+ sprintf(linet1,
+ "Non printable character (Sym=<none>, Dec=%03u, Hex=%02X, Oct=%03o).",
+ (unsigned) uc,(unsigned) uc,(unsigned) uc);
+ else
+ sprintf(linet1,
+ "Non printable character (Sym=%s, Dec=%03u, Hex=%02X, Oct=%03o).",
+ chabbrev(c),(unsigned) uc,(unsigned) uc,(unsigned) uc);
+ lr_err(&ps,linet1);
+ *p=CENSORCH;
+ }
+ p++;
+ }
+ /* Assert: p_line points to the start of the current line. */
+ /* Assert: p points to the EOL at the end of the current line. */
+
+ /* Check that the line is not too long. */
+ if ((p-p_line)>inln_max)
+ {
+ ps_t ps;
+ ps.ps_line = globalno;
+ ps.ps_column = inln_max+1;
+ /* ABC { */
+ ps.ps_localno = localno;
+ ps.ps_fnam = src_cur;
+ ps.ps_declQ = TRUE;
+ /* } ABC */
+ lr_err(&ps,"Input line is too long (this character is the first offender).");
+ sprintf(linet1,"Currently, the maximum allowable input line length is %lu.",
+ (unsigned long) inln_max);
+ lr_mes(&ps,linet1);
+ lr_mes(&ps,"Note: You can change this using a pragma directive (@p).");
+ }
+
+ /* Now check for trailing spaces. */
+ if ((p != p_line) && (*(p-1) == ' '))
+ {
+ ps_t ps;
+ ps.ps_line = globalno;
+ ps.ps_column = p-p_line;
+ /* ABC { */
+ ps.ps_localno = localno;
+ ps.ps_fnam = src_cur;
+ ps.ps_declQ = TRUE;
+ /* } ABC */
+ lr_war(&ps,"Line has trailing spaces up to and including this space.");
+ }
+
+ /* Construct a line record and append the record to the line list. */
+ /* Note that the line scrap encompasses the trailing EOL. */
+ {
+ ln_t line;
+ line.ln_global = globalno;
+ line.ln_local = localno;
+ line.ln_body.sc_first = p_line;
+ line.ln_body.sc_last = p;
+ /* ABC { */
+ line.ln_fnam = src_cur;
+ /* } ABC */
+ /* Note: We do not set sc_white as it is not used in lines. */
+ ls_add(line_list,PV &line);
+ }
+
+ /* Finally, set the line scanning variables to the start of the line. */
+ /* We can't do this earlier in case the start of the line was a */
+ /* non-printable and got substituted (ch might pick it up). */
+ p_sol = p_line;
+ p_ch = p_line;
+ ch = *p_line;
+
+} /* End of prepline. */
+
+/* NEXTCH can be called continuously after an initializing call to prepline. */
+/* After a call to NEXTCH, p_sol, p_ch, ch are all well-defined. p_sol points */
+/* to the start of the current line, p_ch points to the current character, */
+/* and ch contains *p_ch. NEXTCH can be called repeatedly forever. When it */
+/* hits the EOF character, it sticks on it and returns it forever. */
+/* Note: The "ch<' '" is an optimized form of "(ch==EOL)||(ch=EOFCH)". Speed */
+/* is very important here as this macro is called in scanning tightloops. */
+/* This line of code is a little tricky so read it carefully. */
+/* WARNING: The ch<' ' will cause an infinite loop if a character appears */
+/* that satisfies this condition without being EOF or EOL (e.g. a control */
+/* char (meant to be filtered out earlier) or a top-bit-set character on */
+/* machines with signed character type. */
+#define NEXTCH {if (ch<' ') {if (ch==EOL) prepline(p_ch+1);} else ch= *++p_ch;}
+
+/******************************************************************************/
+/* Scanner Support Routines */
+/******************************************************************************/
+
+LOCAL ps_t *psofch P_((void));
+LOCAL ps_t *psofch()
+/* Returns a pointer to an internal static ps structure holding the line and */
+/* column number of the current character ch. */
+{
+ STAVAR ps_t chps;
+ chps.ps_line = globalno;
+ chps.ps_column = p_ch-p_sol+1;
+ /* ABC { */
+ chps.ps_localno = localno;
+ chps.ps_fnam = src_cur;
+ chps.ps_declQ = TRUE;
+ /* } ABC */
+ return &chps;
+}
+
+/******************************************************************************/
+
+LOCAL void grabchps P_((p_ps_t));
+LOCAL void grabchps(p_ps)
+/* Writes the position of the current ch into the argument position struct. */
+p_ps_t p_ps;
+{
+ p_ps->ps_line = globalno;
+ p_ps->ps_column = p_ch-p_sol+1;
+ /* ABC { */
+ p_ps->ps_localno = localno;
+ p_ps->ps_fnam = src_cur;
+ p_ps->ps_declQ = TRUE;
+ /* } ABC */
+}
+
+/******************************************************************************/
+
+LOCAL void sendspec P_((p_ps_t,tk_k_t,ubyte));
+LOCAL void sendspec(p_tkps,tk_kind,tk_gen)
+/* Appends a non-text token of kind tk_kind to the end of the token list. */
+/* p_ps is a pointer to a position structure giving the position of the */
+/* first character of the token. tk_gen is the general token attribute. */
+p_ps_t p_tkps;
+tk_k_t tk_kind;
+ubyte tk_gen;
+{
+ tk_t token;
+ token.tk_kind = tk_kind;
+ ASSIGN(token.tk_ps,*p_tkps);
+ token.tk_sc.sc_first = NULL;
+ token.tk_sc.sc_last = NULL;
+ token.tk_sc.sc_white = TRUE;
+ token.tk_gen = tk_gen;
+ ls_add(token_list,PV &token);
+}
+
+/******************************************************************************/
+
+LOCAL void sendtext P_((p_ps_t,char *,char *,bool));
+LOCAL void sendtext(p_tkps,p_first,p_last,is_white)
+/* Appends a text token to the end of the token list. */
+/* IN: p_ps is a pointer to a position structure giving the position of the */
+/* first character of the token. */
+/* IN: p_first and p_last point to the first and last byte of the text scrap. */
+/* IN: is_white should be set to TRUE iff scrap is entirely whitespace. */
+p_ps_t p_tkps;
+char *p_first;
+char *p_last;
+bool is_white;
+{
+ tk_t token;
+
+ /* Empty text scraps should never be generated. */
+ as_cold(p_first<=p_last,"sendtext: Text scrap bounds are bad.");
+
+ /* If ch=EOL then we should be scanning more text, not shipping it! */
+ as_cold(ch!=EOL,"senttext: Shipping text while still more to scan.");
+
+ /* Send the text token. */
+ token.tk_kind = TK_TEXT;
+ ASSIGN(token.tk_ps,*p_tkps);
+ token.tk_sc.sc_first = p_first;
+ token.tk_sc.sc_last = p_last;
+ token.tk_sc.sc_white = is_white;
+ token.tk_gen = DONTCARE;
+ ls_add(token_list,PV &token);
+}
+
+/******************************************************************************/
+
+LOCAL void add_eof P_((void));
+LOCAL void add_eof()
+/* This function adds terminators to the line and token list. */
+/* 1. It adds a TK_EOF token to the end of the token list. */
+/* 2. It adds a visible <eof> line to the end of the line list. */
+/* This assists the parser by allowing it to point diagnostic messages to a */
+/* visible EOF marker rather than pointing vaguely to the end of the last */
+/* line of the input file which (by the way) may not even exist! */
+{
+ STAVAR char *eofstr = "<End-Of-File>\n";
+ ln_t line;
+ ps_t ps;
+
+ /* When the liner mini package encounters an end of file marker, it stops */
+ /* dead on the marker and returns EOFCH forever. scan_file() eventually gets */
+ /* the message and drops out. However, in all of this, the line numbers are */
+ /* not incremented to indicate that we have moved to an EOF line. This is */
+ /* intended, as we do not want EOFs to appear in the listing for include */
+ /* files; only at the end of the main input file. Thus, here we effectively */
+ /* perform the liner function of moving from the last line of the input file */
+ /* to the imaginary line containing the EOF marker. This is done by */
+ /* incrementing the line numbers. Note that the fact that these line number */
+ /* variables are incorrect from the point of detection of the final EOF to */
+ /* here doesn't matter as no tokens or diagnostics are ever added after an */
+ /* EOF is detected. */
+ globalno++;
+ localno++;
+
+ /* Add a line to represent the EOF marker. */
+ line.ln_global = globalno;
+ line.ln_local = localno;
+ line.ln_body.sc_first = eofstr;
+ line.ln_body.sc_last = eofstr+strlen(eofstr)-1;
+ /* ABC { */
+ line.ln_fnam = src_cur;
+ /* } ABC */
+ /* Note: We do not set sc_white as it is not used in lines. */
+ ls_add(line_list,PV &line);
+
+ /* Add a TK_EOF token to the end of the token list. */
+ ps.ps_line = globalno;
+ ps.ps_column = 1;
+ /* ABC { */
+ ps.ps_localno = localno;
+ ps.ps_fnam = src_cur;
+ ps.ps_declQ = TRUE;
+ /* } ABC */
+ sendspec(&ps,TK_EOF,DONTCARE);
+}
+
+
+/* ABC { */
+/******************************************************************************/
+/* Filename List Manipulation */
+/******************************************************************************/
+
+/******************************************************************************/
+
+LOCAL void fl_set P_((char*));
+LOCAL void fl_set(p_fname)
+/* This function checks to see if the given name currently exists in the */
+/* filename list. If so, it sets the value of src_cur accordingly. If not, */
+/* it adds the filename to the filename list, and then sets src_cur */
+/* accordingly. */
+char *p_fname;
+{
+ /* Check if *any* filenames have been added to the list. */
+ if (!src_1st) {
+ src_1st = (p_fnam_t)mm_temp(sizeof(fnam_t));
+ src_1st->fnam_next = (p_fnam_t)0;
+ src_1st->fnam_name = (char *)mm_temp((strlen(p_fname)+1)*sizeof(char));
+ strcpy(src_1st->fnam_name, p_fname);
+ src_cur = src_1st;
+ return;
+ } /* end if */
+
+ /* Start search from beginning of filename list. */
+
+ src_cur = src_1st;
+
+ /* Search for a match */
+ while (strcmp(src_cur->fnam_name, p_fname) && (src_cur->fnam_next)) {
+ src_cur = src_cur->fnam_next;
+ } /* end while */
+
+ /* If not match, add new filename. */
+ if (strcmp(src_cur->fnam_name, p_fname)) {
+ src_cur->fnam_next = (p_fnam_t)mm_temp(sizeof(fnam_t));
+ src_cur = src_cur->fnam_next;
+ src_cur->fnam_next = (p_fnam_t)0;
+ src_cur->fnam_name = (char *)mm_temp((strlen(p_fname)+1)*sizeof(char));
+ strcpy(src_cur->fnam_name, p_fname);
+ } /* end if */
+}
+/* } ABC */
+
+/******************************************************************************/
+/* The Scanner Proper */
+/******************************************************************************/
+
+LOCAL void skiptoeol P_((void));
+LOCAL void skiptoeol()
+{
+ while (ch != EOL)
+ NEXTCH;
+}
+
+/******************************************************************************/
+
+/* The incl_fil function calls this, so we have to declare it in advance. */
+LOCAL void scan_file P_((char *));
+
+LOCAL void incl_fil P_((p_ps_t));
+LOCAL void incl_fil(p_ps)
+/* Upon entry, the current character is the "i" of an "@i" sequence. Our task */
+/* is first to see if the sequence occurred at the start of a line (the only */
+/* point at which it is legal) and issue an error if it isn't. If it is legal,*/
+/* we have to read in the specified file and scan that. The included file */
+/* replaces exactly the line starting with the "@i" command and we return */
+/* to the "calling" file with the current position being the EOL character of */
+/* the include line. */
+p_ps_t p_ps;
+{
+ /* Complain if the include directive was not at the start of a line. */
+ if (p_ch-1 != p_sol)
+ {
+ lr_err(p_ps,"Include sequence must be at the beginning of a line.");
+ lr_mes(p_ps,"Include ignored.");
+ skiptoeol();
+ return;
+ }
+
+ /* The include command should be followed by a blank. Get the next char. */
+ NEXTCH;
+
+ /* Complain if the next character is not a blank. */
+ if (ch != ' ')
+ {
+ ps_t ps;
+ ASSIGN(ps,*p_ps);
+ ps.ps_column+=2;
+ lr_err(&ps,"Include sequence (@i) must be followed by a blank.");
+ lr_mes(&ps,"Example include: @i macros.fwi");
+ lr_mes(&ps,"Include ignored.");
+ skiptoeol();
+ return;
+ }
+
+ /* Complain if the include level is too high. */
+ if (inclevel == MAX_INCL)
+ {
+ lr_err(p_ps,"This include file is nested too deeply. It's probably recursive.");
+ sprintf(linet1,"The maximum level of nested includes is %u.",
+ (unsigned) MAX_INCL);
+ lr_mes(p_ps,linet1);
+ lr_mes(p_ps,"Include ignored.");
+ skiptoeol();
+ return;
+ }
+
+ {/* This construct does the work of the include. */
+ /* Warning: The following variables MUST be declared automatic. */
+ char *p_filename;
+ char *p_tempname;
+ /* ABC { */
+ char *p_oldname;
+ /* } ABC */
+ ulong length;
+ char *p;
+ ulong xinln_max;
+ char xspecial;
+ char *xp_eof;
+ ulong xlocalno;
+ char *xp_sol;
+ char *xp_ch;
+ char xch;
+
+ /* We save stack space by sticking this filename in the heap. */
+ p_filename=mm_temp((size_t) FILENAME_FWMAX+1+10); /* 10 is for paranoia. */
+ p_tempname=mm_temp((size_t) FILENAME_FWMAX+1+10); /* 10 is for paranoia. */
+ /* ABC { */
+ p_oldname=mm_temp((size_t) FILENAME_FWMAX+1+10); /* 10 is for paranoia. */
+ /* } ABC */
+
+ /* The rest of the line is supposed to hold a filename. Copy it. */
+ NEXTCH;
+ p=p_tempname;
+ length=0;
+ while (ch!=EOL)
+ {
+ if (++length > FILENAME_FWMAX)
+ {
+ lr_err(p_ps,
+ "This include command's file specification is too long.");
+ if (option.op_b7_b)
+ sprintf(linet1,"The maximum file name length is %s characters.",
+ SUPPVAL);
+ else
+ sprintf(linet1,"The maximum file name length is %u characters.",
+ (unsigned) FILENAME_FWMAX);
+ lr_mes(p_ps,linet1);
+ lr_mes(p_ps,"Include ignored.");
+ skiptoeol();
+ return;
+ }
+ *p++=ch;
+ NEXTCH;
+ }
+ *p=EOS;
+ /* Note: Current position is now on the EOL at the end of the @i line. */
+
+ /* Complain if the user has not specified a filename. */
+ if (strlen(p_tempname) ==0)
+ {
+ lr_err(psofch(),"Expecting the name of a file to include.");
+ return;
+ }
+
+ /* Perform the necessary filename inheritance. */
+ strcpy(p_filename,"");
+ fn_ins(p_filename,option.op_f_s);
+ fn_ins(p_filename,".fwi");
+ fn_ins(p_filename,option.op_i_s);
+ fn_ins(p_filename,p_tempname);
+
+ /* Include the included file by calling scan_file recursively. */
+ /* Save and restore all variables in instantiation scope. */
+ xinln_max = inln_max;
+ xspecial = specialch;
+ xp_eof = p_eof;
+ xlocalno = localno;
+ xp_sol = p_sol;
+ xp_ch = p_ch;
+ xch = ch;
+ inclevel++;
+
+ /* ABC { */
+ /* Store current filename */
+ strcpy(p_oldname, src_cur->fnam_name);
+ /* } ABC */
+
+ /* Scan include file */
+ scan_file(p_filename);
+
+ /* ABC { */
+ /* Restore previous filename */
+ fl_set(p_oldname);
+ /* } ABC */
+
+ inclevel--;
+ ch = xch;
+ p_ch = xp_ch;
+ p_sol = xp_sol;
+ localno = xlocalno;
+ p_eof = xp_eof;
+ specialch = xspecial;
+ inln_max = xinln_max;
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void do_ascii P_((p_ps_t));
+LOCAL void do_ascii(p_psspec)
+/* Upon entry, the current character is the '^' of a @^ sequence. The task is */
+/* to parse the following ascii code and generate a text token. */
+p_ps_t p_psspec;
+{
+ ubyte base; /* Base of the number we are scanning. */
+ ubyte digits; /* Number of digits expected. */
+ uword val; /* Value of target character. */
+ ubyte i; /* Looping variable. */
+ STAVAR char alphab[256]; /* Static alphabet array to which to point scraps. */
+ STAVAR bool init=FALSE; /* Tells if alphab has been initialized. */
+
+ /* Establish an array containing the ascii character set. Later on we can */
+ /* point the sc_first and sc_last pointers to particular characters. */
+ if (!init) {uword i; for (i=0;i<256;i++) alphab[i]=(char) i; init=TRUE;}
+
+ /* Make sure that the base character is legal. */
+ NEXTCH;
+ switch(toupper(ch))
+ {
+ case 'B': base= 2; digits=8; break;
+ case 'O':
+ case 'Q': base= 8; digits=3; break;
+ case 'D': base=10; digits=3; break;
+ case 'H':
+ case 'X': base=16; digits=2; break;
+ default : lr_err(psofch(),"Expecting one of 'B', 'Q', 'D', 'H'.");
+ lr_mes(psofch(),"(For Binary, Octal, Decimal, and Hexadecimal).");
+ base=10;
+ goto trouble;
+ }
+
+ /* Parse opening parenthesis. */
+ NEXTCH;
+ if (ch!='(')
+ {lr_err(psofch(),"Expecting '('.");goto trouble;}
+
+ val=0;
+ for (i=0;i<digits;i++)
+ {
+ char uch;
+ ubyte d;
+
+ NEXTCH;
+ uch=toupper(ch);
+ if (('0'<=uch) && (uch<='9'))
+ d=uch-'0';
+ else
+ if ('A'<=uch && uch<='F')
+ d=10+uch-'A';
+ else
+ d=100;
+ if (d>=base)
+ {lr_err(psofch(),"Illegal digit."); goto trouble;}
+ val = base*val + d;
+ }
+
+ /* Parse closing parenthesis. */
+ NEXTCH;
+ if (ch!=')')
+ {lr_err(psofch(),"Expecting ')'.");goto trouble;}
+
+ /* Make sure that the number is not too big (this is possible in decimal). */
+ if (val>255)
+ {
+ lr_err(psofch(),"Character number is too large.");
+ lr_mes(psofch(),"Character number must be in the range [0,255] (decimal).");
+ goto trouble;
+ }
+
+ /* Success! Now we can parcel it up into a scrap! */
+ sendtext(p_psspec,&alphab[val],&alphab[val],ch==' ' || ch==EOL);
+ return;
+
+ trouble:
+ /* Jump here after a specific diagnostic to give the user a reminder of */
+ /* how to specify an ascii character constant. */
+ switch (base)
+ {
+ case 2:
+ lr_mes(psofch(),
+ "A binary character representation takes the form \"@^B(dddddddd)\".");
+ lr_mes(psofch(),
+ "(exactly 8 digits) where each digit d is either 0 or 1.");
+ break;
+ case 8:
+ lr_mes(psofch(),
+ "An octal character representation takes the form \"@^Q(ddd)\" (or \"@^O(ddd)\").");
+ lr_mes(psofch(),
+ "(exactly 3 digits) where each digit d is in the range 0..7.");
+ break;
+ case 10:
+ lr_mes(psofch(),
+ "A decimal character representation takes the form \"@^D(ddd)\".");
+ lr_mes(psofch(),
+ "(exactly 3 digits) where each digit d is in the range 0..9.");
+ break;
+ case 16:
+ lr_mes(psofch(),
+ "A hexadecimal character representation takes the form \"@^X(dd)\" (or \"@^H(dd)\").");
+ lr_mes(psofch(),
+ "(exactly 2 digits) where each digit d is in the range 0..9,A..F.");
+ break;
+ default: as_bomb("do_ascii: trouble base switch defaulted.");
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void do_name P_((p_ps_t));
+LOCAL void do_name (p_psspec)
+/* Upon entry, the current character is the # of a @#. The task is to parse */
+/* it and transmit a name token. */
+p_ps_t p_psspec;
+{
+ as_cold(ch=='#',"do_name: character is wrong.");
+ NEXTCH;
+ if ((ch==EOL) || (ch==' '))
+ {lr_err(psofch(),"Expecting a printable character."); return;}
+
+ /* Transmit a name token. */
+ sendspec(p_psspec,TK_NAME,(ubyte) ch);
+}
+
+/******************************************************************************/
+
+LOCAL void do_pgind P_((uword,p_pt_t));
+LOCAL void do_pgind(numarg,arg)
+/* Parse an indentation pragma. */
+uword numarg;
+p_pt_t arg;
+{
+ bool pragind;
+ ps_t psprag;
+
+ /* Make sure that there are exactly three arguments. */
+ if (numarg != 3) /* "indentation" "none|blank". */
+ {
+ lr_err(&arg[0].pt_ps,
+ "This indentation pragma has the wrong number of arguments.");
+ goto help;
+ }
+
+ /* Make sure that the second argument is an "=". */
+ if (0 != strcmp(arg[2].pt_pstr,"="))
+ {
+ lr_err(&arg[2].pt_ps,"Expecting \"=\".");
+ goto help;
+ }
+
+ /* Check the third argument. */
+ if (strcmp(arg[3].pt_pstr,"none" )==0) pragind=FALSE;
+ else if (strcmp(arg[3].pt_pstr,"blank")==0) pragind=TRUE;
+ else
+ {
+ lr_err(&arg[3].pt_ps,"Expecting either \"none\" or \"blank\".");
+ goto help;
+ }
+
+ /* Construct a shorthand for the start of the pragma. */
+ ASSIGN(psprag,arg[0].pt_ps);
+
+ /* Make sure that the pragma does not contradict an earlier pragma. */
+ if (seenind && (tgindent!=pragind))
+ {
+ sprintf(linet1,"This pragma is opposed by the pragma at line %lu.",
+ (unsigned long) psprag.ps_line);
+ lr_mes(&ps_ind,linet1);
+ sprintf(linet1,"This pragma opposes the pragma at line %lu.",
+ (unsigned long) ps_ind.ps_line);
+ lr_err(&psprag,linet1);
+ lr_mes(&psprag,"You can have as many indentation pragmas as you like,");
+ lr_mes(&psprag,"but they all have to be the same!");
+ lr_mes(&psprag,"Pragma ignored.");
+ return;
+ }
+
+ /* Success: Record the pragma information. */
+ seenind = TRUE; /* Record that we have seen a pragma. */
+ tgindent = pragind; /* Record what the pragma said. */
+ ASSIGN(ps_ind,psprag); /* Record where the pragma was. */
+ return;
+
+ help:
+ lr_mes(&arg[0].pt_ps,
+ "The correct format is: \"@p indentation = none|blank\".");
+ lr_mes(&arg[0].pt_ps,"Pragma ignored.");
+ return;
+}
+
+/******************************************************************************/
+
+LOCAL void do_pginl P_((uword,p_pt_t));
+LOCAL void do_pginl(numarg,arg)
+/* Parse a maximum input line length pragma. */
+uword numarg;
+p_pt_t arg;
+{
+ char *numstr;
+ uword spn;
+
+ /* Make sure that there are exactly three arguments. */
+ if (numarg != 3) /* "max..length = <num>". */
+ {
+ lr_err(&arg[0].pt_ps,"This pragma has the wrong number of arguments.");
+ goto help;
+ }
+
+ /* Make sure that the second argument is "=". */
+ if (0 != strcmp(arg[2].pt_pstr,"="))
+ {lr_err(&arg[2].pt_ps,"Expecting \"=\"."); goto help;}
+
+ /* Set up an abbreviation. */
+ numstr=arg[3].pt_pstr;
+
+ /* See if the value is "infinity". */
+ if (strcmp(numstr,"infinity")==0)
+ {inln_max=INMAXINF; return;}
+
+ /* Calculate length of longest prefix containing all decimal digits. */
+ /* Check that there are no illegal digits. */
+ spn=strspn(numstr,"0123456789");
+ if (spn != strlen(numstr))
+ {
+ ps_t ps;
+ ASSIGN(ps,arg[3].pt_ps);
+ ps.ps_column+=spn;
+ lr_err(&ps,"Illegal digit. Value must consist entirely of decimal digits.");
+ lr_mes(&ps,"You can also use the value \"infinity\".");
+ lr_mes(&ps,"Pragma ignored.");
+ return;
+ }
+
+ /* Check that the number is not too long. */
+ if (strlen(numstr)>8)
+ {
+ lr_err(&arg[3].pt_ps,"Too many digits. The maximum is eight.");
+ lr_mes(&arg[3].pt_ps,"Pragma ignored.");
+ return;
+ }
+
+ /* Convert the argument into an integer. */
+ {
+ ulong val;
+ int result;
+ /* Note: Should really be %lu, but the Vax doesn't know about the %u */
+ /* in sscanf and so we make do with %ld. */
+ result=sscanf(numstr,"%ld",&val);
+ as_cold(result==1,"do_pginl:sscanf failed.");
+ inln_max=val;
+ }
+ return;
+
+ help:
+ lr_mes(&arg[0].pt_ps,
+ "The correct format is: \"@p maximum_input_line_length = <num>|infinity\".");
+ lr_mes(&arg[0].pt_ps,"Pragma ignored.");
+ return;
+}
+
+/******************************************************************************/
+
+LOCAL void do_pgotl P_((uword,p_pt_t));
+LOCAL void do_pgotl(numarg,arg)
+/* Parse a maximum product file line length pragma. */
+uword numarg;
+p_pt_t arg;
+{
+ char *numstr;
+ uword spn;
+ ulong val;
+ ps_t psprag;
+
+ /* Set up an abbreviation. */
+ ASSIGN(psprag,arg[0].pt_ps);
+
+ /* Make sure that there are exactly three arguments. */
+ if (numarg != 3) /* "max..length" "=" "value". */
+ {
+ lr_err(&arg[0].pt_ps,"This pragma has the wrong number of arguments.");
+ goto help;
+ }
+
+ /* Make sure that the second argument is an "=". */
+ if (0 != strcmp(arg[2].pt_pstr,"="))
+ {lr_err(&arg[2].pt_ps,"Expecting \"=\"."); goto help;}
+
+ /* Set up an abbreviation. */
+ numstr=arg[3].pt_pstr;
+
+ /* See if the value is "infinity". */
+ if (strcmp(numstr,"infinity")==0)
+ {val=TGMAXINF; goto gotvalue;}
+
+ /* Calculate length of longest prefix containing all decimal digits. */
+ /* Check that there are no illegal digits. */
+ spn=strspn(numstr,"0123456789");
+ if (spn != strlen(numstr))
+ {
+ ps_t ps;
+ ASSIGN(ps,arg[3].pt_ps);
+ ps.ps_column+=spn;
+ lr_err(&ps,"Illegal digit. Value must consist entirely of decimal digits.");
+ lr_mes(&ps,"You can also use the value \"infinity\".");
+ lr_mes(&ps,"Pragma ignored.");
+ return;
+ }
+
+ /* Check that the number is not too long. */
+ if (strlen(numstr)>8)
+ {
+ lr_err(&arg[3].pt_ps,"Too many digits. The maximum is eight.");
+ lr_mes(&arg[3].pt_ps,"Pragma ignored.");
+ return;
+ }
+
+ /* Convert the argument into an integer. */
+ {
+ int result=sscanf(numstr,"%ld",&val);
+ as_cold(result==1,"do_pgotl:sscanf failed.");
+ }
+
+ gotvalue:
+ /* Make sure that the pragma does not contradict an earlier pragma. */
+ if (seenlimo && (tglinmax!=val))
+ {
+ sprintf(linet1,"This pragma is opposed by the pragma at line %lu.",
+ (unsigned long) psprag.ps_line);
+ lr_mes(&ps_limo,linet1);
+ sprintf(linet1,"This pragma opposes the pragma at line %lu.",
+ (unsigned long) ps_limo.ps_line);
+ lr_err(&psprag,linet1);
+ lr_mes(&psprag,"You can have as many output line length pragmas");
+ lr_mes(&psprag,"as you like, but they all have to be the same!");
+ lr_mes(&psprag,"Pragma ignored.");
+ return;
+ }
+
+ /* If we got this far then the pragma is just the same as an earlier one. */
+ /* We don't want to set the pragma position to the later pragma so we */
+ /* return now. */
+ if (seenlimo) return;
+
+ /* Success. Set the variables. */
+ tglinmax=val;
+ seenlimo=TRUE;
+ ASSIGN(ps_limo,psprag);
+ return;
+
+ help:
+ lr_mes(&arg[0].pt_ps,
+ "The correct format is: \"@p maximum_output_line_length = <num>|infinity\".");
+ lr_mes(&arg[0].pt_ps,"Pragma ignored.");
+ return;
+}
+
+/******************************************************************************/
+
+LOCAL void do_pgnpg P_((uword,p_pt_t));
+LOCAL void do_pgnpg(numarg,arg)
+/* Parse a newpage typesetter directive. */
+uword numarg;
+p_pt_t arg;
+{
+ /* Make sure that there is exactly one argument. */
+ if (numarg > 1) /* "new_page" */
+ {
+ lr_err(&arg[2].pt_ps,"The new_page directive does not take arguments.");
+ lr_mes(&arg[2].pt_ps,"Directive ignored.");
+ return;
+ }
+ sendspec(&arg[0].pt_ps,TK_NPAG,DONTCARE);
+}
+
+/******************************************************************************/
+
+LOCAL void do_pgtoc P_((uword,p_pt_t));
+LOCAL void do_pgtoc(numarg,arg)
+/* Parse a table of contents typesetter directive. */
+uword numarg; /* Number of arguments to table of contents directive. */
+p_pt_t arg; /* Array describing arguments. */
+{
+ /* Make sure that there is exactly one argument. */
+ if (numarg > 1) /* "table_of_contents" */
+ {
+ lr_err(&arg[2].pt_ps,
+ "The table_of_contents directive does not take arguments.");
+ lr_mes(&arg[2].pt_ps,"Directive ignored.");
+ return;
+ }
+ sendspec(&arg[0].pt_ps,TK_TOCS,DONTCARE);
+}
+
+/******************************************************************************/
+
+LOCAL void do_pgvsk P_((uword,p_pt_t));
+LOCAL void do_pgvsk(numarg,arg)
+/* Parse a vskip typesetter directive. */
+uword numarg; /* Number of arguments to indentation directive. */
+p_pt_t arg; /* Array describing arguments. */
+{
+ char *numstr;
+ uword spn;
+
+ /* Make sure that there are exactly three arguments. */
+ if (numarg != 3) /* "vskip" n "mm". */
+ {
+ lr_err(&arg[0].pt_ps,"This directive has the wrong number of arguments.");
+ goto help;
+ }
+
+ /* Make sure that the third argument is "mm". */
+ if (0 != strcmp(arg[3].pt_pstr,"mm"))
+ {lr_err(&arg[3].pt_ps,"Expecting \"mm\"."); goto help;}
+
+ /* Set up an abbreviation. */
+ numstr=arg[2].pt_pstr;
+
+ /* Calculate length of longest prefix containing all decimal digits. */
+ /* Check that there are no illegal digits. */
+ spn=strspn(numstr,"0123456789");
+ if (spn != strlen(numstr))
+ {
+ ps_t ps;
+ ASSIGN(ps,arg[2].pt_ps);
+ ps.ps_column+=spn;
+ lr_err(&ps,"Illegal digit.");
+ lr_mes(&ps,"Value must consist entirely of decimal digits.");
+ lr_mes(&ps,"Directive ignored.");
+ return;
+ }
+
+ /* Check that the number is not too long. */
+ if (strlen(numstr)>3)
+ {
+ lr_err(&arg[2].pt_ps,"Too many digits. The maximum is three.");
+ lr_mes(&arg[2].pt_ps,"Directive ignored.");
+ return;
+ }
+
+ /* Convert the argument into an integer. */
+ {
+ ulong val;
+ int result;
+ result=sscanf(numstr,"%ld",&val);
+ as_cold(result==1,"do_pginl:sscanf failed.");
+ if (val>255)
+ {
+ lr_err(&arg[2].pt_ps,"Value too large. Maximum is 255.");
+ lr_mes(&arg[2].pt_ps,"Directive ignored.");
+ return;
+ }
+ sendspec(&arg[0].pt_ps,TK_SKIP,(ubyte) val);
+ }
+ return;
+
+ help:
+ lr_mes(&arg[0].pt_ps,"The correct format is: \"@t vskip <num> mm\".");
+ lr_mes(&arg[0].pt_ps,"Directive ignored.");
+ return;
+}
+
+/******************************************************************************/
+
+LOCAL void do_pgtit P_((uword,p_pt_t));
+LOCAL void do_pgtit(numarg,arg)
+/* Parse a title typesetter directive. */
+uword numarg; /* Number of arguments to title directive. */
+p_pt_t arg; /* Array describing arguments. */
+{
+ uword align;
+ uword font;
+ char *p_sot,*p_eot;
+
+ /* Make sure that there are at least three arguments. */
+ if (numarg < 4) /* "title <font> <align> <text>". */
+ {lr_err(&arg[0].pt_ps,"This directive has too few arguments."); goto help;}
+
+ /* Check the font argument. */
+ if (strcmp(arg[2].pt_pstr,"normalfont" )==0) font=FT_NORM;
+ else if (strcmp(arg[2].pt_pstr,"titlefont" )==0) font=FT_TITL;
+ else if (strcmp(arg[2].pt_pstr,"smalltitlefont")==0) font=FT_STIT;
+ else
+ {
+ lr_err(&arg[2].pt_ps,
+ "Expecting one of {titlefont,smalltitlefont,normalfont}.");
+ lr_mes(&arg[2].pt_ps,"Directive ignored.");
+ return;
+ }
+
+ /* Check the alignment argument. */
+ if (strcmp(arg[3].pt_pstr,"left" )==0) align=LR_LEFT;
+ else if (strcmp(arg[3].pt_pstr,"right" )==0) align=LR_RIGH;
+ else if (strcmp(arg[3].pt_pstr,"centre")==0) align=LR_CENT;
+ else
+ {
+ lr_err(&arg[3].pt_ps,"Expecting one of {left,right,centre}.");
+ if (strcmp(arg[3].pt_pstr,"center")==0)
+ {
+ lr_mes(&arg[3].pt_ps,"Note: Centre is spelt centRE, not centER.");
+ lr_mes(&arg[3].pt_ps," This is my revenge for years of getting error messages");
+ lr_mes(&arg[3].pt_ps," from TeX whenever I accidentally wrote \\centreline - Ross Williams.");
+ }
+ lr_mes(&arg[3].pt_ps,"Directive ignored.");
+ return;
+ }
+
+ /* Now make sure that the remainder of the line is delimited by quotes. */
+ p_sot=arg[4].pt_pinl;
+ p_eot=p_sot+strlen(p_sot)-1;
+ if (*p_sot!='"' || *p_eot!='"' || p_sot==p_eot)
+ {
+ lr_err(&arg[4].pt_ps,"Text argument must be delimited by double quotes.");
+ lr_mes(&arg[4].pt_ps,"Directive ignored.");
+ return;
+ }
+ p_sot++; p_eot--;
+
+ /* Ship out a token whose fields are all fully laden. */
+ {
+ tk_t token;
+ token.tk_kind = TK_TITL;
+ ASSIGN(token.tk_ps,arg[0].pt_ps);
+ token.tk_sc.sc_first = p_sol+ (3+(p_sot-arg[1].pt_pinl));
+ token.tk_sc.sc_last = p_sol+ (3+(p_eot-arg[1].pt_pinl));
+ token.tk_sc.sc_white = FALSE;
+ token.tk_gen = LRFT_PACK*font+align;
+ ls_add(token_list,PV &token);
+ }
+ return;
+
+ help:
+ lr_mes(&arg[0].pt_ps,
+ "The correct format is: \"@t title <font> <align> <text>\".");
+ lr_mes(&arg[0].pt_ps,
+ " where <font> = titlefont | smalltitlefont | normalfont.");
+ lr_mes(&arg[0].pt_ps,
+ " and <align> = left | centre | right.");
+ lr_mes(&arg[0].pt_ps,
+ " and <text> = text delimited by double quotes.");
+ lr_mes(&arg[0].pt_ps,"Directive ignored.");
+ return;
+}
+
+/******************************************************************************/
+
+LOCAL void do_pgtyp P_((uword,p_pt_t));
+LOCAL void do_pgtyp(numarg,arg)
+/* Parse a typesetter pragma. */
+uword numarg;
+p_pt_t arg;
+{
+ tr_k_t pragtyp;
+ ps_t psprag;
+
+ /* Make sure that there are exactly three arguments. */
+ if (numarg != 3) /* "typesetter" "=" "name". */
+ {
+ lr_err(&arg[0].pt_ps,
+ "This typesetter pragma has the wrong number of arguments.");
+ goto help;
+ }
+
+ /* Make sure that the second argument is "=". */
+ if (0 != strcmp(arg[2].pt_pstr,"="))
+ {
+ lr_err(&arg[2].pt_ps,"Expecting \"=\".");
+ goto help;
+ }
+
+ /* Check the third argument. */
+ if (strcmp(arg[3].pt_pstr,"none")==0) pragtyp=TR_NONE;
+ else if (strcmp(arg[3].pt_pstr,"tex" )==0) pragtyp=TR_TEX;
+ /* ABC { */
+ else if (strcmp(arg[3].pt_pstr,"hypertext" )==0) pragtyp=TR_HTXT;
+ else if (strcmp(arg[3].pt_pstr,"html" )==0) pragtyp=TR_HTML;
+ /* } ABC */
+ else
+ {
+ /* ABC { */
+ lr_err(&arg[3].pt_ps,"Expecting one of:");
+ lr_err(&arg[3].pt_ps," (i) \"none\"");
+ lr_err(&arg[3].pt_ps," (ii) \"tex\"");
+ lr_err(&arg[3].pt_ps," (iii) \"hypertext\"");
+ lr_err(&arg[3].pt_ps," (iv) \"html\".");
+ /* } ABC */
+ goto help;
+ }
+
+ /* Construct a shorthand for the start of the pragma. */
+ ASSIGN(psprag,arg[0].pt_ps);
+
+ /* Make sure that the pragma does not contradict an earlier pragma. */
+ if (seentyp && (tr_codes != pragtyp))
+ {
+ sprintf(linet1,"This pragma is opposed by the pragma at line %lu.",
+ (unsigned long) psprag.ps_line);
+ lr_mes(&ps_typ,linet1);
+ sprintf(linet1,"This pragma opposes the pragma at line %lu.",
+ (unsigned long) ps_typ.ps_line);
+ lr_err(&psprag,linet1);
+ lr_mes(&psprag,"You can have as many typesetter pragmas as you like,");
+ lr_mes(&psprag,"but they all have to be the same!");
+ lr_mes(&psprag,"Pragma ignored.");
+ return;
+ }
+
+ /* Success: Record the pragma information. */
+ seentyp = TRUE; /* Record that we have seen a pragma. */
+ tr_codes = pragtyp; /* Record what the pragma said. */
+ ASSIGN(ps_typ,psprag); /* Record where the pragma was. */
+ return;
+
+ help:
+ /* ABC { */
+ lr_mes(&arg[0].pt_ps,
+ "The correct format is: \"@p typesetter = none|tex\"");
+ lr_mes(&arg[0].pt_ps,
+ " or for hypertext \"@p typesetter = hypertext|html\".");
+ /* } ABC */
+ lr_mes(&arg[0].pt_ps,"Pragma ignored.");
+ return;
+}
+
+/* ABC { */
+/******************************************************************************/
+
+LOCAL void do_pgnoh P_((uword,p_pt_t));
+LOCAL void do_pgnoh(numarg,arg)
+/* Parse a no_doc_header pragma. */
+uword numarg;
+p_pt_t arg;
+{
+ /* Make sure that there is exactly one arguments. */
+ if (numarg != 1) /* "no_doc_header". */
+ {
+ lr_err(&arg[0].pt_ps,
+ "This no_doc_header pragma has the wrong number of arguments.");
+ goto help;
+ }
+
+ /* Success: set the value of doc_incQ. */
+ doc_incQ = FALSE;
+ return;
+
+ help:
+ lr_mes(&arg[0].pt_ps,
+ "The correct format is: \"@p no_doc_header\".");
+ lr_mes(&arg[0].pt_ps,"Pragma ignored.");
+ return;
+}
+
+/******************************************************************************/
+
+LOCAL void do_pgraw P_((uword,p_pt_t));
+LOCAL void do_pgraw(numarg,arg)
+/* Parse a raw_macro_and_section_names pragma. */
+uword numarg;
+p_pt_t arg;
+{
+ /* Make sure that there is exactly one argument. */
+ if (numarg != 1) /* "raw_macro_and_section_names". */
+ {
+ lr_err(&arg[0].pt_ps,
+ "This raw_macro_and_section_names pragma has the wrong number of arguments.");
+ goto help;
+ }
+
+ /* Success: set the value of raw_namQ. */
+ raw_namQ = TRUE;
+ return;
+
+ help:
+ lr_mes(&arg[0].pt_ps,
+ "The correct format is: \"@p raw_macro_and_section_names\".");
+ lr_mes(&arg[0].pt_ps,"Pragma ignored.");
+ return;
+}
+
+/******************************************************************************/
+
+LOCAL void do_pgign P_((uword,p_pt_t));
+LOCAL void do_pgign(numarg,arg)
+/* Parse an ignore_text_after_special_minus pragma. */
+uword numarg;
+p_pt_t arg;
+{
+ /* Make sure that there is exactly one argument. */
+ if (numarg != 1) /* "ignore_text_after_special_minus". */
+ {
+ lr_err(&arg[0].pt_ps,
+ "This ignore_text_after_special_minus pragma has the wrong number of arguments.");
+ goto help;
+ }
+
+ /* Success: set the value of raw_namQ. */
+ igntxtQ = TRUE;
+ return;
+
+ help:
+ lr_mes(&arg[0].pt_ps,
+ "The correct format is: \"@p ignore_text_after_special_minus\".");
+ lr_mes(&arg[0].pt_ps,"Pragma ignored.");
+ return;
+}
+
+/******************************************************************************/
+
+LOCAL void do_pgnpm P_((uword,p_pt_t));
+LOCAL void do_pgnpm(numarg,arg)
+/* Parse a no_paragraph_markups pragma. */
+uword numarg;
+p_pt_t arg;
+{
+ /* Make sure that there is exactly one argument. */
+ if (numarg != 1) /* "no_paragraph_markups". */
+ {
+ lr_err(&arg[0].pt_ps,
+ "This no_paragraph_markups pragma has the wrong number of arguments.");
+ goto help;
+ }
+
+ /* Success: set the value of no_pmrkQ. */
+ no_pmrkQ = TRUE;
+ return;
+
+ help:
+ lr_mes(&arg[0].pt_ps,
+ "The correct format is: \"@p no_paragraph_markups\".");
+ lr_mes(&arg[0].pt_ps,"Pragma ignored.");
+ return;
+}
+
+/******************************************************************************/
+
+LOCAL void do_pgasct P_((uword,p_pt_t));
+LOCAL void do_pgasct(numarg,arg)
+/* Allow source code typing. */
+uword numarg;
+p_pt_t arg;
+{
+
+ /* Make sure that there is exactly one arguments. */
+ if (numarg != 1) /* "allow_source_code_typing".
+ */
+ {
+ lr_err(&arg[0].pt_ps,"This pragma has the wrong number of arguments.");
+ goto help;
+ }
+ xsrctypesQ = TRUE;
+ return;
+
+ help:
+ lr_mes(&arg[0].pt_ps,
+ "The correct format is: '@p declare_source_code_type \"<name>\"'.");
+ lr_mes(&arg[0].pt_ps,"Pragma ignored.");
+ return;
+}
+
+/******************************************************************************/
+
+LOCAL void do_pgdsrc P_((uword,p_pt_t));
+LOCAL void do_pgdsrc(numarg,arg)
+/* Define a user defined source code type. */
+uword numarg;
+p_pt_t arg;
+{
+ char *srcname, *tmp, *clpos;
+ p_srcnmac_t nexttype;
+ srcnmac_t newtype;
+ bool undefinedQ = TRUE;
+
+ /* Make sure that there are exactly two arguments. */
+ if (numarg != 2) /* "declare_source_code_type" "\"name\"".
+ */
+ {
+ lr_err(&arg[0].pt_ps,"This pragma has the wrong number of arguments.");
+ goto help;
+ }
+ /* Are extra source code types allowed? */
+ if (!xsrctypesQ) {
+ lr_err(&arg[0].pt_ps,"A pragma is required to allow source code types.");
+ goto help;
+ } /* end if */
+
+ /* Parse the name of the source type name. */
+ srcname = arg[2].pt_pstr;
+ /* Check for opening quotes surrounding macro name. */
+ if (*srcname != '"') {
+ lr_err(&arg[2].pt_ps,"Expecting opening \".");
+ goto help;
+ } /* end if */
+ /* Check for closing quotes at end of macro name. *
+ * Double quotes can be used in the macro name by *
+ * escaping them with a backslash. */
+ tmp = srcname + 1;
+ for (;;) { /* forever */
+ clpos = strchr(tmp, '"');
+ if (clpos == NULL) {
+ lr_err(&arg[2].pt_ps,"Can't find closing \".");
+ goto help;
+ } /* end if */
+ if (*(clpos+1) == (char)0) break; /* Quotes are at end. OK. */
+ if (*(clpos-1) == '\\') {
+ /* Quotes are quoted into string using backslash. */
+ tmp = clpos + 1;
+ continue; /* Keep searching. */
+ } /* end if */
+ /* Quotes must have text after them. This is bad. */
+ lr_err(&arg[2].pt_ps,"Extraneous text after closing \".");
+ goto help;
+ } /* end forever */
+ /* Check that source type name is unique. */
+ if (strlen(srcname) <= 2) {
+ lr_err(&arg[2].pt_ps,"Length of source type name must be >=1.");
+ goto help;
+ } /* end if */
+ ls_fir(srctlist);
+ for (;;) { /* forever */
+ ls_nxt(srctlist, (pp_lsel_t)&nexttype);
+ if (nexttype == NULL) break;
+ if (nexttype->typnam == NULL) continue;
+ if (!strncmp(nexttype->typnam, srcname+1, strlen(srcname)-2)) {
+ undefinedQ = FALSE;
+ } /* end if */
+ } /* end forever */
+ if (undefinedQ) {
+ newtype.typnam =
+ mm_temp((size_t) (strlen(srcname)-1)*sizeof(char));
+ strncpy(newtype.typnam, srcname+1, strlen(srcname)-2);
+ newtype.lnmac = NULL;
+ ls_add(srctlist, (p_lsel_t)&newtype);
+ } /* end if */
+ return;
+
+ help:
+ lr_mes(&arg[0].pt_ps,
+ "The correct format is: '@p declare_source_code_type \"<name>\"'.");
+ lr_mes(&arg[0].pt_ps,"Pragma ignored.");
+ return;
+}
+
+/******************************************************************************/
+
+LOCAL void do_pgaldm P_((uword,p_pt_t));
+LOCAL void do_pgaldm(numarg,arg)
+/* Parse an automatic line directive macro pragma. */
+uword numarg;
+p_pt_t arg;
+{
+ char *autoname, *srcname, *tmp, *clpos;
+ p_srcnmac_t nexttype;
+
+ /* Make sure that there are three or four arguments. */
+ if ((numarg != 3) && (numarg != 4))
+ /* "automatic_line_directive_macro" "=" "\"name\"" or. *
+ * "automatic_line_directive_macro" "=" "\"name\"" "\"srctype\"" */
+ {
+ lr_err(&arg[0].pt_ps,"This pragma has the wrong number of arguments.");
+ goto help;
+ }
+
+ /* Make sure that the second argument is an "=". */
+ if (0 != strcmp(arg[2].pt_pstr,"="))
+ {lr_err(&arg[2].pt_ps,"Expecting \"=\"."); goto help;}
+
+ /* Parse the name of the automatic line call macro. */
+ autoname = arg[3].pt_pstr;
+ /* Check for opening quotes surrounding macro name. */
+ if (*autoname != '"') {
+ lr_err(&arg[3].pt_ps,"Expecting opening \".");
+ goto help;
+ } /* end if */
+ /* Check for closing quotes at end of macro name. *
+ * Double quotes can be used in the macro name by *
+ * escaping them with a backslash. */
+ tmp = autoname + 1;
+ for (;;) { /* forever */
+ clpos = strchr(tmp, '"');
+ if (clpos == NULL) {
+ lr_err(&arg[3].pt_ps,"Can't find closing \".");
+ goto help;
+ } /* end if */
+ if (*(clpos+1) == (char)0) break; /* Quotes are at end. OK. */
+ if (*(clpos-1) == '\\') {
+ /* Quotes are quoted into string using backslash. */
+ tmp = clpos + 1;
+ continue; /* Keep searching. */
+ } /* end if */
+ /* Quotes must have text after them. This is bad. */
+ lr_err(&arg[3].pt_ps,"Extraneous text after closing \".");
+ goto help;
+ } /* end forever */
+ if (numarg == 4) {
+ /* Parse the name of the source code type. */
+ srcname = arg[4].pt_pstr;
+ /* Check for opening quotes surrounding source type name. */
+ if (*srcname != '"') {
+ lr_err(&arg[4].pt_ps,"Expecting opening \".");
+ goto help;
+ } /* end if */
+ /* Check for closing quotes at end of source type name. *
+ * Double quotes can be used in the macro name by *
+ * escaping them with a backslash. */
+ tmp = srcname + 1;
+ for (;;) { /* forever */
+ clpos = strchr(tmp, '"');
+ if (clpos == NULL) {
+ lr_err(&arg[4].pt_ps,"Can't find closing \".");
+ goto help;
+ } /* end if */
+ if (*(clpos+1) == (char)0) break; /* Quotes are at end. OK. */
+ if (*(clpos-1) == '\\') {
+ /* Quotes are quoted into string using backslash. */
+ tmp = clpos + 1;
+ continue; /* Keep searching. */
+ } /* end if */
+ /* Quotes must have text after them. This is bad. */
+ lr_err(&arg[4].pt_ps,"Extraneous text after closing \".");
+ goto help;
+ } /* end forever */
+ if (strlen(srcname) <= 2) {
+ lr_err(&arg[4].pt_ps,"Length of source code type name must be >= 1.");
+ goto help;
+ } /* end if */
+ } else {
+ srcname = NULL;
+ } /* end if */
+
+ ls_fir(srctlist);
+ ls_nxt(srctlist, (pp_lsel_t)&nexttype);
+ if (srcname != NULL) {
+ for (
+ ;
+ nexttype != NULL;
+ ls_nxt(srctlist, (pp_lsel_t)&nexttype)
+ ) {
+ if (nexttype->typnam == NULL) continue;
+ if (!strncmp(nexttype->typnam, srcname+1, strlen(srcname)-2))
+ break;
+ } /* end for */
+ if (nexttype == NULL) {
+ lr_err(&arg[4].pt_ps,"Source code type not declared.");
+ goto help;
+ } /* end if */
+ } /* end if */
+ if (nexttype->lnmac != NULL) {
+ lr_err(&arg[4].pt_ps,"Automatic line insertion macro already defined for source code type.");
+ goto help;
+ } /* end if */
+ nexttype->lnmac =
+ mm_temp((size_t) (strlen(autoname)-1)*sizeof(char));
+ strncpy(nexttype->lnmac, autoname+1, strlen(autoname)-2);
+ return;
+
+ help:
+ lr_mes(&arg[0].pt_ps,
+ "The correct format is: '@p automatic_line_directive_macro = \"<name>\"'.");
+ lr_mes(&arg[0].pt_ps,
+ " or: '@p automatic_line_directive_macro = \"<name>\" \"<srctype>\"'.");
+ lr_mes(&arg[0].pt_ps,"Pragma ignored.");
+ return;
+}
+
+/******************************************************************************/
+
+LOCAL void do_pglof P_((uword,p_pt_t));
+LOCAL void do_pglof(numarg,arg)
+/* Parse a #line offset pragma. */
+uword numarg;
+p_pt_t arg;
+{
+ char *numstr;
+ uword spn;
+ ulong val;
+
+ /* Make sure that there are exactly three arguments. */
+ if (numarg != 3) /* "#line_offset" "=" "value". */
+ {
+ lr_err(&arg[0].pt_ps,"This pragma has the wrong number of arguments.");
+ goto help;
+ }
+
+ /* Make sure that the second argument is an "=". */
+ if (0 != strcmp(arg[2].pt_pstr,"="))
+ {lr_err(&arg[2].pt_ps,"Expecting \"=\"."); goto help;}
+
+ /* Set up an abbreviation. */
+ numstr=arg[3].pt_pstr;
+
+ /* Calculate length of longest prefix containing all decimal digits. */
+ /* A leading minus sign is also permissible. */
+ /* Check that there are no illegal digits, etc. */
+ spn=strspn(numstr,"0123456789");
+ if ((spn != strlen(numstr)) && (strchr("-",numstr[0]) != NULL))
+ {
+ spn=strspn(numstr+1,"0123456789")+1;
+ }
+ if (spn != strlen(numstr))
+ {
+ ps_t ps;
+ ASSIGN(ps,arg[3].pt_ps);
+ ps.ps_column+=spn;
+ lr_err(&ps,"Illegal digit. Value must consist entirely of decimal digits.");
+ lr_mes(&ps,"A leading \"-\" is also permitted.");
+ lr_mes(&ps,"You can also use the value \"infinity\".");
+ lr_mes(&ps,"Pragma ignored.");
+ return;
+ }
+
+ /* Check that the number is not too long. */
+ if (strlen(numstr)>4)
+ {
+ lr_err(&arg[3].pt_ps,"Too many digits. The maximum is four.");
+ lr_mes(&arg[3].pt_ps,"Pragma ignored.");
+ return;
+ }
+
+ /* Convert the argument into an integer. */
+ {
+ int result=sscanf(numstr,"%ld",&val);
+ as_cold(result==1,"do_pglof:sscanf failed.");
+ }
+
+ /* Success. Set the global variable. */
+ lin_off=(word)val;
+ return;
+
+ help:
+ lr_mes(&arg[0].pt_ps,
+ "The correct format is: \"@p #line_offset = <num>\".");
+ lr_mes(&arg[0].pt_ps,"Pragma ignored.");
+ return;
+}
+
+/******************************************************************************/
+
+LOCAL void do_pgldp P_((uword,p_pt_t));
+LOCAL void do_pgldp(numarg,arg)
+/* Parse a #line depth pragma. */
+uword numarg;
+p_pt_t arg;
+{
+ char *numstr;
+ uword spn;
+ ulong val;
+
+ /* Make sure that there are exactly three arguments. */
+ if (numarg != 3) /* "#line_depth" "=" "value". */
+ {
+ lr_err(&arg[0].pt_ps,"This pragma has the wrong number of arguments.");
+ goto help;
+ }
+
+ /* Make sure that the second argument is an "=". */
+ if (0 != strcmp(arg[2].pt_pstr,"="))
+ {lr_err(&arg[2].pt_ps,"Expecting \"=\"."); goto help;}
+
+ /* Set up an abbreviation. */
+ numstr=arg[3].pt_pstr;
+
+ /* Calculate length of longest prefix containing all decimal digits. */
+ /* Check that there are no illegal digits, etc. */
+ spn=strspn(numstr,"0123456789");
+ if (spn != strlen(numstr))
+ {
+ ps_t ps;
+ ASSIGN(ps,arg[3].pt_ps);
+ ps.ps_column+=spn;
+ lr_err(&ps,"Illegal digit. Value must consist entirely of decimal digits.");
+ lr_mes(&ps,"You can also use the value \"infinity\".");
+ lr_mes(&ps,"Pragma ignored.");
+ return;
+ }
+
+ /* Check that the number is not too long. */
+ if (strlen(numstr)>4)
+ {
+ lr_err(&arg[3].pt_ps,"Too many digits. The maximum is four.");
+ lr_mes(&arg[3].pt_ps,"Pragma ignored.");
+ return;
+ }
+
+ /* Convert the argument into an integer. */
+ {
+ int result=sscanf(numstr,"%ld",&val);
+ as_cold(result==1,"do_pgldp:sscanf failed.");
+ }
+
+ /* Success. Set the global variable. */
+ lin_dep=(word)val;
+ return;
+
+ help:
+ lr_mes(&arg[0].pt_ps,
+ "The correct format is: \"@p #line_depth = <num>\".");
+ lr_mes(&arg[0].pt_ps,"Pragma ignored.");
+ return;
+}
+/* } ABC */
+
+/******************************************************************************/
+
+LOCAL void do_pragma P_((p_ps_t,bool));
+LOCAL void do_pragma(p_ps,is_typ)
+/* Upon entry, the current character is: */
+/* is_typ=FALSE => The P of a @p. */
+/* is_typ=TRUE => The T of a @t. */
+/* This function processes these contructs. */
+p_ps_t p_ps;
+bool is_typ;
+{
+#define MAXPARG 10 /* Maximum recorded arguments to a pragma. */
+#define PRAGMA_FWMAX 100 /* Maximum length of a pragma. */
+ char praglin[PRAGMA_FWMAX+1]; /* Array to hold pragma as a complete line. */
+ char pragstr[PRAGMA_FWMAX+1]; /* Array to hold pragma as strings. */
+ pt_t pragarg[MAXPARG+1]; /* Array of pragma arguments. */
+ uword length; /* Helps prevent scanning overrun. */
+ char *p,*q; /* Temporary. */
+ uword numarg,na; /* Number of arguments seen so far. */
+
+ /* Complain if the pragma directive is not at the start of a line. */
+ if (p_ch-1 != p_sol)
+ {
+ if (is_typ)
+ {
+ lr_err(p_ps,"Typesetter directive @t must be at the start of a line.");
+ lr_mes(p_ps,"The rest of this line will be ignored.");
+ }
+ else
+ {
+ lr_err(p_ps,"Pragma sequence @p must be at the start of a line.");
+ lr_mes(p_ps,"The rest of this line will be ignored.");
+ }
+ skiptoeol();
+ goto help;
+ }
+
+ /* The include command should be followed by a blank. Get the next char. */
+ NEXTCH;
+
+ /* Complain if the next character is not a blank. */
+ if (ch != ' ')
+ {
+ /* Note: If we position this error correctly, it gets put after the */
+ /* help message! */
+ if (is_typ)
+ lr_err(p_ps,"Typesetter directive @t must be followed by a blank.");
+ else
+ lr_err(p_ps,"Pragma sequence @p must be followed by a blank.");
+ skiptoeol();
+ goto help;
+ }
+
+ /* Copy the rest of the line to the pragma arrays. */
+ NEXTCH;
+ p = &praglin[0];
+ q = &pragstr[0];
+ length=0;
+ while (ch!=EOL)
+ {
+ if (++length > PRAGMA_FWMAX-3) /* 3 is for "@p " or "@t " */
+ {
+ if (is_typ)
+ {
+ lr_err(p_ps,"This typestter directive line is too long.");
+ sprintf(linet1,"The maximum typesetter directive line length is %u characters.",
+ (unsigned) PRAGMA_FWMAX);
+ lr_mes(p_ps,linet1);
+ }
+ else
+ {
+ lr_err(p_ps,"This pragma line is too long.");
+ sprintf(linet1,"The maximum pragma line length is %u characters.",
+ (unsigned) PRAGMA_FWMAX);
+ lr_mes(p_ps,linet1);
+ }
+ skiptoeol();
+ goto help;
+ }
+ *p++=ch;
+ *q++=ch;
+ NEXTCH;
+ }
+ *p=EOS;
+ *q=EOS;
+ /* Note: Current position is now on the EOL at the end of the @p line. */
+ /* That is the way we want to leave it for the scanspec() routine. */
+
+ /* So far we have copied the body of the pragma line into two arrays. The */
+ /* next lump of code parses that line into a sequence of non-blank arguments.*/
+ /* The result is an array of pt_t objects each of which contains the */
+ /* position of each argument, a pointer to the first character of each */
+ /* argument in praglin, and also a pointer to a string containing the arg. */
+ /* The string resides in the array pragstr which is the same as praglin */
+ /* except that some blanks have been replaced by EOSs so as to allow us to */
+ /* point into it to form strings. All this probably seems rather overdone */
+ /* for the analysis of a "simple" pragma, but I have found that pulling the */
+ /* different kinds of pragma lines apart separately is very messy. Far */
+ /* better to suffer here in what is at least reasonably neat code than */
+ /* later in the specific pragma routines. */
+ numarg=0;
+ p= &praglin[0];
+ q= &pragstr[0];
+ while (TRUE)
+ {
+ /* Skip whitespace between arguments. */
+ while (*p==' ') {p++;q++;}
+
+ /* Exit if we have hit the end of the line. */
+ if ((numarg==MAXPARG) || (*p==EOS)) break;
+
+ /* We have found another argument! */
+ numarg++;
+
+ /* Record the argument. */
+ ASSIGN(pragarg[numarg].pt_ps,*p_ps);
+ pragarg[numarg].pt_ps.ps_column=4+(p-praglin);
+ pragarg[numarg].pt_pinl=p;
+ pragarg[numarg].pt_pstr=q;
+
+ /* Skip to the end of the argument. */
+ while (*p!=' ' && *p!=EOS) {p++;q++;}
+
+ /* Drop a null in the string array to complete string rep of argument. */
+ *q=EOS;
+ }
+
+ /* At this point numarg is MIN(arguments,MAXPARG), and pragargs contains an */
+ /* entry for each of the numarg arguments. */
+
+ /* It is handy to have the position of the pragma itself handy. */
+ ASSIGN(pragarg[0].pt_ps,*p_ps);
+
+ /* CHECK: Make sure that the line and string arrays square up. */
+ {
+ uword i;
+ for (i=1;i<=numarg;i++)
+ {
+ uword j;
+ uword t=strlen(pragarg[i].pt_pstr);
+ for (j=0;j<t;j++)
+ {
+ as_cold(pragarg[i].pt_pstr[j]==pragarg[i].pt_pinl[j],
+ "do_pragma: String and line arrays are not equal.");
+ as_cold((pragarg[i].pt_pstr-pragstr)==(pragarg[i].pt_pinl-praglin),
+ "do_pragma: String and line arrays are out of synch.");
+ }
+ }
+ }
+
+ /* Complain if there are no arguments at all. */
+ if (numarg==0)
+ {
+ if (is_typ)
+ lr_err(p_ps,"Typesetter directive @t must be followed by a keyword.");
+ else
+ lr_err(p_ps,"Pragma sequence @p must be followed by a keyword.");
+ skiptoeol();
+ goto help;
+ }
+
+ /* Branch off to specific routines based on the first argument. */
+ p=pragarg[1].pt_pstr; na=numarg;
+ if (is_typ)
+ {
+ if (0==strcmp(p,"new_page" )) {do_pgnpg(na,pragarg);return;}
+ if (0==strcmp(p,"table_of_contents" )) {do_pgtoc(na,pragarg);return;}
+ if (0==strcmp(p,"title" )) {do_pgtit(na,pragarg);return;}
+ if (0==strcmp(p,"vskip" )) {do_pgvsk(na,pragarg);return;}
+ }
+ else
+ {
+ if (0==strcmp(p,"indentation" )) {do_pgind(na,pragarg);return;}
+ if (0==strcmp(p,"maximum_input_line_length" )) {do_pginl(na,pragarg);return;}
+ if (0==strcmp(p,"maximum_output_line_length")) {do_pgotl(na,pragarg);return;}
+ if (0==strcmp(p,"typesetter" )) {do_pgtyp(na,pragarg);return;}
+/* ABC { */
+ if (0==strcmp(p,"no_doc_header" )) {do_pgnoh(na,pragarg);return;}
+ if (0==strcmp(p,"raw_macro_and_section_names")) {do_pgraw(na,pragarg);return;}
+ if (0==strcmp(p,"ignore_text_after_special_minus")) {do_pgign(na,pragarg);return;}
+ if (0==strcmp(p,"no_paragraph_markups" )) {do_pgnpm(na,pragarg);return;}
+ if (0==strcmp(p,"allow_source_code_typing" )) {do_pgasct(na,pragarg);return;}
+ if (0==strcmp(p,"declare_source_code_type" )) {do_pgdsrc(na,pragarg);return;}
+ if (0==strcmp(p,"automatic_line_directive_macro")) {do_pgaldm(na,pragarg);return;}
+ if (0==strcmp(p,"#line_offset" )) {do_pglof(na,pragarg);return;}
+ if (0==strcmp(p,"#line_depth" )) {do_pgldp(na,pragarg);return;}
+/* } ABC */
+ }
+
+ help:
+ if (is_typ)
+ {
+ lr_err(p_ps,"Unrecognised typesetter directive. Legal ones are:");
+ lr_mes(p_ps," @t new_page");
+ lr_mes(p_ps," @t table_of_contents");
+ lr_mes(p_ps," @t title <font> <align> <string>");
+ lr_mes(p_ps," @t vskip <num> mm");
+ lr_mes(p_ps,"The blanks between arguments are important.");
+ lr_mes(p_ps,"Typesetter directive ignored.");
+ }
+ else
+ {
+ lr_err(p_ps,"Unrecognised pragma. Possible legal pragmas are:");
+ lr_mes(p_ps," @p indentation = none | blank");
+ lr_mes(p_ps," @p maximum_input_line_length = <num>|infinity");
+ lr_mes(p_ps," @p maximum_output_line_length = <num>|infinity");
+ /* ABC { */
+ lr_mes(p_ps," @p typesetter = none | tex | hypertext | html");
+ lr_mes(p_ps," @p no_doc_header");
+ lr_mes(p_ps," @p raw_macro_and_section_names");
+ lr_mes(p_ps," @p ignore_text_after_special_minus");
+ lr_mes(p_ps," @p no_paragraph_markups");
+ lr_mes(p_ps," @p declare_source_code_type \"<name>\"");
+ lr_mes(p_ps," @p automatic_line_directive_macro = \"<name>\"");
+ lr_mes(p_ps," @p automatic_line_directive_macro = \"<name>\" \"<srctype>\"");
+ lr_mes(p_ps," @p #line_offset = <num>");
+ lr_mes(p_ps," @p #line_depth = <num>");
+ /* } ABC */
+ lr_mes(p_ps,"The blanks between arguments are important.");
+ lr_mes(p_ps,"Pragma ignored.");
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void chksol P_((void));
+LOCAL void chksol()
+/* This function is called when the current character is the character after */
+/* an @. The function checks to see if the @ was at the start of a line and */
+/* issues a error message if it isn't. */
+{
+ ps_t ps;
+ grabchps(&ps);
+ if (ps.ps_column != 2)
+ {
+ ps.ps_column--;
+ sprintf(linet1,"@%c is legal only at the start of a line.",ch);
+ lr_err(&ps,linet1);
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void scanspec P_((void));
+LOCAL void scanspec()
+/* Upon entry the current character is the special character (usually '@'). */
+/* The task is to scan the special sequence. Upon exit, the current character */
+/* is the character following the special sequence. */
+{
+ ps_t ps_spec; /* Position of start of special sequence. */
+
+ /* Make a note of where the special sequence starts. */
+ grabchps(&ps_spec);
+
+ /* Move onto the character following the special (escape) character. */
+ NEXTCH;
+
+ /* Now react to the character. In most cases, the special sequence is simply */
+ /* a marker in the input and we can simply transmit it. The nasty special */
+ /* case sequences are left until the end of the switch statement. */
+ /* Purists will complain about how all the case options are hardwired and */
+ /* say that symbols should have been used. They once were, but were taken */
+ /* out when it was discovered that the symbols had cryptic names (because of */
+ /* the portability eight-character rule) and were only used here anyway. */
+ switch (toupper(ch))
+ {
+ case '<': sendspec(&ps_spec,TK_ONAM,DONTCARE); break;
+ case '>': sendspec(&ps_spec,TK_CNAM,DONTCARE); break;
+ case '{': sendspec(&ps_spec,TK_ODEF,DONTCARE); break;
+ case '}': sendspec(&ps_spec,TK_CDEF,DONTCARE); break;
+ case '(': sendspec(&ps_spec,TK_OPAR,DONTCARE); break;
+ case ')': sendspec(&ps_spec,TK_CPAR,DONTCARE); break;
+ case ',': sendspec(&ps_spec,TK_COMA,DONTCARE); break;
+ case '"': sendspec(&ps_spec,TK_QUOT,DONTCARE); break;
+ case '/': sendspec(&ps_spec,TK_EMPH,DONTCARE); break;
+ case 'A': sendspec(&ps_spec,TK_NSEC,1); chksol(); break;
+ case 'B': sendspec(&ps_spec,TK_NSEC,2); chksol(); break;
+ case 'C': sendspec(&ps_spec,TK_NSEC,3); chksol(); break;
+ case 'D': sendspec(&ps_spec,TK_NSEC,4); chksol(); break;
+ case 'E': sendspec(&ps_spec,TK_NSEC,5); chksol(); break;
+ case '1': sendspec(&ps_spec,TK_PARM,1); break;
+ case '2': sendspec(&ps_spec,TK_PARM,2); break;
+ case '3': sendspec(&ps_spec,TK_PARM,3); break;
+ case '4': sendspec(&ps_spec,TK_PARM,4); break;
+ case '5': sendspec(&ps_spec,TK_PARM,5); break;
+ case '6': sendspec(&ps_spec,TK_PARM,6); break;
+ case '7': sendspec(&ps_spec,TK_PARM,7); break;
+ case '8': sendspec(&ps_spec,TK_PARM,8); break;
+ case '9': sendspec(&ps_spec,TK_PARM,9); break;
+ case 'M': sendspec(&ps_spec,TK_MANY,DONTCARE); break;
+ case 'Z': sendspec(&ps_spec,TK_ZERO,DONTCARE); break;
+ case 'O': sendspec(&ps_spec,TK_FDEF,DONTCARE); chksol(); break;
+ case '$': sendspec(&ps_spec,TK_MDEF,DONTCARE); chksol(); break;
+ case EOL:
+ lr_err(&ps_spec,"<special><endofline> is not a legal special sequence.");
+ break;
+ case ' ':
+ lr_err(&ps_spec,"<special><space> is not a legal special sequence.");
+ break;
+ case '@':
+ /* @ instructs FunnelWeb to replace the special construct with the */
+ /* special character. Luckily one appears just before the @ !! */
+ /* Note: FALSE is OK because space is not a legal specialch. */
+ sendtext(&ps_spec,p_ch-1,p_ch-1,FALSE);
+ break;
+ case '-':
+ /* - instructs FunnelWeb to suppress the following end of line. */
+ if (*(p_ch+1) == EOL) {
+ NEXTCH
+ /* ABC { */
+ } else if (igntxtQ) {
+ while (*(p_ch+1) != EOL) NEXTCH;
+ } else {
+ lr_err(&ps_spec,
+ "Suppress EOL sequence is legal only at the end of a line");
+ lr_mes(&ps_spec,
+ "unless `@p ignore_text_after_special_minus' is used.");
+ } /* end if */
+ /* } ABC */
+ break;
+ case '+':
+ /* + instructs FunnelWeb to insert an EOL. We can't look to the end of */
+ /* the previous line to find an EOL as this might be the first line. */
+ /* Running ahead to the end of the line is expensive, and having the */
+ /* liner mini-package maintain a variable for it would be extra */
+ /* housekeeping. Instead of all this, we just point to a static. */
+ {STAVAR char stateol = EOL;
+ sendtext(&ps_spec,&stateol,&stateol,TRUE);}
+ break;
+ case '=':
+ /* = instructs FunnelWeb to change the special character to the */
+ /* character following the <special>= sequence. */
+ NEXTCH;
+ if (ch == ' ')
+ {
+ lr_err(&ps_spec,"You cannot set the special character to <space>!");
+ lr_mes(&ps_spec,"Special sequence ignored.");
+ }
+ else if (ch == EOL)
+ {
+ lr_err(&ps_spec,
+ "You cannot set the special character to <endofline>!");
+ lr_mes(&ps_spec,"Special sequence ignored.");
+ }
+ else
+ specialch=ch;
+ break;
+ case '!':
+ /* ! instructs FunnelWeb to ignore the rest of the line (a comment). */
+ skiptoeol();
+ break;
+ case 'I':
+ /* i instructs FunnelWeb to include a file. */
+ incl_fil(&ps_spec);
+ break;
+ case '^':
+ /* ^ instructs FunnelWeb to insert a specific ascii character. */
+ do_ascii(&ps_spec);
+ break;
+ case '#':
+ /* # instructs FunnelWeb to transmit a two character name "#c". */
+ do_name(&ps_spec);
+ break;
+ case 'P':
+ /* P is used as a miscellaneous PRAGMA. */
+ do_pragma(&ps_spec,FALSE);
+ break;
+ case 'T':
+ /* T introduces a one-line typesetting directive. */
+ do_pragma(&ps_spec,TRUE);
+ break;
+ default:
+ lr_err(&ps_spec,"Unknown special sequence.");
+ break;
+ }
+
+ /* The switch statment absorbs the special sequence and its effects. */
+ /* This NEXTCH places us on the character following the special sequence. */
+ NEXTCH;
+}
+
+/******************************************************************************/
+
+LOCAL void scantext P_((void));
+LOCAL void scantext()
+/* Upon entry, we know that the current character is not EOF and that it is */
+/* not the special character. Our task is to parse as much text as we can and */
+/* ship it off as a text token. The scanner will probably spend most of its */
+/* time in the loops in this function so it is important that they be */
+/* efficient. That is why two loops are used to deal with detecting */
+/* whitespace rather than a flag. */
+/* Upon return, the current character is the character following the text */
+/* sequence. This is guaranteed to be the special character or an EOF. */
+{
+ ps_t ps_start; /* Position of first character of text sequence. */
+ char *p_first = p_ch; /* Pointer to first character of text sequence. */
+
+ /* Grab a copy of the position of this token. */
+ grabchps(&ps_start);
+
+ /* Scan whitespace. */
+ while (ch==' ' || ch==EOL)
+ NEXTCH;
+
+ /* If we hit something that ends a text token */
+ /* then we can transmit a white text token. */
+ if (ch==specialch || ch==EOFCH)
+ {sendtext(&ps_start,p_first,p_ch-1,TRUE); return;}
+
+ /* Otherwise we have some more (non-white) text to scan. */
+ /* We can then send a non-white text token. */
+ while (ch!=specialch && ch!=EOFCH)
+ NEXTCH;
+ sendtext(&ps_start,p_first,p_ch-1,FALSE);
+}
+
+/******************************************************************************/
+
+LOCAL void scan_file(p_fname)
+/* This function scans a single file. It's argument is the name of the file */
+/* to be scanned. scan_file calls the mapper to map in the file and then */
+/* scans the text of the mapped file using the liner mini-package. The result */
+/* of the scan is additions to the line and token list, and diagnostics sent */
+/* to the lister package. If an include directive is encountered, this */
+/* function is called recursively. */
+char *p_fname;
+{
+ char *p_mapped; /* Pointer to the mapped file. */
+ ulong length; /* Number of bytes in the mapped file. */
+ char *errstr; /* Error string returned by mapper. */
+ bool addedeol; /* Did we have to add an EOL to the end of the last line? */
+
+ /* Check to see if the file exists. */
+ if (!fexists(p_fname))
+ {
+ if (inclevel==0)
+ {
+ /* Failure to find the main file is a severe error. */
+ if (option.op_b7_b)
+ sprintf(linet1,"S: Error opening input file \"%s\".",SUPPNAME);
+ else
+ sprintf(linet1,"S: Error opening input file \"%s\".",p_fname);
+ wl_l(linet1);
+ /* Although strictly speaking we should suppress this error from the */
+ /* screen stream unless option.op_s_b is set, absence of an input file */
+ /* is such an important error, that we write it out anyway. */
+ /* if (option.op_s_b) */
+ wl_sj(linet1);
+ num_sev++;
+ return;
+ }
+ else
+ {
+ /* Failure to find an include file is an ordinary error. */
+ ps_t ps;
+ ps.ps_line = globalno;
+ ps.ps_column = 4;
+ /* ABC { */
+ ps.ps_localno = localno;
+ ps.ps_fnam = src_cur;
+ ps.ps_declQ = TRUE;
+ /* } ABC */
+ lr_err(&ps,"Error opening include file.");
+ if (option.op_b7_b)
+ sprintf(linet1,
+ "The include file's expanded name was \"%s\".",SUPPNAME);
+ else
+ sprintf(linet1,
+ "The include file's expanded name was \"%s\".",p_fname);
+ lr_mes(&ps,linet1);
+ return;
+ }
+ }
+
+ /* ABC { */
+ /* Set the current file in the filename list */
+ fl_set(p_fname);
+ /* } ABC */
+
+ /* Map the specified file into memory. We need to change from the scanner */
+ /* clock to the mapper clock to keep the time accounting correct here. */
+ ck_stop(p_scan);
+ ck_start(p_mapp);
+ errstr=map_file(p_fname,&p_mapped,&length);
+ ck_stop(p_mapp);
+ ck_start(p_scan);
+
+ /* Abort if the mapping was not possible. */
+ if (errstr != NULL)
+ if (inclevel==0)
+ {
+ /* Failure to map the main file is a severe error. */
+ if (option.op_b7_b)
+ sprintf(linet1,"S: Error reading input file \"%s\".",SUPPNAME);
+ else
+ sprintf(linet1,"S: Error reading input file \"%s\".",p_fname);
+ wl_l(linet1); if (option.op_s_b) wl_sj(linet1);
+ wl_l(errstr); if (option.op_s_b) wl_sj(errstr);
+ num_sev++;
+ return;
+ }
+ else
+ {
+ /* Failure to find an include file is an ordinary error. */
+ ps_t ps;
+ ps.ps_line = globalno;
+ ps.ps_column = 4;
+ /* ABC { */
+ ps.ps_localno = localno;
+ ps.ps_fnam = src_cur;
+ ps.ps_declQ = TRUE;
+ /* } ABC */
+ lr_err(&ps,"Error reading include file.");
+ lr_mes(&ps,errstr);
+ if (option.op_b7_b)
+ sprintf(linet1,"The include file's expanded name was \"%s\".",
+ SUPPNAME);
+ else
+ sprintf(linet1,"The include file's expanded name was \"%s\".",
+ p_fname);
+ lr_mes(&ps,linet1);
+ return;
+ }
+
+ /* Dump the mapped file if requested. */
+ if (option.op_b1_b)
+ {
+ if (option.op_b7_b)
+ sprintf(linet1,"Dump of mapped file \"%s\".",SUPPNAME);
+ else
+ sprintf(linet1,"Dump of mapped file \"%s\".",p_fname);
+ wl_l(linet1);
+ dm_mem(&f_l,p_mapped,length);
+ }
+
+ /* If the file is absolutely empty, we have to warn the user. Also, this is */
+ /* a special case we can do without, and so we return here if file is empty. */
+ if (length==0)
+ {
+ ps_t ps;
+ /* The empty file could be the main file or an include file. */
+ /* If the empty file is the main file, we want the diagnostic to point to */
+ /* the EOF marker which will appear as line 1. */
+ /* If the empty file is an include file, we wish to point the diagnostic */
+ /* to the line containing the include command. This is globalno. */
+ /* In both cases, we want the diagnostic to point to column 1. */
+ ps.ps_column=1;
+ /* ABC { */
+ ps.ps_fnam = src_cur;
+ ps.ps_declQ = TRUE;
+ /* } ABC */
+ if (inclevel==0)
+ {
+ ps.ps_line=1;
+ /* ABC { */
+ ps.ps_localno = 1;
+ /* } ABC */
+ lr_war(&ps,"Input file is empty (not a byte in syte)!");
+ }
+ else
+ {
+ ps.ps_line=globalno;
+ /* ABC { */
+ ps.ps_localno = localno;
+ /* } ABC */
+ lr_war(&ps,"Include file is empty (not a byte in syte)!");
+ }
+ return;
+ }
+
+ /* Scanning is considerably simplified if we can guarantee that we will not */
+ /* run into an EOF without first hitting an EOL. The following code takes */
+ /* care of this by tacking one on the end if necessary and also adds an */
+ /* EOF character on the end, which also simplifies the scanning. We can get */
+ /* away with all this because the mapper purposefully leaves at least two */
+ /* bytes free for us at the end of the mapped file. */
+ addedeol=FALSE;
+ if (p_mapped[length-1] != EOL)
+ {p_mapped[length++]=EOL; addedeol=TRUE;}
+ p_mapped[length]=EOFCH;
+
+ /* Initialize the variables "instantiated over a single file". */
+ inln_max = 80;
+ specialch = CH_DSPE;
+ localno = 0;
+ p_eof = &p_mapped[length];
+
+ /* Crank up the line subscanner system with a call to prepline. */
+ /* Then enter the main scanning loop. */
+ /* All input consists of alternating special and text sequences */
+ /* terminated by EOF. */
+ prepline(p_mapped);
+ while (ch!=EOFCH)
+ if (ch==specialch)
+ scanspec();
+ else
+ scantext();
+
+ /* Now that we are at the end of the scanned file and the scanning markers */
+ /* are all sitting on the end of the file, it is a good time to issue */
+ /* diagnostics about problems at the end of the file. */
+ if (addedeol)
+ {
+ ps_t ps;
+ /* We want the diagnostic to point to the EOF line. Hence "global+1". */
+ ps.ps_line = globalno+1;
+ ps.ps_column = 1;
+ /* ABC { */
+ ps.ps_localno = localno;
+ ps.ps_fnam = src_cur;
+ ps.ps_declQ = TRUE;
+ /* } ABC */
+ if (inclevel==0)
+ lr_war(&ps,"The last line of the input file was terminated by EOF.");
+ else
+ lr_war(&ps,"The last line of the include file was terminated by EOF.");
+ lr_mes(&ps,"An EOL was inserted at the end of the last line.");
+ }
+}
+
+/******************************************************************************/
+
+EXPORT void scanner(p_amapp,p_ascan)
+/* This is the scanner's main routine and the only exported function. */
+p_ck_t p_amapp; /* Mapper's clock (stopped). */
+p_ck_t p_ascan; /* Scanner's clock (running). */
+{
+ srcnmac_t newtype;
+ /* Copy the arguments into globals where we can get at them. */
+ p_mapp=p_amapp;
+ p_scan=p_ascan;
+
+ /* Apart from diagnostic messages sent to the lister, the only output of */
+ /* the scanner is two global lists holding a list of lines and a list of */
+ /* tokens. The scanner creates these lists simultaneously. */
+ /* We have to initialize them here before we get into 'scan_file' which */
+ /* calls itself recursively if an include file command is encountered. */
+ line_list =ls_cre(sizeof(ln_t));
+ token_list=ls_cre(sizeof(tk_t));
+
+ /* Initialize all the variables instantiated throughout the entire scan. */
+ globalno = 0;
+ inclevel = 0;
+ seenind = FALSE;
+ seentyp = FALSE;
+ seenlimo = FALSE;
+ /* ABC { */
+ src_1st = (p_fnam_t)0;
+ src_cur = (p_fnam_t)0;
+ /* } ABC */
+
+ /* We also have to initialize localno in case the input file is empty and */
+ /* it never gets initialized before being sucked into being used as the */
+ /* local number for the end of file marker. */
+ localno=0;
+
+ /* Initialize the global indentation flag to the default value. */
+ tgindent=TRUE;
+
+ /* Initialize the global product line length limit to the default value. */
+ tglinmax=80;
+
+ /* Initialize the global typesetter flag to the default value. */
+ tr_codes=TR_NONE;
+
+/* ABC { */
+ /* Initialise the global TeX header inclusion flag. */
+ doc_incQ = TRUE; /* Whether to include TeX/HTML header at weave time. */
+
+ /* Initialise the raw TeX/HTML macro/section names flag. */
+ /* Whether to allow raw TeX/HTML in macro/section names at weave time. */
+ raw_namQ = FALSE;
+
+ /* Whether to ignore text on a line after `@-' */
+ igntxtQ = FALSE;
+
+ /* Whether to suppress <P> markups for HTML modes */
+ no_pmrkQ = FALSE;
+
+ /* Initially, extra source code types are not allowed. */
+ xsrctypesQ = FALSE;
+
+ /* The source code type list and a first element are created *
+ * here. */
+ srctlist = ls_cre(sizeof(srcnmac_t));
+ newtype.typnam = newtype.lnmac = NULL;
+ ls_add(srctlist, (p_lsel_t)&newtype);
+
+ /* Initialise the #line macro offset. */
+ lin_off = 1; /* C and C++ offset */
+
+ /* Initialise the #line macro unwind depth. */
+ lin_dep = 1; /* as used in ccline.fwi example */
+/* } ABC */
+
+ /* Scan the top level file whose name is obtained from the command line. */
+ as_cold(option.op_f_b,"scanner: -F!!!!");
+
+ /* Work out what the input file name should be. */
+ {
+ fn_t fname;
+ strcpy(fname,""); /* Start with an empty string. */
+ fn_ins(fname,".fw");
+ fn_ins(fname,option.op_f_s);
+ scan_file(fname);
+ }
+
+ /* The scan_file function scans the main input file and all of its included */
+ /* files, but it does not append a TK_EOF token to the end. This call does */
+ /* this and also adds a line to the line list for EOF. */
+ add_eof();
+}
+
+/******************************************************************************/
+/* End of SCANNER.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/scanner.h b/web/funnelAC/fwACsrc/scanner.h
new file mode 100644
index 0000000000..859538db3c
--- /dev/null
+++ b/web/funnelAC/fwACsrc/scanner.h
@@ -0,0 +1,67 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* SCANNER.H */
+/******************************************************************************/
+/* */
+/* This package contains the scanner. When called (though the only exported */
+/* routine below), the scanner maps in the file whose filename is given in */
+/* the global option.op_f_s variable. The scanner scans the file, mapping in */
+/* any included files, and builds two lists in the global list variables */
+/* 'line_list' and 'token_list'. The line list contains a list of the lines */
+/* of the input. The token list contains a tokenized form of the input, which */
+/* is used by the parser. The scanner also sends diagnostics to the lister */
+/* package which has the effect of possibly incrementing the global error */
+/* counters num_*. See data.h for more information on data structures. */
+/* */
+/******************************************************************************/
+
+#include "style.h"
+
+#include "clock.h"
+
+/******************************************************************************/
+
+EXPORT void scanner P_((p_ck_t,p_ck_t));
+/* The arguments are first a mapper clock, and second a scanner clock. The */
+/* scanner should turn off the scanner clock and turn on the mapper clock */
+/* when calling the mapper. */
+
+/******************************************************************************/
+/* End of SCANNER.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/section.c b/web/funnelAC/fwACsrc/section.c
new file mode 100644
index 0000000000..7b9d99ac4e
--- /dev/null
+++ b/web/funnelAC/fwACsrc/section.c
@@ -0,0 +1,151 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 16-Sep-1993 ABC Changed all constants *_MAX to *_FWMAX to avoid
+ conflict with some standard UNIX constants.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* SECTION.C */
+/******************************************************************************/
+
+#include "style.h"
+
+#include "as.h"
+#include "section.h"
+
+/******************************************************************************/
+
+#define MAGIC (89201129L) /* Magic number detects uninitialized sections. */
+#define SECMAX (30000L) /* Maximum value of a single level's section num. */
+
+/******************************************************************************/
+
+LOCAL void sn_chk P_((p_sn_t));
+LOCAL void sn_chk(p_sn)
+/* Checks that the given section object has a legal internal state. */
+p_sn_t p_sn;
+{
+ ubyte i;
+
+ as_cold(p_sn->sn_magic==MAGIC,"sn_chk: Section has bad magic number.");
+ as_cold(p_sn->sn_lev<=SECLEV_FWMAX,
+ "sn_chk: Section has bad level number.");
+ for (i=1;i<=p_sn->sn_lev;i++)
+ as_cold(p_sn->sn_num[i]>0,
+ "sn_chk: Section has zero hierarchical number.");
+}
+
+/******************************************************************************/
+
+EXPORT void sn_ini(p_sn)
+p_sn_t p_sn;
+{
+ p_sn->sn_magic = MAGIC;
+ p_sn->sn_lev = 0;
+}
+
+/******************************************************************************/
+
+EXPORT void sn_set(p_sn,level)
+p_sn_t p_sn;
+ubyte level;
+{
+ ubyte i;
+ sn_chk(p_sn);
+ as_cold(level>0 && level<=SECLEV_FWMAX,
+ "sn_set: Specified level is too high.");
+ p_sn->sn_lev=level;
+ for(i=1;i<=level;i++)
+ p_sn->sn_num[i]=1;
+}
+
+/******************************************************************************/
+
+EXPORT void sn_inc (p_sn,lev)
+p_sn_t p_sn;
+ubyte lev;
+{
+ sn_chk(p_sn);
+
+ /* Check the parameter level. */
+ as_cold(1<=lev && lev<=SECLEV_FWMAX,"sn_inc: Bad level number specified.");
+
+ /* Check that we are not skipping a hierarchical level. */
+ as_cold(lev<=p_sn->sn_lev+1,"sn_inc: Discountinuous level increment.");
+
+ /* Actually increment the section. */
+ if (lev==p_sn->sn_lev+1) p_sn->sn_num[lev]=0;
+ p_sn->sn_lev=lev;
+ p_sn->sn_num[lev]++;
+
+ /* Check that the section number hasn't got too big. */
+ as_cold(p_sn->sn_num[lev]<=SECMAX,"sn_inc: Section number is too large.");
+}
+
+/******************************************************************************/
+
+EXPORT ubyte sn_lev(p_sn)
+p_sn_t p_sn;
+{
+ sn_chk(p_sn);
+ return p_sn->sn_lev;
+}
+
+/******************************************************************************/
+
+EXPORT void sn_str(p_sn,s)
+p_sn_t p_sn;
+char *s;
+{
+ char t[20];
+ ubyte i;
+
+ sn_chk(p_sn);
+
+ s[0]=EOS;
+ for (i=1;i<=p_sn->sn_lev;i++)
+ {
+ if (i>1) strcat(s,".");
+ sprintf(t,"%u",(unsigned) p_sn->sn_num[i]);
+ strcat(s,t);
+ }
+}
+
+/******************************************************************************/
+/* End of SECTION.C */
+/******************************************************************************/
+
diff --git a/web/funnelAC/fwACsrc/section.h b/web/funnelAC/fwACsrc/section.h
new file mode 100644
index 0000000000..04b6538044
--- /dev/null
+++ b/web/funnelAC/fwACsrc/section.h
@@ -0,0 +1,123 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 16-Sep-1993 ABC Changed all constants *_MAX to *_FWMAX to avoid
+ conflict with some standard UNIX constants.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* SECTION.H */
+/******************************************************************************/
+/* */
+/* This package provides a very simple, very small abstraction for a section */
+/* number. A section number is a hierarchical group of numbers such as is */
+/* used to number the sections in documents. For example: 4.5.1.3 is a */
+/* section number. This package provides an abstraction for these numbers */
+/* that assists in their incrementing at different levels and in writing them */
+/* out. The package also checks for hierarchical inconsistencies. */
+/* */
+/******************************************************************************/
+
+/* Ensure that the body of this header file is included at most once. */
+#ifndef DONE_SECTION
+#define DONE_SECTION
+
+/******************************************************************************/
+
+#include "style.h"
+
+/******************************************************************************/
+
+/* The following constant defines the maximum number of levels that a */
+/* FunnelWeb document can have. @A corresponds to level 1. */
+#define SECLEV_FWMAX 5
+
+/* The following constant defines the maximum length of a string representing */
+/* a section. This is calculated as the maximum number of levels multiplied */
+/* by 1 (for the separating dots) plus a safe size for a decimal number. */
+#define SECSTR_FWMAX (SECLEV_FWMAX*(1+10))
+
+/* The following structure stores a single section number. The sc_level */
+/* field is the level of this field and is in the range [1,SECLEV_FWMAX]. The */
+/* sc_num field is defined only for elements [1,level] and contains the */
+/* hierarchy number at each level. */
+/* Example: For SECLEVMAX=4 and "3.4.1", level=3 and num=[?,3,4,1,?]. */
+/* Note: The first question mark is for element zero which is always unknown. */
+typedef struct
+ {
+ ulong sn_magic; /* Used to detect uninitialized sn objects. */
+ ubyte_ sn_lev; /* Level number of section. */
+ uword_ sn_num[SECLEV_FWMAX+1]; /* Hierarchical level numbers. */
+ } sn_t;
+
+typedef sn_t *p_sn_t;
+
+/******************************************************************************/
+
+EXPORT void sn_ini P_((p_sn_t));
+/* Initializes the specified section object to the empty section at level 0. */
+/* All sections must be initialized before any other operations are performed.*/
+
+EXPORT void sn_set P_((p_sn_t,ubyte));
+/* Sets the specified section to 1.1.1.1.1.1... at the given level. */
+/* Example: sn_set(p_sn,3) yields a section set to 1.1.1. */
+/* Raises an error if the specified level is out of range. */
+
+EXPORT void sn_inc P_((p_sn_t,ubyte));
+/* Increments the number of the specified section object at the specified */
+/* level. This also has the effect of setting all lower levels to 0. For */
+/* example, 3.4.5.1 followed by sn_inc(&sn,2) would become 3.5. */
+/* Raises an error if the level is two or more lower than the current level */
+/* Example: You can't increment 2.4.1 at level 5. */
+/* Raises an error if the specified level is out of range. */
+/* Raises an error if a number at any level becomes too large (>60000). */
+
+EXPORT ubyte sn_lev P_((p_sn_t));
+/* Returns the level number of the specified section. */
+
+EXPORT void sn_str P_((p_sn_t,char *));
+/* Writes a textual representation of the specified section into the given */
+/* string. The string must be able to hold at least SECSTRMAX characters. */
+
+/******************************************************************************/
+
+/* For #ifndef preventing multiple inclusion of the body of this header file. */
+#endif
+
+/******************************************************************************/
+/* End of SECTION.H */
+/******************************************************************************/
+
diff --git a/web/funnelAC/fwACsrc/style.h b/web/funnelAC/fwACsrc/style.h
new file mode 100644
index 0000000000..5cd8f94fe2
--- /dev/null
+++ b/web/funnelAC/fwACsrc/style.h
@@ -0,0 +1,270 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 09-Sep-1993 ABC Adjusted data types to match OSF/1 definitions.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* STYLE.H */
+/******************************************************************************/
+/* */
+/* WARNING: DO NOT ADD ANY MACHINE OR PROGRAM DEPENDENT DEFINITIONS. */
+/* */
+/* This style.h file contains program-independent, machine-independent */
+/* definitions that assist C programming in general. Nothing in this file */
+/* should require modification if this file is moved to a new machine or used */
+/* in a new computer program. However, it may use abstracted second-order */
+/* definitions from the machine-dependent, program independent module */
+/* "environ". */
+/* */
+/******************************************************************************/
+
+/* Ensure that the body of this header file is included at most once. */
+#ifndef DONE_STYLE
+#define DONE_STYLE
+
+/******************************************************************************/
+
+/* System File Inclusions */
+/* ---------------------- */
+/* In order to support a readable programming style, symbols such as TRUE and */
+/* NULL are essential. However, environments differ as to whether and where */
+/* these symbols are defined. This can lead to multiple definition errors */
+/* where (say) this style.h file is included in a .C file before <stdlib.h>. */
+/* I did a quick survey of all the .C FunnelWeb modules and found the */
+/* following: */
+/* */
+/* Total files = 54 */
+/* Number .C files = 22 */
+/* Number .H files = 32 */
+/* Used <stdlib.h> = 19 */
+/* Used <stdio.h> = 16 */
+/* Used <string.h> = 12 */
+/* Used <ctype.h> = 6 */
+/* Used <stddef.h> = 4 */
+/* Used <limits.h> = 2 */
+/* Used <setjmp.h> = 1 */
+/* */
+/* Most of these inclusions were in the .C files. */
+/* It therefore seemed sensible to include some very commonly used system */
+/* header files here and header files that cause problems if not included */
+/* before style.h (<stddef.h>). */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stddef.h>
+
+/******************************************************************************/
+
+/* Although this file is machine independent, it still needs some generic */
+/* definitions whose values vary from machine to machine (see above). */
+#include "environ.h"
+
+/******************************************************************************/
+
+/* The following types provide a clear and consistent collection of names for */
+/* C's arithmetic types. Each name describes only the portable range that the */
+/* underlying type supports. As in C, there are no guarantees about the */
+/* MAXIMUM size of each underlying type and these types can provide no */
+/* guarantees either. In the normal case, they translate to the most speed */
+/* efficient type that will support the specified range. However, to support */
+/* the situations where space efficiency is required, types ending in */
+/* underscores have been defined that strive to conserve memory. */
+/* Note: The signedness of a type does not change when an _ is added. */
+/* ABC { */
+/* Note: a _t added to a name does *not* imply space efficiency. Such names */
+/* are for compatibility with OSF/1. */
+/* } ABC */
+/* */
+/* The following terminology may be a touch vaxcentric, but it works for me. */
+/* A BYTE is an 8 bit quantity. */
+/* A WORD is a 16 bit quantity. */
+/* A LONG is a 32 bit quantity. */
+/* ABC { */
+/* A WIDE is an address-sized quantity */
+/* (as such, the wide types are not defined here, but in environ.h) */
+
+/* FunnelWeb types */
+typedef uint_t ubyte ; /* Unsigned, [0,255]. */
+typedef uchar_t ubyte_ ; /* Unsigned, [0,255]. Space first. */
+typedef int_t word; /* Signed , [-32767,+32767]. */
+typedef short_t word_ ; /* Signed , [-32767,+32767]. Space first. */
+typedef uint_t uword ; /* Unsigned, [0,65535]. */
+typedef ushort_t uword_ ; /* Unsigned, [0,+65535]. Space first. */
+/* ulong ; ** Unsigned, [0,(2^32)-1]. */
+
+typedef uint_t bool ; /* Unsigned, [0,1]. */
+typedef uchar_t bool_ ; /* Unsigned, [0,1]. Space first. */
+
+typedef int_t sign ; /* Signed , [-1,0,1]. */
+
+/* } ABC */
+
+/******************************************************************************/
+
+/* C overloads the attribute keyword "static" horribly giving it meaning on */
+/* both the scoping and lifetime dimensions. This section gives definitions */
+/* that clarify its use. If these macros are used, there should be no need */
+/* for the keyword "static" in programs using this style file. */
+
+/* The following macros assist in making the scope of functions clearer. In */
+/* deciding on the names of these macros, I chose from the following lists: */
+/* file scope: PRIVATE, LOCAL, HIDDEN. */
+/* program scope: EXPORT, PUBLIC, GLOBAL. */
+/* In the end I chose LOCAL and EXPORT. Note: I didn't want to allow more */
+/* than one form as that would have created too much confusion. */
+#define LOCAL static
+#define EXPORT
+
+/* It is desirable to use separate keywords for variables. This makes it */
+/* easier to search for them without stopping at every function. There are */
+/* four classes of variable that we wish to tag, along the two dimensions */
+/* scope:(local,global) and lifetime:(permanent,temporary). In C, all */
+/* variables declared outside of functions have permanent lifetime and so */
+/* the following two names (which should be used only to tag variables not */
+/* declared within a function) have been designed to emphasise the scope */
+/* dimension which is the principal concern for these variables. */
+#define LOCVAR static
+#define GLOVAR
+
+/* Variables local to functions always have local scope and so the dimension */
+/* to emphasise is the lifetime. Automatic variables are the most common in */
+/* C and it would be messy to declare them all using a keyword. Far better */
+/* just to tag static local variables, emphasising their lifetime (STAtic). */
+#define STAVAR static
+
+/******************************************************************************/
+
+/* The following definitions are useful for dealing with void. */
+/* The typedefed definition "p_void" should always be used instead of */
+/* "void *" so as to improve portability. */
+/* The definition of "void" and "p_void" come from environ.h */
+typedef p_void *p_p_void;
+#define PV (p_void)
+#define PPV (p_p_void)
+
+/******************************************************************************/
+
+/* The following symbols are more mnemonic than character escape sequences. */
+#define EOS '\0'
+#define EOL '\n'
+
+/******************************************************************************/
+
+/* The ANSI library functions use many different techniques for returning */
+/* status information. For example, fopen returns NULL upon failure, but */
+/* fclose returns EOF upon failure. The result is that it is hard to */
+/* proofread calls to these routines without constantly referring to the */
+/* library manual. To avoid this problem, we define symbols with helpful */
+/* names for the different values returned. This makes the code obvious. */
+
+/* 07-Feb-1992: During porting I ran into a problem here with FPUTS_S. I had */
+/* defined it to be zero, as stated in the THINK C V4 ANSI library guide. */
+/* However, it turned out that fputs() returns EOF (-1) on failure and the */
+/* value that it returns on success is non negative! (See ANSI (7.9.7.4)). */
+/* Caught by an overspecification by the THINK C people! The lesson is that */
+/* it is very important to make sure that each function's status check symbol */
+/* is defined on the "right" side (success or failure) - that is, the side */
+/* for which a single value for that status is guaranteed portably. */
+/* The following values have all been checked for this. */
+
+/* Note: _F=Failure, _S=Success, _FE=Failure or End of File. */
+
+#define FOPEN_F (NULL)
+#define FSEEK_S (0)
+#define FTELL_F (-1L)
+#define FGETC_FE (EOF)
+#define FGETS_FE (NULL)
+#define FPUTC_F (EOF)
+#define FPUTS_F (EOF)
+#define FFLUSH_S (0)
+#define FCLOSE_F (EOF)
+#define REMOVE_S (0)
+#define RENAME_S (0)
+#define MALLOC_F (NULL)
+
+/******************************************************************************/
+
+/* The following macro functions are handy. However, be sure not to hand them */
+/* an argument with a non-idempotent side effect!!! (e.g. MAX(a++,b)). */
+#define MIN(A,B) ((A)<(B) ? (A) : (B))
+#define MAX(A,B) ((A)>(B) ? (A) : (B))
+
+/******************************************************************************/
+
+/* Some environments don't define some stuff we need so we do it here. */
+/* Cautiously! */
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+#ifndef TRUE
+#define TRUE (1)
+#endif
+
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE (-1)
+#endif
+
+#ifndef EXIT_SUCCESS
+#define EXIT_SUCCESS (0)
+#endif
+
+/******************************************************************************/
+
+/* The standard library macro/function "isprint" can be too loose in some */
+/* circumstances on some machines and it is convenient to define a macro */
+/* that provides a more strict 7-bit ASCII definition of "printable". */
+#define isascprn(ch) ((' '<=ch) && (ch<='~'))
+
+/******************************************************************************/
+
+/* Some compilers (GCC at least) complain about characters as a type in a */
+/* function argument. The following typedef is a quick hack that lets me say */
+/* that I really wanted the function argument to be a character, while */
+/* actually supplying an integer. */
+typedef int intchar;
+
+/******************************************************************************/
+/* For #ifndef preventing multiple inclusion of the body of this header file. */
+#endif
+
+/******************************************************************************/
+/* End of STYLE.H */
+/******************************************************************************/
+
diff --git a/web/funnelAC/fwACsrc/table.c b/web/funnelAC/fwACsrc/table.c
new file mode 100644
index 0000000000..155b7e146c
--- /dev/null
+++ b/web/funnelAC/fwACsrc/table.c
@@ -0,0 +1,433 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 08-Aug-1995 ABC Changed include file name from "memory.h"
+ to "fwmem.h" to avoid a clash with the C++
+ standard header file "memory.h".
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* TABLE.C */
+/******************************************************************************/
+/* */
+/* Notes */
+/* ----- */
+/* - There are few comments at the start of each function. As definitions */
+/* appear in the .H file, and it is dangerous to duplicate definitions, I */
+/* have simply omitted them here. */
+/* */
+/* About The Cache */
+/* --------------- */
+/* A typical usage sequence for tables is for the user to first call tb_itb */
+/* to see if a key is in the table and then call either tb_loo or tb_ins */
+/* to lookup the value or to add a new (key,value) pair to the table. */
+/* In order to avoid performing TWO searches down the binary tree in such */
+/* cases, a CACHE is maintained in the table data structure between calls. */
+/* */
+/* ca_valid stores whether the cache contents are valid. If TRUE then: */
+/* ca_p_key points to a key. */
+/* ca_p_node points to the node in the tree containing the key, or contains */
+/* NULL if no such node exists. */
+/* ca_p_parent points to the node in the tree that is the parent of the node */
+/* ca_p_node in the tree, or (if ca_p_node==NULL) WOULD BE the parent if a */
+/* node containing the key were inserted in the tree. If the tree is */
+/* currently empty, ca_p_parent will be NULL. */
+/* */
+/******************************************************************************/
+
+#include "style.h"
+
+#include "as.h"
+#include "machin.h"
+#include "fwmem.h"
+
+/******************************************************************************/
+
+/* In order to catch uninitialized and corrupted tables, the first and last */
+/* fields of legitimate table objects contain magic numbers. The following */
+/* #defines give the values of these numbers. The first thing that each */
+/* function of this package does is to check the two magic number fields of */
+/* the table it has just been passed, and bomb the package if the fields have */
+/* the wrong values. This technique is likely to pick uninitialized tables, */
+/* as well as tables that have been partially overwritten. */
+#define MAGIC_HEAD_VALUE (53456839L)
+#define MAGIC_TAIL_VALUE (28434290L)
+
+/* Comparing keys is messy and so we define a macro to help us out. */
+#define key_compare(a,b) ((*(p_tb->p_kycm))((a),(b)))
+
+/******************************************************************************/
+
+/* The functions of the table abstraction pass keys and values exclusively */
+/* using pointers. These two definitions define types for these pointers. */
+/* Although the two types are both 'p_void', the different types are useful */
+/* to indicate what is expected in each position of the parameter lists. */
+typedef p_void p_tbky_t;
+typedef p_void p_tbvl_t;
+
+/* Define a type for a function to compare two keys. Such functions are */
+/* needed to organize the storage of (key,value) pairs inside the table. */
+/* Given the arguments are (a,b), the function should return: */
+/* -1 if a<b */
+/* 0 if a==b */
+/* 1 if a>b */
+/* The user must create such a function and hand it to the 'tb_create' */
+/* function when creating new a new table. */
+typedef sign (*p_kycm_t) P_((p_tbky_t,p_tbky_t));
+
+/* The (key,value) pairs in the table are stored in a binary tree. The tree */
+/* is ordered by the key ordering function passed in at table creation. */
+typedef struct node_t_
+ {
+ struct node_t_ *p_left;
+ struct node_t_ *p_right;
+ struct node_t_ *p_parent;
+ p_tbky_t p_key;
+ p_tbvl_t p_value;
+ }
+ node_t;
+typedef node_t *p_node_t;
+
+/* The type tb_t (table type) defines the root table data record. This */
+/* record stores attributes of the table along with the main binary tree of */
+/* (key,value) pairs. */
+typedef struct
+ {
+ ulong magic_head; /* Magic number to allow corruption checks. */
+ size_t key_bytes; /* Number of bytes in a key. */
+ size_t value_bytes; /* Number of bytes in a value. */
+ p_kycm_t p_kycm; /* Pointer to function to compare keys. */
+ p_node_t tree; /* Ptr to root of (key,value) binary tree. */
+ ulong num_keys; /* Number of (k,v) pairs in the table. */
+ bool ca_valid; /* Cache: TRUE iff cache contents are valid. */
+ p_tbky_t ca_p_key; /* Cache: Key value cache contents refer to. */
+ p_node_t ca_p_node; /* Cache: Pointer to node in binary tree. */
+ p_node_t ca_p_parent; /* Cache: Pointer to parent of ca_p_node. */
+ p_node_t p_read_next; /* Pointer to next node to be read. */
+ ulong magic_tail; /* Magic number to allow corruption checks. */
+ } tb_t;
+
+typedef tb_t *p_tb_t; /* Pointer to main table record. */
+
+/* Defining INTABLEC hides the abstract definition. */
+#define INTABLEC
+#include "table.h"
+
+/******************************************************************************/
+/* PRIVATE FUNCTIONS */
+/******************************************************************************/
+
+LOCAL p_node_t new_node P_((p_tb_t,p_tbky_t,p_tbvl_t));
+LOCAL p_node_t new_node(p_tb,p_tbky,p_tbvl)
+/* Creates a new tree node and returns a pointer to it. */
+/* p_tb is the table for which the new node is to be created. */
+/* p_tbky and p_tbvl point to the key and value to go in the new node. */
+/* Assumes that a tb_check(p_tb) has already been performed by the caller. */
+p_tb_t p_tb;
+p_tbky_t p_tbky;
+p_tbvl_t p_tbvl;
+{
+ p_node_t p_node;
+
+ p_node=(p_node_t) mm_temp(sizeof(node_t));
+
+ p_node->p_left = NULL;
+ p_node->p_right = NULL;
+ p_node->p_parent = NULL;
+ p_node->p_key = mm_temp(p_tb->key_bytes );
+ p_node->p_value = mm_temp(p_tb->value_bytes);
+
+ memcpy(p_node->p_key ,p_tbky,p_tb->key_bytes );
+ memcpy(p_node->p_value,p_tbvl,p_tb->value_bytes);
+
+ return p_node;
+}
+
+/******************************************************************************/
+
+LOCAL void tb_check P_((p_tb_t));
+LOCAL void tb_check(p_tb)
+/* Accepts a pointer to a table and performs a series of checks to make sure */
+/* that the table has not been corrupted in some way. */
+p_tb_t p_tb;
+{
+ as_cold(p_tb!=NULL,"tb_check: Table pointer is NULL.");
+ as_cold(p_tb->magic_head==MAGIC_HEAD_VALUE,
+ "tb_check: Magic number at head of record is incorrect.");
+ as_cold(p_tb->magic_tail==MAGIC_TAIL_VALUE,
+ "tb_check: Magic number at tail of record is incorrect.");
+}
+
+/******************************************************************************/
+
+LOCAL p_node_t min_leaf P_((p_node_t));
+LOCAL p_node_t min_leaf(p_node)
+/* Returns a pointer to the node that is leftmost (has the smallest value */
+/* according to the ordering function) in the specified node's subtree. */
+p_node_t p_node;
+{
+ if (p_node==NULL)
+ return NULL;
+ while (p_node->p_left != NULL)
+ p_node=p_node->p_left;
+ return p_node;
+}
+
+/******************************************************************************/
+
+LOCAL p_node_t next_node P_((p_node_t));
+LOCAL p_node_t next_node(p_node)
+/* Give a pointer to a node in the binary tree, returns a pointer to the next */
+/* node (in sequence defined by the order function) or NULL if the given node */
+/* is the last node in the ordered sequence. */
+p_node_t p_node;
+{
+ /* If there is a right subtree, we need the minimum node of that subtree. */
+ if (p_node->p_right != NULL)
+ return min_leaf(p_node->p_right);
+
+ /* Otherwise go up as far as possible through right arcs. */
+ while (p_node->p_parent!=NULL && p_node->p_parent->p_right==p_node)
+ p_node=p_node->p_parent;
+ return p_node->p_parent;
+}
+
+/******************************************************************************/
+
+LOCAL void tb_search P_((p_tb_t,p_tbky_t));
+LOCAL void tb_search(p_tb,p_tbky)
+/* Calling this function with a particular key value results in the cache */
+/* becoming valid and containing the specified key. */
+p_tb_t p_tb;
+p_tbky_t p_tbky;
+{
+ p_node_t p,p_parent;
+
+ tb_check(p_tb);
+
+ /* Return if the cache is already up to date. */
+ if (p_tb->ca_valid)
+ if (key_compare(p_tbky,p_tb->ca_p_key) == 0)
+ return;
+
+ p_parent=NULL;
+ p=p_tb->tree;
+ while (p != NULL)
+ switch(key_compare(p_tbky,p->p_key))
+ {
+ case -1: p_parent=p; p=p->p_left; break;
+ case 1: p_parent=p; p=p->p_right; break;
+ case 0: goto found;
+ default:
+ as_bomb("tb_search: Key comparison function returned bad value.");
+ }
+ found:
+ p_tb->ca_valid = TRUE;
+ memcpy(p_tb->ca_p_key,p_tbky,p_tb->key_bytes);
+ p_tb->ca_p_node = p;
+ p_tb->ca_p_parent = p_parent;
+}
+
+/******************************************************************************/
+
+LOCAL void des_tree P_((p_node_t));
+LOCAL void des_tree(p_root)
+p_node_t p_root;
+{
+ if (p_root==NULL)
+ return;
+ des_tree(p_root->p_left);
+ des_tree(p_root->p_right);
+
+ /* This is what we would need if it wasn't for the MM watermark system. */
+ /* DEALLOCATE(PV p_root); */
+}
+
+/******************************************************************************/
+/* EXPORTED FUNCTIONS */
+/******************************************************************************/
+
+EXPORT p_tb_t tb_cre(key_bytes,value_bytes,p_kycm)
+size_t key_bytes;
+size_t value_bytes;
+p_kycm_t p_kycm;
+{
+ p_tb_t p_tb;
+
+ p_tb = (p_tb_t) mm_temp(sizeof(tb_t));
+ p_tb->magic_head = MAGIC_HEAD_VALUE;
+ p_tb->key_bytes = key_bytes;
+ p_tb->value_bytes = value_bytes;
+ p_tb->p_kycm = p_kycm;
+ p_tb->tree = NULL;
+ p_tb->num_keys = 0;
+ p_tb->ca_valid = FALSE;
+ p_tb->ca_p_key = (p_tbky_t) mm_temp(key_bytes);
+ p_tb->ca_p_node = NULL; /* This initialization not strictly necessary. */
+ p_tb->ca_p_parent = NULL; /* This initialization not strictly necessary. */
+ p_tb->p_read_next = NULL;
+ p_tb->magic_tail = MAGIC_TAIL_VALUE;
+
+ return p_tb;
+}
+
+/******************************************************************************/
+
+EXPORT bool tb_itb(p_tb,p_tbky)
+p_tb_t p_tb;
+p_tbky_t p_tbky;
+{
+ tb_check(p_tb);
+
+ tb_search(p_tb,p_tbky);
+ return p_tb->ca_p_node != NULL;
+}
+
+/******************************************************************************/
+
+EXPORT void tb_loo(p_tb,p_tbky,p_tbvl)
+p_tb_t p_tb;
+p_tbky_t p_tbky;
+p_tbvl_t p_tbvl;
+{
+ tb_check(p_tb);
+
+ tb_search(p_tb,p_tbky);
+ as_cold(p_tb->ca_p_node!=NULL,"tb_loo: Requested key is absent.");
+ memcpy(p_tbvl,p_tb->ca_p_node->p_value,p_tb->value_bytes);
+}
+
+/******************************************************************************/
+
+EXPORT void tb_ins(p_tb,p_tbky,p_tbvl)
+p_tb_t p_tb;
+p_tbky_t p_tbky;
+p_tbvl_t p_tbvl;
+{
+ p_node_t p_new;
+
+ tb_check(p_tb);
+
+ /* Validate the cache. Note: tb_search does it's own cache check. */
+ tb_search(p_tb,p_tbky);
+
+ /* Ensure that the table does not already contain the key. */
+ as_cold(p_tb->ca_p_node==NULL,"tb_ins: Key is already present in the p_tb.");
+
+ /* Create the new node. */
+ p_new=new_node(p_tb,p_tbky,p_tbvl);
+
+ /* Insert the new node into the tree. */
+ if (p_tb->ca_p_parent==NULL)
+ p_tb->tree=p_new;
+ else {
+ switch(key_compare(p_tbky,p_tb->ca_p_parent->p_key))
+ {
+ case -1: p_tb->ca_p_parent->p_left =p_new; break;
+ case 1: p_tb->ca_p_parent->p_right=p_new; break;
+ default: as_bomb("tb_ins: Key comparison function is inconsistent.");
+ }
+ } /* end if */
+ p_new->p_parent=p_tb->ca_p_parent;
+
+ /* Need to fiddle cache to make it correct, and inc num_keys. */
+ p_tb->ca_p_node=p_new;
+ p_tb->num_keys++;
+}
+
+/******************************************************************************/
+
+EXPORT ulong tb_len(p_tb)
+p_tb_t p_tb;
+{
+ tb_check(p_tb);
+ return p_tb->num_keys;
+}
+
+/******************************************************************************/
+
+EXPORT void tb_fir(p_tb)
+p_tb_t p_tb;
+{
+ tb_check(p_tb);
+
+ p_tb->p_read_next=min_leaf(p_tb->tree);
+}
+
+/******************************************************************************/
+
+EXPORT bool tb_rea(p_tb,p_tbky,p_tbvl)
+p_tb_t p_tb;
+p_tbky_t p_tbky;
+p_tbvl_t p_tbvl;
+{
+ tb_check(p_tb);
+
+ if (p_tb->p_read_next == NULL)
+ return FALSE;
+
+ memcpy(p_tbky,p_tb->p_read_next->p_key ,p_tb->key_bytes );
+ memcpy(p_tbvl,p_tb->p_read_next->p_value,p_tb->value_bytes);
+
+ p_tb->p_read_next=next_node(p_tb->p_read_next);
+
+ return TRUE;
+}
+
+/******************************************************************************/
+
+#if FALSE
+EXPORT void tb_des(p_tb)
+p_tb_t p_tb;
+{
+ /* This routine now unused because of the watermark system. */
+ return;
+
+ /* tb_check(p_tb); */
+
+ /* Zap the magic numbers in case the memory is re-used in same alignment. */
+ /* p_tb->magic_head=0; */
+ /* p_tb->magic_tail=0; */
+
+ /* This is what we would need if it wasn't for the MM watermark system. */
+ /* des_tree(p_tb->tree); */ /* Zap the binary tree. */
+ /* DEALLOCATE(PV p_tb); */ /* Zap the node itself. */
+}
+#endif
+
+/******************************************************************************/
+/* TABLE.C */
+/******************************************************************************/
+
diff --git a/web/funnelAC/fwACsrc/table.h b/web/funnelAC/fwACsrc/table.h
new file mode 100644
index 0000000000..ba8ec90d6a
--- /dev/null
+++ b/web/funnelAC/fwACsrc/table.h
@@ -0,0 +1,189 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* TABLE.H */
+/******************************************************************************/
+/* */
+/* Introduction */
+/* ------------ */
+/* This table package (table.h and table.c) implements a table abstraction. */
+/* */
+/* Facts about Tables */
+/* ------------------ */
+/* - A TABLE stores zero or more (KEY,VALUE) PAIRS. */
+/* - The user decides the types of keys and values and provides a */
+/* COMPARISON FUNCTION providing a complete ordering of the set of keys. */
+/* - The comparison function must be consistent between calls. */
+/* - Tables store pairs in key order. */
+/* - A table cannot store more than one pair with the same key. */
+/* - Pairs can be added, but not deleted. */
+/* - A table can return the value corresponding to a given key. */
+/* - The pairs in a table can be read sequentially in key order. At all */
+/* times, the table has an imaginary MARKER positioned on one of its pairs */
+/* (or after the last pair). You can move the marker to the first pair and */
+/* you can move the marker to the next pair, reading the pair as you go. */
+/* Upon table creation, a table's marker is at the end-of-table position. */
+/* - If you try to perform an illegal operation on a table, the table package */
+/* will call "error" to write out an error message and bomb the program. */
+/* - Tables store copies of (key,value) pairs. They do not hold pointers to */
+/* outside data (unless your keys or values are pointers themselves). */
+/* - If the keys are pointers themselves and point to other data which is */
+/* used by the comparison function, then that data must not be modified */
+/* in a way that will change the order of pairs in the table. */
+/* - A table can hold from zero to about 2^31 pairs. */
+/* - The identifier "tb" is used as an abbreviation for "table". */
+/* - The identifier "ky" is used as an abbreviation for "key". */
+/* - The identifier "vl" is used as an abbreviation for "value". */
+/* - The author would like to use longer names, but has chosen to use the */
+/* abbreviations so as to enhance the portability of the code. */
+/* - IMPORTANT: Tables get all their memory using mm_temp calls. */
+/* */
+/* How To Use This Table Package */
+/* ----------------------------- */
+/* 1. Include this .H file in your program file. */
+/* 2. Identify the key and value types that you are going to use. */
+/* 3. Define a function (having two parameters being pointers to keys) */
+/* that compares two keys and returns [-1,0,1] accordingly. */
+/* 4. Define a variable of type p_tb as a view to a table. */
+/* 5. Use the tb_* functions to perform the desired operations. */
+/* Start with a call to tb_cre and (optionally) end with a call to tb_des. */
+/* */
+/******************************************************************************/
+
+/* Ensure that the body of this header file is included at most once. */
+#ifndef DONE_TABLE
+#define DONE_TABLE
+
+/******************************************************************************/
+
+#include <stddef.h>
+#include "style.h"
+
+/******************************************************************************/
+
+/* Hide the exported abstract definition of a table from the table.c package. */
+/* Table.c defines INTABLEC so as to prevent itself from seeing the following */
+/* definitions. It defines its own more concrete definitions. */
+#ifndef INTABLEC
+
+/* The functions of the table abstraction pass keys and values exclusively */
+/* using pointers. These two definitions define types for these pointers. */
+/* Although the two types are both 'p_void', the different types are useful */
+/* to indicate what is expected in each position of the parameter lists. */
+typedef p_void p_tbky_t;
+typedef p_void p_tbvl_t;
+
+/* Define a type for a function to compare two keys. Such functions are */
+/* needed to organize the storage of (key,value) pairs inside the table. */
+/* Given the arguments are (a,b), the function should return: */
+/* -1 if a<b */
+/* 0 if a==b */
+/* 1 if a>b */
+/* The user must create such a function and hand it to the 'tb_create' */
+/* function when creating new a new table. */
+typedef sign (*p_kycm_t) P_((p_tbky_t,p_tbky_t));
+
+/* Users manipulate tables through pointers to tables. Here the actual table */
+/* internals are hidden from the user. */
+typedef struct {word NEVER_USE_THIS_FIELD_UQJTKC;} tb_t;
+typedef tb_t *p_tb_t;
+
+#endif
+
+/******************************************************************************/
+
+/* General Notes About These Functions */
+/* ----------------------------------- */
+/* - All tables, keys, and values are passed by pointer. Whether a parameter */
+/* is read or written is determined by it's functions description. */
+/* - Each function (except tb_cre) accepts a single pointer to a table and */
+/* each function's description is assumed to be referring to the table. */
+/* - "Raising an error" means calling the external function "error" to */
+/* write out a message and bomb the program. */
+/* - You must create a table using tb_cre before performing any operations */
+/* upon it. The table operations will usually raise an error if they are */
+/* handed a pointer that does not point to a properly CREated table. */
+
+/* The Functions */
+/* ------------- */
+EXPORT p_tb_t tb_cre P_((size_t,size_t,p_kycm_t));
+/* CREate. This function creates a new table and returns a pointer to the */
+/* table. The user must supply 1) the size in bytes of keys, 2) the size in */
+/* bytes of values, 3) a pointer to a function that compares two keys. */
+
+EXPORT bool tb_itb P_((p_tb_t,p_tbky_t));
+/* InTaBle. Returns TRUE iff the given key is in the table. */
+
+EXPORT void tb_loo P_((p_tb_t,p_tbky_t,p_tbvl_t));
+/* LOOkup. Feed this function a table and a key and it will return (in the */
+/* p_tbvl_t parameter) the value corresponding to the key. The function */
+/* raises an error if the table does not contain the key. */
+
+EXPORT void tb_ins P_((p_tb_t,p_tbky_t,p_tbvl_t));
+/* INSert. Inserts the (key,value) pair into the table. Raises an error if */
+/* the key is already in the table. */
+
+EXPORT ulong tb_len P_((p_tb_t));
+/* LENgth. Returns the number of pairs in the table. */
+
+EXPORT void tb_fir P_((p_tb_t));
+/* FIRst. Set's the table's marker to the first pair in the table (or the end */
+/* of table position if the table is empty. */
+
+EXPORT bool tb_rea P_((p_tb_t,p_tbky_t,p_tbvl_t));
+/* REAd. Returns in (p_tbky_t,p_tbvl_t) the (key,value) pair corresponding to */
+/* the marker and them moves the marker onto the next pair. */
+/* Returns TRUE => Returned a pair. */
+/* Returns FALSE => Did not return a pair. No more pairs left. */
+/* of key) to be read from the table. Returns TRUE if it returns a pair */
+/* This function will not raise an error if it is called more than once with */
+/* the marker at the end of the table (it just keeps returning FALSE). */
+
+#if FALSE
+void tb_des P_((p_tb_t));
+/* DEStroy. Destroys a table, deallocating all its memory. */
+#endif
+
+/******************************************************************************/
+
+/* For #ifndef preventing multiple inclusion of the body of this header file. */
+#endif
+
+/******************************************************************************/
+/* End of TABLE.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/tangle.c b/web/funnelAC/fwACsrc/tangle.c
new file mode 100644
index 0000000000..121995f2c0
--- /dev/null
+++ b/web/funnelAC/fwACsrc/tangle.c
@@ -0,0 +1,887 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 31-Aug-1993 ABC Added support for EL_SPEC.
+ Added an extra parameter, for the position of the
+ parent macro call, to many of the functions
+ ex_ex...
+ 10-May-1994 ABC Added DYN_NAMES option to allow macro and
+ section names to be allocated dynamically
+ instead of statically.
+ 18-Sep-1994 ABC Added support for the automatic insertion of
+ line directives when `aldmname' is a non-null
+ string referring to a macro without parameters.
+ 25-Jul-1995 ABC Replaced `aldmname' with a list of structures
+ containing a source code type name (or NULL)
+ and a corresponding automatic line directive
+ insertion macro name.
+ 08-Aug-1995 ABC Changed include file name from "memory.h"
+ to "fwmem.h" to avoid a clash with the C++
+ standard header file "memory.h".
+ 10-Aug-1995 ABC Added support for SF_TMS (#timestamp) internal
+ macro.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* TANGLE.C */
+/******************************************************************************/
+
+/* Note: In this module, "ex_" at the start of a function name means "expand" */
+/* rather than the standard meaning of "ex" of "expression. */
+
+/******************************************************************************/
+
+#include "style.h"
+/* ABC { */
+/* The ANSI time functions are required for the #timestamp macro */
+#include <time.h>
+/* } ABC */
+
+#include "as.h"
+#include "data.h"
+#include "lister.h"
+#include "fwmem.h"
+#include "misc.h"
+#include "table.h"
+#include "tangle.h"
+#include "writfile.h"
+
+/******************************************************************************/
+
+/* The following variable keeps track of the output line number. This is */
+/* needed to report lines that are too long. */
+LOCVAR ulong lineno;
+
+/* Last line for which error message was generated. */
+LOCVAR ulong errlin;
+
+/* Number of too-long lines seen so far in this file. */
+LOCVAR ulong numlong;
+/* Number of long line error messages we can tolerate per product file. */
+#define LONGMESS 5
+
+/* Note: An indentation of n means n blanks before current material. */
+/* tgindent is a global variable set by the scanner. It is TRUE if blank */
+/* indenting is required and FALSE if no indenting is required. */
+LOCVAR ulong ind_base; /* Base indenting level of macro being expanded. */
+LOCVAR ulong ind_curr; /* Current indenting position. */
+
+LOCVAR char *fn_targ; /* Name of current (target) product file. */
+LOCVAR wf_t f_o; /* Current product file. */
+/* ABC { */
+LOCVAR bool inaldmQ; /* Whether inside the automatic line directive */
+ /* insertion macro or not. */
+LOCVAR bool Need_aldmQ; /* Whether to insert a line directive before the */
+ /* next scrap. */
+LOCVAR bool no_next_aldmQ; /* Whether to suppress the next line directive */
+ /* before a scrap. */
+/* } ABC */
+
+/******************************************************************************/
+
+/* The expression expansion function has to have a forward declaration. */
+/* ABC { The second parameter points to the parent invocation. } */
+LOCAL void ex_ex P_((p_ells_t,p_el_t,p_srcnmac_t));
+
+/******************************************************************************/
+
+LOCAL void eolblank P_((ulong));
+LOCAL void eolblank(n)
+/* Writes an EOL followed by n blanks to the product file. Efficiently! */
+ulong n;
+{
+ /* The whole aim of this routine is to write blanks EFFICIENTLY. In */
+ /* particular avoiding any per-char procedure call overhead (e.g. calls to */
+ /* wf_chr). The best way to avoid this is to create a static array of blanks */
+ /* and write out large blocks of blanks all at once. */
+#define BLANKLEN 100 /* Number of BLANKS in blank array. */
+ STAVAR bool notinit=TRUE; /* Has blank array been initialized? */
+ STAVAR char blanks[1+BLANKLEN]; /* EOL followed by BLANKLEN blanks. */
+
+ /* Set up the blank array. This only ever done once because of the static */
+ /* boolean. Note that use of an initialized static here does not make the */
+ /* code non-reentrant, as the state does not change after initialization. */
+ if (notinit)
+ {blanks[0]=EOL; memset(blanks+1,' ',(size_t) BLANKLEN); notinit=FALSE;}
+
+ /* The most common case will be a small indentation. Do this case fast. */
+ if (n<=BLANKLEN)
+ wf_blk(&f_o,&blanks[0],(size_t) n+1);
+ else
+ {
+ /* We now know that n>=BLANKLEN. Write out a long line with \n at front. */
+ wf_blk(&f_o,&blanks[0],BLANKLEN+1); n-=BLANKLEN;
+
+ /* Now get into large scale blank production! */
+ while (n>0)
+ {
+ ulong len=MIN(n,BLANKLEN);
+ wf_blk(&f_o,&blanks[1],(size_t) len); n-=len;
+ }
+ }
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void blank P_((ulong));
+LOCAL void blank(n)
+/* Writes an EOL followed by n blanks to the product file. Efficiently! */
+/* This is like `eolblank', but without the `eol' first. */
+ulong n;
+{
+ /* The whole aim of this routine is to write blanks EFFICIENTLY. In */
+ /* particular avoiding any per-char procedure call overhead (e.g. calls to */
+ /* wf_chr). The best way to avoid this is to create a static array of blanks */
+ /* and write out large blocks of blanks all at once. */
+#define BLANKLEN 100 /* Number of BLANKS in blank array. */
+ STAVAR bool notinit=TRUE; /* Has blank array been initialized? */
+ STAVAR char blanks[BLANKLEN]; /* EOL followed by BLANKLEN blanks. */
+
+ /* Set up the blank array. This only ever done once because of the static */
+ /* boolean. Note that use of an initialized static here does not make the */
+ /* code non-reentrant, as the state does not change after initialization. */
+ if (notinit)
+ {memset(blanks,' ',(size_t) BLANKLEN); notinit=FALSE;}
+
+ /* The most common case will be a small indentation. Do this case fast. */
+ if (n<=BLANKLEN)
+ wf_blk(&f_o,&blanks[0],(size_t) n);
+ else
+ {
+ /* We now know that n>=BLANKLEN. Write out a long line with \n at front. */
+ wf_blk(&f_o,&blanks[0],BLANKLEN); n-=BLANKLEN;
+
+ /* Now get into large scale blank production! */
+ while (n>0)
+ {
+ ulong len=MIN(n,BLANKLEN);
+ wf_blk(&f_o,&blanks[0],(size_t) len); n-=len;
+ }
+ }
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void ex_call P_((char*,p_ps_t,p_srcnmac_t));
+LOCAL void ex_call(mcname,p_ps,p_srctype)
+/* This function calls the named FunnelWeb macro without parameters.
+ */
+char *mcname;
+p_ps_t p_ps;
+p_srcnmac_t p_srctype;
+{
+ STAVAR el_t el = {
+ EL_INVC, /* el_kind */
+ NULL, /* el_text */
+ NULL, /* el_p_mac */
+ NULL, /* el_parls */
+ NULL, /* el_pretx */
+ NULL, /* el_postx */
+ NULL, /* el_p_par */
+ NULL, /* el_which */
+ 0, /* el_parno */
+ SF_ERR, /* el_selec */
+ { 0, 0, 0, NULL, FALSE } /* el_ps */
+ };
+ p_ma_t p_ma;
+ p_bp_t p_bp;
+ ulong ind_save;
+ p_void p_mark;
+ bool oldaldmQ = inaldmQ;
+
+ /* Save the current indentation base and set it to the current level. */
+ ind_save=ind_base;
+ ind_base=ind_curr;
+
+ /* Get up the macro parameters */
+ tb_loo(macro_table, PV mcname, PV &p_ma);
+
+ /* Note if macro is that used for automatic line directives */
+ if ((p_srctype != NULL) && (p_srctype->lnmac != NULL))
+ inaldmQ |= !strcmp(mcname, p_srctype->lnmac);
+
+ /* Set up an empty actual parameter list */
+ el.el_p_mac = p_ma;
+ if (el.el_parls == NULL) el.el_parls = ls_cre(sizeof(p_ells_t));
+ if (el.el_pretx == NULL) el.el_pretx = ls_cre(sizeof(p_scls_t));
+ if (el.el_postx == NULL) el.el_postx = ls_cre(sizeof(p_scls_t));
+ el.el_ps = *p_ps;
+
+ /* Push the actual parameter list onto the invoked macro's activation list. */
+ ls_add(p_ma->ma_actn,PV &el.el_parls);
+
+ /* Expand each body part expression. */
+ ls_fir(p_ma->ma_defn.md_body);
+ while (TRUE)
+ {
+ ls_nxt(p_ma->ma_defn.md_body,PPV &p_bp);
+ if (p_bp==NULL) break;
+ p_mark=ls_mar(p_ma->ma_defn.md_body); /* Protect againt recursion. */
+ ex_ex(p_bp->bp_ex, &el, p_srctype);
+ ls_set(p_ma->ma_defn.md_body,p_mark);
+ }
+
+ /* Pop the activated macro's parameter list. */
+ ls_lop(p_ma->ma_actn);
+
+ /* Restore the indentation base. */
+ ind_base=ind_save;
+
+ /* ABC { */
+ /* Restore the initial state of `inaldmQ' */
+ inaldmQ = oldaldmQ;
+ /* } ABC */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+#define SENDLINE {wl_l(linet1); if (option.op_s_b) wl_sj(linet1);}
+
+/* ABC { */
+LOCAL void ex_sc P_((p_sc_t,p_ps_t,p_srcnmac_t));
+LOCAL void ex_sc(p_sc,p_ps,p_srctype)
+/* } ABC */
+/* This function writes the specified scrap to the product file. It also */
+/* performs two other tasks: */
+/* If tgindent==TRUE, inserts indentation at the start of each line. */
+/* If tglinmax>0, checks for product file lines longer than tglinmax. */
+/* Note: The speed of this routine is fairly critical. */
+p_sc_t p_sc;
+p_ps_t p_ps;
+p_srcnmac_t p_srctype;
+{
+ /* Add an automatic line insertion macro if necessary, *
+ * taking care of preserving the indenting */
+ if (
+ (p_srctype != NULL)
+ && (p_srctype->lnmac != NULL)
+ && !(inaldmQ) && Need_aldmQ && !no_next_aldmQ
+ && (p_ps != NULL)
+ ) {
+ int ind_save = ind_curr;
+ if (ind_curr > 0) wf_chr(&f_o, '\n');
+ ind_curr = 0; /* directive starts at beginning of line */
+ ex_call(p_srctype->lnmac,p_ps,p_srctype);
+ if (ind_curr > 0) wf_chr(&f_o, '\n');
+ if (ind_save > 0) blank(ind_save);
+ ind_curr = ind_save;
+ } /* end if */
+ Need_aldmQ = FALSE;
+ /* } ABC */
+
+ /* Output of a scrap is straightforward if we are not inserting indentation */
+ /* or watching for lines that are too long. If neither of these tasks have */
+ /* to be performed, we can bang the scrap out directly with a wf_blk. */
+ if (!tgindent && tglinmax==TGMAXINF)
+ {
+ wf_blk(&f_o, p_sc->sc_first, (size_t) (p_sc->sc_last-p_sc->sc_first+1));
+ return;
+ }
+
+ /* Otherwise it gets rather messy. Basically, we have to watch for end of */
+ /* lines and perform special actions there. */
+ /* ind_curr is the number of characters already written to the current line. */
+ {
+ char *p = p_sc->sc_first;
+ char *p_post = p_sc->sc_last+1;
+ while (TRUE)
+ {
+ char *p_sot = p; /* SOT=Start of Text. */
+
+ /* Scan scrap until we hit either its end or an EOL. */
+ while (p!=p_post && *p!=EOL) p++;
+
+ /* Assert: p==p_post || (p_sot<=p<p_post && *p==EOL). */
+
+ /* If we scanned any non-EOL text, write out what we scanned. */
+ if (p>p_sot) {wf_blk(&f_o,p_sot,(size_t) (p-p_sot));ind_curr+=p-p_sot;}
+
+ /* Check that what we have written so far is not too long. */
+ /* Performing this check here rather than with the EOL processing */
+ /* means that we will detect overlong final non-EOL terminated lines. */
+ /* Use of errlin suppresses multiple errors on the same line. */
+ /* Note: We assume that TGMAXINF is very large. */
+ if (ind_curr>tglinmax && lineno!=errlin)
+ {
+ numlong++;
+ if (numlong <= LONGMESS)
+ {
+ if (option.op_b7_b)
+ sprintf(linet1,
+ "E: Product file line is too long (line %lu of \"%s\").",
+ (ulong) lineno,SUPPNAME);
+ else
+ sprintf(linet1,
+ "E: Product file line is too long (line %lu of \"%s\").",
+ (ulong) lineno,fn_targ);
+ SENDLINE;
+ if (numlong==1)
+ {
+ sprintf(linet1," Product file line length limit is %lu characters.",
+ (ulong) tglinmax);
+ SENDLINE;
+ sprintf(linet1," Note: You can change the limit by specifying.");
+ SENDLINE;
+ sprintf(linet1," @p maximum_output_line_length = <desired length>");
+ SENDLINE;
+ sprintf(linet1," somewhere in the input file.");
+ SENDLINE;
+ }
+ errlin=lineno;
+ num_err++;
+ }
+ if (numlong == LONGMESS+1)
+ {
+ sprintf(linet1,
+ "Further line-too-long warnings for file \"%s\" have been suppressed.",
+ fn_targ);
+ SENDLINE;
+ }
+ }
+
+ /* Exit if we hit the end of the scrap. */
+ if (p==p_post) break;
+
+ /* Move past the EOL and bump up the line counter. */
+ p++; lineno++;
+
+ /* Output an EOL with indentation if desired. */
+ if (tgindent)
+ eolblank(ind_base);
+ else
+ wf_chr(&f_o,EOL);
+ ind_curr=ind_base;
+ }
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void ex_eltx P_((p_el_t,p_el_t,p_srcnmac_t));
+LOCAL void ex_eltx(p_el,p_par,p_srctype)
+/* Writes the given text element to the product file. */
+p_el_t p_el;
+p_el_t p_par;
+p_srcnmac_t p_srctype;
+{
+ p_sc_t p_sc;
+
+ /* Make sure that we have actually been handed a text element. */
+ as_cold(p_el->el_kind==EL_TEXT,"ex_eltx: Not a text element!");
+
+ /* Write all the scraps in the text list to the product file. */
+ ls_fir(p_el->el_text);
+ while (TRUE)
+ {
+ ls_nxt(p_el->el_text,PPV &p_sc);
+ if (p_sc==NULL) break;
+ /* ABC { */
+ ex_sc(p_sc,&(p_el->el_ps),p_srctype);
+ /* } ABC */
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void ex_elpr P_((p_el_t,p_el_t,p_srcnmac_t));
+LOCAL void ex_elpr(p_el,p_par,p_srctype)
+/* Write the expansion of the given parameter element to the product file. */
+p_el_t p_el;
+p_el_t p_par;
+p_srcnmac_t p_srctype;
+{
+ p_ell3_t actn = p_el->el_which->ma_actn;
+ p_elll_t *pp_parls;
+ p_ells_t *pp_exp;
+ ulong ind_save;
+
+ /* Make sure that we have been handed a parameter element. */
+ as_cold(p_el->el_kind==EL_PARM,"ex_elpr: Not a parameter element!");
+
+ /* Save the current indentation base and set it to the current level. */
+ ind_save=ind_base;
+ ind_base=ind_curr;
+
+ /* Get a pointer to the most recent parameter list of the target macro. */
+ ls_loo(actn,ls_len(actn),PPV &pp_parls);
+
+ /* Get the expression corresponding to the el_parno'th parameter. */
+ ls_loo(*pp_parls,p_el->el_parno,PPV &pp_exp);
+
+ /* Expand that expression. */
+ ex_ex(*pp_exp,p_el,p_srctype);
+
+ /* Restore the indentation base. */
+ ind_base=ind_save;
+}
+
+/******************************************************************************/
+
+LOCAL void ex_elin P_((p_el_t,p_el_t,p_srcnmac_t));
+LOCAL void ex_elin(p_el,p_par,p_srctype)
+/* Expand invocation element. */
+p_el_t p_el;
+p_el_t p_par;
+p_srcnmac_t p_srctype;
+{
+ p_ma_t p_ma;
+ p_bp_t p_bp;
+ ulong ind_save;
+ p_void p_mark;
+ /* ABC { */
+ bool oldaldmQ = inaldmQ;
+ /* } ABC */
+
+ /* Make sure that we have been handed an invocation element. */
+ as_cold(p_el->el_kind==EL_INVC,"ex_elin: Not an invocation element!");
+
+ /* Save the current indentation base and set it to the current level. */
+ ind_save=ind_base;
+ ind_base=ind_curr;
+
+ /* ABC { */
+ /* Mark parent */
+ p_el->el_p_par = p_par;
+ /* } ABC */
+
+ /* Grab a pointer to the macro being invoked. */
+ p_ma=p_el->el_p_mac;
+
+ /* ABC { */
+ /* Note if macro is that used for automatic line directives */
+ if ((p_srctype != NULL) && (p_srctype->lnmac != NULL))
+ inaldmQ |= !strcmp(p_ma->ma_name, p_srctype->lnmac);
+ /* } ABC */
+
+ /* Push the actual parameter list onto the invoked macro's activation list. */
+ ls_add(p_ma->ma_actn,PV &p_el->el_parls);
+
+ /* Expand each body part expression. */
+ ls_fir(p_ma->ma_defn.md_body);
+ while (TRUE)
+ {
+ ls_nxt(p_ma->ma_defn.md_body,PPV &p_bp);
+ if (p_bp==NULL) break;
+ p_mark=ls_mar(p_ma->ma_defn.md_body); /* Protect againt recursion. */
+ /* ABC { */
+ /* May need a line directive for each part of the macro */
+ if (!inaldmQ) Need_aldmQ = TRUE;
+ /* } ABC */
+ ex_ex(p_bp->bp_ex, p_el, p_srctype);
+ ls_set(p_ma->ma_defn.md_body,p_mark);
+ }
+
+ /* Pop the activated macro's parameter list. */
+ ls_lop(p_ma->ma_actn);
+
+ /* Restore the indentation base. */
+ ind_base=ind_save;
+
+ /* ABC { */
+ /* May need a line directive for the end of the macro */
+ if (!inaldmQ) Need_aldmQ = TRUE;
+ /* Restore the initial state of `inaldmQ' */
+ inaldmQ = oldaldmQ;
+ /* } ABC */
+}
+
+/* ABC { */
+/******************************************************************************/
+
+#define ELSP_NUMSZ (32)
+
+LOCAL void ex_tstamp P_((char*));
+LOCAL void ex_tstamp(strptr)
+/* Copies the FunnelWeb timestamp into the argument string. */
+char *strptr;
+{
+ static bool unfixedQ = TRUE;
+ static char timestamp[ELSP_NUMSZ];
+ time_t current = -1; /* time_t is defined in `time.h' */
+
+ if (unfixedQ) {
+ /* Initialise on the first call. */
+ current = time(NULL);
+ if (current == -1) {
+ /* `time' failed */
+ strcpy(timestamp, "????/??/??/??/??/??");
+ } else {
+ /* `time' was successful */
+ strftime(
+ timestamp, ELSP_NUMSZ,
+ "%Y/%m/%d/%H/%M/%S",
+ localtime(&current)
+ );
+ } /* end if */
+ unfixedQ = FALSE;
+ } /* end if */
+
+ strcpy(strptr, timestamp);
+}
+
+/******************************************************************************/
+
+LOCAL void ex_elsp P_((p_el_t,p_el_t,p_srcnmac_t));
+LOCAL void ex_elsp(p_el,p_par,p_srctype)
+/* Writes the given internal function result to the product file. */
+p_el_t p_el;
+p_el_t p_par;
+p_srcnmac_t p_srctype;
+{
+ p_sc_t p_sc;
+ char *p_res = NULL;
+ char errmss[32];
+ p_el_t punwnd;
+ uword i;
+
+ /* Make sure that we have actually been handed a text element. */
+ as_cold(p_el->el_kind==EL_SPEC,"ex_elsp: Not a special function!");
+
+ /* Check special function and write result string. */
+ p_sc = (p_sc_t)mm_temp(sizeof(sc_t));
+ switch (p_el->el_selec) {
+ case SF_LIN :
+ if (p_par) {
+ punwnd = p_par;
+ for (i=0; (i<lin_dep)&&punwnd; i++) punwnd = punwnd->el_p_par;
+ if (punwnd) {
+ p_res = (char *)mm_temp(ELSP_NUMSZ*sizeof(char));
+ sprintf(p_res, "%lu", punwnd->el_ps.ps_localno+lin_off);
+ p_sc->sc_white = FALSE;
+ } /* end if */
+ } /* end if */
+ break;
+ case SF_FIL :
+ if (p_par) {
+ punwnd = p_par;
+ for (i=0; (i<lin_dep)&&punwnd; i++) punwnd = punwnd->el_p_par;
+ if (punwnd) {
+ p_res = (char *)mm_temp(
+ (strlen(punwnd->el_ps.ps_fnam->fnam_name)+1) * sizeof(char)
+ );
+ strcpy(p_res, punwnd->el_ps.ps_fnam->fnam_name);
+ p_sc->sc_white = FALSE;
+ } /* end if */
+ } /* end if */
+ break;
+ case SF_TMS :
+ p_res = (char *)mm_temp(ELSP_NUMSZ*sizeof(char));
+ ex_tstamp(p_res);
+ p_sc->sc_white = FALSE;
+ break;
+ case SF_ERR :
+ default :
+ wl_sjl("An erroneous internal function designator was seen.");
+ if (p_el->el_selec == SF_ERR) {
+ wl_sjl("Type: SF_ERR");
+ } else {
+ sprintf(errmss, "Type: SF_??? = %lu", (ulong)p_el->el_selec);
+ wl_sjl(errmss);
+ } /* end if */
+ wl_sjl("Aborted internal function.");
+ return;
+ } /* end switch */
+
+ /* Write internal result to the product file. */
+ p_sc->sc_first = p_res;
+ p_sc->sc_last = p_res + strlen(p_res) - 1;
+ ex_sc(p_sc, NULL, NULL);
+}
+
+/* } ABC */
+
+/******************************************************************************/
+
+LOCAL void ex_ex(p_exp,p_par,p_srctype)
+/* Expand the specified expression. */
+p_ells_t p_exp;
+p_el_t p_par;
+p_srcnmac_t p_srctype;
+{
+ p_void p_mark;
+
+ /* We need to save the current position in the expression list in case we */
+ /* are being recursively invoked (e.g. in @<X@>@(@"@<X@>@(@"sloth@"@)@"@). */
+ ls_fir(p_exp);
+ while (TRUE)
+ {
+ p_el_t p_el;
+ ls_nxt(p_exp,PPV &p_el);
+ if (p_el==NULL) break;
+ p_mark=ls_mar(p_exp);
+ switch (p_el->el_kind)
+ {
+ /* ABC { */
+ case EL_TEXT: ex_eltx(p_el,p_par,p_srctype);
+ no_next_aldmQ = FALSE; break;
+ case EL_INVC: ex_elin(p_el,p_par,p_srctype); break;
+ case EL_PARM: ex_elpr(p_el,p_par,p_srctype); break;
+ case EL_SPEC: ex_elsp(p_el,p_par,p_srctype);
+ no_next_aldmQ = TRUE; break;
+ /* } ABC */
+ default : as_bomb("ex_ex: Case defaulted.");
+ }
+ ls_set(p_exp,p_mark);
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void ex_file P_((p_ma_t));
+LOCAL void ex_file(p_ma)
+/* This function accepts a pointer to a macro. It creates a product file */
+/* with the same name as the macro (inheriting any filename parts given in */
+/* the command line) and expands the macro, writing the expansion to the */
+/* product file. */
+p_ma_t p_ma;
+{
+ fn_t fn_tmp; /* Name of temporary file. */
+ bool renfil; /* Do we wish to rename product file? */
+ bool istarg; /* Does a target file already exist? */
+/* ABC { */
+ p_srcnmac_t p_srctype; /* Source code type */
+/* } ABC */
+
+ /* Writing product files differs to the other output files. With non */
+ /* critical files such as the listing file that are really just logs, */
+ /* generation of half a listing file is acceptable if not desirable. However */
+ /* in the case of product files, it is very bad to generate half a product */
+ /* file; far better to generate none at all. For this reason, and also */
+ /* because of the presence of the D option (which prohibits the writing */
+ /* of product files identical to existing files (to prevent MAKE */
+ /* propagations)) it is best to write a temporary file and then rename it. */
+
+ /* Construct the target file name. */
+ strcpy(fn_targ,""); /* Start with an empty name. */
+ fn_ins(fn_targ,&option.op_o_s[0]);
+ /* ABC { */
+#if DYN_NAMES
+ fn_ins(fn_targ,p_ma->ma_name);
+#else /* !DYN_NAMES */
+ fn_ins(fn_targ,&p_ma->ma_name[0]);
+#endif /* DYN_NAMES */
+ /* } ABC */
+
+ /* The temporary file has to inherit too, because the output directory may */
+ /* not be the default directory and some computers can't rename across */
+ /* directories (and we have to rename it later). */
+ strcpy(fn_tmp,fn_targ);
+ fn_ins(fn_tmp,fn_temp());
+
+/* ABC { */
+ /* Set the source code type */
+ p_srctype = p_ma->ma_defn.md_aldm;
+/* } ABC */
+
+ /* Expand the macro to the temporary file. */
+ wf_ini(&f_o,TRUE);
+ wf_ope(&f_o,fn_tmp);
+ if (wf_err(&f_o))
+ {
+ sprintf(linet1,"Error creating temporary product file \"%s\".",&fn_tmp[0]);
+ wl_sjl(linet1);
+ (void) remove(fn_tmp);
+ goto severe;
+ }
+
+ /* Now expand the target macro into the file. */
+ /* ABC { */
+ /* An automatic line directive may be needed at the start */
+ Need_aldmQ = TRUE;
+ no_next_aldmQ = FALSE;
+ /* } ABC */
+ {
+ el_t el;
+ el.el_kind = EL_INVC;
+ el.el_p_mac = p_ma;
+ el.el_parls = ls_cre(sizeof(p_ells_t));
+ /* Note: We don't set el_pretx and el_postx as they are not used here. */
+ ind_base = 0;
+ ind_curr = 0;
+ lineno = 1;
+ errlin = 0;
+ numlong = 0;
+ ex_elin(&el, (p_el_t)0, p_srctype);
+ }
+
+ /* Make sure that there weren't any errors writing to the product file. */
+ if (wf_err(&f_o))
+ {
+ sprintf(linet1,"S: Error writing to temporary product file \"%s\".",&fn_tmp[0]);
+ wl_sjl(linet1);
+ (void) remove(fn_tmp);
+ goto severe;
+ }
+
+ /* Close the product file. */
+ wf_clo(&f_o);
+ if (wf_err(&f_o))
+ {
+ sprintf(linet1,"S: Error closing temporary product file \"%s\".",&fn_tmp[0]);
+ wl_sjl(linet1);
+ (void) remove(fn_tmp);
+ goto severe;
+ }
+
+ /* The rest of the code in this function copes with the renaming. */
+
+ /* By default, we wish to rename the temporary file. */
+ renfil=TRUE;
+
+ /* Deal with any existing file of the target name. */
+ istarg=fexists(fn_targ);
+ if (istarg && option.op_d_b)
+ {
+ /* A target already exists, and the D option is on. If the target is */
+ /* identical to the temporary, we can simply delete the temporary! */
+ char *errstr;
+ bool same;
+ errstr=eq_files(fn_tmp,fn_targ,&same);
+ if (errstr != NULL)
+ {
+ wl_sjl("S: Error comparing temporary file with previous product file.");
+ wl_sjl("(A comparison was attempted because the D option was turned on.)");
+ wl_sjl("Error from comparison routine was as follows (first=temp):");
+ wr_sjl(" ");wl_sjl(errstr);
+ sprintf(linet1,"Temporary file name was \"%s\".",&fn_tmp[0]);
+ wl_sjl(linet1);
+ sprintf(linet1,"Product file name was \"%s\".",fn_targ);
+ wl_sjl(linet1);
+ wl_sjl("FunnelWeb will leave both files intact so you can look at them.");
+ goto severe;
+ }
+ /* If the two files are the same, we can simply delete the temporary. */
+ if (same)
+ {
+ int status;
+ status=remove(fn_tmp);
+ if (status != REMOVE_S)
+ {
+ sprintf(linet1,"S: Error deleting (under +D option) temporary file \"%s\".",&fn_tmp[0]);
+ wl_sjl(linet1);
+ goto severe;
+ }
+ sprintf(linet1,"Deleted identical product file \"%s\".",fn_targ);
+ wl_sjl(linet1);
+ renfil=FALSE;
+ }
+ }
+
+ if (renfil)
+ {
+ int status;
+ /* We need to delete any existing file of the target name. */
+ if (istarg)
+ {
+ status=remove(fn_targ);
+ if (status != REMOVE_S)
+ {
+ sprintf(linet1,"S: Error deleting existing product file \"%s\".",fn_targ);
+ wl_sjl(linet1);
+ goto severe;
+ }
+ }
+ /* Rename the temporary file to the product file. */
+ status=rename(fn_tmp,fn_targ);
+ if (status != RENAME_S)
+ {
+ wl_sjl("S: Error renaming temporary product file to product file.");
+ sprintf(linet1,"Temporary file name was \"%s\".",&fn_tmp[0]);
+ wl_sjl(linet1);
+ sprintf(linet1,"Product file name was \"%s\".",fn_targ);
+ wl_sjl(linet1);
+ wl_sjl("FunnelWeb will leave both files intact so you can look at them.");
+ goto severe;
+ }
+ }
+
+ /* Tell everyone that we have written a product file. */
+ /* Note that we use the macro name. The full name is usually too messy. */
+ /* ABC { */
+#if DYN_NAMES
+ sprintf(linet1,"Tangle: Completed %s.",p_ma->ma_name);
+#else /* !DYN_NAMES */
+ sprintf(linet1,"Tangle: Completed %s.",&p_ma->ma_name[0]);
+#endif /* DYN_NAMES */
+ /* } ABC */
+ wl_sjl(linet1);
+ return;
+
+ /* Jump here is a nasty file error occurs. */
+ severe:
+ sprintf(linet1,"A problem occurred during the generation of product file \"%s\".",&fn_targ[0]);
+ wl_sjl(linet1);
+ wl_sjl("S: Aborting...");
+ num_sev++;
+ return;
+
+}
+
+/******************************************************************************/
+
+EXPORT void tangle()
+{
+ name_t dummyname;
+ p_ma_t p_ma;
+
+ /* ABC { */
+ /* Initialise inaldmQ: not in auto line directive macro */
+ inaldmQ = FALSE;
+ /* Initialise Need_aldmQ: no directive needed before next scrap */
+ Need_aldmQ = FALSE;
+ /* } ABC */
+
+ /* Possibly decrease tglinmax if W option is turned on. */
+ if (option.op_w_b)
+ tglinmax=MIN(tglinmax,option.op_w_i);
+
+ /* Some compilers do not allow much space for statics so we allocate fn_targ */
+ /* dynamically to save static space. */
+ fn_targ=(char *) mm_temp(sizeof(fn_t));
+
+ /* Generate each file contained in the file table. */
+ tb_fir(file_table);
+ while (num_sev==0 && tb_rea(file_table,PV dummyname,PV &p_ma))
+ ex_file(p_ma);
+}
+
+/******************************************************************************/
+/* End of TANGLE.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/tangle.h b/web/funnelAC/fwACsrc/tangle.h
new file mode 100644
index 0000000000..800a609cad
--- /dev/null
+++ b/web/funnelAC/fwACsrc/tangle.h
@@ -0,0 +1,56 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* TANGLE.H */
+/******************************************************************************/
+/* */
+/* This package exports a single function "tangle" that generates all the */
+/* product files for FunnelWeb. */
+/* */
+/******************************************************************************/
+
+#include "style.h"
+
+/******************************************************************************/
+
+EXPORT void tangle P_((void));
+/* Generate product files. */
+
+/******************************************************************************/
+/* End of TANGLE.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/texhead.c b/web/funnelAC/fwACsrc/texhead.c
new file mode 100644
index 0000000000..8a94553471
--- /dev/null
+++ b/web/funnelAC/fwACsrc/texhead.c
@@ -0,0 +1,108 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* TEXHEAD.C */
+/******************************************************************************/
+/* */
+/* TEX HEADER PACKAGE */
+/* ================== */
+/* This package contains a single function that writes the TeX header */
+/* (containing all the Weave macros) to the specified stream. The package */
+/* consists of: */
+/* */
+/* texhead.tex - The header file ("source code" for texhead.ctx). */
+/* texhead.ctx - Automatically generated C code based on texhead.tex. */
+/* texhead.h - Exported header file containing function definition. */
+/* texhead.c - Contains the function body and the codified header file. */
+/* */
+/* WARNING: THE ONLY FILE THAT SHOULD EVER BE MODIFIED BY HAND IS TEXHEAD.TEX.*/
+/* From this can be generated a new version of texhead.ctx. Here's how: */
+/* 1. Edit texhead.tex as desired. */
+/* 2. Fire up the FunnelWeb shell and give the command: */
+/* codify texhead.tex texhead.ctx */
+/* */
+/******************************************************************************/
+
+#include "style.h"
+
+#include "texhead.h"
+#include "writfile.h"
+
+/******************************************************************************/
+
+EXPORT void tex_head(p_wf)
+p_wf_t p_wf;
+/* Writes the FunnelWeb TeX header block to the argument stream. */
+{
+
+ /*#############################################################################
+ IMPORTANT COPYRIGHT NOTICE
+ --------------------------
+ The set of FunnelWeb TeX definitions, embodied in C code in the file
+ included by the #include directive below, is a public domain work.
+
+ Notwithstanding the fact that the public domain set of FunnelWeb TeX
+ definitions is represented in the form of strings in C code #included by the
+ FunnelWeb literate-programming preprocessor program released under GNU General
+ Public License Version 2, the set of TeX definitions themselves do not fall
+ under GNU license. Instead, the set of FunnelWeb TeX definitions is classified
+ as a public domain work that is distributed with FunnelWeb as a "separate
+ work". The set of definitions is included as strings in the FunnelWeb code for
+ the sole reason that this organization avoids FunnelWeb having to locate the
+ file at run time. Thus, when FunnelWeb writes the set of TeX definitions to a
+ .TeX output file, it is not generating a work based on itself, but is merely
+ copying a public domain file (which it happened to represent in the form of
+ code rather than data) into the output file.
+
+ The motivation for rigorously clarifying the status of the set of
+ FunnelWeb TeX definitions is that it will appear in TeX output files
+ generated by FunnelWeb, and I do not want any output files generated by
+ FunnelWeb to be under any copyright restrictions.
+
+ -- Ross N. Williams, 5:42pm 07-May-1992, Adelaide, Australia.
+
+ #############################################################################*/
+
+#define WX(STR) wf_wl(p_wf,STR)
+
+#include "texhead.ctx"
+}
+
+/******************************************************************************/
+/* End of TEXHEAD.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/texhead.ctx b/web/funnelAC/fwACsrc/texhead.ctx
new file mode 100644
index 0000000000..b873bd70ba
--- /dev/null
+++ b/web/funnelAC/fwACsrc/texhead.ctx
@@ -0,0 +1,320 @@
+ WX("%===================== Start of FunnelWeb TeX Definitions ======================");
+ WX("");
+ WX("");
+ WX("% Version");
+ WX("% -------");
+ WX("% This is FunnelWeb TeX Macro Library Version 1.0.");
+ WX("");
+ WX("");
+ WX("% Copyright");
+ WX("% ---------");
+ WX("% This set of FunnelWeb TeX definitions was written by Ross Williams and was");
+ WX("% originally Copyright (C) 1992 Ross N. Williams. However, I, Ross Williams,");
+ WX("% hereby forego any claim to Copyright in this set of FunnelWeb TeX definitions");
+ WX("% and hereby authorize that the set of TeX definitions pass into the public");
+ WX("% domain. -- Ross N. Williams, 3:41pm 07-May-1992, Adelaide, Australia.");
+ WX("");
+ WX("");
+ WX("% Modification");
+ WX("% ------------");
+ WX("% Please record all modifications to these TeX definitions here. Unless");
+ WX("% otherwise specified, all modified definitions fall in the public domain too.");
+ WX("%");
+ WX("% Programmers:");
+ WX("% RNW Ross N. Williams ross@spam.adelaide.edu.au");
+ WX("%");
+ WX("% Changes:");
+ WX("% 07-May-1992 RNW Prepared this work for public domain release.");
+ WX("%");
+ WX("");
+ WX("");
+ WX("% General Comments");
+ WX("% ----------------");
+ WX("% This set of TeX definitions exists for two reasons:");
+ WX("%");
+ WX("% 1. To shorten and neaten the FunnelWeb TeX output.");
+ WX("% 2. To allow users to fiddle with the output format in their input files");
+ WX("% (by inserting redefining \"\\def\"s) without having to resort to");
+ WX("% modifying the FunnelWeb code.");
+ WX("%");
+ WX("% The user is warned that these definitions may be changed from time to time");
+ WX("% (but probably not much). The user should not be too sneaky. In particular,");
+ WX("% users wishing to redefine some of these macros should do so in an explicitly");
+ WX("% defined section at the top of their input file. This will mean that in the");
+ WX("% event of problems, that section can simply be deleted or commented out to");
+ WX("% allow the document to at least be typeset in the default format. Users should");
+ WX("% limit themselves to redefining these macros in such a section and should");
+ WX("% refrain from using the macros throughout their documents.");
+ WX("");
+ WX("");
+ WX("% Environment Parameters");
+ WX("% ----------------------");
+ WX("% \\tolerance tells TeX how tolerant it should be about making bad line and");
+ WX("% page breaks. Here we set it to it's maximum, as");
+ WX("% 1) Computer programs are likely to cause lots of bad breaks.");
+ WX("% 2) In most cases the user would probably rather get the TeX file through");
+ WX("% TeX without any errors than fiddle with spacings for perfection.");
+ WX("\\tolerance=10000");
+ WX("");
+ WX("% I don't like indentation as it makes the page look more busy. Instead,");
+ WX("% paragraphs are separated by a little space (see next).");
+ WX("\\parindent=0pt");
+ WX("");
+ WX("% In many cases, users will produce documents with long runs of paragraphs.");
+ WX("% In order to space out these paragraphs, it is convenient to maintain a");
+ WX("% prevailing non-zero \\parskip (end-of-paragaph skip). The only trouble is");
+ WX("% that the skip becomes a problem in macro definitions which require no skip");
+ WX("% and so we have to turn the skip on and off. The following two macros");
+ WX("% simplify this process.");
+ WX("\\def\\fwparskipon{\\parskip=\\medskipamount}");
+ WX("\\def\\fwparskipoff{\\parskip=0pt}");
+ WX("\\fwparskipon");
+ WX("");
+ WX("% Setting raggedbottom allows TeX to leave a bit of space at the bottom of the");
+ WX("% page in order to better vertically align the rest of the page (e.g. skips");
+ WX("% won't stretch as much). It also means that headings are less likely to be");
+ WX("% isolated at the bottom of the page without any following text.");
+ WX("\\raggedbottom");
+ WX("");
+ WX("");
+ WX("% Fonts");
+ WX("% -----");
+ WX("% Most of the typeset output is set in 10pt roman and 10pt tt font.");
+ WX("% The major extra font needs spring from titles and headings.");
+ WX("% For portability's sake we use only the following fonts:");
+ WX("% cmr10");
+ WX("% cmbx10");
+ WX("% cmtt10");
+ WX("% and some enlargements of them. These fonts are all \"standard\" fonts");
+ WX("% in Plain TeX. See The TeXbook p.350.");
+ WX("\\font\\fwfontnote=cmr7");
+ WX("");
+ WX("\\font\\fwfontnorm=cmr10");
+ WX("\\font\\fwfontnorma=cmr10 scaled \\magstep1");
+ WX("\\font\\fwfontnormb=cmr10 scaled \\magstep2");
+ WX("");
+ WX("\\font\\fwfontbold=cmbx10");
+ WX("\\font\\fwfontbolda=cmbx10 scaled \\magstep1");
+ WX("\\font\\fwfontboldb=cmbx10 scaled \\magstep2");
+ WX("\\font\\fwfontboldc=cmbx10 scaled \\magstep3");
+ WX("\\font\\fwfontboldd=cmbx10 scaled \\magstep4");
+ WX("");
+ WX("");
+ WX("% Macros for Stylistic Details");
+ WX("% ----------------------------");
+ WX("% This section contains all the fiddly little macros for setting the details");
+ WX("% of each macro definition.");
+ WX("");
+ WX("% Macro definitions are sandwiched by calls to these macros which can be used");
+ WX("% to sort out the spacing before and after the macro definition.");
+ WX("\\def\\fwbeginmacro{\\fwparskipoff\\bigskip}");
+ WX("\\def\\fwendmacro{\\fwparskipon\\par}");
+ WX("");
+ WX("% These macros deal with the macro name and definition line.");
+ WX("\\def\\fwmacroname#1#2{{\\sl #1\\/}$\\lbrack$#2$\\rbrack$}");
+ WX("\\def\\fwfilename#1#2{{\\bf #1}$\\lbrack$#2$\\rbrack$}");
+ WX("\\def\\fwzero#1{{\\bf Z}}");
+ WX("\\def\\fwmany#1{{\\bf M}}");
+ WX("\\def\\fwequals{ $\\equiv$}");
+ WX("\\def\\fwplusequals{ $+\\equiv$}");
+ WX("");
+ WX("% Now for the actual body of the definition. It looks nice to have the tt");
+ WX("% code indented a little. Again, we use macros instead of writing direct TeX,");
+ WX("% so as to allow the user to fiddle this stuff to taste without having to");
+ WX("% modify the FunnelWeb C code.");
+ WX("\\def\\fwodef{\\parindent=15pt\\vskip0pt$\\lbrace$\\parindent=20pt}");
+ WX("\\def\\fwcdef{$\\rbrace$\\vskip0pt\\parindent=0pt}");
+ WX("\\def\\fwoquote{`}");
+ WX("\\def\\fwcquote{'}");
+ WX("\\def\\fwoparen{$($}");
+ WX("\\def\\fwcomma{$,$}");
+ WX("\\def\\fwcparen{$)$}");
+ WX("\\def\\fwparam#1{$\\diamond #1$}");
+ WX("\\def\\fwparams#1{$(\\diamond #1)$}");
+ WX("");
+ WX("% These macros deal with the notes that are appended at the end of each");
+ WX("% macro definition. Note that even though \\fwisafile,\\fwusedin, and \\fwseealso");
+ WX("% have the same definition, they are given different names so as to allow the");
+ WX("% user to redefine these macros to typeset each kind of information differently");
+ WX("% if desired.");
+ WX("\\def\\fwbeginmacronotes{\\begingroup\\baselineskip=9pt\\smallskip}");
+ WX("\\def\\fwnote#1{{\\fwfontnote #1}\\par}");
+ WX("\\def\\fwisafile#1{\\fwnote{#1}}");
+ WX("\\def\\fwusedin#1{\\fwnote{#1}}");
+ WX("\\def\\fwseealso#1{\\fwnote{#1}}");
+ WX("\\def\\fwendmacronotes{\\endgroup}");
+ WX("");
+ WX("");
+ WX("% Macros to Typeset Program Code Verbatim");
+ WX("% ---------------------------------------");
+ WX("% This is by far the hairiest and most difficult part of the typesetting task");
+ WX("% because we have to turn off most of TeX's natural instincts in order to");
+ WX("% typeset the program text exactly as it appears in the input file.");
+ WX("% Two macros are defined to pull this off: \\fwbtx and \\fwverbatimgobble.");
+ WX("% Their code was inspired by the following sections of \"The TeXbook\":");
+ WX("% Appendix D: Dirty Tricks, 3.Verbatim listing, p.380-382.");
+ WX("% Appendix E: Example Formats, p.421.");
+ WX("% The \\fwbtx[ (for \"FunnelWeb Begin TeXt\") macro does most of the hard work.");
+ WX("% The liberal use of \"%\" is because I don't understand TeX well enough to");
+ WX("% understand when an end of line will cause trouble, and I am playing it safe.");
+ WX("");
+ WX("% Before defining the main \\fwbtx macro, we have to stash away some definitions");
+ WX("% in the hidden part of TeX's environment. Let's hope that these \"hidden\"");
+ WX("% definitions don't affect anything except what is desired to be affected.");
+ WX("");
+ WX("% The tt font in which we wish to set the text has two Latin lurking ligatures!");
+ WX("% These are ?` and !`. To disable them, we define the left quote when ACTIVE");
+ WX("% to be defined in such a way as to prevent ligatures. The main TeX text will");
+ WX("% normally not be exposed to this definition because normally the leftquote");
+ WX("% character is not active. The \\fwbtx macro temporarily makes the left quote");
+ WX("% character active thus activating the deactivation of left quote ligatures.");
+ WX("% See The TeXbook p.381.");
+ WX("{\\catcode`\\`=\\active \\gdef`{\\relax\\lq}}");
+ WX("");
+ WX("% TeX is fairly carefree about spaces and so we have to make it more serious.");
+ WX("% To do so we pull the same trick as above, setting up a definition for active");
+ WX("% space, but only making space active during the span of the verbatim text.");
+ WX("% In Plain TeX the active space is defined to be simply a space, but here we");
+ WX("% define it to be a control space. This ensures that the space cannot");
+ WX("% be gobbled up by one of TeX's mysterious mechanisms when activated.");
+ WX("% See The TeXbook, p.381 and p.352.");
+ WX("{\\obeyspaces\\global\\let =\\ }");
+ WX("");
+ WX("% Here is the main \\fwbtx verbatim text macro.");
+ WX("% Note: The order in which all these pieces of business have to be done is");
+ WX("% still a partial mystery to me. Don't fiddle with this stuff unless you");
+ WX("% think you know what you are doing.");
+ WX("\\def\\fwbtx[{%");
+ WX("%");
+ WX("% The funnies involved in getting verbatim output are safely housed inside");
+ WX("% this \\begingroup, and the \\endgroup in \\fwverbatimgobble. Groups are used");
+ WX("% instead of curly braces because we have to be able to signal the end of");
+ WX("% this macro with a curly brace.");
+ WX("\\begingroup%");
+ WX("%");
+ WX("% \\pars at the end of empty lines in the verbatim text won't come out normally");
+ WX("% because TeX is in vertical mode and they get gobbled up. To prevent this,");
+ WX("% we force \\par to exit vertical mode first. See The TeXbook p.381.");
+ WX("\\def\\par{\\leavevmode\\endgraf}%");
+ WX("%");
+ WX("% Activate the leftquote character so as to avoid ligatures (see above).");
+ WX("\\catcode`\\`=\\active%");
+ WX("%");
+ WX("% The \\obeylines macro simply defines end of line (^M) to be \\par. This ensures");
+ WX("% that TeX will treat each verbatim line as a new paragraph.");
+ WX("\\obeylines%");
+ WX("%");
+ WX("% To get verbatim output, we have to desex all the special characters. This");
+ WX("% is explained in detail in The TeXbook p.380.");
+ WX("\\def\\do##1{\\catcode`##1=12 }\\dospecials%");
+ WX("%");
+ WX("% Activate the space character so as to make TeX treat blanks seriously.");
+ WX("% This activation invokes an eralier definition (see above).");
+ WX("\\obeyspaces");
+ WX("%");
+ WX("% Interparagraph skips do not help the cause.");
+ WX("% Note: We have to preserve the indentation though, as the code is actually");
+ WX("% indented in the final output. See \\fwodef in an earlier section.");
+ WX("\\parskip=0pt%");
+ WX("%");
+ WX("% We typeset the verbatim text in tt font (courier on the Macintosh) for a");
+ WX("% number of reasons:");
+ WX("% - tt font has the same horizontal spacing for each character.");
+ WX("% - tt font covers the ASCII character set.");
+ WX("% - tt font doesn't have many surprises (e.g. ligatures).");
+ WX("% - tt font looks much what you might see on a computer terminal screen.");
+ WX("\\tt%");
+ WX("%");
+ WX("% Having set up an environment for verbatim, we are ready to use it.");
+ WX("% By invoking \\fwverbatimgobble, this \\fwbtx macro gobbles up text verbatim (as");
+ WX("% part of the parameter of \\fwverbatimgobble) until it sees the termination");
+ WX("% string \"]fwetx=\" (the \"=\" was thrown in to add obscurity as this sequence");
+ WX("% must never occur in the verbatim text).");
+ WX("\\fwverbatimgobble}");
+ WX("");
+ WX("% The \\fwverbatimgobble macro exists to allow \\fwbtx to bracket verbatim text.");
+ WX("\\def\\fwverbatimgobble#1]fwetx={#1\\endgroup}");
+ WX("");
+ WX("");
+ WX("% Table of Contents");
+ WX("% -----------------");
+ WX("% The five levels of table of contents that FunnelWeb supports are identified");
+ WX("% by the five letters [A..E]. These are used throughout the following macros.");
+ WX("");
+ WX("% The following macros are utilities to the TOC macros to follow.");
+ WX("\\def\\fwrule{\\medskip\\hrule\\medskip}");
+ WX("\\def\\fwqh{\\hskip1.5em\\relax}");
+ WX("\\def\\fwbeforesec{\\penalty-200\\bigskip\\medskip\\par}");
+ WX("");
+ WX("% The following macros are used to typeset the table of contents.");
+ WX("\\def\\fwtocstart#1{\\fwrule\\leftline{\\fwfontbolda Table of Contents}\\fwrule}");
+ WX("\\def\\fwtoca#1#2{\\leftline{{\\bf #1 #2}}}");
+ WX("\\def\\fwtocb#1#2{\\leftline{\\fwqh #1 #2}}");
+ WX("\\def\\fwtocc#1#2{\\leftline{\\fwqh\\fwqh #1 #2}}");
+ WX("\\def\\fwtocd#1#2{\\leftline{\\fwqh\\fwqh\\fwqh #1 #2}}");
+ WX("\\def\\fwtoce#1#2{\\leftline{\\fwqh\\fwqh\\fwqh\\fwqh #1 #2}}");
+ WX("\\def\\fwtocfinish#1{\\fwrule}");
+ WX("");
+ WX("% The following \"library\" macros define five different strengths of headings");
+ WX("% which can be used later in the section macros.");
+ WX("\\def\\fwliba#1#2{\\vfill\\eject{\\fwfontboldc #1 #2}\\penalty200\\smallskip}");
+ WX("\\def\\fwlibb#1#2{\\fwbeforesec{\\fwfontboldb #1 #2}\\penalty200\\smallskip}");
+ WX("\\def\\fwlibc#1#2{\\fwbeforesec{\\fwfontnormb #1 #2}\\penalty200\\smallskip}");
+ WX("\\def\\fwlibd#1#2{\\fwbeforesec{\\bf #1 #2}\\penalty200}");
+ WX("\\def\\fwlibe#1#2{\\fwbeforesec{\\bf #1 #2}}");
+ WX("");
+ WX("% Here are the macros that actually typeset the section headings throughout");
+ WX("% the document. The fwlib system has been employed so as to easily allow the");
+ WX("% user to redefine the strengths of headings to taste. For example, the");
+ WX("% user could insert in the input document a similar set of definitions to these");
+ WX("% but with the b..e headings set to \\fwlibc. This would tone down the output.");
+ WX("\\def\\fwseca#1#2{\\fwliba{#1}{#2}}");
+ WX("\\def\\fwsecb#1#2{\\fwlibb{#1}{#2}}");
+ WX("\\def\\fwsecc#1#2{\\fwlibc{#1}{#2}}");
+ WX("\\def\\fwsecd#1#2{\\fwlibd{#1}{#2}}");
+ WX("\\def\\fwsece#1#2{\\fwlibe{#1}{#2}}");
+ WX("");
+ WX("");
+ WX("% Support for Explicit Typesetting");
+ WX("% --------------------------------");
+ WX("% FunnelWeb supports pragmas and other constructs that allow");
+ WX("% typesetter-independent typesetting commands to be given. The");
+ WX("% following macros support these features.");
+ WX("");
+ WX("% The in-text literal @{sloth@} and emphasise @[walrus@] features.");
+ WX("\\def\\fwlit#1{{\\tt #1}}");
+ WX("\\def\\fwemp#1{{\\it #1}}");
+ WX("");
+ WX("% The \"@p new_page\" pragma.");
+ WX("\\def\\fwnewpage{\\vfill\\eject}");
+ WX("");
+ WX("% The \"@p vskip Nmm\" pragma.");
+ WX("\\def\\fwvskip#1{\\null\\vskip #1mm}");
+ WX("");
+ WX("% The \"@p title <font> <align> <text>\" pragma.");
+ WX("\\def\\fwfontnormal#1{{\\fwfontnorm {#1}}}");
+ WX("\\def\\fwfonttitle#1{{\\fwfontboldd {#1}}}");
+ WX("\\def\\fwfontsmalltitle#1{{\\fwfontboldb {#1}}}");
+ WX("\\def\\fwleftline#1{\\leftline{#1}}");
+ WX("\\def\\fwcenterline#1{\\centerline{#1}}");
+ WX("\\def\\fwrightline#1{\\rightline{#1}}");
+ WX("");
+ WX("");
+ WX("% Support for Old FunnelWeb");
+ WX("% -------------------------");
+ WX("% The following macros were used extensively in the first version of");
+ WX("% FunnelWeb and are retained so that these older input files will still");
+ WX("% typeset cleanly.");
+ WX("\\def\\p#1{{\\tt #1}} % P for Program text.");
+ WX("\\def\\flagpage#1#2{");
+ WX(" \\null");
+ WX(" \\vfill");
+ WX(" \\centerline{\\fwfontboldd #1}");
+ WX(" \\vskip 1cm");
+ WX(" \\centerline{\\fwfontboldd #2}");
+ WX(" \\vfill");
+ WX(" \\null");
+ WX(" \\vfill");
+ WX("}");
+ WX("");
+ WX("%====================== End of FunnelWeb TeX Definitions =======================");
diff --git a/web/funnelAC/fwACsrc/texhead.h b/web/funnelAC/fwACsrc/texhead.h
new file mode 100644
index 0000000000..cc5c31fcd9
--- /dev/null
+++ b/web/funnelAC/fwACsrc/texhead.h
@@ -0,0 +1,125 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* TEXHEAD.H */
+/******************************************************************************/
+/* */
+/* TEX HEADER PACKAGE */
+/* ================== */
+/* This package contains a single function that writes the TeX header */
+/* (containing all the Weave macros) to the specified stream. The package */
+/* consists of: */
+/* */
+/* texhead.tex - The header file ("source code" for texhead.ctx). */
+/* texhead.ctx - C code automatically generated by texhead.tex. */
+/* texhead.h - This file, containing a function definition. */
+/* texhead.c - Contains a function body. */
+/* */
+/* The first version of FunnelWeb (1986) generated TeX output files that used */
+/* a collection of macros to neaten and simplify the bulk of the TeX output */
+/* file. For example, the macro \fwbtx provided a simple way to specify */
+/* verbatim text. This system worked extremely well, the only inconvenience */
+/* being that each FunnelWeb TeX output file had to "\input" the TeX header */
+/* file containing all the macros. At the time, this seemed a sensible */
+/* factorization of the macros, and, within the limited environment in which */
+/* FunnelWeb was operating, worked well. */
+/* */
+/* In NEW, IMPROVED FunnelWeb, "\input"ing the header file has the potential */
+/* to cause lots of problems, the major ones being: */
+/* */
+/* - The header file would have to be installed as part of the FunnelWeb */
+/* system. Currently this means that it would be the ONLY other file */
+/* necessary apart from the FunnelWeb executable. It would be far more */
+/* desirable to avoid having to install the header file. */
+/* */
+/* - The header file would have to be referred to somehow by the TeX file. */
+/* As it makes sense to have only one copy of the header file on a machine, */
+/* TeX files would have to refer to that copy. This would require one of a */
+/* number of messy machine-specific mechanisms such as (VMS) logical name */
+/* translation or environment variable translation. */
+/* */
+/* - TeX files could not be easily moved to other machines (particularly */
+/* those not running FunnelWeb themselves) without also sending the header */
+/* file. */
+/* */
+/* - If FunnelWeb and the header file were ever jointly modified, the dynamic */
+/* binding of old TeX files would mean that they may no longer be printable.*/
+/* */
+/* For all these reasons, the decision was made to write the library of TeX */
+/* macros at the start of each TeX output file, thus making each TeX output */
+/* file entirely self-contained. To do this, the header file had to be */
+/* converted into a sequence of C output statments. To this end, a new */
+/* FunnelWeb shell command CODIFY was added that performs this transformation.*/
+/* CODIFY could have been a separate utility program, but if it was, it might */
+/* somehow be separated from the rest of FunnelWeb during distribution. By */
+/* building CODIFY into FunnelWeb itself, this possibility is eliminated. */
+/* */
+/* This package encapsulates the automatically generated C code. This header */
+/* file defines a function that writes it to a specified stream. The package */
+/* body texhead.c contains the body of the function which consists mainly of */
+/* a #include of the automatically generated C code in texhead.ctx. */
+/* */
+/******************************************************************************/
+
+/* Ensure that the body of this header file is included at most once. */
+#ifndef DONE_TEXH
+#define DONE_TEXH
+
+/******************************************************************************/
+
+/* Define NO_HEADER to suppress inclusion of the FunnelWeb tex header
+ (for users of the LaTeX include file 'fw-latex.sty' who wish must
+ define a document style such as '\documentstyle[fw-latex]{report}'). */
+
+#include "style.h"
+
+#include "writfile.h"
+
+/******************************************************************************/
+
+EXPORT void tex_head P_((p_wf_t));
+/* Writes the FunnelWeb TeX header block to the argument stream. */
+
+/******************************************************************************/
+
+/* For #ifndef preventing multiple inclusion of the body of this header file. */
+#endif
+
+/******************************************************************************/
+/* End of TEXHEAD.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/texhead.tex b/web/funnelAC/fwACsrc/texhead.tex
new file mode 100644
index 0000000000..0109a04fb0
--- /dev/null
+++ b/web/funnelAC/fwACsrc/texhead.tex
@@ -0,0 +1,320 @@
+%===================== Start of FunnelWeb TeX Definitions ======================
+
+
+% Version
+% -------
+% This is FunnelWeb TeX Macro Library Version 1.0.
+
+
+% Copyright
+% ---------
+% This set of FunnelWeb TeX definitions was written by Ross Williams and was
+% originally Copyright (C) 1992 Ross N. Williams. However, I, Ross Williams,
+% hereby forego any claim to Copyright in this set of FunnelWeb TeX definitions
+% and hereby authorize that the set of TeX definitions pass into the public
+% domain. -- Ross N. Williams, 3:41pm 07-May-1992, Adelaide, Australia.
+
+
+% Modification
+% ------------
+% Please record all modifications to these TeX definitions here. Unless
+% otherwise specified, all modified definitions fall in the public domain too.
+%
+% Programmers:
+% RNW Ross N. Williams ross@spam.adelaide.edu.au
+%
+% Changes:
+% 07-May-1992 RNW Prepared this work for public domain release.
+%
+
+
+% General Comments
+% ----------------
+% This set of TeX definitions exists for two reasons:
+%
+% 1. To shorten and neaten the FunnelWeb TeX output.
+% 2. To allow users to fiddle with the output format in their input files
+% (by inserting redefining "\def"s) without having to resort to
+% modifying the FunnelWeb code.
+%
+% The user is warned that these definitions may be changed from time to time
+% (but probably not much). The user should not be too sneaky. In particular,
+% users wishing to redefine some of these macros should do so in an explicitly
+% defined section at the top of their input file. This will mean that in the
+% event of problems, that section can simply be deleted or commented out to
+% allow the document to at least be typeset in the default format. Users should
+% limit themselves to redefining these macros in such a section and should
+% refrain from using the macros throughout their documents.
+
+
+% Environment Parameters
+% ----------------------
+% \tolerance tells TeX how tolerant it should be about making bad line and
+% page breaks. Here we set it to it's maximum, as
+% 1) Computer programs are likely to cause lots of bad breaks.
+% 2) In most cases the user would probably rather get the TeX file through
+% TeX without any errors than fiddle with spacings for perfection.
+\tolerance=10000
+
+% I don't like indentation as it makes the page look more busy. Instead,
+% paragraphs are separated by a little space (see next).
+\parindent=0pt
+
+% In many cases, users will produce documents with long runs of paragraphs.
+% In order to space out these paragraphs, it is convenient to maintain a
+% prevailing non-zero \parskip (end-of-paragaph skip). The only trouble is
+% that the skip becomes a problem in macro definitions which require no skip
+% and so we have to turn the skip on and off. The following two macros
+% simplify this process.
+\def\fwparskipon{\parskip=\medskipamount}
+\def\fwparskipoff{\parskip=0pt}
+\fwparskipon
+
+% Setting raggedbottom allows TeX to leave a bit of space at the bottom of the
+% page in order to better vertically align the rest of the page (e.g. skips
+% won't stretch as much). It also means that headings are less likely to be
+% isolated at the bottom of the page without any following text.
+\raggedbottom
+
+
+% Fonts
+% -----
+% Most of the typeset output is set in 10pt roman and 10pt tt font.
+% The major extra font needs spring from titles and headings.
+% For portability's sake we use only the following fonts:
+% cmr10
+% cmbx10
+% cmtt10
+% and some enlargements of them. These fonts are all "standard" fonts
+% in Plain TeX. See The TeXbook p.350.
+\font\fwfontnote=cmr7
+
+\font\fwfontnorm=cmr10
+\font\fwfontnorma=cmr10 scaled \magstep1
+\font\fwfontnormb=cmr10 scaled \magstep2
+
+\font\fwfontbold=cmbx10
+\font\fwfontbolda=cmbx10 scaled \magstep1
+\font\fwfontboldb=cmbx10 scaled \magstep2
+\font\fwfontboldc=cmbx10 scaled \magstep3
+\font\fwfontboldd=cmbx10 scaled \magstep4
+
+
+% Macros for Stylistic Details
+% ----------------------------
+% This section contains all the fiddly little macros for setting the details
+% of each macro definition.
+
+% Macro definitions are sandwiched by calls to these macros which can be used
+% to sort out the spacing before and after the macro definition.
+\def\fwbeginmacro{\fwparskipoff\bigskip}
+\def\fwendmacro{\fwparskipon\par}
+
+% These macros deal with the macro name and definition line.
+\def\fwmacroname#1#2{{\sl #1\/}$\lbrack$#2$\rbrack$}
+\def\fwfilename#1#2{{\bf #1}$\lbrack$#2$\rbrack$}
+\def\fwzero#1{{\bf Z}}
+\def\fwmany#1{{\bf M}}
+\def\fwequals{ $\equiv$}
+\def\fwplusequals{ $+\equiv$}
+
+% Now for the actual body of the definition. It looks nice to have the tt
+% code indented a little. Again, we use macros instead of writing direct TeX,
+% so as to allow the user to fiddle this stuff to taste without having to
+% modify the FunnelWeb C code.
+\def\fwodef{\parindent=15pt\vskip0pt$\lbrace$\parindent=20pt}
+\def\fwcdef{$\rbrace$\vskip0pt\parindent=0pt}
+\def\fwoquote{`}
+\def\fwcquote{'}
+\def\fwoparen{$($}
+\def\fwcomma{$,$}
+\def\fwcparen{$)$}
+\def\fwparam#1{$\diamond #1$}
+\def\fwparams#1{$(\diamond #1)$}
+
+% These macros deal with the notes that are appended at the end of each
+% macro definition. Note that even though \fwisafile,\fwusedin, and \fwseealso
+% have the same definition, they are given different names so as to allow the
+% user to redefine these macros to typeset each kind of information differently
+% if desired.
+\def\fwbeginmacronotes{\begingroup\baselineskip=9pt\smallskip}
+\def\fwnote#1{{\fwfontnote #1}\par}
+\def\fwisafile#1{\fwnote{#1}}
+\def\fwusedin#1{\fwnote{#1}}
+\def\fwseealso#1{\fwnote{#1}}
+\def\fwendmacronotes{\endgroup}
+
+
+% Macros to Typeset Program Code Verbatim
+% ---------------------------------------
+% This is by far the hairiest and most difficult part of the typesetting task
+% because we have to turn off most of TeX's natural instincts in order to
+% typeset the program text exactly as it appears in the input file.
+% Two macros are defined to pull this off: \fwbtx and \fwverbatimgobble.
+% Their code was inspired by the following sections of "The TeXbook":
+% Appendix D: Dirty Tricks, 3.Verbatim listing, p.380-382.
+% Appendix E: Example Formats, p.421.
+% The \fwbtx[ (for "FunnelWeb Begin TeXt") macro does most of the hard work.
+% The liberal use of "%" is because I don't understand TeX well enough to
+% understand when an end of line will cause trouble, and I am playing it safe.
+
+% Before defining the main \fwbtx macro, we have to stash away some definitions
+% in the hidden part of TeX's environment. Let's hope that these "hidden"
+% definitions don't affect anything except what is desired to be affected.
+
+% The tt font in which we wish to set the text has two Latin lurking ligatures!
+% These are ?` and !`. To disable them, we define the left quote when ACTIVE
+% to be defined in such a way as to prevent ligatures. The main TeX text will
+% normally not be exposed to this definition because normally the leftquote
+% character is not active. The \fwbtx macro temporarily makes the left quote
+% character active thus activating the deactivation of left quote ligatures.
+% See The TeXbook p.381.
+{\catcode`\`=\active \gdef`{\relax\lq}}
+
+% TeX is fairly carefree about spaces and so we have to make it more serious.
+% To do so we pull the same trick as above, setting up a definition for active
+% space, but only making space active during the span of the verbatim text.
+% In Plain TeX the active space is defined to be simply a space, but here we
+% define it to be a control space. This ensures that the space cannot
+% be gobbled up by one of TeX's mysterious mechanisms when activated.
+% See The TeXbook, p.381 and p.352.
+{\obeyspaces\global\let =\ }
+
+% Here is the main \fwbtx verbatim text macro.
+% Note: The order in which all these pieces of business have to be done is
+% still a partial mystery to me. Don't fiddle with this stuff unless you
+% think you know what you are doing.
+\def\fwbtx[{%
+%
+% The funnies involved in getting verbatim output are safely housed inside
+% this \begingroup, and the \endgroup in \fwverbatimgobble. Groups are used
+% instead of curly braces because we have to be able to signal the end of
+% this macro with a curly brace.
+\begingroup%
+%
+% \pars at the end of empty lines in the verbatim text won't come out normally
+% because TeX is in vertical mode and they get gobbled up. To prevent this,
+% we force \par to exit vertical mode first. See The TeXbook p.381.
+\def\par{\leavevmode\endgraf}%
+%
+% Activate the leftquote character so as to avoid ligatures (see above).
+\catcode`\`=\active%
+%
+% The \obeylines macro simply defines end of line (^M) to be \par. This ensures
+% that TeX will treat each verbatim line as a new paragraph.
+\obeylines%
+%
+% To get verbatim output, we have to desex all the special characters. This
+% is explained in detail in The TeXbook p.380.
+\def\do##1{\catcode`##1=12 }\dospecials%
+%
+% Activate the space character so as to make TeX treat blanks seriously.
+% This activation invokes an eralier definition (see above).
+\obeyspaces
+%
+% Interparagraph skips do not help the cause.
+% Note: We have to preserve the indentation though, as the code is actually
+% indented in the final output. See \fwodef in an earlier section.
+\parskip=0pt%
+%
+% We typeset the verbatim text in tt font (courier on the Macintosh) for a
+% number of reasons:
+% - tt font has the same horizontal spacing for each character.
+% - tt font covers the ASCII character set.
+% - tt font doesn't have many surprises (e.g. ligatures).
+% - tt font looks much what you might see on a computer terminal screen.
+\tt%
+%
+% Having set up an environment for verbatim, we are ready to use it.
+% By invoking \fwverbatimgobble, this \fwbtx macro gobbles up text verbatim (as
+% part of the parameter of \fwverbatimgobble) until it sees the termination
+% string "]fwetx=" (the "=" was thrown in to add obscurity as this sequence
+% must never occur in the verbatim text).
+\fwverbatimgobble}
+
+% The \fwverbatimgobble macro exists to allow \fwbtx to bracket verbatim text.
+\def\fwverbatimgobble#1]fwetx={#1\endgroup}
+
+
+% Table of Contents
+% -----------------
+% The five levels of table of contents that FunnelWeb supports are identified
+% by the five letters [A..E]. These are used throughout the following macros.
+
+% The following macros are utilities to the TOC macros to follow.
+\def\fwrule{\medskip\hrule\medskip}
+\def\fwqh{\hskip1.5em\relax}
+\def\fwbeforesec{\penalty-200\bigskip\medskip\par}
+
+% The following macros are used to typeset the table of contents.
+\def\fwtocstart#1{\fwrule\leftline{\fwfontbolda Table of Contents}\fwrule}
+\def\fwtoca#1#2{\leftline{{\bf #1 #2}}}
+\def\fwtocb#1#2{\leftline{\fwqh #1 #2}}
+\def\fwtocc#1#2{\leftline{\fwqh\fwqh #1 #2}}
+\def\fwtocd#1#2{\leftline{\fwqh\fwqh\fwqh #1 #2}}
+\def\fwtoce#1#2{\leftline{\fwqh\fwqh\fwqh\fwqh #1 #2}}
+\def\fwtocfinish#1{\fwrule}
+
+% The following "library" macros define five different strengths of headings
+% which can be used later in the section macros.
+\def\fwliba#1#2{\vfill\eject{\fwfontboldc #1 #2}\penalty200\smallskip}
+\def\fwlibb#1#2{\fwbeforesec{\fwfontboldb #1 #2}\penalty200\smallskip}
+\def\fwlibc#1#2{\fwbeforesec{\fwfontnormb #1 #2}\penalty200\smallskip}
+\def\fwlibd#1#2{\fwbeforesec{\bf #1 #2}\penalty200}
+\def\fwlibe#1#2{\fwbeforesec{\bf #1 #2}}
+
+% Here are the macros that actually typeset the section headings throughout
+% the document. The fwlib system has been employed so as to easily allow the
+% user to redefine the strengths of headings to taste. For example, the
+% user could insert in the input document a similar set of definitions to these
+% but with the b..e headings set to \fwlibc. This would tone down the output.
+\def\fwseca#1#2{\fwliba{#1}{#2}}
+\def\fwsecb#1#2{\fwlibb{#1}{#2}}
+\def\fwsecc#1#2{\fwlibc{#1}{#2}}
+\def\fwsecd#1#2{\fwlibd{#1}{#2}}
+\def\fwsece#1#2{\fwlibe{#1}{#2}}
+
+
+% Support for Explicit Typesetting
+% --------------------------------
+% FunnelWeb supports pragmas and other constructs that allow
+% typesetter-independent typesetting commands to be given. The
+% following macros support these features.
+
+% The in-text literal @{sloth@} and emphasise @[walrus@] features.
+\def\fwlit#1{{\tt #1}}
+\def\fwemp#1{{\it #1}}
+
+% The "@p new_page" pragma.
+\def\fwnewpage{\vfill\eject}
+
+% The "@p vskip Nmm" pragma.
+\def\fwvskip#1{\null\vskip #1mm}
+
+% The "@p title <font> <align> <text>" pragma.
+\def\fwfontnormal#1{{\fwfontnorm {#1}}}
+\def\fwfonttitle#1{{\fwfontboldd {#1}}}
+\def\fwfontsmalltitle#1{{\fwfontboldb {#1}}}
+\def\fwleftline#1{\leftline{#1}}
+\def\fwcenterline#1{\centerline{#1}}
+\def\fwrightline#1{\rightline{#1}}
+
+
+% Support for Old FunnelWeb
+% -------------------------
+% The following macros were used extensively in the first version of
+% FunnelWeb and are retained so that these older input files will still
+% typeset cleanly.
+\def\p#1{{\tt #1}} % P for Program text.
+\def\flagpage#1#2{
+ \null
+ \vfill
+ \centerline{\fwfontboldd #1}
+ \vskip 1cm
+ \centerline{\fwfontboldd #2}
+ \vfill
+ \null
+ \vfill
+}
+
+%====================== End of FunnelWeb TeX Definitions =======================
diff --git a/web/funnelAC/fwACsrc/weave.c b/web/funnelAC/fwACsrc/weave.c
new file mode 100644
index 0000000000..f530285dc2
--- /dev/null
+++ b/web/funnelAC/fwACsrc/weave.c
@@ -0,0 +1,2330 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 31-Aug-1993 ABC Added support for EL_SPEC
+ 11-Jan-1994 ABC Added MAXINV which defines the maximum
+ number of macro invocation citations
+ which should be put on the one TeX line.
+ 15-Apr-1994 ABC Added hypertext typesetter types
+ TR_HTXT and TR_HTML, which are to HTML hypertext
+ what TR_NONE and TR_TEX are to TeX respectively.
+ 15-Apr-1994 ABC Added doc_incQ flag for inclusion or not of
+ FunnelWeb TeX/HTML header. If FALSE, also
+ suppresses the "\bye" at the end of TeX files
+ and the <HTML>...</HTML> markup surrounding
+ HTML files.
+ 20-May-1994 ABC Added raw_namQ flag for allowing or not of
+ raw TeX/HTML in macro/section names
+ (TR_TEX or TR_HTML modes only).
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* WEAVE.C */
+/******************************************************************************/
+
+#include <ctype.h>
+#include "style.h"
+
+#include "as.h"
+#include "data.h"
+#include "lister.h"
+#include "machin.h"
+#include "misc.h"
+#include "table.h"
+#include "texhead.h"
+/* ABC { */
+#include "htmlhead.h"
+/* } ABC */
+#include "weave.h"
+
+/* ABC { */
+/* MAXINV is the maximum number of macro invocation references */
+/* that should be put on one TeX line */
+/* This stops line to big for the TeX buffer from being created. */
+#define MAXINV 20
+/* } ABC */
+
+/* IMPORTANT WARNING: The Macintosh THINK C compiler sets up strings that */
+/* start with \p or \P as PASCAL strings rather than C strings. So be very */
+/* careful not to start any strings with \p or \P. */
+
+/******************************************************************************/
+
+LOCVAR wf_t f_t; /* Variable representing documentation file. */
+LOCVAR bool literal; /* True if we are inside a literal @{. */
+/* ABC { */
+LOCVAR bool title1Q; /* True if a title is the first for the document. */
+LOCVAR bool lastEOLQ; /* last written text scrap finished with EOL? */
+/* } ABC */
+
+/******************************************************************************/
+
+LOCAL void wv_ex P_((p_ells_t));
+
+/******************************************************************************/
+
+LOCAL char * fn_nodir P_((char *));
+LOCAL char * fn_nodir (p)
+/* Given a pointer to a string, returns a pointer to the character just past */
+/* the last occurrance of FN_DELIM, or a pointer to the start of the string */
+/* if it does not occur. In other words, given a filename, return a pointer */
+/* to the start of the name field. */
+char *p;
+{
+ char *q = strrchr(p,FN_DELIM);
+ if (q==NULL)
+ return p;
+ else
+ return q+1;
+}
+
+/******************************************************************************/
+
+LOCAL void wf_dec P_((p_wf_t,ulong));
+LOCAL void wf_dec(p_wf,n)
+/* Writes the unsigned number n to the specified output stream as a decimal. */
+/* This function has been named wf_dec so that it can be moved to the wf */
+/* package if it turns out to be popular. */
+p_wf_t p_wf;
+ulong n;
+{
+ char t[20];
+ sprintf(t,"%lu",n);
+ wf_wr(p_wf,t);
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txugch P_((int));
+LOCAL void wv_txugch(ch)
+/* WeaVe TeX UGly CHaracter. */
+/* } ABC */
+/* Sometimes it is necessary to output text without causing the typesetting */
+/* program (TeX) to interpret it as control sequences and generate errors. */
+/* There are two ways of doing this. First, we can get the typesetter to do */
+/* the work by making it less sensitive. This has been done with the */
+/* typesetting of the main macro text. The other approach is to convert each */
+/* offending character into the typesetter control sequence that will simply */
+/* output the character. For example, in TeX, "$" becomes "\$". This function */
+/* accepts a single character and writes out its safe equivalent. */
+/* The term "ugly" is used to describe potentially harmful text/characters. */
+int ch;
+{
+ /* End of lines are the only non-printable allowed. */
+ if (ch==EOL) {wf_chr(&f_t,EOL); return;}
+
+ /* All other non-printables result in a bullet. In the absence of bugs, the */
+ /* only way a non-printable can get to us here is as a result of the user */
+ /* explicitly inserting one using the scanner's @^ control sequence. */
+ if (!isascprn(ch))
+ {
+ wf_wr(&f_t,"$\\bullet$");
+ return;
+ }
+ /* If it IS printable, then print it ... carefully! */
+ switch (ch)
+ {
+ /* Go through the printables in ASCII order. */
+ /* ' ': is an ordinary character. */
+ /* '!': is an ordinary character. */
+ case '\"': wf_wr(&f_t,"\\char`\\\""); break;
+ case '#': wf_wr(&f_t,"\\#"); break;
+ case '$': wf_wr(&f_t,"\\$"); break;
+ /* Note: The string "\\%" triggers a unknown sequence "\%" in GNUC. */
+ case '%': wf_chr(&f_t,'\\'); wf_chr(&f_t,'%'); break;
+ case '&': wf_wr(&f_t,"\\&"); break;
+ /* ''': is an ordinary character. */
+ /* '(': is an ordinary character. */
+ /* ')': is an ordinary character. */
+ /* '*': is an ordinary character. */
+ /* '+': is an ordinary character. */
+ /* ',': is an ordinary character. */
+ /* '-': is an ordinary character. */
+ /* '.': is an ordinary character. */
+ /* '/': is an ordinary character. */
+ /* '0-9': are ordinary characters.*/
+ /* ':': is an ordinary character. */
+ /* ';': is an ordinary character. */
+ /* Note: Some \chars work well in roman. Others don't. */
+ case '<': if (literal)
+ wf_wr(&f_t,"\\char`\\<");
+ else
+ wf_wr(&f_t,"$<$");
+ break;
+ /* '=': is an ordinary character. */
+ case '>': if (literal)
+ wf_wr(&f_t,"\\char`\\>");
+ else
+ wf_wr(&f_t,"$>$");
+ break;
+ /* '?': is an ordinary character. */
+ /* '@': is an ordinary character. */
+ /* 'A-Z': are ordinary characters.*/
+ /* '[': is an ordinary character. */
+ case '\\': if (literal)
+ wf_wr(&f_t,"\\char`\\\\");
+ else
+ wf_wr(&f_t,"$\\backslash$");
+ break;
+ /* ']': is an ordinary character. */
+ case '^': wf_wr(&f_t,"\\char`\\^"); break;
+ case '_': wf_wr(&f_t,"\\_"); break;
+ /* '`': is an ordinary character. */
+ /* 'a-z': are ordinary characters.*/
+ case '{': if (literal)
+ wf_wr(&f_t,"\\char`\\{");
+ else
+ wf_wr(&f_t,"$\\{$");
+ break;
+ case '|': if (literal)
+ wf_wr(&f_t,"\\char`\\|");
+ else
+ wf_wr(&f_t,"$|$");
+ break;
+ case '}': if (literal)
+ wf_wr(&f_t,"\\char`\\}");
+ else
+ wf_wr(&f_t,"$\\}$");
+ break;
+ case '~': wf_wr(&f_t,"\\char`\\~"); break;
+ default: wf_chr(&f_t,ch); break;
+ }
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_htugch P_((int));
+LOCAL void wv_htugch(ch)
+/* WeaVe HTml UGly CHaracter. */
+/* Sometimes it is necessary to output text without causing the typesetting */
+/* program (HTML displayer) to interpret it as control sequences and generate */
+/* errors. */
+/* There are two ways of doing this. First, we can get the typesetter to do */
+/* the work by making it less sensitive. This has been done with the */
+/* typesetting of the main macro text. The other approach is to convert each */
+/* offending character into the typesetter control sequence that will simply */
+/* output the character. For example, in HTML, "<" becomes "&lt;". This */
+/* function accepts a single character and writes out its safe equivalent. */
+/* The term "ugly" is used to describe potentially harmful text/characters. */
+int ch;
+{
+ /* End of lines are the only non-printable allowed. */
+ if (ch==EOL) {wf_chr(&f_t,EOL); return;}
+
+ /* All other non-printables result in an inverted question mark. In the */
+ /* absence of bugs, the only way a non-printable can get to us here is as a */
+ /* result of the user explicitly inserting one using the scanner's @^ */
+ /* control sequence. */
+ if (!isascprn(ch))
+ {
+ wf_wr(&f_t,"&#191;"); /* inverted question mark */
+ return;
+ }
+ /* If it IS printable, then print it ... carefully! */
+ switch (ch)
+ {
+ /* Go through the printables in ASCII order. */
+ /* ' ': is an ordinary character. */
+ /* '!': is an ordinary character. */
+ /* '\"': is an ordinary character. */
+ /* '#': is an ordinary character. */
+ /* '$': is an ordinary character. */
+ /* '%': is an ordinary character. */
+ case '&': wf_wr(&f_t,"&amp;");
+ break;
+ /* ''': is an ordinary character. */
+ /* '(': is an ordinary character. */
+ /* ')': is an ordinary character. */
+ /* '*': is an ordinary character. */
+ /* '+': is an ordinary character. */
+ /* ',': is an ordinary character. */
+ /* '-': is an ordinary character. */
+ /* '.': is an ordinary character. */
+ /* '/': is an ordinary character. */
+ /* '0-9': are ordinary characters.*/
+ /* ':': is an ordinary character. */
+ /* ';': is an ordinary character. */
+ case '<': wf_wr(&f_t,"&lt;");
+ break;
+ /* '=': is an ordinary character. */
+ case '>': wf_wr(&f_t,"&gt;");
+ break;
+ /* '?': is an ordinary character. */
+ /* '@': is an ordinary character. */
+ /* 'A-Z': are ordinary characters.*/
+ /* '[': is an ordinary character. */
+ /* '\\': is an ordinary character. */
+ /* ']': is an ordinary character. */
+ /* '^': is an ordinary character. */
+ /* '_': is an ordinary character. */
+ /* '`': is an ordinary character. */
+ /* 'a-z': are ordinary characters.*/
+ /* '{': is an ordinary character. */
+ /* '|': is an ordinary character. */
+ /* '}': is an ordinary character. */
+ /* '~': is an ordinary character. */
+ default: wf_chr(&f_t,ch); break;
+ }
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_ugch P_((int));
+LOCAL void wv_ugch(ch)
+/* WeaVe TeX UGly CHaracter. */
+/* Selects either the TeX or HTML ugly character pre-processing function. */
+int ch;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txugch(ch); break;
+ case TR_HTXT :
+ case TR_HTML : wv_htugch(ch); break;
+ default : as_bomb("wv_ugch:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+LOCAL void wv_ugstr P_((char *));
+LOCAL void wv_ugstr(s)
+/* Writes out a potentially ugly string. */
+char *s;
+{
+ while (*s != EOS)
+ wv_ugch(*s++);
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txugsc P_((p_sc_t));
+LOCAL void wv_txugsc(p_sc)
+/* } ABC */
+/* Writes out a potentially ugly TeX text scrap. */
+p_sc_t p_sc;
+{
+ char *p = p_sc->sc_first;
+ char *p_last = p_sc->sc_last;
+
+ while (p<=p_last)
+ wv_ugch(*p++);
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_htugsc P_((p_sc_t));
+LOCAL void wv_htugsc(p_sc)
+/* Writes out a potentially ugly HTML text scrap. */
+/* This is where paragraph (<P>) markups may be added for */
+/* hypertext mode wherever groups of contiguous blank */
+/* lines are left in the text (not inside macros). */
+p_sc_t p_sc;
+{
+ char *p_first = p_sc->sc_first;
+ char *p_last = p_sc->sc_last;
+ char *p = p_first;
+
+ if (no_pmrkQ) {
+ while (p<=p_last) wv_ugch(*p++);
+ } else {
+ if ((f_t.wf_last == EOL) && (*p == EOL)) {
+ /* if two EOLs in a row are found, it signals */
+ /* the start of a new HTML paragraph */
+ wf_wl(&f_t, "<P>");
+ /* scan past further EOLs in a row */
+ while ((*(++p) == EOL) && (p <= p_last));
+ } /* end if */
+ while (p<=p_last) {
+ /* if two EOLs in a row are found, it signals */
+ /* the start of a new HTML paragraph */
+ if ((*p == EOL) && (p != p_first) && (*(p-1) == EOL)) {
+ wf_wl(&f_t, "<P>");
+ /* scan past further EOLs in a row */
+ while ((*(++p) == EOL) && (p <= p_last));
+ } else {
+ wv_ugch(*p++);
+ } /* end if */
+ } /* end while */
+ } /* end if */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_htsc P_((p_sc_t));
+LOCAL void wv_htsc(p_sc)
+/* Writes out a potentially ugly HTML text code scrap. */
+/* This function does not insert paragraph markups. */
+p_sc_t p_sc;
+{
+ char *p_first = p_sc->sc_first;
+ char *p_last = p_sc->sc_last;
+ char *p = p_first;
+
+ while (p<=p_last) wv_ugch(*p++);
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_ugsc P_((p_sc_t));
+LOCAL void wv_ugsc(p_sc)
+/* Writes out a potentially ugly text scrap. */
+p_sc_t p_sc;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txugsc(p_sc); break;
+ case TR_HTXT :
+ case TR_HTML : wv_htugsc(p_sc); break;
+ default : as_bomb("wv_ugsc:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+LOCAL void wv_ugscls P_((p_scls_t));
+LOCAL void wv_ugscls(p_scls)
+/* This function writes the specified text list to the output stream. It */
+/* writes it cleaning up all ugly characters. */
+p_scls_t p_scls;
+{
+ ls_fir(p_scls);
+ while (TRUE)
+ {
+ p_sc_t p_sc;
+ ls_nxt(p_scls,PPV &p_sc);
+ if (p_sc==NULL) break;
+ wv_ugsc(p_sc);
+ }
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txmanm P_((p_ma_t,ulong));
+LOCAL void wv_txmanm(p_ma,part)
+/* } ABC */
+/* This function writes the specified macro name and no. in TeX. */
+/* The part number is the part to write out. */
+p_ma_t p_ma;
+ulong part;
+{
+ p_bp_t p_bp;
+
+ /* ABC { */
+ if (p_ma->ma_defn.md_isfil) {
+ wf_wr(&f_t,"\\fwfilename{");
+ wv_ugstr(p_ma->ma_name);
+ } else {
+ wf_wr(&f_t,"\\fwmacroname{");
+ if (raw_namQ && (tr_codes==TR_TEX)) {
+ wf_wr(&f_t,p_ma->ma_name);
+ } else {
+ wv_ugstr(p_ma->ma_name);
+ } /* end if */
+ } /* end if */
+ /* } ABC */
+ wf_wr(&f_t,"}{");
+ ls_loo(p_ma->ma_defn.md_body,part,PPV &p_bp);
+ wf_dec(&f_t,(ulong) p_bp->bp_seq);
+ wf_wr(&f_t,"}");
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_htmanm P_((p_ma_t,ulong));
+LOCAL void wv_htmanm(p_ma,part)
+/* This function writes the specified macro name and no. in HTML. */
+/* The part number is the part to write out. */
+p_ma_t p_ma;
+ulong part;
+{
+ p_bp_t p_bp;
+
+ if (p_ma->ma_defn.md_isfil) {
+ wf_wr(&f_t,"<STRONG>");
+ wv_ugstr(p_ma->ma_name);
+ } else {
+ wf_wr(&f_t,"<CITE>");
+ if (raw_namQ && (tr_codes==TR_HTML)) {
+ wf_wr(&f_t,p_ma->ma_name);
+ } else {
+ wv_ugstr(p_ma->ma_name);
+ } /* end if */
+ } /* end if */
+ if (p_ma->ma_defn.md_isfil)
+ wf_wr(&f_t,"</STRONG>");
+ else
+ wf_wr(&f_t,"</CITE>");
+ wf_wr(&f_t,"[");
+ ls_loo(p_ma->ma_defn.md_body,part,PPV &p_bp);
+ wf_dec(&f_t,(ulong) p_bp->bp_seq);
+ wf_wr(&f_t,"]");
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_manm P_((p_ma_t,ulong));
+LOCAL void wv_manm(p_ma,part)
+/* This function writes the specified macro name and no. */
+/* The part number is the part to write out. */
+p_ma_t p_ma;
+ulong part;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txmanm(p_ma,part); break;
+ case TR_HTXT :
+ case TR_HTML : wv_htmanm(p_ma,part); break;
+ default : as_bomb("wv_manm:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_mano P_((p_ma_t,ulong));
+LOCAL void wv_mano(p_ma,part)
+/* This function writes the specified macro no. */
+/* The part number is the part to write out. */
+p_ma_t p_ma;
+ulong part;
+{
+ p_bp_t p_bp;
+
+ ls_loo(p_ma->ma_defn.md_body,part,PPV &p_bp);
+ wf_dec(&f_t,(ulong) p_bp->bp_seq);
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txsecnn P_((p_ty_t));
+LOCAL void wv_txsecnn(p_ty)
+/* } ABC */
+/* Write out the section number and name, each in curly braces. */
+p_ty_t p_ty;
+{
+ /* Write as arguments the section number and name. */
+ wf_chr(&f_t,'{');
+ sn_str(&p_ty->ty_sn,linet1);
+ wf_wr(&f_t,linet1);
+ wf_wr(&f_t,"}{");
+ /* ABC { */
+ if (raw_namQ && (tr_codes==TR_TEX)) {
+ wf_wr(&f_t,p_ty->ty_name);
+ } else {
+ wv_ugstr(p_ty->ty_name);
+ } /* end if */
+ /* } ABC */
+ wf_chr(&f_t,'}');
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_htsecnn P_((p_ty_t));
+LOCAL void wv_htsecnn(p_ty)
+/* Write out the section number and name. */
+p_ty_t p_ty;
+{
+ /* Write as arguments the section number and name. */
+ sn_str(&p_ty->ty_sn,linet1);
+ wf_wr(&f_t,linet1);
+ wf_wr(&f_t," ");
+ /* ABC { */
+ if (raw_namQ && (tr_codes==TR_HTML)) {
+ wf_wr(&f_t,p_ty->ty_name);
+ } else {
+ wv_ugstr(p_ty->ty_name);
+ } /* end if */
+ /* } ABC */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_secnn P_((p_ty_t));
+LOCAL void wv_secnn(p_ty)
+/* Write out the section number and name. */
+p_ty_t p_ty;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txsecnn(p_ty); break;
+ case TR_HTXT :
+ case TR_HTML : wv_htsecnn(p_ty); break;
+ default : as_bomb("wv_secnn:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txecho P_((p_scls_t));
+LOCAL void wv_txecho(p_scls)
+/* This function writes the specified text list to the output stream. It */
+/* writes it just as it is, with no modifications whatsoever. */
+p_scls_t p_scls;
+{
+ ls_fir(p_scls);
+ while (TRUE)
+ {
+ p_sc_t p_sc;
+ ls_nxt(p_scls,PPV &p_sc);
+ if (p_sc==NULL) break;
+ wf_blk(&f_t,p_sc->sc_first,(size_t)
+ (p_sc->sc_last-p_sc->sc_first+1));
+ }
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_htecho P_((p_scls_t));
+LOCAL void wv_htecho(p_scls)
+/* This function writes the specified text list to the output stream. It */
+/* writes it just as it is, except that '<' --> "&lt;" and '>' --> "&gt;" */
+/* and '&' --> "&amp;". */
+p_scls_t p_scls;
+{
+ ls_fir(p_scls);
+ while (TRUE)
+ {
+ p_sc_t p_sc;
+ ls_nxt(p_scls,PPV &p_sc);
+ if (p_sc==NULL) break;
+ wv_htsc(p_sc);
+ }
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+/* This function writes the specified text list to the output stream. It */
+/* writes it just as it is, changing as few characters as possible . */
+LOCAL void wv_echo P_((p_scls_t));
+LOCAL void wv_echo(p_scls)
+p_scls_t p_scls;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txecho(p_scls); break;
+ case TR_HTXT :
+ case TR_HTML : wv_htecho(p_scls); break;
+ default : as_bomb("wv_echo:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txverb P_((p_scls_t));
+LOCAL void wv_txverb(p_scls)
+/* } ABC */
+/* Writes a TeX text list verbetim, but brackets it with sequences that */
+/* instruct the typesetter not to interpret the text in any special way. */
+p_scls_t p_scls;
+{
+ if (ls_len(p_scls) > 0)
+ {
+ wf_wr(&f_t,"\\fwbtx[");
+ wv_echo(p_scls);
+ wf_wl(&f_t,"]fwetx=%");
+ }
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_htverb P_((p_scls_t));
+LOCAL void wv_htverb(p_scls)
+/* } ABC */
+/* Writes an HTML text list verbetim, but brackets it with sequences that */
+/* instruct the typesetter not to interpret the text in any special way. */
+p_scls_t p_scls;
+{
+ if (ls_len(p_scls) > 0)
+ {
+ wf_wr(&f_t,"<CODE>");
+ wv_echo(p_scls);
+ wf_wr(&f_t,"</CODE>");
+ }
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_verb P_((p_scls_t));
+LOCAL void wv_verb(p_scls)
+/* } ABC */
+/* Writes a text list verbetim, but brackets it with sequences that */
+/* instruct the typesetter not to interpret the text in any special way. */
+p_scls_t p_scls;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txverb(p_scls); break;
+ case TR_HTXT :
+ case TR_HTML : wv_htverb(p_scls); break;
+ default : as_bomb("wv_verb:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txhead P_((void));
+LOCAL void wv_txhead()
+/* } ABC */
+{
+ wf_wl(&f_t,"");
+ wf_wl(&f_t,"%*******************************************************************************");
+ wf_wl(&f_t,"%* START OF AUTOMATICALLY GENERATED TEX FILE *");
+ wf_wl(&f_t,"%*******************************************************************************");
+ wf_wl(&f_t,"%* *");
+ wf_wl(&f_t,"%* This TeX file was automatically generated by the FunnelWeb preprocessor. *");
+ wf_wl(&f_t,"%* You can typeset this file to produce printed documentation by running it *");
+ wf_wl(&f_t,"%* through the TeX typesetter using a command such as: *");
+ /* ABC { */
+ if (doc_incQ) {
+ wf_wl(&f_t,"%* tex thisfilename *");
+ } else {
+ wf_wl(&f_t,"%* latex thisfilename *");
+ wf_wl(&f_t,"%* (the standard TeX header was not included, due to the presence of a *");
+ wf_wl(&f_t,"%* `@p no_doc_header' pragma in the original FunnelWeb source file. *");
+ wf_wl(&f_t,"%* It is hence assumed that the FunnelWeb code was in the form of a LaTeX *");
+ wf_wl(&f_t,"%* file starting with a line of the form *");
+ wf_wl(&f_t,"%* \\documentstyle[fw-latex,...]{...} *");
+ wf_wl(&f_t,"%* If not, don't blame FunnelWeb for the resulting TeX or LaTeX errors ... *");
+ wf_wl(&f_t,"%* The file `fw-latex.sty' can be found at the ftp archive noted below.) *");
+ } /* end if */
+ /* } ABC */
+ wf_wl(&f_t,"%* The resultant file thisfilename.dvi can be printed using a command such as: *");
+ wf_wl(&f_t,"%* lpr -Pcslw -d thisfilename.dvi *");
+ wf_wl(&f_t,"%* *");
+ wf_wl(&f_t,"%* FunnelWeb is a preprocessor that allows programmers to weave programs and *");
+ wf_wl(&f_t,"%* their documentation together in a single document. The FunnelWeb program *");
+ wf_wl(&f_t,"%* analyses such documents producing both program files and typeset *");
+ wf_wl(&f_t,"%* documentation such as this TeX file. *");
+ wf_wl(&f_t,"%* FunnelWeb was created by Ross Williams. *");
+ wf_wl(&f_t,"%* *");
+ wf_wl(&f_t,"%* For more information on FunnelWeb look in the following FTP archive: *");
+ wf_wl(&f_t,"%* Machine : sirius.itd.adelaide.edu.au [IP=129.127.40.3]. *");
+ wf_wl(&f_t,"%* Directory: ~pub/funnelweb/ *");
+ wf_wl(&f_t,"%* (or some other appropriately named directory). *");
+ wf_wl(&f_t,"%* or email Ross Williams at ross@spam.adelaide.edu.au *");
+ if (!doc_incQ) {
+ wf_wl(&f_t,"%* (Tony Coates at coates@physics.uq.edu.au for pragma `no_doc_header') *");
+ } /* end if */
+ if (raw_namQ) {
+ wf_wl(&f_t,"%* (Tony Coates at coates@physics.uq.edu.au for pragma `raw_macro_and_section_names') *");
+ } /* end if */
+ wf_wl(&f_t,"%* *");
+ wf_wl(&f_t,"%*******************************************************************************");
+ wf_wl(&f_t,"");
+ wf_wl(&f_t,"");
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_hthead P_((void));
+LOCAL void wv_hthead()
+{
+ wf_wl(&f_t,"");
+ wf_wl(&f_t,"<!--*************************************************************************-->");
+ wf_wl(&f_t,"<!-- START OF AUTOMATICALLY GENERATED HTML FILE -->");
+ wf_wl(&f_t,"<!--*************************************************************************-->");
+ wf_wl(&f_t,"<!-- -->");
+ wf_wl(&f_t,"<!--This HTML file was automatically generated by the FunnelWeb preprocessor.-->");
+ wf_wl(&f_t,"<!--You can view this file using an HTML viewer such as `Mosaic'. -->");
+ wf_wl(&f_t,"<!--FunnelWeb is a preprocessor that allows programmers to weave programs and-->");
+ wf_wl(&f_t,"<!--their documentation together in a single document. The FunnelWeb program -->");
+ wf_wl(&f_t,"<!--analyses such documents producing both program files and typeset -->");
+ wf_wl(&f_t,"<!--documentation such as this HTML file. -->");
+ wf_wl(&f_t,"<!--FunnelWeb was created by Ross Williams. -->");
+ wf_wl(&f_t,"<!-- -->");
+ wf_wl(&f_t,"<!--For more information on FunnelWeb look in the following FTP archive: -->");
+ wf_wl(&f_t,"<!-- Machine : sirius.itd.adelaide.edu.au [IP=129.127.40.3]. -->");
+ wf_wl(&f_t,"<!-- Directory: ~pub/funnelweb/ -->");
+ wf_wl(&f_t,"<!-- (or some other appropriately named directory). -->");
+ wf_wl(&f_t,"<!--or email Ross Williams at ross@spam.adelaide.edu.au -->");
+ wf_wl(&f_t,"<!-- (Tony Coates at coates@physics.uq.edu.au for HTML support) -->");
+ wf_wl(&f_t,"<!-- -->");
+ wf_wl(&f_t,"<!--*************************************************************************-->");
+ wf_wl(&f_t,"");
+ wf_wl(&f_t,"");
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_head P_((void));
+LOCAL void wv_head()
+{
+ if ((tr_codes==TR_HTXT) || (tr_codes==TR_HTML)) wv_hthead();
+ else wv_txhead();
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txtail P_((void));
+LOCAL void wv_txtail()
+/* } ABC */
+{
+ wf_wl(&f_t,"");
+ wf_wl(&f_t,"");
+ wf_wl(&f_t,"%*******************************************************************************");
+ wf_wl(&f_t,"%* END OF AUTOMATICALLY GENERATED TEX FILE *");
+ wf_wl(&f_t,"%*******************************************************************************");
+ wf_wl(&f_t,"");
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_httail P_((void));
+LOCAL void wv_httail()
+{
+ wf_wl(&f_t,"");
+ wf_wl(&f_t,"");
+ wf_wl(&f_t,"<!--*************************************************************************-->");
+ wf_wl(&f_t,"<!-- END OF AUTOMATICALLY GENERATED HTML FILE -->");
+ wf_wl(&f_t,"<!--*************************************************************************-->");
+ wf_wl(&f_t,"");
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_tail P_((void));
+LOCAL void wv_tail()
+{
+ if ((tr_codes==TR_HTXT) || (tr_codes==TR_HTML)) wv_httail();
+ else wv_txtail();
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txnsec P_((p_ty_t));
+LOCAL void wv_txnsec(p_ty)
+/* } ABC */
+/* Weaves the start of a new TeX section. */
+p_ty_t p_ty;
+{
+ as_cold(p_ty->ty_kind==TY_NSEC,"wv_txnsec: Not a section!");
+
+ /* Work out what kind of section macro should be used. */
+ switch (sn_lev(&p_ty->ty_sn))
+ {
+ case 1: wf_wr(&f_t,"\\fwseca"); break;
+ case 2: wf_wr(&f_t,"\\fwsecb"); break;
+ case 3: wf_wr(&f_t,"\\fwsecc"); break;
+ case 4: wf_wr(&f_t,"\\fwsecd"); break;
+ case 5: wf_wr(&f_t,"\\fwsece"); break;
+ default: as_bomb("wv_txnsec:case defaulted.");
+ }
+
+ /* Write out the section number and name. */
+ wv_secnn(p_ty);
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_htnsec P_((p_ty_t));
+LOCAL void wv_htnsec(p_ty)
+/* Weaves the start of a new HTML section. */
+p_ty_t p_ty;
+{
+ as_cold(p_ty->ty_kind==TY_NSEC,"wv_htnsec: Not a section!");
+
+ /* Work out what kind of section macro should be used. */
+ switch (sn_lev(&p_ty->ty_sn))
+ {
+ case 1: wf_wr(&f_t,"<H1>"); break;
+ case 2: wf_wr(&f_t,"<H2>"); break;
+ case 3: wf_wr(&f_t,"<H3>"); break;
+ case 4: wf_wr(&f_t,"<H4>"); break;
+ case 5: wf_wr(&f_t,"<H5>"); break;
+ default: as_bomb("wv_htnsec:case defaulted.");
+ }
+
+ /* Write out an HTML anchor, which will be attached to
+ * the index if any
+ */
+ wf_wr(&f_t,"<A NAME=\"");
+ wv_secnn(p_ty);
+ wf_wr(&f_t,"\">");
+
+ /* Write out the section number and name. */
+ wv_secnn(p_ty);
+
+ /* Close anchor */
+ wf_wr(&f_t,"</A>");
+
+ /* Close section heading. */
+ switch (sn_lev(&p_ty->ty_sn))
+ {
+ case 1: wf_wr(&f_t,"</H1>"); break;
+ case 2: wf_wr(&f_t,"</H2>"); break;
+ case 3: wf_wr(&f_t,"</H3>"); break;
+ case 4: wf_wr(&f_t,"</H4>"); break;
+ case 5: wf_wr(&f_t,"</H5>"); break;
+ default: as_bomb("wv_htnsec:case defaulted.");
+ }
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_nsec P_((p_ty_t));
+LOCAL void wv_nsec(p_ty)
+/* Weaves the start of a new section. */
+p_ty_t p_ty;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txnsec(p_ty); break;
+ case TR_HTXT :
+ case TR_HTML : wv_htnsec(p_ty); break;
+ default : as_bomb("wv_nsec:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txolit P_((p_ty_t));
+LOCAL void wv_txolit(p_ty)
+/* } ABC */
+p_ty_t p_ty;
+{
+ as_cold(p_ty->ty_kind==TY_OLIT,"wv_txolit: Not an open literal!");
+ wf_wr(&f_t,"\\fwlit{");
+ literal=TRUE;
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_htolit P_((p_ty_t));
+LOCAL void wv_htolit(p_ty)
+p_ty_t p_ty;
+{
+ as_cold(p_ty->ty_kind==TY_OLIT,"wv_htolit: Not an open literal!");
+ wf_wr(&f_t,"<CODE>");
+ literal=TRUE;
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_olit P_((p_ty_t));
+LOCAL void wv_olit(p_ty)
+p_ty_t p_ty;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txolit(p_ty); break;
+ case TR_HTXT :
+ case TR_HTML : wv_htolit(p_ty); break;
+ default : as_bomb("wv_olit:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txclit P_((p_ty_t));
+LOCAL void wv_txclit(p_ty)
+/* } ABC */
+p_ty_t p_ty;
+{
+ as_cold(p_ty->ty_kind==TY_CLIT,"wv_txclit: Not a close literal!");
+ wf_wr(&f_t,"}");
+ literal=FALSE;
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_htclit P_((p_ty_t));
+LOCAL void wv_htclit(p_ty)
+p_ty_t p_ty;
+{
+ as_cold(p_ty->ty_kind==TY_CLIT,"wv_htclit: Not a close literal!");
+ wf_wr(&f_t,"</CODE>");
+ literal=FALSE;
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_clit P_((p_ty_t));
+LOCAL void wv_clit(p_ty)
+p_ty_t p_ty;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txclit(p_ty); break;
+ case TR_HTXT :
+ case TR_HTML : wv_htclit(p_ty); break;
+ default : as_bomb("wv_clit:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txoemp P_((p_ty_t));
+LOCAL void wv_txoemp(p_ty)
+/* } ABC */
+p_ty_t p_ty;
+{
+ as_cold(p_ty->ty_kind==TY_OEMP,"wv_txoemp: Not an open emphasize!");
+ wf_wr(&f_t,"\\fwemp{");
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_htoemp P_((p_ty_t));
+LOCAL void wv_htoemp(p_ty)
+p_ty_t p_ty;
+{
+ as_cold(p_ty->ty_kind==TY_OEMP,"wv_htoemp: Not an open emphasize!");
+ wf_wr(&f_t,"<EM>");
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_oemp P_((p_ty_t));
+LOCAL void wv_oemp(p_ty)
+p_ty_t p_ty;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txoemp(p_ty); break;
+ case TR_HTXT :
+ case TR_HTML : wv_htoemp(p_ty); break;
+ default : as_bomb("wv_oemp:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txcemp P_((p_ty_t));
+LOCAL void wv_txcemp(p_ty)
+/* } ABC */
+p_ty_t p_ty;
+{
+ as_cold(p_ty->ty_kind==TY_CEMP,"wv_txcemp: Not a close emphasize!");
+ wf_wr(&f_t,"}");
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_htcemp P_((p_ty_t));
+LOCAL void wv_htcemp(p_ty)
+p_ty_t p_ty;
+{
+ as_cold(p_ty->ty_kind==TY_CEMP,"wv_htcemp: Not a close emphasize!");
+ wf_wr(&f_t,"</EM>");
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_cemp P_((p_ty_t));
+LOCAL void wv_cemp(p_ty)
+p_ty_t p_ty;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txcemp(p_ty); break;
+ case TR_HTXT :
+ case TR_HTML : wv_htcemp(p_ty); break;
+ default : as_bomb("wv_cemp:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txnpag P_((p_ty_t));
+LOCAL void wv_txnpag(p_ty)
+/* } ABC */
+p_ty_t p_ty;
+{
+ as_cold(p_ty->ty_kind==TY_NPAG,"wv_txnpag: Not a new page!");
+ wf_wl(&f_t,"");
+ wf_wl(&f_t,"\\fwnewpage");
+ wf_wl(&f_t,"");
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_htnpag P_((p_ty_t));
+LOCAL void wv_htnpag(p_ty)
+p_ty_t p_ty;
+{
+ as_cold(p_ty->ty_kind==TY_NPAG,"wv_htnpag: Not a new page!");
+ /* new pages are currently ignored for HTML */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_npag P_((p_ty_t));
+LOCAL void wv_npag(p_ty)
+p_ty_t p_ty;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txnpag(p_ty); break;
+ case TR_HTXT :
+ case TR_HTML : wv_htnpag(p_ty); break;
+ default : as_bomb("wv_npag:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txtocs P_((p_ty_t));
+LOCAL void wv_txtocs(p_ty)
+/* } ABC */
+/* Writes a TeX table of contents to the weave output file. */
+p_ty_t p_ty;
+{
+ /* We need to save the document list position as the rest of the weaver is */
+ /* in the process of traversing it!!! */
+ p_void p_mark = ls_mar(document_list);
+
+ as_cold(p_ty->ty_kind==TY_TOCS,"wv_txtocs: Not a table of contents!");
+
+ wf_wl(&f_t,"");
+ wf_wl(&f_t,"\\fwtocstart{}");
+ ls_fir(document_list);
+ while (TRUE)
+ {
+ p_dc_t p_dc;
+ ls_nxt(document_list,PPV &p_dc);
+ if (p_dc == NULL) break;
+ if (p_dc->dc_kind==DC_TYPE && p_dc->dc_ty.ty_kind==TY_NSEC)
+ {
+ switch(sn_lev(&p_dc->dc_ty.ty_sn))
+ {
+ case 1: wf_wr(&f_t,"\\fwtoca"); break;
+ case 2: wf_wr(&f_t,"\\fwtocb"); break;
+ case 3: wf_wr(&f_t,"\\fwtocc"); break;
+ case 4: wf_wr(&f_t,"\\fwtocd"); break;
+ case 5: wf_wr(&f_t,"\\fwtoce"); break;
+ default: as_bomb("wv_txtocs: switch defaulted.");
+ }
+ wv_secnn(&p_dc->dc_ty);
+ wf_wl(&f_t,"");
+ }
+ }
+ wf_wl(&f_t,"\\fwtocfinish{}");
+ wf_wl(&f_t,"");
+
+ /* Restore the document list position. */
+ ls_set(document_list,p_mark);
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_httocs P_((p_ty_t));
+LOCAL void wv_httocs(p_ty)
+/* Writes a table of contents to the weave output file. */
+p_ty_t p_ty;
+{
+ /* We need to save the document list position as the rest of the weaver is */
+ /* in the process of traversing it!!! */
+ p_void p_mark = ls_mar(document_list);
+
+ as_cold(p_ty->ty_kind==TY_TOCS,"wv_httocs: Not a table of contents!");
+
+ wf_wl(&f_t,"<HR>");
+ wf_wl(&f_t,"<H1>Table of Contents</H1>");
+ wf_wl(&f_t,"<HR>");
+ ls_fir(document_list);
+ while (TRUE)
+ {
+ p_dc_t p_dc;
+ ls_nxt(document_list,PPV &p_dc);
+ if (p_dc == NULL) break;
+ if (p_dc->dc_kind==DC_TYPE && p_dc->dc_ty.ty_kind==TY_NSEC)
+ {
+ switch(sn_lev(&p_dc->dc_ty.ty_sn))
+ {
+ case 1: wf_wr(&f_t,"<H2>"); break;
+ case 2: wf_wr(&f_t,"<H3>"); break;
+ case 3: wf_wr(&f_t,"<H4>"); break;
+ case 4: wf_wr(&f_t,"<H5>"); break;
+ case 5: wf_wr(&f_t,"<H6>"); break;
+ default: as_bomb("wv_httoc: switch defaulted.");
+ }
+ wf_wr(&f_t,"<A HREF=\"#");
+ wv_secnn(&p_dc->dc_ty);
+ wf_wr(&f_t,"\">");
+ wv_secnn(&p_dc->dc_ty);
+ wf_wr(&f_t,"</A>");
+ switch(sn_lev(&p_dc->dc_ty.ty_sn))
+ {
+ case 1: wf_wl(&f_t,"</H2>"); break;
+ case 2: wf_wl(&f_t,"</H3>"); break;
+ case 3: wf_wl(&f_t,"</H4>"); break;
+ case 4: wf_wl(&f_t,"</H5>"); break;
+ case 5: wf_wl(&f_t,"</H6>"); break;
+ default: as_bomb("wv_httoc: switch defaulted.");
+ }
+ }
+ }
+ wf_wl(&f_t,"<HR>");
+
+ /* Restore the document list position. */
+ ls_set(document_list,p_mark);
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_tocs P_((p_ty_t));
+LOCAL void wv_tocs(p_ty)
+/* Writes a table of contents to the weave output file. */
+p_ty_t p_ty;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txtocs(p_ty); break;
+ case TR_HTXT :
+ case TR_HTML : wv_httocs(p_ty); break;
+ default : as_bomb("wv_tocs:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txskip P_((p_ty_t));
+LOCAL void wv_txskip(p_ty)
+/* } ABC */
+/* Writes a vertical space to the output file. */
+p_ty_t p_ty;
+{
+ as_cold(p_ty->ty_kind==TY_SKIP,"wv_txskip: Not a skip directive!");
+
+ sprintf(linet1,"\\fwvskip{%lu}",(ulong) p_ty->ty_mm);
+ wf_wl(&f_t,linet1);
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_htskip P_((p_ty_t));
+LOCAL void wv_htskip(p_ty)
+/* Writes a vertical space to the output file. */
+p_ty_t p_ty;
+{
+ as_cold(p_ty->ty_kind==TY_SKIP,"wv_htskip: Not a skip directive!");
+
+ /* no skipping is currently done for HTML files */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_skip P_((p_ty_t));
+LOCAL void wv_skip(p_ty)
+/* Writes a vertical space to the output file. */
+p_ty_t p_ty;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txskip(p_ty); break;
+ case TR_HTXT :
+ case TR_HTML : wv_htskip(p_ty); break;
+ default : as_bomb("wv_skip:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txtitl P_((p_ty_t));
+LOCAL void wv_txtitl(p_ty)
+/* Writes a TeX title line to the output file. */
+/* } ABC */
+p_ty_t p_ty;
+{
+ as_cold(p_ty->ty_kind==TY_TITL,"wv_txtitl: Not a title!");
+
+ switch(p_ty->ty_align)
+ {
+ case LR_LEFT: wf_wr(&f_t,"\\fwleftline{"); break;
+ case LR_RIGH: wf_wr(&f_t,"\\fwrightline{"); break;
+ case LR_CENT: wf_wr(&f_t,"\\fwcenterline{"); break;
+ default: as_bomb("wv_txtitle: Alignment switch defaulted.");
+ }
+ switch(p_ty->ty_font)
+ {
+ case FT_NORM: wf_wr(&f_t,"\\fwfontnormal{"); break;
+ case FT_TITL: wf_wr(&f_t,"\\fwfonttitle{"); break;
+ case FT_STIT: wf_wr(&f_t,"\\fwfontsmalltitle{"); break;
+ default: as_bomb("wv_txtitle: Font switch defaulted.");
+ }
+ wv_ugsc(&p_ty->ty_sc);
+ wf_wl(&f_t,"}}");
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_httitl P_((p_ty_t));
+LOCAL void wv_httitl(p_ty)
+/* Writes an HTML title line to the output file,
+ * creating a document title if the title line is the
+ * first for the document.
+ */
+p_ty_t p_ty;
+{
+ as_cold(p_ty->ty_kind==TY_TITL,"wv_httitl: Not a title!");
+
+ if (title1Q) {
+ title1Q = FALSE;
+ wf_wl(&f_t, "<TITLE>");
+ switch(p_ty->ty_align)
+ {
+ /* Title alignment is currently ignored */
+ case LR_LEFT:
+ case LR_RIGH:
+ case LR_CENT: break;
+ default: as_bomb("wv_httitle: Alignment switch defaulted.");
+ }
+ switch(p_ty->ty_font)
+ {
+ /* Title font is currently ignored */
+ case FT_NORM:
+ case FT_TITL:
+ case FT_STIT: break;
+ default: as_bomb("wv_httitle: Font switch defaulted.");
+ }
+ wv_ugsc(&p_ty->ty_sc);
+ if (*(p_ty->ty_sc.sc_last) != '.') {
+ /* there may be more title lines to come */
+ wf_wr(&f_t," ...");
+ } /* end if */
+ wf_wl(&f_t,"\n</TITLE>");
+ } /* end if */
+
+ wf_wl(&f_t, "<H1>");
+ switch(p_ty->ty_align)
+ {
+ /* Title alignment is currently ignored */
+ case LR_LEFT:
+ case LR_RIGH:
+ case LR_CENT: break;
+ default: as_bomb("wv_httitle: Alignment switch defaulted.");
+ }
+ switch(p_ty->ty_font)
+ {
+ /* Title font is currently ignored */
+ case FT_NORM:
+ case FT_TITL:
+ case FT_STIT: break;
+ default: as_bomb("wv_httitle: Font switch defaulted.");
+ }
+ wv_ugsc(&p_ty->ty_sc);
+ wf_wl(&f_t,"\n</H1>");
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_titl P_((p_ty_t));
+LOCAL void wv_titl(p_ty)
+/* Writes a title line to the output file. */
+p_ty_t p_ty;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txtitl(p_ty); break;
+ case TR_HTXT :
+ case TR_HTML : wv_httitl(p_ty); break;
+ default : as_bomb("wv_titl:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+LOCAL void wv_dcty P_((p_dc_t));
+LOCAL void wv_dcty(p_dc)
+/* Weaves a document typesetter element. */
+p_dc_t p_dc;
+{
+ p_ty_t p_ty = &p_dc->dc_ty;
+
+ as_cold(p_dc->dc_kind==DC_TYPE,"wv_dcty: Not a typesetter component!");
+
+ switch (p_ty->ty_kind)
+ {
+ case TY_NSEC: wv_nsec(p_ty); break;
+ case TY_OLIT: wv_olit(p_ty); break;
+ case TY_CLIT: wv_clit(p_ty); break;
+ case TY_OEMP: wv_oemp(p_ty); break;
+ case TY_CEMP: wv_cemp(p_ty); break;
+ case TY_NPAG: wv_npag(p_ty); break;
+ case TY_TOCS: wv_tocs(p_ty); break;
+ case TY_SKIP: wv_skip(p_ty); break;
+ case TY_TITL: wv_titl(p_ty); break;
+ default : as_bomb("wv_dcty: Switch defaulted.");
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void wv_dctx P_((p_dc_t));
+LOCAL void wv_dctx(p_dc)
+/* Write out a document text item. */
+p_dc_t p_dc;
+{
+ as_cold(p_dc->dc_kind==DC_TEXT,"wv_dctx: Not text.");
+
+/* ABC { */
+ if (literal || (tr_codes==TR_NONE) || (tr_codes==TR_HTXT))
+/* } ABC */
+ wv_ugscls(p_dc->dc_text);
+ else
+ wv_echo(p_dc->dc_text);
+}
+
+/******************************************************************************/
+
+LOCAL void wv_eltx P_((p_el_t));
+LOCAL void wv_eltx(p_el)
+/* Weaves a text element. */
+p_el_t p_el;
+{
+ as_cold(p_el->el_kind==EL_TEXT,"wv_eltx: Not text.");
+ wv_verb(p_el->el_text);
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_ohtdf P_((void));
+LOCAL void wv_ohtdf()
+/* Write a macro definition tag opening */
+{
+ wf_wr(&f_t, "FWDEF[");
+}
+/* ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_chtdf P_((void));
+LOCAL void wv_chtdf()
+/* Write a macro definition tag closing */
+{
+ wf_wr(&f_t, "]DEFFW");
+}
+/* ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txelin P_((p_el_t));
+LOCAL void wv_txelin(p_el)
+/* } ABC */
+/* Weaves a TeX invocation element. */
+p_el_t p_el;
+{
+ as_cold(p_el->el_kind==EL_INVC,"wv_txelin: Not an invocation.");
+
+ /* Write out the macro call proper. */
+ wv_manm(p_el->el_p_mac,1L);
+
+ /* Write out the actual parameter list, if any. */
+ if (ls_len(p_el->el_parls) > 0)
+ {
+ ulong parnum;
+ wf_wr(&f_t,"\\fwoparen ");
+ ls_fir(p_el->el_parls); /* List of actual parameter expressions. */
+ ls_fir(p_el->el_pretx); /* List of crud before each expression. */
+ ls_fir(p_el->el_postx); /* List of crud after each expression. */
+ parnum=1;
+ while (TRUE)
+ {
+ p_ells_t *pp_exp;
+ p_scls_t *pp_scls1;
+ p_scls_t *pp_scls2;
+ ls_nxt(p_el->el_parls,PPV &pp_exp);
+ ls_nxt(p_el->el_pretx,PPV &pp_scls1);
+ ls_nxt(p_el->el_postx,PPV &pp_scls2);
+ if (pp_exp==NULL) break;
+ if (parnum++>1) wf_wr(&f_t,"\\fwcomma ");
+ wv_verb(*pp_scls1);
+ wf_wr(&f_t,"\\fwoquote"); wv_ex(*pp_exp); wf_wr(&f_t,"\\fwcquote");
+ wv_verb(*pp_scls2);
+ }
+ wf_wr(&f_t,"\\fwcparen ");
+ }
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_htelin P_((p_el_t));
+LOCAL void wv_htelin(p_el)
+/* Weaves an HTML invocation element. */
+p_el_t p_el;
+{
+ as_cold(p_el->el_kind==EL_INVC,"wv_htelin: Not an invocation.");
+
+ /* Write an anchor to reference the definition */
+ wf_wr(&f_t, "<A HREF=\"#");
+ wv_ohtdf();
+
+ /* Write out the macro no. */
+ wv_mano(p_el->el_p_mac,1L);
+
+ /* Close the anchor name */
+ wv_chtdf();
+ wf_wr(&f_t, "\">");
+
+ /* Write out the macro call proper. */
+ wv_manm(p_el->el_p_mac,1L);
+
+ /* Close anchor */
+ wf_wr(&f_t, "</A>");
+
+ /* Write out the actual parameter list, if any. */
+ if (ls_len(p_el->el_parls) > 0)
+ {
+ ulong parnum;
+ wf_wr(&f_t,"(");
+ ls_fir(p_el->el_parls); /* List of actual parameter expressions. */
+ ls_fir(p_el->el_pretx); /* List of crud before each expression. */
+ ls_fir(p_el->el_postx); /* List of crud after each expression. */
+ parnum=1;
+ while (TRUE)
+ {
+ p_ells_t *pp_exp;
+ p_scls_t *pp_scls1;
+ p_scls_t *pp_scls2;
+ ls_nxt(p_el->el_parls,PPV &pp_exp);
+ ls_nxt(p_el->el_pretx,PPV &pp_scls1);
+ ls_nxt(p_el->el_postx,PPV &pp_scls2);
+ if (pp_exp==NULL) break;
+ if (parnum++>1) wf_wr(&f_t,",");
+ wv_verb(*pp_scls1);
+ wf_wr(&f_t,"`"); wv_ex(*pp_exp); wf_wr(&f_t,"'");
+ wv_verb(*pp_scls2);
+ }
+ wf_wr(&f_t,")");
+ }
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_elin P_((p_el_t));
+LOCAL void wv_elin(p_el)
+/* Weaves an invocation element. */
+p_el_t p_el;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txelin(p_el); break;
+ case TR_HTXT :
+ case TR_HTML : wv_htelin(p_el); break;
+ default : as_bomb("wv_elin:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txelpr P_((p_el_t));
+LOCAL void wv_txelpr(p_el)
+/* } ABC */
+/* Weaves a TeX parameter element. */
+p_el_t p_el;
+{
+ as_cold(p_el->el_kind==EL_PARM,"wv_txelpr: Not a parameter.");
+ wf_wr (&f_t,"\\fwparam{");
+ wf_dec(&f_t,(ulong) p_el->el_parno);
+ wf_wr (&f_t,"}");
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_htelpr P_((p_el_t));
+LOCAL void wv_htelpr(p_el)
+/* Weaves an HTML parameter element. */
+p_el_t p_el;
+{
+ as_cold(p_el->el_kind==EL_PARM,"wv_htelpr: Not a parameter.");
+ wf_wr (&f_t,"#");
+ wf_dec(&f_t,(ulong) p_el->el_parno);
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_elpr P_((p_el_t));
+LOCAL void wv_elpr(p_el)
+/* Weaves a parameter element. */
+p_el_t p_el;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txelpr(p_el); break;
+ case TR_HTXT :
+ case TR_HTML : wv_htelpr(p_el); break;
+ default : as_bomb("wv_elpr:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/* ABC { */
+/******************************************************************************/
+
+LOCAL void wv_elsp P_((p_el_t));
+LOCAL void wv_elsp(p_el)
+/* Weaves a special function element. */
+p_el_t p_el;
+{
+ as_cold(p_el->el_kind==EL_SPEC,"wv_elsp: Not an internal function.");
+}
+
+/* } ABC */
+
+/******************************************************************************/
+
+LOCAL void wv_ex(p_exp)
+/* Weaves a expression. */
+p_ells_t p_exp;
+{
+
+ ls_fir(p_exp);
+ while (TRUE)
+ {
+ p_el_t p_el;
+ ls_nxt(p_exp,PPV &p_el);
+ if (p_el==NULL) break;
+ switch (p_el->el_kind)
+ {
+ case EL_TEXT: wv_eltx(p_el); break;
+ case EL_INVC: wv_elin(p_el); break;
+ case EL_PARM: wv_elpr(p_el); break;
+ /* ABC { */
+ case EL_SPEC: wv_elsp(p_el); break;
+ /* } ABC */
+ default: as_bomb("wv_ex: Case defaulted.");
+ }
+ }
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txusage P_((p_ma_t));
+LOCAL void wv_txusage(p_ma)
+/* } ABC */
+/* Weaves a TeX list of all the sections in which the specified macro is used. */
+p_ma_t p_ma;
+{
+ ulong no_calls = ls_len(p_ma->ma_calls);
+ ulong callno;
+
+ /* If it is a file macro then it is not allowed to be called. */
+ if (p_ma->ma_defn.md_isfil)
+ {
+ wf_wl(&f_t,"\\fwisafile{This macro is attached to an output file.}");
+ return;
+ }
+
+ if (no_calls==0)
+ {
+ wf_wl(&f_t,"\\fwusedin{This macro is NEVER invoked.}");
+ return;
+ }
+
+ wf_wr(&f_t,"\\fwusedin{This macro is invoked in definition");
+ if (no_calls>1) wf_chr(&f_t,'s');
+ wf_chr(&f_t,' ');
+ ls_fir(p_ma->ma_calls);
+ for (callno=1;callno<=no_calls;callno++)
+ {
+ p_mc_t p_mc;
+ ls_nxt(p_ma->ma_calls,PPV &p_mc);
+ as_cold(p_mc!=NULL,"wv_txusage: Awk!");
+ wf_dec(&f_t,(ulong) p_mc->mc_seq);
+ if (callno < no_calls-1) {
+ wf_wr(&f_t,", ");
+ /* ABC{ */
+ /* add return if necessary [ABC] */
+ if (callno % MAXINV == 0) wf_wr(&f_t,"\n");
+ /* } ABC */
+ } else
+ if (callno==no_calls-1)
+ if (no_calls>2)
+ wf_wr(&f_t,", and ");
+ else
+ wf_wr(&f_t," and ");
+ }
+ wf_wl(&f_t,".}");
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_htusage P_((p_ma_t));
+LOCAL void wv_htusage(p_ma)
+/* Weaves an HTML list of all the sections in which the specified macro is used. */
+p_ma_t p_ma;
+{
+ ulong no_calls = ls_len(p_ma->ma_calls);
+ ulong callno;
+
+ /* If it is a file macro then it is not allowed to be called. */
+ if (p_ma->ma_defn.md_isfil)
+ {
+ wf_wr(&f_t,"<CITE>");
+ wf_wr(&f_t,"This macro is attached to an output file.");
+ wf_wl(&f_t,"</CITE>");
+ return;
+ }
+
+ if (no_calls==0)
+ {
+ wf_wl(&f_t,"<CITE>This macro is NEVER invoked.</CITE>");
+ return;
+ }
+
+ wf_wr(&f_t,"<CITE>This macro is invoked in definition");
+ if (no_calls>1) wf_chr(&f_t,'s');
+ wf_chr(&f_t,' ');
+ ls_fir(p_ma->ma_calls);
+ for (callno=1;callno<=no_calls;callno++)
+ {
+ p_mc_t p_mc;
+ ls_nxt(p_ma->ma_calls,PPV &p_mc);
+ as_cold(p_mc!=NULL,"wv_htusage: Awk!");
+ wf_wr(&f_t, "<A HREF=\"#");
+ wv_ohtdf();
+ wf_dec(&f_t,(ulong) p_mc->mc_seq);
+ wv_chtdf();
+ wf_wr(&f_t, "\">");
+ wf_dec(&f_t,(ulong) p_mc->mc_seq);
+ wf_wr(&f_t, "</A>");
+ if (callno < no_calls-1) {
+ wf_wr(&f_t,", ");
+ /* ABC{ */
+ /* add HTML return if necessary [ABC] */
+ if (callno % MAXINV == 0) wf_wr(&f_t,"\n");
+ /* } ABC */
+ } else
+ if (callno==no_calls-1)
+ if (no_calls>2)
+ wf_wr(&f_t,", and ");
+ else
+ wf_wr(&f_t," and ");
+ }
+ wf_wl(&f_t,".</CITE>");
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_usage P_((p_ma_t));
+LOCAL void wv_usage(p_ma)
+/* Weaves a list of all the sections in which the specified macro is used. */
+p_ma_t p_ma;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txusage(p_ma); break;
+ case TR_HTXT :
+ case TR_HTML : wv_htusage(p_ma); break;
+ default : as_bomb("wv_usage:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txdefin P_((p_ma_t));
+LOCAL void wv_txdefin(p_ma)
+/* } ABC */
+/* Just after each macro body part definition comes a note listing the */
+/* containing the macro's body parts. This function weaves that list. */
+p_ma_t p_ma;
+{
+ ulong no_parts = ls_len(p_ma->ma_defn.md_body);
+ ulong partno;
+
+ /* If it's not an additive macro, we don't write anything. */
+ if (!p_ma->ma_defn.md_isadd) return;
+
+ wf_wr(&f_t,"\\fwseealso{This macro is defined in definitions ");
+ ls_fir(p_ma->ma_defn.md_body);
+ for (partno=1;partno<=no_parts;partno++)
+ {
+ p_bp_t p_bp;
+ ls_nxt(p_ma->ma_defn.md_body,PPV &p_bp);
+ as_cold(p_bp!=NULL,"wv_txdefin: Awk!");
+ wf_dec(&f_t,(ulong) p_bp->bp_seq);
+ if (partno<no_parts-1)
+ wf_wr(&f_t,", ");
+ else
+ if (partno==no_parts-1)
+ if (no_parts>2)
+ wf_wr(&f_t,", and ");
+ else
+ wf_wr(&f_t," and ");
+ }
+ wf_wl(&f_t,".}");
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_htdefin P_((p_ma_t));
+LOCAL void wv_htdefin(p_ma)
+/* Just after each macro body part definition comes a note listing the */
+/* containing the macro's body parts. This function weaves that list. */
+p_ma_t p_ma;
+{
+ ulong no_parts = ls_len(p_ma->ma_defn.md_body);
+ ulong partno;
+
+ /* If it's not an additive macro, we don't write anything. */
+ if (!p_ma->ma_defn.md_isadd) return;
+
+ wf_wr(&f_t,"<CITE>This macro is defined in definitions ");
+ ls_fir(p_ma->ma_defn.md_body);
+ for (partno=1;partno<=no_parts;partno++)
+ {
+ p_bp_t p_bp;
+ ls_nxt(p_ma->ma_defn.md_body,PPV &p_bp);
+ as_cold(p_bp!=NULL,"wv_htdefin: Awk!");
+ wf_wr(&f_t, "<A HREF=\"#");
+ wv_ohtdf();
+ wf_dec(&f_t,(ulong) p_bp->bp_seq);
+ wv_chtdf();
+ wf_wr(&f_t, "\">");
+ wf_dec(&f_t,(ulong) p_bp->bp_seq);
+ wf_wr(&f_t, "</A>");
+ if (partno<no_parts-1)
+ wf_wr(&f_t,", ");
+ else
+ if (partno==no_parts-1)
+ if (no_parts>2)
+ wf_wr(&f_t,", and ");
+ else
+ wf_wr(&f_t," and ");
+ }
+ wf_wl(&f_t,".</CITE>");
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_defin P_((p_ma_t));
+LOCAL void wv_defin(p_ma)
+/* Just after each macro body part definition comes a note listing the */
+/* containing the macro's body parts. This function weaves that list. */
+p_ma_t p_ma;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txdefin(p_ma); break;
+ case TR_HTXT :
+ case TR_HTML : wv_htdefin(p_ma); break;
+ default : as_bomb("wv_defin:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_txdcma P_((p_dc_t));
+LOCAL void wv_txdcma(p_dc)
+/* } ABC */
+/* Weaves a macro definition in TeX. */
+p_dc_t p_dc;
+{
+ p_bp_t p_bp;
+
+ /* Macro calls sandwich the definition itsef. */
+ wf_wl(&f_t,"\\fwbeginmacro");
+
+ /* Write out the macro's name. */
+ wv_manm(p_dc->dc_p_ma,p_dc->dc_part);
+
+ /* Write the formal parameter list. */
+ if (p_dc->dc_p_ma->ma_defn.md_npar>0)
+ {
+ wf_wr(&f_t,"\\fwparams{");
+ wf_dec(&f_t,(ulong) p_dc->dc_p_ma->ma_defn.md_npar);
+ wf_wr(&f_t,"}");
+ }
+
+ /* Zero and many options are indicated by bold letters. */
+ if (p_dc->dc_p_ma->ma_defn.md_iszer) wf_wr(&f_t,"\\fwzero{}");
+ if (p_dc->dc_p_ma->ma_defn.md_isman) wf_wr(&f_t,"\\fwmany{}");
+
+ /* Write the "equals". */
+ if (p_dc->dc_p_ma->ma_defn.md_isadd)
+ wf_wr(&f_t,"\\fwplusequals ");
+ else
+ wf_wr(&f_t,"\\fwequals ");
+
+ /* Write out this particular body part. */
+ ls_loo(p_dc->dc_p_ma->ma_defn.md_body,p_dc->dc_part,PPV &p_bp);
+ wf_wr(&f_t,"\\fwodef ");
+ wv_ex(p_bp->bp_ex);
+ wf_wl(&f_t,"\\fwcdef ");
+
+ /* After the macro definition, write out notes on the macro. */
+ wf_wl(&f_t,"\\fwbeginmacronotes");
+ wv_defin(p_dc->dc_p_ma); /* A list of the macro's body parts. */
+ wv_usage(p_dc->dc_p_ma); /* A list of where the macro is used. */
+ wf_wl(&f_t,"\\fwendmacronotes");
+
+ /* The macro definition is sandwiched by macro calls. */
+ wf_wl(&f_t,"\\fwendmacro");
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_htdcma P_((p_dc_t));
+LOCAL void wv_htdcma(p_dc)
+/* } ABC */
+/* Weaves a macro definition in HTML. */
+p_dc_t p_dc;
+{
+ p_bp_t p_bp;
+
+ /* Write an anchor for the macro */
+ wf_wr(&f_t, "<PRE><A NAME=\"");
+ wv_ohtdf();
+
+ /* Write out the macro's number. */
+ wv_mano(p_dc->dc_p_ma,p_dc->dc_part);
+
+ /* Finish anchor name */
+ wv_chtdf();
+ wf_wr(&f_t, "\">");
+
+ /* Write out the macro's name. */
+ wv_manm(p_dc->dc_p_ma,p_dc->dc_part);
+
+ /* Close anchor */
+ wf_wr(&f_t, "</A>");
+
+ /* Write the formal parameter list. */
+ if (p_dc->dc_p_ma->ma_defn.md_npar>0)
+ {
+ wf_wr(&f_t,"(#");
+ wf_dec(&f_t,(ulong) p_dc->dc_p_ma->ma_defn.md_npar);
+ wf_wr(&f_t,")");
+ }
+
+ /* Zero and many options are indicated by bold letters. */
+ if (p_dc->dc_p_ma->ma_defn.md_iszer)
+ wf_wr(&f_t,"<STRONG>Z</STRONG>");
+ if (p_dc->dc_p_ma->ma_defn.md_isman)
+ wf_wr(&f_t,"<STRONG>M</STRONG>");
+
+ /* Write the "equals". */
+ if (p_dc->dc_p_ma->ma_defn.md_isadd)
+ wf_wl(&f_t,"+=");
+ else
+ wf_wl(&f_t,"=");
+
+ /* Write out this particular body part. */
+ ls_loo(p_dc->dc_p_ma->ma_defn.md_body,p_dc->dc_part,PPV &p_bp);
+ wf_wr(&f_t,"{");
+ wv_ex(p_bp->bp_ex);
+ wf_wl(&f_t,"}");
+
+ /* After the macro definition, write out notes on the macro. */
+ wv_defin(p_dc->dc_p_ma); /* A list of the macro's body parts. */
+ wv_usage(p_dc->dc_p_ma); /* A list of where the macro is used. */
+ wf_wl(&f_t,"</PRE>");
+}
+
+/******************************************************************************/
+
+/* ABC { */
+LOCAL void wv_dcma P_((p_dc_t));
+LOCAL void wv_dcma(p_dc)
+/* } ABC */
+/* Weaves a macro definition. */
+p_dc_t p_dc;
+{
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : wv_txdcma(p_dc); break;
+ case TR_HTXT :
+ case TR_HTML : wv_htdcma(p_dc); break;
+ default : as_bomb("wv_dcma:case defaulted.");
+ } /* end switch */
+}
+/* } ABC */
+
+/******************************************************************************/
+
+LOCAL void wv_dc P_((p_dc_t));
+LOCAL void wv_dc(p_dc)
+/* Weaves a document component (p_dc). */
+p_dc_t p_dc;
+{
+ switch (p_dc->dc_kind)
+ {
+ case DC_TEXT: wv_dctx(p_dc); break;
+ case DC_TYPE: wv_dcty(p_dc); break;
+ case DC_MACR: wv_dcma(p_dc); break;
+ default : as_bomb("wv_dc: Case defaulted.");
+ }
+}
+
+/******************************************************************************/
+
+LOCAL void wv_docnt P_((void));
+LOCAL void wv_docnt()
+/* Weaves the entire document. This functions and most functions above assume */
+/* that the output stream f_t is prepared for writing. */
+{
+ /* Write the typeset header. */
+ wv_head();
+
+ /* Writes the library macros. */
+ /* ABC { */
+ if (doc_incQ) {
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : tex_head(&f_t); break;
+ case TR_HTXT :
+ case TR_HTML : html_head(&f_t); break;
+ default : as_bomb("wv_docnt:case defaulted.");
+ } /* end switch */
+ } /* end if */
+ if (
+ (tr_codes==TR_HTXT)
+ || ((tr_codes==TR_HTML) && doc_incQ)
+ ) {
+ /* Writes the opening HTML markup */
+ wf_wl(&f_t,"<HTML>");
+ } /* end if */
+ /* } ABC */
+
+ ls_fir(document_list);
+ literal=FALSE;
+ while (TRUE)
+ {
+ p_dc_t p_dc;
+ ls_nxt(document_list,PPV &p_dc);
+ if (p_dc == NULL) break;
+ wv_dc(p_dc);
+ }
+ /* ABC { */
+ if (
+ (tr_codes==TR_NONE)
+ || ((tr_codes==TR_TEX) && doc_incQ)
+ ) {
+ /* Writes the closing TeX command */
+ wf_wl(&f_t,"\\bye");
+ } else if (
+ (tr_codes==TR_HTXT)
+ || ((tr_codes==TR_HTML) && doc_incQ)
+ ) {
+ /* Writes the closing HTML markup */
+ wf_wl(&f_t,"</HTML>");
+ } /* end if */
+ /* } ABC */
+
+ /* Write the typeset trailer. */
+ wv_tail();
+}
+
+/******************************************************************************/
+
+EXPORT void weave()
+/* Writes out the documentation file. */
+{
+ fn_t fn_tmp; /* Name of temporary file. */
+ fn_t fn_targ; /* Name of documentation file. */
+ bool renfil; /* Do we wish to rename output file? */
+ bool istarg; /* Does a target file already exist? */
+
+ /* Writing the documentation file differs from some other output files. With */
+ /* non critical files such as the listing file that are really just logs, */
+ /* generation of half a listing file is acceptable if not desirable. However */
+ /* in the case of the documentation file, it is very bad to generate half an */
+ /* output file; far better to generate none at all. For this reason, and */
+ /* also because of the presence of the D option (which prevents the writing */
+ /* of output files identical to existing files (to prevent MAKE */
+ /* propagations)) it is best to write a temporary file and then rename it. */
+
+ /* We shouldn't be here if the weave option is off! */
+ as_cold(option.op_t_b,"weave: option.op_t_b==FALSE!");
+
+ /* ABC { */
+ /* There are no titles yet, so the next is the first */
+ title1Q = TRUE;
+ /* No text scraps have been written yet */
+ lastEOLQ = FALSE;
+ /* } ABC */
+
+ /* Work out what the typeset file's name should be. */
+ strcpy(fn_targ,""); /* Start with an empty string. */
+ fn_ins(fn_targ,option.op_f_s);
+ /* ABC { */
+ switch (tr_codes) {
+ case TR_NONE :
+ case TR_TEX : fn_ins(fn_targ,".tex"); break;
+ case TR_HTXT :
+ case TR_HTML :
+#if PC
+ fn_ins(fn_targ,".htm");
+#else /* !PC */
+ fn_ins(fn_targ,".html");
+#endif /* PC */
+ break;
+ default : as_bomb("weave:case defaulted.");
+ } /* end switch */
+ /* } ABC */
+ fn_ins(fn_targ,option.op_t_s);
+
+ /* The temporary file has to inherit too, because the output directory may */
+ /* not be the default directory and some computers can't rename across */
+ /* directories (and we have to rename it later). */
+ strcpy(fn_tmp,fn_targ);
+ fn_ins(fn_tmp,fn_temp());
+
+ /* Expand the macro to the temporary file. */
+ wf_ini(&f_t,TRUE);
+ wf_ope(&f_t,fn_tmp);
+ if (wf_err(&f_t))
+ {
+ sprintf(linet1,"Error creating temporary documentation file \"%s\".",&fn_tmp[0]);
+ wl_sjl(linet1);
+ (void) remove(fn_tmp);
+ goto severe;
+ }
+
+ wv_docnt();
+
+ /* Make sure that there weren't any errors writing to the temporary file. */
+ if (wf_err(&f_t))
+ {
+ sprintf(linet1,"Error writing to temporary documentation file \"%s\".",&fn_tmp[0]);
+ wl_sjl(linet1);
+ (void) remove(fn_tmp);
+ goto severe;
+ }
+
+ /* Close the temporary file. */
+ wf_clo(&f_t);
+ if (wf_err(&f_t))
+ {
+ sprintf(linet1,"Error closing temporary documentation file \"%s\".",&fn_tmp[0]);
+ wl_sjl(linet1);
+ remove(fn_tmp);
+ goto severe;
+ }
+
+ /* The rest of the code in this function copes with the renaming. */
+
+ /* By default, we wish to rename the temporary file. */
+ renfil=TRUE;
+
+ /* Deal with any existing file of the target name. */
+ istarg=fexists(fn_targ);
+ if (istarg && option.op_d_b)
+ {
+ /* A target already exists, and the D option is on. If the target is */
+ /* identical to the temporary, we can simply delete the temporary! */
+ char *errstr;
+ bool same;
+ errstr=eq_files(fn_tmp,fn_targ,&same);
+ if (errstr != NULL)
+ {
+ wl_sjl("Error comparing temporary file with previous documentation file.");
+ wl_sjl("(A comparison was attempted because the D option was turned on.)");
+ wl_sjl("Error from comparison routine was as follows (first=temp):");
+ wr_sjl(" ");wl_sjl(errstr);
+ sprintf(linet1,"Temporary file name was \"%s\".",&fn_tmp[0]);
+ wl_sjl(linet1);
+ sprintf(linet1,"Output file name was \"%s\".",&fn_targ[0]);
+ wl_sjl(linet1);
+ wl_sjl("FunnelWeb will leave both files intact so you can look at them.");
+ goto severe;
+ }
+ /* If the two files are the same, we can simply delete the temporary. */
+ if (same)
+ {
+ int status;
+ status=remove(fn_tmp);
+ if (status != REMOVE_S)
+ {
+ sprintf(linet1,"Error deleting (under +D option) temporary file \"%s\".",&fn_tmp[0]);
+ wl_sjl(linet1);
+ goto severe;
+ }
+ sprintf(linet1,"Deleted identical documentation file \"%s\".",&fn_targ[0]);
+ wl_sjl(linet1);
+ renfil=FALSE;
+ }
+ }
+
+ if (renfil)
+ {
+ int status;
+ /* We need to delete any existing file of the target name. */
+ if (istarg)
+ {
+ status=remove(fn_targ);
+ if (status != REMOVE_S)
+ {
+ sprintf(linet1,"Error deleting existing documentation file \"%s\".",&fn_targ[0]);
+ wl_sjl(linet1);
+ goto severe;
+ }
+ }
+ /* Rename the temporary file to the output file. */
+ status=rename(fn_tmp,fn_targ);
+ if (status != RENAME_S)
+ {
+ wl_sjl("Error renaming temporary documentation file to documentation file.");
+ sprintf(linet1,"Temporary file name was \"%s\".",&fn_tmp[0]);
+ wl_sjl(linet1);
+ sprintf(linet1,"Output file name was \"%s\".",&fn_targ[0]);
+ wl_sjl(linet1);
+ wl_sjl("FunnelWeb will leave both files intact so you can look at them.");
+ goto severe;
+ }
+ }
+
+ /* Tell everyone that we have written an output file. */
+ sprintf(linet1,"Weave : Completed %s.",fn_nodir(&fn_targ[0]));
+ wl_s(linet1);
+ if (option.op_b7_b)
+ sprintf(linet1,"Weave: Completed %s.",SUPPNAME);
+ wl_j(linet1);
+ wl_l(linet1);
+ return;
+
+ /* Jump here is a nasty file error occurs. */
+ severe:
+ sprintf(linet1,"A problem occurred during the generation of documentation file \"%s\".",&fn_targ[0]);
+ wl_sjl(linet1);
+ wl_sjl("S: Aborting...");
+ num_sev++;
+ return;
+}
+
+/******************************************************************************/
+
diff --git a/web/funnelAC/fwACsrc/weave.h b/web/funnelAC/fwACsrc/weave.h
new file mode 100644
index 0000000000..9ca3d4357a
--- /dev/null
+++ b/web/funnelAC/fwACsrc/weave.h
@@ -0,0 +1,55 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* WEAVE.H */
+/******************************************************************************/
+/* */
+/* This package exports a single function "weave" that generates the typeset */
+/* output file. */
+/* */
+/******************************************************************************/
+
+#include "style.h"
+
+/******************************************************************************/
+
+EXPORT void weave P_((void));
+
+/******************************************************************************/
+/* End of WEAVE.H */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/writfile.c b/web/funnelAC/fwACsrc/writfile.c
new file mode 100644
index 0000000000..3a94717a68
--- /dev/null
+++ b/web/funnelAC/fwACsrc/writfile.c
@@ -0,0 +1,319 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 28-May-1994 ABC Added `wf_last' member to `wf_t' structure to
+ aid in inserting `<P>' paragraph markups
+ into hypertext documents. This member stores
+ the last character written to the file.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* WRITFILE.C */
+/******************************************************************************/
+/* */
+/* Implementation Notes */
+/* -------------------- */
+/* The .H file gives most of the details of what this package does. Here we */
+/* just give some notes on how it is implemented. */
+/* */
+/* MAGIC NUMBERS: These are placed at the head and tail of wf_t records so as */
+/* to assist in the detection of uninitialized or corrupted variables. */
+/* */
+/* TEXT VS BINARY: A big problem arises in choosing whether to write binary */
+/* or text files. Binary files are far faster because they allow us to write */
+/* out large slabs of text using fwrite. The only catch is that they do not */
+/* translate EOL characters in the end of line representation of the host */
+/* environment. Text files, on the other hand are slower (because we have */
+/* only fputc and fputs) but do provide the translation. The solution we */
+/* adopt is to use binary if the host environment's representation for end of */
+/* file is EOL (='\n'), but text otherwise. We can determine this by testing */
+/* the symbol UNIX_EOL defined in machin.h. If binary output is chosen, */
+/* only fwrite is called as we don't know if fwrite and fputc calls can be */
+/* mixed (it would seem not). */
+/* Note: We could test the preprocessor symbol in each function. However, */
+/* the wf_att function introduces a problem as we may be attaching to a text */
+/* file in a UNIX_EOL environment (e.g. stdout). So we make the text/binary */
+/* attribute and attribute of each file, rather than the environment which we */
+/* use only to direct us in how to create and tag (as binary or text) a file. */
+/* */
+/******************************************************************************/
+
+#include "style.h"
+
+#include "as.h"
+#include "machin.h"
+#include "writfile.h"
+
+/******************************************************************************/
+
+#define MGC_HEAD (4837295L)
+#define MGC_TAIL (1213839L)
+
+/* Set the following to TRUE to bomb the package upon the first error. */
+/* This is a good idea during debugging if no output appears. */
+#define BOMB_ON_ERROR FALSE
+
+/******************************************************************************/
+
+LOCAL void wf_check P_((p_wf_t));
+LOCAL void wf_check(p_wf)
+p_wf_t p_wf;
+{
+ as_cold(p_wf!=NULL,"wf_check: p_wf==NULL.");
+
+ as_cold(p_wf->wf_mhead==MGC_HEAD,
+ "wf_check: Magic header field has non-magic value.");
+
+ as_cold(p_wf->wf_mtail==MGC_TAIL,
+ "wf_check: Magic trailer field has non-magic value.");
+
+ as_cold(p_wf->wf_isope || p_wf->wf_pfile==NULL,
+ "wf_check: WF is closed but wf_pfile!=NULL.");
+}
+
+/******************************************************************************/
+
+LOCAL void wf_errlg P_((p_wf_t, char *));
+LOCAL void wf_errlg(p_wf,mess)
+/* This function is called whenever an error occurs on a stream. The main */
+/* responsibility of this function is to set the error flag in the stream. */
+/* However, it can do other stuff too such as log the error to the screen. */
+p_wf_t p_wf;
+char *mess;
+{
+ p_wf->wf_iserr=TRUE;
+#if BOMB_ON_ERROR
+ if (p_wf->wf_pfile == stdout)
+ fprintf(stderr,"The output file error occurred on STANDARD OUTPUT.\n");
+ else
+ fprintf(stderr,"The output file error occurred on an ordinary file.\n");
+ as_bomb(mess);
+#endif
+}
+
+/******************************************************************************/
+
+EXPORT void wf_ini(p_wf,normal)
+p_wf_t p_wf;
+bool normal;
+{
+ p_wf->wf_mhead = MGC_HEAD;
+ p_wf->wf_iserr = !normal;
+ p_wf->wf_isope = FALSE;
+ p_wf->wf_istxt = FALSE;
+ p_wf->wf_pfile = NULL;
+ /* ABC { */
+ p_wf->wf_last = (char)0;
+ /* } ABC */
+ p_wf->wf_mtail = MGC_TAIL;
+}
+
+/******************************************************************************/
+
+EXPORT void wf_att(p_wf,wf_pfile)
+p_wf_t p_wf;
+FILE *wf_pfile;
+{
+ wf_check(p_wf);
+ if (p_wf->wf_iserr) return;
+ as_cold(!p_wf->wf_isope,"wf_att: WF is already open.");
+
+ p_wf->wf_pfile = wf_pfile;
+ p_wf->wf_isope = TRUE;
+ p_wf->wf_istxt = TRUE; /* Play it safe with files we didn't open. */
+ wf_check(p_wf);
+}
+
+/******************************************************************************/
+
+EXPORT void wf_ope(p_wf,p_name)
+p_wf_t p_wf;
+char *p_name;
+{
+ FILE *result;
+
+ wf_check(p_wf);
+ if (p_wf->wf_iserr) return;
+ as_cold(!p_wf->wf_isope,"wf_ope: WF is already open.");
+
+/* Whether we open the file as text or binary depends on whether EOL maps */
+/* to an end of line in the current environment. */
+#if UNIX_EOL
+ result=fopen(p_name,"wb"); p_wf->wf_istxt=FALSE;
+#else
+ result=fopen(p_name,"w"); p_wf->wf_istxt=TRUE;
+#endif
+
+ if (result == FOPEN_F)
+ {
+ /* TRACE printf("Output file in error is \"%s\".\n",p_name); */
+ wf_errlg(p_wf,"wf_ope: Error opening output file.");
+ }
+ else
+ {p_wf->wf_isope=TRUE; p_wf->wf_pfile=result;}
+ wf_check(p_wf);
+}
+
+/******************************************************************************/
+
+EXPORT void wf_chr(p_wf,ch)
+p_wf_t p_wf;
+intchar ch;
+{
+ wf_check(p_wf);
+ if ( p_wf->wf_iserr) return;
+ as_cold(p_wf->wf_isope,"wf_chr: WF is closed.");
+
+ if (p_wf->wf_istxt)
+ {
+ if (fputc((int) ch,p_wf->wf_pfile) == FPUTC_F)
+ wf_errlg(p_wf,"wf_chr: Error fputc()ing to output file.");
+ }
+ else
+ {
+ if (fwrite(&ch,(size_t) 1,(size_t) 1,p_wf->wf_pfile) != 1)
+ wf_errlg(p_wf,"wf_chr: Error fwrite()ing to output file.");
+ }
+ /* ABC { */
+ p_wf->wf_last = ch;
+ /* } ABC */
+ wf_check(p_wf);
+}
+
+/******************************************************************************/
+
+EXPORT void wf_wr(p_wf,p_str)
+p_wf_t p_wf;
+char *p_str;
+{
+ /* ABC { */
+ size_t len = strlen(p_str);
+ /* } ABC */
+ wf_check(p_wf);
+ if ( p_wf->wf_iserr) return;
+ as_cold(p_wf->wf_isope,"wf_wr: WF is closed.");
+
+ if (p_wf->wf_istxt)
+ {
+ if (fputs(p_str,p_wf->wf_pfile) == FPUTS_F)
+ wf_errlg(p_wf,"wf_wr: Error fputs()ing to output file.");
+ }
+ else
+ {
+ /* [ABC] *** size_t len = strlen(p_str); */
+ if (fwrite(p_str,(size_t) 1,(size_t) len,p_wf->wf_pfile) != len)
+ wf_errlg(p_wf,"wf_wr: Error fwrite()ing to output file.");
+ }
+ /* ABC { */
+ p_wf->wf_last = p_str[len-1];
+ /* } ABC */
+ wf_check(p_wf);
+}
+
+/******************************************************************************/
+
+EXPORT void wf_blk(p_wf,p_blk,blk_len)
+p_wf_t p_wf;
+char *p_blk;
+size_t blk_len;
+{
+ wf_check(p_wf);
+ if ( p_wf->wf_iserr) return;
+ as_cold(p_wf->wf_isope,"wf_blk: WF is closed.");
+
+ if (p_wf->wf_istxt)
+ {
+ /* Amazingly, fputc seems to be the only way to write out a block of */
+ /* bytes with end of line translation. Shocking, but true. */
+ /* See Section B1.4 (p.246-247) of Kernighan and Ritchie. */
+ /* Note: We can't use fputs because that requires a terminating nul. */
+ char *p;
+ char *p_post = p_blk+blk_len;
+ for (p=p_blk; p<p_post; p++)
+ if (fputc(*p,p_wf->wf_pfile) == FPUTC_F)
+ {
+ wf_errlg(p_wf,"wf_blk: Error fputc()ing to output file.");
+ break;
+ }
+ }
+ else
+ if (fwrite(p_blk,(size_t) 1,(size_t) blk_len,p_wf->wf_pfile) != blk_len)
+ wf_errlg(p_wf,"wf_blk: Error fwrite()ing to output file.");
+ wf_check(p_wf);
+ /* ABC { */
+ p_wf->wf_last = p_blk[blk_len-1];
+ /* } ABC */
+}
+
+/******************************************************************************/
+
+EXPORT void wf_wl(p_wf,p_str)
+p_wf_t p_wf;
+char *p_str;
+{
+ wf_wr(p_wf,p_str);
+ wf_chr(p_wf,'\n');
+}
+
+/******************************************************************************/
+
+EXPORT void wf_clo(p_wf)
+p_wf_t p_wf;
+{
+ wf_check(p_wf);
+ if ( p_wf->wf_iserr) return;
+ as_cold(p_wf->wf_isope,"wf_clo: WF is not open.");
+ if (fflush(p_wf->wf_pfile) != FFLUSH_S)
+ wf_errlg(p_wf,"wf_clo: Error fflush()ing output file.");
+ if (fclose(p_wf->wf_pfile) == FCLOSE_F)
+ wf_errlg(p_wf,"wf_clo: Error fclose()ing output file.");
+ p_wf->wf_isope=FALSE;
+ p_wf->wf_pfile=NULL;
+ wf_check(p_wf);
+}
+
+/******************************************************************************/
+
+EXPORT bool wf_err(p_wf)
+p_wf_t p_wf;
+{
+ wf_check(p_wf);
+ return p_wf->wf_iserr;
+}
+
+/******************************************************************************/
+/* End of WRITFILE.C */
+/******************************************************************************/
diff --git a/web/funnelAC/fwACsrc/writfile.h b/web/funnelAC/fwACsrc/writfile.h
new file mode 100644
index 0000000000..c56db567a9
--- /dev/null
+++ b/web/funnelAC/fwACsrc/writfile.h
@@ -0,0 +1,196 @@
+/*##############################################################################
+
+FUNNNELWEB COPYRIGHT
+====================
+FunnelWeb is a literate-programming macro preprocessor.
+
+Copyright (C) 1992 Ross N. Williams.
+
+ Ross N. Williams
+ ross@spam.adelaide.edu.au
+ 16 Lerwick Avenue, Hazelwood Park 5066, Australia.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of Version 2 of the GNU General Public License as
+published by the Free Software Foundation.
+
+This program is distributed WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See Version 2 of the GNU General Public License for more details.
+
+You should have received a copy of Version 2 of the GNU General Public
+License along with this program. If not, you can FTP the license from
+prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Section 2a of the license requires that all changes to this file be
+recorded prominently in this file. Please record all changes here.
+
+Programmers:
+ RNW Ross N. Williams ross@spam.adelaide.edu.au
+ ABC Anthony B. Coates coates@physics.uq.edu.au
+
+Changes:
+ 07-May-1992 RNW Program prepared for release under GNU GPL V2.
+ 28-May-1994 ABC Added `wf_last' member to `wf_t' structure to
+ aid in inserting `<P>' paragraph markups
+ into hypertext documents.
+
+##############################################################################*/
+
+
+/******************************************************************************/
+/* WRITFILE.H */
+/******************************************************************************/
+/* */
+/* Introduction */
+/* ------------ */
+/* This package performs all of FunnelWeb's file output. */
+/* FunnelWeb performs lots of output to lots of different files: */
+/* */
+/* - Standard output (to write to the screen). */
+/* - The journal file. */
+/* - The listing file. */
+/* - The tangle output files. */
+/* - The weave output file. */
+/* */
+/* Error Detection */
+/* --------------- */
+/* As we are serious about detecting errors, every call to every IO function */
+/* must have its status checked. Unfortunately this makes everything very */
+/* messy. Having to check result statuses and react to them can be very */
+/* awkward in deeply nested pieces of code, particularly as C does not have */
+/* exceptions. As a result, the policy adopted in FunnelWeb is to RECORD when */
+/* an error occurs on an output stream and silently shut down that stream. */
+/* Then later, at a convenient time, the error status of the stream can be */
+/* checked, and an error message issued. */
+/* */
+/* The C libraries make an effort to be helpful here by providing the ferror */
+/* function. However, it is not useful here for two reasons: */
+/* */
+/* 1. Some calls (e.g. fwrite) are not listed as setting the error status. */
+/* 2. It is not guaranteed that IO calls to a stream with error status */
+/* will not cause a crash. */
+/* 3. Even if ferror were used, it may not be supported by older compilers.*/
+/* */
+/* This package was created to take care of the vexing problems of IO errors */
+/* in output streams. It is a layer above the ANSI file library that provides */
+/* the elementary calls for writing. It differs in that if an error occurs, */
+/* the package records that fact and simply ignores all further operations */
+/* on the file. At any time, it is possible to find out whether a file is in */
+/* normal mode or error mode. All this means that a piece of code can use */
+/* this package to create and write to a file without worrying about errors. */
+/* Then later, when the dust settles, the package can check the status of */
+/* the file, and take appropriate action if an error has been detected. */
+/* */
+/* Text vs Binary */
+/* -------------- */
+/* This package translates all '\n' (contained in the data it has been given */
+/* to write) into the appropriate environment specific representation. */
+/* */
+/* Facts About WF Objects */
+/* ---------------------- */
+/* - A WF object is either in NORMAL or ERROR mode. */
+/* - A WF object in NORMAL mode is also either in OPEN or CLOSED mode. */
+/* - The term "raise an error" means bomb the program with a message. */
+/* - The comments attached to the functions given below are meant to be read */
+/* sequentially with each action or check being performed before the next. */
+/* - This package can not guarantee to detect uninitialized WF objects. The */
+/* reason is that policing is performed using magic number mechanism and it */
+/* is possible that a piece of random memory may contain just the right */
+/* numbers to fool the package. */
+/* */
+/******************************************************************************/
+
+/* Ensure that the body of this header file is included at most once. */
+#ifndef DONE_WRITFILE
+#define DONE_WRITFILE
+
+/******************************************************************************/
+
+#include "style.h"
+
+/******************************************************************************/
+
+/* We really don't want to show all the guts of this record here, but as */
+/* users of the package have to be able to declare objects of this type and */
+/* make them the right size, it seems as if we have no choice. */
+typedef struct
+ {
+ ulong wf_mhead; /* Helps detect uninitialized and corrupted records. */
+ bool wf_iserr; /* TRUE=>ERROR, FALSE=>NORMAL. */
+ bool wf_isope; /* TRUE=>OPEN, FALSE=>CLOSED. */
+ bool wf_istxt; /* TRUE=>TEXT, FALSE=>BINARY. */
+ FILE *wf_pfile; /* Pointer to the file object. */
+ /* ABC { */
+ char wf_last; /* Last character written to file. */
+ /* } ABC */
+ ulong wf_mtail; /* Helps detect uninitialized and corrupted records. */
+ } wf_t;
+
+typedef wf_t *p_wf_t;
+
+/******************************************************************************/
+
+EXPORT void wf_ini P_((p_wf_t,bool));
+/* Initializes a WF to a well defined state in accordance with the boolean. */
+/* FALSE => State=(ERROR). */
+/* TRUE => State=(NORMAL,CLOSED). */
+/* wf_ini must be applied to a WF before any other operation. */
+/* It can be re-applied repeatedly. */
+
+EXPORT void wf_att P_((p_wf_t,FILE *));
+/* If WF is uninitialized, raises an error (probably). */
+/* If WF is in ERROR mode, returns with no effect. */
+/* If WF is OPEN, raises an error. */
+/* Attaches an already opened output file to the specified FW object. */
+/* Changes the WF to the OPEN state. */
+/* The memory that the second parameter points to must be stable. */
+
+EXPORT void wf_ope P_((p_wf_t,char *));
+/* If WF is uninitialized, raises an error (probably). */
+/* If WF is in ERROR mode, returns with no effect. */
+/* If WF is OPEN, raises an error. */
+/* Creates an output file of the specified name and prepares it for writing. */
+/* Changes the WF to the OPEN state. */
+/* Sets the WF to the ERROR state if the file cannot be opened for writing. */
+
+EXPORT void wf_chr P_((p_wf_t,intchar));
+/* If WF is uninitialized, raises an error (probably). */
+/* If WF is in ERROR mode, returns with no effect. */
+/* If WF is CLOSED, raises an error. */
+/* Writes the specified character to the output file associated with WF. */
+/* Sets WF to the ERROR state if an error occurs during the write. */
+
+EXPORT void wf_wr P_((p_wf_t,char *));
+/* Same as wf_chr except that it writes an entire string. */
+
+EXPORT void wf_wl P_((p_wf_t,char *));
+/* Same as wf_wr except that appends a '\n'. */
+
+EXPORT void wf_blk P_((p_wf_t,char *,size_t));
+/* Same as wf_wr but writes a block of bytes whose address is given by the */
+/* second parameter and whose length (in bytes) is given by the third */
+/* parameter. */
+
+EXPORT void wf_clo P_((p_wf_t));
+/* If WF is uninitialized, raises an error (probably). */
+/* If WF is in ERROR mode, returns with no effect. */
+/* If WF is CLOSED, raises an error. */
+/* Flushes and closes the output file attached to WF. */
+/* Sets WF to the CLOSED state. */
+/* Sets WF to the ERROR state if an error occurs during the close. */
+
+EXPORT bool wf_err P_((p_wf_t));
+/* If WF is uninitialized, raises an error (probably). */
+/* Returns TRUE iff WF is in the ERROR state, otherwise FALSE. */
+/* This function can be called at any time so long as the WF is initialized. */
+
+/******************************************************************************/
+
+/* For #ifndef preventing multiple inclusion of the body of this header file. */
+#endif
+
+/******************************************************************************/
+/* End of WRITFILE.H */
+/******************************************************************************/