PUB Manual

PUB Manual project page

Page 30 PUB SAILON-70


SECTION 4

EXPRESSIONS




4.1 DATA TYPE
____ ____

PUB has only one data type: String. A string consists
______
of zero or more ASCII characters.

Strings may participate in arithmetic operations. The
string "764" is automatically converted to the integer
764 for this purpose. The result of the operation is
similarly converted back to a string. Because of this
convention, the data type Integer exists for all
_______
practical purposes.



4.2 VARIABLES
_________

Variables may be declared by the command:
.VARIABLE A, BETA, C

This would make A, BETA, and C local to the innermost
block in which the declaration occurred. The
variables are of course type String.

Any variable that is assigned but not declared is
automatically Global.
______
All declared variables are initialized to NULL, the
string of length zero.

The name of a variable is an identifier. The first
__________
character of an identifier should be a letter The
letter may be followed by letters, digits, _, and !.
The identifier is terminated by any other character,
including CR. Before looking up an identifer in its
symbol table, PUB changes all lower case letters to
upper case and changes _ to !.

In syntactic descriptions in this manual, <id> will


4.1 - 4.2
SAILON-70 EXPRESSIONS Page 31


denote any identifier, and <v> will denote a variable
in particular.



4.3 AUTOMATICALLY DECLARED VARIABLES
_____________ ________ _________

Some variables are automatically declared for you by
the compiler, in a block outside your outermost block.
A few of these are read-only -- it is not possible to
assign them a value by an assignment statement.

CHAR (read-only) The number of characters so far
printed on the current output line, not counting
justification spaces. This is sometimes an
overestimate.
LINE (read-only) Value is zero if the current output
column is empty. Otherwise, the sequential number of
the last line output.
COLUMN (read-only) Value is zero if the current page is
empty. Otherwise the sequential number of the last
column in which output went.
CHARS (read-only) The number of character positions
remaining to be filled on the current output line.
LINES (read-only) The number of unused lines remaining
in the current output column.
COLUMNS (read-only) The number of unused columns remaining
in the current page.
TOPLINE (read-only) The line number on this page that
starts the current area. (see Section 6.7).
FILLING (read-only) FALSE ("0") if in a NOFILL mode. TRUE
if in FILL mode -- "1" if ADJUST, "-1" if NOJUST.
NULL (read-only) The empty string ("").
TRUE (read-only) "-1"
FALSE (read-only) "0"
SPREAD The intra-paragraph output line spacing. SPREAD=1

is single spacing, SPREAD=2 is double spacing, etc.

Its initial value is 1 unless otherwise specified in

the (nS) CUSP option.
INDENT1, INDENT2, INDENT3 Control paragraph indentation (see
Section 6.4).
LMARG, RMARG The left and right margins (see Section 6.8).
DATE Today's date, in the form October 16, 1848 .


4.3
Page 32 EXPRESSIONS SAILON-70


Initialized from the system DATE UUO just before your
manuscript is compiled. Also available individually
are MONTH, DAY, and YEAR. To fully capitalize the
month or date, use the ↑ operator described in Section
4.4 (e.g., ↑MONTH).
TIME The time your compilation began, in the form
16:47 .
FILE The first name of your manuscript file. Useful
for headings.
PAGE The current page number, initially NULL. Don't
declare this LOCAL!
_SKIP_ (read-only) May be set by extreme substring
operators (see SAIL manual, 9-43). To examine the
left and right halves, examine _SKIPL_ and _SKIPR_.
FOOTSEP Before the first footnote (if any) in each column,
a blank line is usually left. This is because FOOTSEP
is initially NULL. If you assign it another value,
then that string will be printed instead.



4.4 SIMPLE EXPRESSIONS
______ ___________

Most of the SAIL <string expression> syntax has been
implemented. Exceptions: function designators (but
there are macro calls); exponentiation; LDB, ILDB, and
LOP; shifts and masks; LEAP operators.

PUB has three unary operators of its own: "↑"
capitalizes its argument (only lower case letters and
underbar are affected). EVEN and ODD are predicates
which tell whether the low order bit of the last
character of a string is off or on. They are used
primarily to distinguish left and right facing pages:
.IF ODD PAGE THEN etc.

All the available operators are listed in the table
below. If operator op1 is listed above operator op2
then op1 is performed before op2.









4.4
SAILON-70 EXPRESSIONS Page 33


( )
[ ]
+ - ABS LENGTH ↑ (this + and - are unary)
* DIV / MOD &
+ - EQV ≡ XOR ⊗ (this + and - are binary)
MAX MIN
EVEN ODD
> < = ≤ LEQ ≥ GEQ ≠ NEQ
⌈ NOT
∧ AND
∨ OR

The identifiers OR, LEQ, etc. are not reserved words
except in context. (The same holds for all
identifiers in the language except command names.)

Both division operators (/, DIV) are equivalent --
they yield the truncated integer.

= and ≠ compare strings character-by-character; <, >,
etc. compare integers algebraically.

If neither TO nor FOR occurs in a substring
specification, FOR 1 is assumed. Note that:

7654[∞] = 4
76 & 54 = 7654



4.5 GENERAL EXPRESSIONS
_______ ___________

Assignment expressions and conditional expressions are
allowed. If used alone to compute text, enclose them
in parentheses, otherwise they will look to the
compiler like assignment statements or conditional
__________
statements, and the text processor won't scan their
__________
values.

In syntactic descriptions, <e> will denote a general
expression -- simple, assignment, or conditional,
while <se> will denote a strictly simple expression.






4.5
Page 34 EXPRESSIONS SAILON-70


4.6 CONSTANTS
_________

PUB recognizes three forms of constants: quoted,
decimal, and octal. WARNING: CR will terminate any
form, so don't continue a quoted constant on a new
line.

A quoted constant (<qc>) is a sequence of characters
surrounded by quotes ("..."). To include a quote in
the represented string, write two quotes ("") in the
constant.

A decimal constant (<dc>) is a sequence of decimal
digits.

