diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /web/funnelAC/fwACsrc |
Initial commit
Diffstat (limited to 'web/funnelAC/fwACsrc')
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 </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ö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. + + < The less than sign < + + > The "greater than" sign > + + & The ampersand sign & itself. + + " 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". + + Æ capital AE diphthong (ligature) + + Á capital A, acute accent + + Â capital A, circumflex accent + + À capital A, grave accent + + + +Berners-Lee and Connolly 28 + + Å capital A, ring + + Ã capital A, tilde + + Ä capital A, dieresis or umlaut mark + + Ç capital C, cedilla + + Ð capital Eth, Icelandic + + É capital E, acute accent + + Ê capital E, circumflex accent + + È capital E, grave accent + + Ë capital E, dieresis or umlaut mark + + Í capital I, acute accent + + Î capital I, circumflex accent + + Ì capital I, grave accent + + Ï capital I, dieresis or umlaut mark + + Ñ capital N, tilde + + Ó capital O, acute accent + + Ô capital O, circumflex accent + + Ò capital O, grave accent + + Ø capital O, slash + + Õ capital O, tilde + + Ö capital O, dieresis or umlaut mark + + Þ capital THORN, Icelandic + + Ú capital U, acute accent + + Û capital U, circumflex accent + + Ù capital U, grave accent + + Ü capital U, dieresis or umlaut mark + + Ý capital Y, acute accent + + á small a, acute accent + + + +Berners-Lee and Connolly 29 + + â small a, circumflex accent + + æ small ae diphthong (ligature) + + à small a, grave accent + + å small a, ring + + ã small a, tilde + + ä small a, dieresis or umlaut mark + + ç small c, cedilla + + é small e, acute accent + + ê small e, circumflex accent + + è small e, grave accent + + ð small eth, Icelandic + + ë small e, dieresis or umlaut mark + + í small i, acute accent + + î small i, circumflex accent + + ì small i, grave accent + + ï small i, dieresis or umlaut mark + + ñ small n, tilde + + ó small o, acute accent + + ô small o, circumflex accent + + ò small o, grave accent + + ø small o, slash + + õ small o, tilde + + ö small o, dieresis or umlaut mark + + ß small sharp s, German (sz ligature) + + þ small thorn, Icelandic + + ú small u, acute accent + + û small u, circumflex accent + + + +Berners-Lee and Connolly 30 + + ù small u, grave accent + + ü small u, dieresis or umlaut mark + + ý small y, acute accent + + ÿ 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 "Æ" -- capital AE diphthong (ligature) --> +<!ENTITY Aacute "Á" -- capital A, acute accent --> +<!ENTITY Acirc "Â" -- capital A, circumflex accent --> +<!ENTITY Agrave "À" -- capital A, grave accent --> +<!ENTITY Aring "Å" -- capital A, ring --> +<!ENTITY Atilde "Ã" -- capital A, tilde --> +<!ENTITY Auml "Ä" -- capital A, dieresis or umlaut mark --> +<!ENTITY Ccedil "Ç" -- capital C, cedilla --> +<!ENTITY ETH "Ð" -- capital Eth, Icelandic --> +<!ENTITY Eacute "É" -- capital E, acute accent --> +<!ENTITY Ecirc "Ê" -- capital E, circumflex accent --> +<!ENTITY Egrave "È" -- capital E, grave accent --> +<!ENTITY Euml "Ë" -- capital E, dieresis or umlaut mark --> +<!ENTITY Iacute "Í" -- capital I, acute accent --> +<!ENTITY Icirc "Î" -- capital I, circumflex accent --> +<!ENTITY Igrave "Ì" -- capital I, grave accent --> +<!ENTITY Iuml "Ï" -- capital I, dieresis or umlaut mark --> +<!ENTITY Ntilde "Ñ" -- capital N, tilde --> +<!ENTITY Oacute "Ó" -- capital O, acute accent --> +<!ENTITY Ocirc "Ô" -- capital O, circumflex accent --> +<!ENTITY Ograve "Ò" -- capital O, grave accent --> +<!ENTITY Oslash "Ø" -- capital O, slash --> +<!ENTITY Otilde "Õ" -- capital O, tilde --> +<!ENTITY Ouml "Ö" -- capital O, dieresis or umlaut mark --> +<!ENTITY THORN "Þ" -- capital THORN, Icelandic --> +<!ENTITY Uacute "Ú" -- capital U, acute accent --> + + + +Berners-Lee and Connolly 35 + +<!ENTITY Ucirc "Û" -- capital U, circumflex accent --> +<!ENTITY Ugrave "Ù" -- capital U, grave accent --> +<!ENTITY Uuml "Ü" -- capital U, dieresis or umlaut mark --> +<!ENTITY Yacute "Ý" -- capital Y, acute accent --> +<!ENTITY aacute "á" -- small a, acute accent --> +<!ENTITY acirc "â" -- small a, circumflex accent --> +<!ENTITY aelig "æ" -- small ae diphthong (ligature) --> +<!ENTITY agrave "à" -- small a, grave accent --> +<!ENTITY amp "&" -- ampersand --> +<!ENTITY aring "å" -- small a, ring --> +<!ENTITY atilde "ã" -- small a, tilde --> +<!ENTITY auml "ä" -- small a, dieresis or umlaut mark --> +<!ENTITY ccedil "ç" -- small c, cedilla --> +<!ENTITY eacute "é" -- small e, acute accent --> +<!ENTITY ecirc "ê" -- small e, circumflex accent --> +<!ENTITY egrave "è" -- small e, grave accent --> +<!ENTITY eth "ð" -- small eth, Icelandic --> +<!ENTITY euml "ë" -- small e, dieresis or umlaut mark --> +<!ENTITY gt ">" -- greater than --> +<!ENTITY iacute "í" -- small i, acute accent --> +<!ENTITY icirc "î" -- small i, circumflex accent --> +<!ENTITY igrave "ì" -- small i, grave accent --> +<!ENTITY iuml "ï" -- small i, dieresis or umlaut mark --> +<!ENTITY lt "<" -- less than --> +<!ENTITY ntilde "ñ" -- small n, tilde --> +<!ENTITY oacute "ó" -- small o, acute accent --> +<!ENTITY ocirc "ô" -- small o, circumflex accent --> +<!ENTITY ograve "ò" -- small o, grave accent --> +<!ENTITY oslash "ø" -- small o, slash --> +<!ENTITY otilde "õ" -- small o, tilde --> +<!ENTITY ouml "ö" -- small o, dieresis or umlaut mark --> +<!ENTITY szlig "ß" -- small sharp s, German (sz ligature) --> +<!ENTITY thorn "þ" -- small thorn, Icelandic --> +<!ENTITY uacute "ú" -- small u, acute accent --> +<!ENTITY ucirc "û" -- small u, circumflex accent --> +<!ENTITY ugrave "ù" -- small u, grave accent --> +<!ENTITY uuml "ü" -- small u, dieresis or umlaut mark --> +<!ENTITY yacute "ý" -- small y, acute accent --> +<!ENTITY yuml "ÿ" -- 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(¤t) + ); + } /* 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 "<". 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,"¿"); /* 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,"&"); + 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,"<"); + break; + /* '=': is an ordinary character. */ + case '>': wf_wr(&f_t,">"); + 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 '<' --> "<" and '>' --> ">" */ +/* and '&' --> "&". */ +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 */ +/******************************************************************************/ |