An octal constant (<oc>) is an apostrophe (') followed
by a sequence of octal digits. The value of the octal
number is taken modulo 200 and converted to a one
8
character ASCII string. The following octal codes are
illegal: '0, '11-'15, '175, '177.



























4.6
SAILON-70 PUB Page 35


SECTION 5

STATEMENTS




5.1 STATEMENT TYPES
_________ _____

Syntactically, any command can be a statement
(abbreviated in this manual). There are two
categories of commands: declarative and imperative. A
declaration is limited in its scope by block
___________
structure, while an imperative isn't.
__________


5.2 BLOCK
_____
Syntax:
BEGIN [<qc>] ; ... END [<qc>]

The optional block name [<qc>] should be the same in
both places. Mismatches will be flagged. Missing
END's are calamitous to say the least!

Note that declarations don't have to be the first
thing in the block. The scope of a declaration is the
remainder of the innermost block in which it occurs.

Both BEGIN and END cause a paragraph break. Neither
produces output, not even a blank line.

The semicolons between statements may be omitted as
long as no ambiguity is presented thereby.



5.3 COMPOUND STATEMENT or CLUMP
________ _________ __ _____
Syntax:
START [<qc>] ; ... END [<qc>]

Declarations are not local to clumps, and START and
END never break. Thus:
.IF TRUE THEN START FILL ; ADJUST END ;


5.1 - 5.3
Page 36 STATEMENTS SAILON-70


sets the modes FILL and ADJUST and leaves them set
after END. If BEGIN had been used instead of START,
the scope of the modes would have extended only to
END.



5.4 ONE PARAGRAPH SCOPE
___ _________ _____
Syntax:
ONCE

The command ONCE breaks and begins a local scope which
is implicitly terminated by the end of the next
paragraph. There must not be an END provided to match
___
it. If a BEGIN is encountered before a paragraph
breaks, then everything that has been declared in the
ONCE's scope is donated to the scope of the BEGIN's
block and the ONCE is forgotten. Examples:

.ONCE FLUSH RIGHT
George
is equivalent to:

.BEGIN FLUSH RIGHT
George
.END
and

.ONCE FILL
.BEGIN NOJUST
Harry
.END
is equivalent to:

.BEGIN FILL NOJUST
Harry
.END

You will find the ONCE construct useful in writing
macros and in formatting odd paragraphs here and
there. Note that ONCE is a complete statement, unlike
BEGIN, which introduces a statement that extends to
the matching END. Thus, you can say "IF X THEN ONCE
ELSE i←i+1" but you can't say "IF X THEN BEGIN ELSE
i←i+1".



5.4
SAILON-70 PUB Page 37


SECTION 6

DECLARATIONS




6.1 SCOPE
_____

(For the third time:) A declaration is in force until
the occurrence of an overriding declaration or until
the end of the innermost block in which it occurred
(see Section 5.2 through Section 5.4).



6.2 MODE DECLARATIONS
____ ____________

Most of these have already been described. Some mode
declarations cause paragraph breaks and some don't.
The ones that first Break are: FILL, all the NOFILLs,
ADJUST, NOJUST, GROUP, and APART. The ones that don't
are: CRBREAK, CRSPACE, COMPACT and RETAIN.



6.3 TABS DECLARATION
____ ___________
Syntax:
TABS <e>, ...

The expressions are sorted in algebraic ascending
order and duplicates are eliminated. These then
become the tab stops for the \ control character. If
you tab when the target is already passed, no spaces
are inserted, but justification to the left of the
current position in the output line is inhibited
anyway. Tab distances are measured from the left
margin.








6.1 - 6.3
Page 38 DECLARATIONS SAILON-70


6.4 INDENT DECLARATION
______ ___________
Syntax:
INDENT [<e>] [ ,<e>] [,<e>]

This command can change the values of three parameters
that control paragraph format: INDENT1, INDENT2, and
INDENT3. They can also be changed directly by
assignment statements. Every change is local to the
current block.

INDENT1 and INDENT2 specify indentation
from the left margin.

INDENT1 specifies the value of the crown
_____
indentation, which affects only the
___________
first line of output paragraphs.

INDENT2 specifies the value of the vest
____
indentation, which affects non-first
___________
lines in FILL mode.

In NOFILL, SUPERIMPOSE, and JUSTJUST
modes, INDENT1 is observed, and
INDENT2 is ignored. Old PUB users
note: this is a change from previous
conventions.

INDENT3 specifies indentation from the
right margin in FILL mode. It is
ignored in NOFILL modes, and in text
affected by the control characters
"→", "←", and "∞".

Lines in VERBATIM, FLUSH LEFT, CENTER,
and FLUSH RIGHT modes are never
indented.

If any argument is omitted, the
corresponding parameter remains
unchanged.








6.4
SAILON-70 DECLARATIONS Page 39


6.5 PREFACE DECLARATION
_______ ___________
Syntax:
PREFACE <e>



PREFACE N will cause every output paragraph to be
preceded by an implicit SKIP N. There are actually
two Preface numbers maintained -- one for FILL mode
and one for NOFILL modes. The one you change by this
command depends on the current mode.



Initially, the FILL Preface is 1 and the NOFILL
Preface is 0.

You may want to vary the Prefaces according to SPREAD,
e.g., PREFACE 1+SPREAD .



6.6 DOUBLE SPACING
______ _______
Syntax:
SINGLE SPACE
DOUBLE SPACE
TRIPLE SPACE

These are standard macros that set SPREAD to 1, 2, and
3, respectively. At the end of the current block, the
old value is restored. SPREAD controls the spacing
between lines within a paragraph.



6.7 AREA DECLARATION
____ ___________
Syntax:
[TEXT|TITLE] AREA <id> [LINE[s] <e> [TO <e>]] [CHAR[S] <e> [TO <e>]]
[IN <e> COLUMNS <e> WIDE|APART]

Each page is divided into Areas into which the
_____
compiler will place output text. The areas HEADING,
TEXT, and FOOTING are pre-declared for you as follows:
____________


6.5 - 6.7
Page 40 DECLARATIONS SAILON-70


.AREA TEXT LINES 4 TO 51 ;
.TITLE AREA HEADING LINES 1 TO 3 ;
.TITLE AREA FOOTING LINE 53 ;

Each area is a rectangle that begun. In the case of a TITLE
must lie within the bounds set AREA overflow, an error message
by the last PAGE FRAME is issued.
Statement (see Section 7.13).
If the CHARS clause of the AREA An area has one column unless
declaration should be omitted an IN..COLUMNS clause is
(as it is in the predeclared included, e.g.,
areas), then the full width of
the Page Frame is assumed. .AREA LISTING LINES 30 TO
Similarly, if the LINES clause . 50 IN 2 COLUMNS 7 APART
should be omitted, full page
height is assumed. Either how WIDE each column is
or how far APART they are can
An area is assumed to be a TEXT be specified.
AREA unless "TITLE AREA" is
stated explicitly. The only Associated with each area are a
difference between a TEXT AREA left and right margin, located
and a TITLE AREA is the action initially at the left and right
taken when so many lines are edges of each column. How they
written in it that it can be moved inward and back
overflows. In the case of a out is explained in Section
TEXT AREA overflow, all areas 6.8.
are "closed", the whole page is
written out, and a new page is


The bottom line of a TEXT AREA is not used except to
print the last line of a paragraph. This convention
prevents the appearance of "widows" at the top of a
page.



6.8 MARGIN CONTROL
______ _______
Syntax:
NARROW <se> [ ,<e>] <paragraphs and statements> WIDEN

NARROW and WIDEN cause paragraph breaks. NARROW L,R
moves the left and right margins of the current PLACE
area inward L and R, respectively. Their initial
positions are determined by the AREA declaration. L
and R may be negative. If either is omitted, it is


6.8
SAILON-70 DECLARATIONS Page 41


assumed 0. The matching WIDEN restores the margins to
their former positions.

Alternatively, you can have:
WIDEN <se> [ ,<e>] <paragraphs and statements> NARROW

which moves the margins outward. Both kinds can nest.

These commands change the automatically declared
variables LMARG and RMARG (the Left and Right
Margins). They can also be changed directly by
assignment statements; such changes are local to the
current block and to the current NARROW-WIDEN nest of
the current PLACE area.

Upon exit from a block, if the margin positions are
different than they were at the beginning, then they
are restored and instead of the usual Break, END
causes a CONTINUE (See Section 7.15), which treats
the next line as a vest instead of a crown line.

Every paragraph is output in the following format:

| ---------------------------------------- |
| | | | |
| | (P blank lines) | | |
← A-1 →| | | | |
| |←- I1 -→The crown line of the paragraph.| | |
| |←----- I2 ----→a vest line .............|← I3 →| |
|← L →| another vest line .......| |← R →|
| | the hem line. | | |
| ---------------------------------------- |
↑ ↑ ↑ ↑
A Left-margin Right-margin B
The format suggested by the diagram above may be
achieved by the following declarations:

.AREA TEXT CHARS A TO B ;
.NARROW L, R ;
.FILL ; PREFACE P ; INDENT I1, I2, I3 ;

The automatically declared variable CHAR and all tab
stops count characters from the left margin; they may
at times be negative. It is possible to produce
output past the right margin by setting tab stops out
there.



6.8

Page 42 DECLARATIONS SAILON-70


6.9 PLACE DECLARATION
_____ ___________
Syntax:
PLACE <area id>

This breaks and switches output to the named area.
This may be done many times on the same page; output
to each area always picks up where it left off.

If a column of the current Place Area overflows,
output continues at the top of the next column. When
the last column overflows, either a new page is begun
(if a TEXT AREA overflowed) or an error message is
given (if a TITLE AREA overfowed).



6.10 TEMPORARY AREAS
_________ _____

This section is complicated. Only read it if you need
to create temporary areas within a page. To do this,
you need to know where you're up to on the page so
far. If there's not enough room for the new area, you
will want to go to a new page. Then a temporary area
(local to a block) should be declared, and text placed
in it. Finally, you may need to find out where you're
up to on the page again before you exit that block,
skip over the temporary area, and resume regular
output.

A more convenient way to handle this may be available
in a future version of PUB in the form of a BOX FRAME
declaration. In the meantime, you should be able to
get by as follows.

To determine the top line on the whole page that the
current PLACE area uses, look at TOPLINE. Within that
area, lines are numbered starting from 1 -- but if
TOPLINE is 6 that means "line 1" of the area is really
the 6'th line on the page. We can distinguish P-lines
(numbered relative to the whole page) from A-lines
(numbered local to the area); A-line 1 might be P-line
6.

To determine the column number and A-line number of
the last line output in this area, look at COLUMN and


6.9 - 6.10
SAILON-70 DECLARATIONS Page 43


LINE. To determine how many empty columns remain in
this area, look at COLUMNS; for how many empty lines
remain in this column, look at LINES. Note that
LINE+LINES can be less than the full height of the
area, because a few lines at the bottom may be
occupied by footnotes.

To declare a two-column area 10 lines high for a table
starting just below the last output line, write:

.IF LINES < 10 THEN NEXT PAGE ;
.BEGIN
.AREA AXE LINES TOPLINE+LINE TO TOPLINE+LINE+9 IN 2 COLUMNS 5 APART
.PLACE AXE


.END
.GROUP SKIP 10
Adding TOPLINE in the AREA declaration is necessary
because it expects P-line numbers.



6.11 COUNTER DECLARATION
_______ ___________
Syntax:
COUNT <id> [INLINE] [FROM <e>] [TO <e>] [BY <e>] [IN <counter id>]
[PRINTING <e>|<template>]

This is PUB's excuse for a FOR statement. The user
can declare certain identifiers to be counters, and
________
arrange them in hierarchies. A counter is anything
you want numbered sequentially. Typical counters are
SECTION, APPENDIX, SUBSECTION, PAGE, FOOTNOTE,
EQUATION, TABLE, FIGURE, NOTE, and REFERENCE. A
common hierarchy is:

SECTION
/ \
SUBSECTION PAGE
|
FOOTNOTE

The declarations for this hierarchy might be:

.COUNT SECTION FROM 1 TO 9
.COUNT SUBSECTION FROM 1 TO 99 IN SECTION
.COUNT PAGE FROM 1 TO 99 IN SECTION
.COUNT FOOTNOTE INLINE FROM 1 TO 9 IN PAGE

6.11
Page 44 DECLARATIONS SAILON-70


The "IN" clause specifies the hierarchial parent
counter; it must have been previously declared.

The range of each counter is specified by the FROM,
TO, and BY clauses; if omitted, FROM 1, TO 18, and BY
1 are assumed. The counter need not ever attain the
TO-value; it is just an upper limit used to determine
the maximum number of characters needed to print the
counter in case it is referred to in a Forward Cross-
Reference (see Section 9.1).

The INLINE option suppresses a BREAK which is
otherwise automatically generated before each stepping
of the counter.

The PRINTING clause is explained in Section 7.3.

































6.11

SAILON-70 PUB Page 45


SECTION 7

IMPERATIVES


The commands in this section are non-declarative.
That means that their scope is not limited by block
structure. an occasional exception to this rule is
the assignment statement; when the assigned variable
is SPREAD, LMARG, RMARG, INDENT1, INDENT2, or INDENT3,
then the change is local to the current block.



7.1 ASSIGNMENT STATEMENT
__________ _________
Syntax:


Example:
.SPREAD ← T ← r - 4 ;

Assignment statements don't break.



7.2 CONDITIONAL STATEMENT
___________ _________
Syntax:
IF <e> THEN ELSE

Example:

.IF ODD PAGE OR LINES < 10 THEN START
this text line
.END ELSE START
that text line
.END

"IF", "THEN", and "ELSE" don't break.



7.3 NEXT COUNTER VALUE STATEMENT
____ _______ _____ _________
Syntax:
NEXT <counter id>


7.1 - 7.3
Page 46 IMPERATIVES SAILON-70


This breaks (unless INLINE appeared in the designated
counter's COUNT declaration), and the counter is
stepped to its next value. The first time it is
called, the counter's value is initialized.

Every COUNT declaration automatically declares two
variables with special properties, and initializes
them to NULL. The first variable has the same name as
the <counter id>, e.g., "SUBSECTION", and its value is
always the decimal integer value of the counter. The
other variable's name is constructed by appending an
"!" to the <counter id>, e.g., "SUBSECTION!". The two
variables are called the counting or "C-value" and the
printing or "P-value", respectively.

The precise effect of the statement "NEXT U" in terms
of these variables is as follows.

(1) If U=NULL, then U is set to the FROM value of the
COUNT declaration; otherwise, U is incremented by the
BY value of the COUNT declaration.

(2) The P-value is computed under control of the
PRINTING clause of the COUNT declaration (just how
will be explained shortly). In addition, the P-value
is assigned to the variable "!" as a convenient
abbreviation.

(3) If the counter has hierarchically subordinate
counters, all their C-values and P-values are set to
NULL; thus, when you say NEXT SECTION, SECTION becomes
a new number while SUBSECTION, PAGE, and FOOTNOTE
become NULL (assuming the hierarchy of the recent
example). Exception: If "PAGE" was one of the
subordinate counters, after it is cleared it is
immediately initialized.

The computation of the P-value depends on the PRINTING
clause of the COUNT declaration. There are three
cases.

Case One The PRINTING clause is omitted. P-value is the same as the
____ ___
C-value.

Case Two PRINTING <template>. After each C-value is computed, the
____ ___
expression inside the template is evaluated, and the result
is the P-value. Thus, the template should contain an
expression which involves the C-value. Examples:

7.3
SAILON-70 IMPERATIVES Page 47


.COUNT FOOTNOTE TO 9 IN PAGE PRINTING ⊂"*********"[1 TO FOOTNOTE]⊃ ;
When FOOTNOTE=1, this sets FOOTNOTE!=*; when FOOTNOTE=5,
this sets FOOTNOTE!=*****.

.COUNT SUBSECTION IN SECTION PRINTING ⊂SECTION! & "." & SUBSECTION⊃ ;
When SECTION!=4 and SUBSECTION is counted to 7, SUBSECTION!
becomes 4.7 .

Case ThreePRINTING <e>. The expression is evaluated only once, at
____ _____
declaration time, and its value serves as a pattern for
conversion of the C-value to the P-value. For example, the
pattern "(i)" will produce P-values such as (iv) and
(xlii), and the pattern "!-A" will produce P-values such as
6-A and 33-L. The pattern should evaluate to a string of
the form:
<prefix> [ ! <middle> ] <format> <suffix>
where <prefix>, <middle>, and <suffix> may be empty, and
<format> must be 1, a, A, i, or I. This is roughly
equivalent to the template:
⊂& ! && CONVERT(,) &⊃
Here's what happens. The P-value becomes this pattern
after substituting the parent counter's P-value for "!" (if
present) and after converting the C-value to the specified
format and substituting it for <format>. Before explaining
formats, let's give a simple example:

.COUNT SUBSECTION IN SECTION PRINTING "!.1" ;
Here, <prefix> and <suffix> are empty and <middle> is ".".
Format "1" is no-conversion, so the C-value is substituted
unchanged for the "1". The P-value of SECTION is
substituted for the "!". Say SECTION! is 6 and SUBSECTION
is stepped to 4; then SUBSECTION! becomes 6.4 .
The various <format> conversions are:

1 No conversion
I Upper case Roman, i.e., 59 → LIX
i Lower case Roman
A Capital letters A,...Z,AA,BB,...ZZ,AAA,...
a Little letters



7.4 NEXT PAGE STATEMENT
____ ____ _________

This variety of Next Statement has special properties.
Before stepping the PAGE counter, it "closes" and


7.4
Page 48 IMPERATIVES SAILON-70


outputs all the areas on the current page and sets up
a fresh page frame.

Conversely, when a page is closed due to text area
overflow or "SKIP TO COLUMN 1", etc., the page counter
is automatically stepped before the new page is
opened, as if the command NEXT PAGE had been given.



7.5 HEADINGS AND FOOTINGS
________ ___ ________

As soon as the first line is ready to be placed in a
page, the page is "opened". There are fancy ways you
can create fancy headings and footings at that or at
other times (see Section 10.2). For simple cases,
the following command (which is actually a call to a
built-in macro) is provided.
Syntax:
.EVEN|ODD|EVERY HEADING|FOOTING ( <text>, <text>, <text> )

On left-facing (EVEN), on right-facing (ODD), or on
all pages (EVERY); on the top line (HEADING) or the
bottom line (FOOTING); the three <text>s will be
printed at the left edge, the center, and the right
edge of the page, respectively. A <text> may not
contain quote ("). Example:
.ODD HEADING({DATE}, MACHINES THAT WONDER, {SUBSECTION!})

This would cause to print on the top line of every
right-facing page something like:
July 14, 1789 MACHINES THAT WONDER VII.iii



7.6 SECTIONING
__________

The correct way to start every new section on a new
page is:
.NEXT PAGE ; NEXT SECTION ;

If the order of these were reversed and if SECTION
were the parent of PAGE, then NEXT SECTION would
change PAGE's value before the old page got written
out.


7.5 - 7.6
SAILON-70 IMPERATIVES Page 49


7.7 COMMAND CHARACTER STATEMENT
_______ _________ _________
Syntax:
COMMAND CHARACTER <qc>|<v> ;

The parameter must evaluate to a single character
string. That character subsequently assumes the
function of dot in column 1. Since this command is
not a declaration, its scope is global; i.e, it is not
affected by block nesting. Don't omit the semicolon!



7.8 PORTION DEMARCATION
_______ ___________
Syntax:
PORTION <id>

The manuscript may be (ought to be) divided into
Portions, such as TITLEPAGE, CONTENTS, THESIS,
________
APPENDICES, NOTES, INDEX, and BIBLIOGRAPHY.

Precede each portion by a Portion Demarcation, e.g.,
.PORTION NOTES

The compiler will assure that each portion starts on a
fresh page and ends with a paragraph break.

In general, the order of appearance of the portions in
the manuscript becomes their order of appearance in
the document. However, this is not always convenient.
For example, the entries for PORTION CONTENTS are
usually generated during the processing of the other
portions (see Section 7.9); therefore, PORTION
_______
CONTENTS must appear at the end of the manuscript. To
________ ____ ______ __ ___ ___ __ ___ __________
show where you would like its output to be inserted in
the document, use the statement:
.INSERT <id>, ...

which is sort of a "forward portion demarcation".
Example:








7.7 - 7.8
Page 50 IMPERATIVES SAILON-70


.PORTION TITLEPAGE
...
.INSERT CONTENTS
. COMMENT This is where the table of contents should be printed;
.PORTION THESIS
.COUNT PAGE ; COMMENT Before NEXT SECTION starts a new page;
.NEXT SECTION
...
.PORTION INDEX
...
.COUNT PAGE PRINTING "i"; COMMENT Before PORTION starts new page;
.PORTION CONTENTS
. COMMENT This is where the table of contents is defined ;
...



7.9 SEND STATEMENT
____ _________
Syntax:
SEND <portion id> [;] <template>

With every portion is associated a file called its
generated file. A generated file is in manuscript
_________ ____ __________
format. The idea is that you can avoid manual
preparation of certain portions of your manuscript
(such as the table of contents and the index) by
making PUB prepare them mechanically.

The generated file of a portion may remain empty, or
may be written on during the processing of portions
that appear earlier in the manuscript. For example,
the generated files for PORTION CONTENTS and PORTION
INDEX are usually generated during the processing of
earlier portions.

The SEND statement writes a template onto the end of
the generated file for the named portion. The portion
must appear later in the manuscript. Before sending
the template, the compiler substitutes for every
occurrence of:
{ <v> }

the (unquoted) value of the variable <v>.

Thus, if S=6 and PAGE=26, then the statement:



7.9
SAILON-70 IMPERATIVES Page 51


.SEND CONTENTS ⊂
Section {S} -- Findings ∞.→ {PAGE}
⊃ ;
would send the following data to the file associated
with PORTION CONTENTS (CRLF shown here for clarity):

<CRLF>
Section 6 -- Findings ∞.→ 26
.

If a similar SEND were performed at the beginning of
every section and subsection of the manuscript, then
by the time the compiler reached PORTION CONTENTS, its
generated file would be in perfect manuscript format,
e.g.:

Section 1 -- Introduction ∞.→ 1
.
Section 2 -- Remarks ∞.→ 6
.
(etcetera)
Section 6 -- Extraneous Factors ∞.→ 26
.
(etcetera)
Section 413 -- Conclusions ∞.→ 864
.
The empty command lines are of course harmless; their
inclusion was caused by the method of conforming with
one of the rules of writing templates: a template must
end on a command line. Of course, a template
alternatively could end with a text line terminated by
"{".

The subtleties of generated files are discussed in the
Appendices to this manual. If you would rather
postpone becoming an expert on the technique, you can
still obtain a table of contents and index by the use
of someone else's macros. These macros (STANDARD
FRONT and STANDARD BACK) are stored in file
PUBMAC.DFS[1,3] and described in file
PUBMAC.TES[UP,DOC].








7.9

Page 52 IMPERATIVES SAILON-70


7.10 RECEIVE STATEMENT
_______ _________
Syntax:
RECEIVE [<qc>|<v>]

This statement substitutes the generated file of the
current portion for the statement and causes the
compiler to compile it. Thus, PORTION CONTENTS
typically consists of a few mode setting commands, a
title, and then the statement "RECEIVE".

If the optional parameter is present, it should
evaluate to a string of one or two characters, say "L"
or "LR". The presence of the parameter causes the
generated file to be alphabetized before it is
compiled. Entries in the file should be in the form:
<0 or more characters> L <Key> [R <0 or more characters>]

PUB will alphabetize the entries by the <Key>s using
the ASCII collating sequence, except lower case
letters and "_" are ranked with the corresponding
upper case letters and "!". Then it will read the
alphabetized file, including the L and R characters.

WARNING: The characters L and R must be chosen
carefully. They may not occur in the generated file
in any role except as key delimiters. Furthermore,
the characters "[", "]", "@" may not be used. It is
legal for L and R to be the same character.

If your index is very large, PUB may exhaust SAIL
string space trying to alphabetize it. The error
message "STRING SPACE EXHAUSTED" will be typed out.
Unfortunately, the only way to get more string space
is to REEenter the program and go through the ALLOC
ritual (see SAIL manual 14-22). The original
allocation is presently 4000 words; try 7000 or 10000.

To generate a simple index, use SEND statements such
as:

.SEND INDEX ; ⊂
βKeyword ∞.→ {PAGE}
⊃ ;
and the RECEIVE statement:
.RECEIVE "β∞"



7.10
SAILON-70 IMPERATIVES Page 53


The file generated will be quite funny-looking, but
will result in the document:

...
Keyshmurd ......................... 9
Keyword .......................... 15
...
Rather than all those hideous dots, it is suggested
that the number immediately follow or precede the
word.

To learn how to create two-level and KWIC indexes, see
Appendix A.3.



7.11 REQUIRE STATEMENT
_______ _________
Syntax:
REQUIRE <qc>|<v> SOURCE_FILE

The parameter must evaluate to a file name, e.g.,
"BRAIN.BAZ[H,AHA]". The file must be in manuscript
format. It will be substituted for the REQUIRE
statement and compiled. If the last line of the file
is a text line, PUB will still be scanning for text
when it resumes the original file, so don't put a
semicolon after the REQUIRE statement -- put a CR.

REQUIREd files may REQUIRE other files. You will run
out of channels if the number of open SOURCE_FILEs,
generated files (extension ".PUG") and pass one output
files (extension ".PUI") exceeds 15.



7.12 SKIP STATEMENTS
____ __________
Syntax:
[GROUP] SKIP [<se>]
SKIP TO LINE <e>
SKIP TO COLUMN <e>







7.11 - 7.12
Page 54 IMPERATIVES SAILON-70











SKIP N breaks and leaves N blank lines in the
document. If N is omitted, SKIP 1 is assumed. Note
that N must be a simple expression -- no assignment or
conditional expression is allowed unless it is
parenthesized.

Blank lines that would appear at the top of any column
are automatically suppressed; if you want to force
them to appear (say, to leave space for a drawing),
use GROUP SKIP.

If you are going to run off the same document with
different values of SPREAD (i.e., sometimes single
space and sometimes double space), you should write
all your KIP statements with this factor taken into
account, e.g., SKIP 2*SPREAD-1 .

SKIP TO LINE N outputs blank lines up to but not
including the N'th line (A-line) in the current column
of output text, unless the N'th line has already been
passed, in which case it goes to the N'th line in the
next column. The most common use of this statement is
SKIP TO LINE 1, which assures you are at the top of a
clean column.

SKIP TO COLUMN N outputs blank lines until it reaches
the top of the N'th column of this or the next page.
If the compiler is already at the top of the N'th
column, this statement does nothing. The most common
use is SKIP TO COLUMN 1, which goes to a new page
unless a new page has just been begun. (To go to a
new page regardless, use "NEXT PAGE" -- See Section
7.3).







7.12

SAILON-70 IMPERATIVES Page 55


7.13 PAGE FRAME STATEMENT
____ _____ _________
Syntax:
PAGE FRAME <e> HIGH <e> WIDE

This statement causes a break, goes to a new page, and
sets up its size as specified (number of lines, number
of characters). No output can appear outside the
bounds set by this statement. Area declarations
normally follow it.



7.14 BREAK STATEMENT
_____ _________
Syntax:
BREAK

If a paragraph has been started, BREAK terminates it.
Breaks are implicitly caused by many other commands
and conditions.



7.15 CONTINUE STATEMENT
________ _________
Syntax:
CONTINUE

Sometimes you would like to insert an indented
quotation or equation in the middle of a paragraph of
prose. After the quotation, a paragraph break is
necessary to terminate it.
Unfortunately, the break also causes the
next output line to be treated as a crown
line (in FILL mode). If you would rather
continue the interrupted paragraph than
start a new one, use the command CONTINUE.
It breaks, but causes the next paragraph to have no
crown, as long as no regular breaks intervene.



7.16 DEVICE STATEMENT
______ _________
Syntax:
DEVICE LPT|MIC|TTY


7.13 - 7.16
Page 56 IMPERATIVES SAILON-70


This statement is equivalent to setting the /L, /M, or
/T switch when starting up PUB. It has no effect on
Pass One output. However, Pass Two reacts to the
switch setting as follows.

DEVICE MIC makes the document file be in FR-80 command
format. Pass Two will output two temporary files with
extension ".RPG" and automatically run a program
called "TXTF80", written by Russ Taylor, which
generates the document file. Simply copy this file to
a tape and bring it to the FR-80 operator at Lockheed.

DEVICE LPT and DEVICE TTY produce identical output
unless the page frame is higher than 53 lines. In
that case, DEVICE LPT uses strange control characters
instead of line feeds to inhibit page-ejection.
DEVICE TTY assures that only line feeds are issued.

Files produced under DEVICE TTY can be edited with
TECO. Hardly any document file can be edited with SOS
or TVEDIT, which don't like CR's without LF's (used
for underlining and superimposing).



7.17 UNIMPLEMENTED STATEMENTS
_____________ __________

The following commands have not been implemented, but
ought to be, so their names are reserved words:

CASE statement -- SAIL-style
ALIGN statement -- it would align output to side-by-side areas
PACK statement -- it would align the bottoms of parallel columns
BOX FRAME STATEMENT -- to insert a table in a corner of the page
LOCK statement -- to protect lines from being moved by a BOX FRAME
SHOW statement -- to output to the console during compilation
NOPRINT mode -- would suppress output
PRINT mode -- would renew output

LDX output will soon be available. This will require
a few new commands and automatically declared
variables, probably the following:






7.17
Glossary
The LDX was Long Distance Xerography, a xerographic facsimile system. The print end was turned into a computer peripheral called the Xerox Graphics Printer (XGP). At the time this manual was written, we knew the machine was coming but did not know its new name.

SAILON-70 IMPERATIVES Page 57


DEVICE LDX
FONT <font-name> ON <file-name> -- would declare a font
RASTER <e> UNITS PER INCH -- to specify raster density
BELOW,ABOVE,ONLEFT,ONRIGHT -- like LINES,LINE,CHAR,CHARS
CHARACTER <name> <font-name> <coordinates> -- define character












































7.17

Page 58 PUB SAILON-70


SECTION 8

COMMENTS


There are two ways to get comments into a command line
-- not in the middle of an identifier or constant,
however.
Syntax:
COMMENT anything but semicolon ;

This one is probably familiar. The other one is:
<< anything but two greater-than-signs in a row >>

Comments may extend over several command lines. If
you leave out the terminator, you'll lose everything
up to the next text line.

Comments have no effect on the document. Why would
you want them? Maybe you could write English comments
on a French manuscript to help you find your way
around. Or maybe you've got complicated macros that
need explanation. Or you left out a bunch of text and
want to leave a reminder in the manuscript. Don't ask
me why -- I just implemented them.

To get a comment into a text line, use curly brackets
around a regular comment {<< Like this >>}.
Continuation lines must be command lines.

SAILON-70 PUB Page 59


SECTION 9

LABELS AND CROSS-REFERENCES




9.1 CROSS-REFERENCES
________________

A cross-reference is like computed text in that it
causes characters to be processed by the text scanner,
and in that it normally appears between curly brackets
in the midst of a text line. First there will be an
example, and then an explanation.
... invented by Owsley (See {"Page!" PURE}) ...

This might produce output such as:
... invented by Owsley (See Page 3-7) ...

The identifier PURE is called a label and must be
_____
defined once and only once in the manuscript, either
before or after the cross-reference. Every label has
a value, much like a variable, but the value is
assigned only once, at the place the label is defined.
Several cross-reference statements may reference the
same label. Labels willbe explained further in
Section 9.2.

There is a major problem in handling forward-
references in a text-justifier. The justifier must
know how many characters there will be in the value
before it can decide where to break off the output
line and how many spaces to insert during
justification. PUB solves this problem by two
slightly awkward hacks. One hack is that you must
state or imply an upper limit on the number of
characters, so it can leave enough room for it and not
break off the line too soon. The other hack is that
PUB has two passes. In the second pass, the actual
values are substituted, and only then are lines
justified.

To "state or imply" the upper limit, you have a choice
of three forms of cross-reference.

Form 1: [ <e> ] <label id>
_ _

9.1
Page 60 LABELS AND CROSS-REFERENCES SAILON-70


Those are really square brackets!!!! Write them in
the manuscript, really! The expression evaluates to a
number which is the maximum number of characters, and
the value printed is the value of the label <label
id>. If this is a backward reference (unless to the
current page), the number is ignored, so you can say
just: {[] <label id>}. You can't just say the label
name.

Form 2: <counter id>[!] <label id>
Those square brackets mean the "!" is optional --
don't write them in the manuscript! This form means
that the value of the label will be the C-value (if
there is no "!") or P-value (if there is an "!") of
the counter <counter id>. PUB can compute the upper
limit at declaration time by looking at the TO clause
of the counter's COUNT declaration and at the PRINTING
clause, so you don't have to state it. In case the
PRINTING clause used a template, the upper limit is
determined by a not quite foolproof heuristic:
suitably large numbers are substituted temporarily for
the C-value of the counter, for both values of its
parent, and for !, and the expression is evaluated.

Form 3: "<counter id>[!]" <label id>
This is identical to form 2, except before sending the
value of the label to the text scanner, it sends the
string (without the "!") and a space. Thus, the
following are exactly equivalent:

... See Section {Section! X} ...
... See {"Section!" X} ...

The macro used for cross-references in this manual
was:
.MACRO YON(LBL) ⊂ "Section " ; SUBSECTION! LBL ⊃

which was called like this:
...lots of useless words (See {yon someplace}). Lots more ......



9.2 LABELS
______

The syntax of <label definition> and <label definer>
are defined (::=) as:
Syntax:

9.2
SAILON-70 LABELS AND CROSS-REFERENCES Page 61


<label definition> ::= <label id> : <label definer>
<label definer> ::= [NEXT] <counter id>[!] | <e> | <text line>

Here is an example of each kind of <label definer>:

.INTRO: NEXT SECTION

.LAPLACE: IF ODD PAGE THEN PAGE ELSE PAGE+1

.EXPLANATION:
This is the line that is labelled by the label "EXPLANATION".

The first kind of definer makes the value of the label
be the current C-value (if there is no "!") or P-value
(if there is an "!") of the named counter. If NEXT is
present, the counter is stepped before the assignment
is made. The second kind makes the value of the label
be the value of the expression. The third kind makes
it be the value of PAGE! for the page that the <text
line> begins on.

The first and third kinds of definer both cause a
consistency check between all forward-references to
this label that mention a counter name and the counter
named here. The second kind does not cause a
consistency check. CAUTION: There is no consistency
check on backward-references. There is no check when
a cross-reference specifies a P-value (or C-value)
that the label definition also specifies a P-value (or
C-value). So if the output is incorrect, check for
such inconsistencies yourself.

A label must always be on a command line, or inside
curly brackets on a text line. If the /D switch was
used to obtain debugging information, then the label
will be printed on the right side of the document.

There is a slight ambiguity if your <label definer>
involves PAGE (or PAGE!). If you use the first or
third kind of definer, the evaluation is deferred
until the next text line is output, i.e., until the
next paragraph break or overflowed FILL line. Thus,
you may think of a PAGE label as labelling the
following text line; even if a new page is begun
before that line is output, the label value will be
the page on which that line appears. On the other
hand, if you use the second kind of definer (i.e., an


9.2

Page 62 LABELS AND CROSS-REFERENCES SAILON-70


expression involving PAGE or PAGE!), the value used
will be the current one at the time of evaluation --
even if the following text line doesn't get output
until the next page.

Note that L:NEXT PAGE will go to a new page and then
assign L a value when the first line is output to that
page. If the page is blank, the assignment is
deferred another page. All this kludgery is to insure
that if you say: See {"Page" X} there will really be
something to see! Be sure to position the label just
before the text line you want them to see.
______




































9.2
SAILON-70 PUB Page 63


SECTION 10

RESPONSES




10.1 TEXT RESPONSES
____ _________

A Text Response enables you to detect certain
conditions in the text, and to call macro-like
subroutines without using {...}. Presently, four
conditions can be responded to:

(1) Page Mark or Form Feed
(2) Blank Text Line
(3) Indented Text Line
(4) Presence of a one-to-five character signal

Syntax:
AT <condition> [;] <template>

When the condition is detected, the characters causing
it are replaced by:
{ <template> }

which is immediately executed.

To dis-declare a response exit the block in which it
was declared, or use a null template:
AT [;] ⊂⊃

The various <condition>s available are as follows:

AT PAGEMARK responds to an SOS page mark or a TECO
__ ________
<CR LF FF>. A typical use is:
.AT PAGEMARK ⊂SKIP TO COLUMN 1⊃

AT NULL responds to a blank text line. There is a
__ ____
predeclared response for this:
.AT NULL ⊂IF FILLING THEN BREAK ELSE SKIP 1⊃

This is the only reason that blank lines break in FILL
mode. You can redeclare it to treat them otherwise.
If you want them ignored, write:
.AT NULL ⊂IF NOT FILLING THEN SKIP 1⊃


10.1
Page 64 RESPONSES SAILON-70


AT N, where N is a positive integer N, responds to
__ _
each text line indented exactly N spaces. For
example, the standard macro TABBREAK declares:
.AT 8 ⊂IF FILLING THEN BREAK ELSE " "⊃

AT S, where S is a string beginning with a non-
__ _
alphanumeric character, responds to the occurrence of
that string (up to 5 characters long) appearing
uninterrupted in a text line. This one <condition>
can be followed by a formal parameter list of up to
five arguments, e.g.:
.AT "%%" A "$" B "%" C "$" ⊂ SEND INDEX ⊂ }A B-C{BREAK ⊃ ⊃

Each parameter name is followed by a string containing
a single character called its delimiter. When the
_________
signal (in the example, %%) is spotted in a text line,
the compiler continues to scan for actual parameters,
terminating each scan at the appropriate delimiter.
An actual parameter may span several text lines, but
each carriage-return is converted to a space if this
happens. No parameters may be omitted. None are
evaluated -- they are all literal.



10.2 TRANSITION RESPONSES
__________ _________

A transition response permits the specification of an
action to be taken at the beginning or end of any
counter or at the opening or closing of any area.
Syntax:
BEFORE|AFTER <counter id>|<area id> [;] <template>

Here is how this response fits into the NEXT <counter>
algorithm. To execute NEXT SECTION, PUB performs six
steps:

1) If SECTION≠ NULL then do AFTER SECTION response (if any)
2) Step SECTION using FROM and BY values
3) Compute SECTION! using PRINTING clause, and assign it to !
4) Do BEFORE SECTION response (if any)
5) For each sub-counter of SECTION, and each of their sub-counters:
a) If C-value≠ NULL: AFTER sub-counter response (if any)
b) Clear sub-counter C-value and P-value to NULL
c) If it is PAGE, initialize PAGE and PAGE!
6) Re-assign SECTION! to ! (steps 4 and 5 may have changed it)


10.2
SAILON-70 RESPONSES Page 65


The END of the block in which any counter is declared
(except PAGE) also causes Step 1 to occur.

The most useful transition responses are BEFORE PAGE
and AFTER PAGE. The BEFORE PAGE template is executed
not immediately after NEXT PAGE is executed, but a
little later, when the first line of output is ready
to be put on the new page. BEFORE <area id> responses
are similarly deferred until the first output is ready
for the named area. The AFTER PAGE template is
executed just before the page is written out -- it had
better not place into a text area that is already
full!

One transition response is pre-declared for you:
BEFORE PAGE ⊂ STANDARD TITLES ⊃

STANDARD TITLES is a pre-declared macro that prints
the headings and footings set up by EVERY HEADING and
its friends. You can of course redeclare this
response.

Every transition response template is automatically a
block. It is surrounded by BEGIN !?@3 ... END !?@3 or
something of that sort (which you will occasionally
spot in error messages). It is usually necessary to
declare all the mode settings and formats you want to
be in force inside the <template>. Consider the case
of BEFORE PAGE. At the time that a page happens to
overflow, it is entirely possible that the compiler is
in the midst of a FILL block with INDENT 10,20, all
control characters off, and the NOFILL PREFACE set to
2. However, the headings and footings should be
processed in NOFILL mode with preface 0, no
indentation, and several control characters activated.
You might declare:

.BEFORE PAGE ⊂ NOFILL ; INDENT 0 ; PREFACE 0 ; TURN ON "{←→"
.PLACE HEADING
{DATE}←AUTOMATIC VETERINARIAN→{SECTION!}

←{SUBTITLE!}
.PLACE FOOTING
{IF ODD PAGE THEN "→"}{PAGE!}





10.2

Page 66 PUB SAILON-70


SECTION 11

FOOTNOTES


Every column of every area has two portions, the calf
____
and the foot. During preparation of the calf,
____
paragraphs can be sent to the foot. A column is
considered full when the sum of the lines in the calf
and the foot exceeds the height of the area.

You can not declare Portion FOOT nor do a RECEIVE for
it. The compiler automatically declares a FOOT for
each area you declare, and does a RECEIVE for it after
each line is placed in the calf. Your only foothold
is the command "SEND FOOT".

Example:

.COUNT FOOTNOTE INLINE IN PAGE PRINTING "(i)"
.AT "$$" ENTRY "*" ⊂ NEXT FOOTNOTE ; ! ;
.SEND FOOT ⊂ TURN ON "{" PREFACE 1 SPREAD←1 INDENT 0,0
{!} ENTRY
.BREAK ⊃ ⊃

*
An example of the use of the "$$" signal response is:

...have been shown $$Abelwitz has obtained
similar results in his experiments with
hippopotami.*.
which will print in the calf:
...have been shown (iv).

and in the foot:

(iv) Abelwitz has obtained similar results
in his experiments with hippopotami.

There is an implicit BEGIN FILL ; ... END around
footnotes.




- - - - - - - - - - - - - - - - - - - - - - - - -
*) Thanks are due to Profs. G.I. Wish and O.U. Kidd of Steady State
University for this example.
Page 68 PUB SAILON-70


APPENDIX A

THOROUGHLY EXPLAINED EXAMPLES




A.1 SECTIONING MACROS
__________ ______
At the beginning of each section, it is customary to
perform the following ritual:

<<1>> Begin a fresh page
<<2>> Count up the section number
<<3>> Print the section number and name
<<4>> Skip a few lines
<<5>> Send the section number, name, and page number to the CONTENTS

See the document PUBMAC.TES[UP,DOC] for a description
of the macros STANDARD FRONT and STANDARD BACK, which
do all these things for you. If you want to define
your own macros, read on.

A macro to perform all the steps listed above
<<commented for reference>> is:

.MACRO SEC(NAME)
.<<1>> NEXT PAGE
.<<2>> NEXT SECTION
.<<3>> ONCE CENTER
↓_SECTION {!}_↓ -- ↓_NAME_↓
.<<4>> SKIP 3
.<<5>> SEND CONTENTS ⊂
{!}\\NAME→{PAGE!}{⊃⊃

A sample call on this macro is:
.SEC SPECIAL FEATURES

At the beginning of each subsection, a similar macro
can be called. The one below prints the subsection
name on a line by itself but prints the subsection
number at the beginning of the first line of the first
paragraph of the subsection. It makes sure that there
are enough lines for all this to be contiguous; if
not, it first goes to a new page. Finally, it allows
the macro call to specify a label to be used in cross-
references to this subsection.


A.1
SAILON-70 THOROUGHLY EXPLAINED EXAMPLES Page 69


.MACRO SS(NAME, LABEL) ⊂
.IF LINES < 10 THEN NEXT PAGE
.SKIP 2
.LABEL NEXT SUBSECTION
.ONCE NOFILL
NAME
.SEND CONTENTS ⊂
\{!}\\NAME→{PAGE!}{⊃⊃
{SUBSECTION!}. {⊃

The second argument is optional. If present, it must
include a colon at the end:
.SS MISCELLANEOUS FEATURES,MISC:

which would define the label MISC and output something
like this:



MISCELLANEOUS FEATURES

33-7. This is the first line of the paragraph that follows.



A.2 SAMPLE TABLE OF CONTENTS
______ _____ __ ________
The following CONTENTS portion expects a file
generated by the SENDs in the SEC and SS macros shown
above.

.PORTION CONTENTS
.NOFILL
.TABS 12, 20, 30
.SKIP 2
.RECEIVE

and might output:











A.2
Page 70 THOROUGHLY EXPLAINED EXAMPLES SAILON-70


SECTION Subsection PAGE
_______ __________ ____

1 INTRODUCTION 3
1-1 PURPOSE 3
1-2 APPROACH 3
2 BACKGROUND 11
2-1 HISTORY 11
2-2 SIMILAR WORK 13
2-3 STATE-OF-THE-ART 19

Notice that nearly all formatting is accomplished in
the SEND template.

Long titles will not be handled by the portion
declared above. Instead, FILL mode must be used. The
following declarations are approximately what was used
to produce the table of contents of this manual.

.PORTION CONTENTS
.FILL CRBREAK NOJUST
.INDENT 0, 35, 10
.TABS 10, 15, 25
.SKIP 2
.RECEIVE



A.3 ONE-LEVEL INDEXES
_________ _______
There is presently no way to have a phrase indexed
automatically every time it occurs. PUB now requires
that you mark each phrase to be indexed at every
occurrence that you wish to be referenced. The AT
<signal characters> response is particularly useful
for this purpose.

Choose a character or a pair of characters that will
never appear in the text of your manuscript; for
example "%<". This will be your signal that the next
phrase is to be indexed. Then choose a character that
will never appear in such a phrase; for example, ">".
This will be your end-of-phrase delimiter. Suppose
you would like the phrase "Simple variables" to be
indexed. Find each occurrence of this phrase in your
manuscript and surround it by your chosen characters:

Nothing warms the heart like %<simple variables>. We

A.3
SAILON-70 THOROUGHLY EXPLAINED EXAMPLES Page 71


Your favorite text editor may be of some help in this
task; however, watch out for a phrase that is broken
across two lines: the editor will miss it if your
search string is too stringent.

Suppose you would like your index to look something
like this:

signed constants 8.0
significant digits 10.3, 10.7
signs 2.4, 3.7
simple variables 8.1, 20.8, 20.11

Now you need to declare a signal response (see Section
10.1) at the beginning of your manuscript:

.AT "%<" PHRASE ">" ⊂ }PHRASE{
.SEND INDEX ⊂ }∧{PAGE!}∨{⊃⊃

This will respond to each occurrence in the text of
the signal "%<". The characters that follow this
signal, up to but not including the next ">", will be
substituted in the body of the template for every
occurrence of the word PHRASE. Then the body of the
template will be surrounded by "{...}" and embedded in
the text, replacing all characters from and including
"%<" to and including ">". The effect in the example
above would be:

Nothing warms the heart like {}simple variables{}
.SEND INDEX ⊂ }∧{PAGE!}∨{⊃. We

SEND causes the current PAGE! to be substituted in the
SEND template. Thus, the characters sent to the
generated file will be:

}∧2.6∨{

In the generated file, each index entry is signalled
by the character pair "∧<, followed by the phrase,
followed by ">", followed by the page number and "∨".
You may of course choose your own delimiters. They
will be recognized by the following signal response
that appears in PORTION INDEX:





A.3

Page 72 THOROUGHLY EXPLAINED EXAMPLES SAILON-70


.PORTION INDEX
.NOFILL
.LETTER ← PHR ← NULL
.AT "∧<" PHRASE ">" PGNO "∨" ⊂
.IF "PHRASE" = PHR THEN START },#PGNO{ END
.ELSE START COMMENT NEW PHRASE, GO TO A NEW LINE ;
. IF ↑LETTER = ↑"PHRASE"[1] THEN BREAK
. ELSE SKIP 1 ;
PHRASE##PGNO{
. PHR ← "PHRASE" ; LETTER ← "PHRASE"[1] ;
. END ⊃ ; COMMENT END SIGNAL RESPONSE ;
.RECEIVE "<>" ; COMMENT ALPHABETIZE BEFORE READING ;

RECEIVE will alphabetize the entries. The "AT" signal
response will analyze each entry and make a couple of
checks before outputting it:

(1) If the phrase is the same as the one just printed,
it simply appends the page number of the new entry to
the last line printed. For example, if the
alphabetized file contained:
...∧2.4∨{}∧3.7∨...

then the index would include:
Signs 2.4, 3.7

(2) Else, if the first letter of this and the previous
phrase are the same, it goes to the next line; else,
it skips a line. Thus, between the A's (and a's) and
the B's (and b's) there will be a blank line. Then,
it prints both the phrase and the page number.



A.4 TWO-LEVEL INDEXES
_________ _______
A "two-level index" divides some phrases into two
parts: a "generic" part and a "specific" part, e.g.:

compilers,
Algol 13, 15
Fortran 18
LISP 22
SAIL 15
computers,
analog 29
digital 10, 64, 80
consoles 16, 25

A.4
SAILON-70 THOROUGHLY EXPLAINED EXAMPLES Page 73


In the phrase "Fortran compilers", "Fortran" is the
specific part and "compilers" is the generic part.

This time we will approach the problem analytically
instead of synthetically. There are two kinds of
entries: one part and two part If two entries have
the same generic part (e.g., "computers"), then the
generic part should print only once.

As PORTION INDEX receives each entry, it must compare
it with the preceding entry. Say that the generic
part of the preceding entry was WASL and the specific
part was WASR (WASL was thus printed on the Left and
WASR on the Right). The generic part of the current
entry is L and the specific part is R. If WASL and L
are different, a whole new generic entry is to be
printed. Otherwise, if WASR and R are different, a
new specific entry is to be printed. Otherwise, a new
page number is to be added to the last entry printed.

As an extra feature in this index, we will not print
the same page number twice on the same line, i.e.,
twice in a row. Thus, an additional variable, WASP,
will be needed to remember the page number last
printed.

Furthermore, if the entry has no specific part (see
"consoles" in the above example), the page numbers
will be printed on the same line as the generic part.

The PORTION INDEX that follows assumes that the
generated file has entries of the form:

"<" generic-part "/" specific-part ">" page-number "%"

where the specific-part can be empty.













A.4

Page 74 THOROUGHLY EXPLAINED EXAMPLES SAILON-70


.PORTION INDEX
.WASL ← WASR ← WASP ← NULL ;
.NOFILL ; TABS 6 ;
.AT "<" L "/" R ">" PGNO "%" ⊂
. IF ↑WASL[1] ≠ ↑"L"[1] THEN SKIP 1 ; <<1ST LETTER DIFFERENT>>
. IF WASL ≠ "L" THEN
. START "NEW GENERIC" BREAK ;
L{IF "R"≠ NULL THEN START "WITH SPECIFIC PART" },
\R##{ END "WITH SPECIFIC PART" ; }PGNO{
. END "NEW GENERIC"
. ELSE IF WASR ≠ "R" THEN
. START "NEW SPECIFIC" BREAK ;
\R##PGNO{ END "NEW SPECIFIC"
. ELSE IF WASP ≠ "PGNO" THEN START },PGNO{ END
. ⊃ ;
.RECEIVE "<>" ;

To create the generated file for PORTION INDEX
requires a signal response such as:

.AT "%<" SPECIFIC "/" GENERIC ">" ⊂
. IF "SPECIFIC"≠ NULL THEN START }SPECIFIC { END ;
. }GENERIC{ ; comment print SPECIFIC and GENERIC in the text ;
. SEND INDEX ⊂ }{PAGE!}%{⊃ ;
. ⊃ ;

Every phrase to be sent to the index should be
bracketed as follows where it appears in the
manuscript:

that there are more %<Algol/compilers> than Algol users ...
the world's leading expert on %</consoles>.



A.5 KWIC INDEXES
____ _______
This one is easy. The desired output is:

writers of compilers often balk 16
_________
The XYZ compilers 35
_________
certain Algol compilers 8
_________
compilers I've known 41
_________
IBM computer 72
________
uses of the computer in government 64
________
At the end of the manuscript:


A.5
SAILON-70 THOROUGHLY EXPLAINED EXAMPLES Page 75


.PORTION KWIC
.NOFILL TABS 30
.AT "<" KEY "/" PRE "/" POST ">" PGNO "%" ⊂
→PRE\#↓_KEY_↓#POST→PGNO

.RECEIVE "<>"

At the beginning:

.AT "%<" PRE "≤" KEY "≥" POST ">" ⊂
.}PREβKEYβPOST{
.SEND KWIC ⊂
. }<KEY/{
. "PRE"[∞-25 TO ∞] }/{
. "POST"[1 TO 30-LENGTH("KEY")] }>{
. PAGE! }%{
. ⊃ ; ⊃ ;

Each phrase to be indexed is bracketed as follows:

It is said that % at
The last %> we bought was



























A.5

SAILON-70 PUB Page I


SUBJECT AND COMMAND INDEX

(References are to Page numbers)


_SKIP_ 32 BREAKING AT CARRIAGE-RETURNS 15
BREAKING AT TABS 15
! 46 BY 46

<dc> 34 C-value 46
<e> 33 CALLING A MACRO FROM A COMMAND
<id> 30 LINE 25
<oc> 34 CALLING A MACRO FROM A TEXT LINE
<qc> 34 25
35 CAPABILITIES 1
<se> 33 carriage-return 15, 64
<v> 31 CASE 56
CENTER 16, 19
ABOVE 57 channels 53
ADJUST 14 CHAR 31, 41
AFTER 64 CHARACTER 57
ALIGN 56 CHARS 31
alphabetize 52 collating sequence 52
APART 17 COLUMN 31
APPENDICES 49 COLUMNS 31, 40
APPENDIX 43 COMMAND AND TEXT LINES 13
AREA DECLARATION 39 COMMAND CHARACTER STATEMENT 49
arithmetic 30 command line 13
ASCII 34, 52 Command Processing 20, 24
Assignment expressions 33 COMMENTS 58
assignment statement 45 COMPACT 16
AT N 64 COMPILER OUTPUT 4
AT NULL 63 COMPOUND STATEMENT or CLUMP 35
AT PAGEMARK 63 COMPUTED TEXT 23
AT S 64 conditional expressions 33
AUTOMATICALLY DECLARED VARIABLES CONDITIONAL STATEMENT 45
31 CONSTANTS 34
CONTENTS 49, 50, 69
BEFORE 64 CONTINUE 41
BEFORE PAGE 65 CONTINUE STATEMENT 55
BEGIN 35 CONTROL CHARACTER ACTIVATION 21
BELOW 57 control characters 18
BIBLIOGRAPHY 49 CONTROL FUNCTIONS 18
BLOCK 35 COUNT 43, 46
block structure 35, 45 COUNTER DECLARATION 43
BOX FRAME STATEMENT 56 CRBREAK 15
BREAK STATEMENT 55 CROSS-REFERENCES 59
BREAKING AT BLANK LINES 15 crown 14

Page II INDEX SAILON-70







CRSPACE 15 GENERAL EXPRESSIONS 33
generated file 50, 52
DATA TYPE 30 Global 30
DATE 31 GROUP 17
decimal 34 GROUP SKIP 54
declaration 35
DECLARATIONS 37 HEADING 39
declarative 35 HEADINGS AND FOOTINGS 48
DEVICE LDX 57 hem 14
DEVICE LPT 56 hierarchy 43
DEVICE MIC 56 HORIZONTAL SPACE COMPACTION 16
DEVICE STATEMENT 55 hyphen 19
DEVICE TTY 56
document 1 IF 45
dot in column 1 49 ILLEGAL CHARACTERS 13
DOUBLE SPACE 39 imperative 35
DOUBLE SPACING 39 IMPERATIVES 45
INDENT DECLARATION 38
edit 56 INDENT1 31, 38, 45
ELSE 45 INDENT2 31, 38, 45
END 35 INDENT3 31, 38, 45
EQUATION 43 INDEX 49, 50, 52, 70
error messages 4 INLINE 46
EVERY HEADING 65 INSERT 49
EXPRESSIONS 30 integer 30
INTRODUCTION 1
FALSE 31
FIGURE 43 JUSTIFICATION 14, 18, 59
FILE 32 justifying 8
FILL MODE 14 JUSTJUST 16
filling 8, 31, 63
FLUSH LEFT 16 KWIC INDEXES 74
FLUSH RIGHT 16
FONT 57 LABELS 60
FOOTING 39 LABELS AND CROSS-REFERENCES 59
FOOTNOTE 43 LDX 56
FOOTNOTES 66 LINE 31
FOOTSEP 32 LINES 31
Forward Cross-Reference 44 LMARG 31, 45
forward-references 59 local 30
FR-80 56 LOCK 56
FROM 46
MACRO CALLS 27

SAILON-70 INDEX Page III







MACRO DECLARATION 27 PUBSTD.DFS 26
MACROS 25 PUG 2
manuscript 1 PUI 2
MARGIN CONTROL 40 PURPOSE 1
MODE AND SWITCH SETTING COMMANDS PUZ 2
17
MODE DECLARATIONS 37 quotes 34

NARROW 40 RASTER 57
NEXT COUNTER VALUE STATEMENT 45 READING THIS MANUAL 5
NEXT PAGE STATEMENT 47 RECEIVE STATEMENT 52
NOFILL 8, 16 RECURSIVE MACROS 29
NOFILL MODE 15 REFERENCE 43
NOJUST 8, 14 REQUIRE STATEMENT 53
NOPRINT 56 reserved words 33
NULL 30, 31 RESPONSES 63
RETAIN 16
octal 34 Right Flush 19
OMISSIONS 28 RMARG 31, 45
ONCE 36 Roman 47
ONE PARAGRAPH SCOPE 36 RPG 2
ONE-LEVEL INDEXES 70
ONLEFT 57 SAMPLE COMPILATION 9
ONRIGHT 57 SAMPLE TABLE OF CONTENTS 69
OPERATION 2 scope 35, 36, 37
output past the right margin 41 SECTION 43
SECTIONING 48
P-value 46 SECTIONING MACROS 68
PACK 56 SEND STATEMENT 50
PAGE 32, 43 SHOW 56
PAGE FRAME STATEMENT 55 SIMPLE EXPRESSIONS 32
PAGEMARK 63 SINGLE SPACE 39
Paracybernetic Society 12 SKIP N 54
paragraph break 14, 37 SKIP STATEMENTS 53
PARAGRAPHING 14 SKIP TO COLUMN N 54
PLACE DECLARATION 42 SKIP TO LINE N 54
PORTION DEMARCATION 49 SPREAD 31, 39, 45
PREFACE DECLARATION 39 STANDARD BACK 51
PRINT 56 STANDARD FRONT 51
PRINTING 46, 60 STANDARD TITLES 65
PUB2 2 START 35
PUBMAC.DFS 26, 51 STATEMENT TYPES 35
PUBMAC.TES 51 STATEMENTS 35

Page IV INDEX SAILON-70







string 34 VERBATIM 8
STRING SPACE EXHAUSTED 52 VERTICAL GROUPING 17
Strings 30 vest 14
Subscript 20
SUBSECTION 43 WIDEN 40
substring 33 widows 40
SUPERIMPOSE [n] 16 WORD BREAKS 18
Superscript 20
switches 3
syntax of PUB commands 5

TAB 19, 41
TABBREAK 15
TABLE 43
table of contents 50
TABS DECLARATION 37
TABSPACE 15
TEMPLATES 26
TEMPORARY AREAS 42
TEXT 39
TEXT AREA 40
TEXT CONVENTIONS 13
text line 13
text processing 23
TEXT RESPONSES 63
THEN 45
THOROUGHLY EXPLAINED EXAMPLES 68
TIME 32
TITLE AREA 40
TITLEPAGE 49
TOPLINE 31
TRANSITION RESPONSES 64
TRIPLE SPACE 39
TRUE 31
TURN OFF 22
TURN ON 21
TUTORIAL FOR BEGINNERS 5
TWO-LEVEL INDEXES 72

Underline 20
UNIMPLEMENTED STATEMENTS 56

VARIABLES 30