perm filename 22AUG.PUB[OK,TES] blob sn#117731 filedate 1974-08-24 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00002 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	.macro sec(name)$(if lines<6 then next page 
C00017 ENDMK
C⊗;
.macro sec(name)$(if lines<6 then next page ;
.begin center skip 2
*** NAME ***
.skip 1
.end)$
.once nofill
August 22 PUB -- *.SAI and PUBSTD.DFS[OK,TES] at SU-AI.
.skip 1
.SEC(|EVENLEFTBORDER, ODDLEFTBORDER|)

These variables in XGP mode specify the left border widths in mills of even and
odd numbered pages.
They both start out at 1300 mills (1.3 inches) and
the minimum value possible on our XGP is 500 (1/2 inch).
Any change you make will take effect
on the next page that is closed.

.BEGIN CENTER GROUP
---- If you want this feature: ----
--- Make the appropriate settings for your XGP in PUBDFS.SAI ---.
---- and adapt all code dealing with LFTMAR in pub2.sai ---
.end
The title page has special considerations.
When you begin the manuscript, PAGE=PAGE!=NULL, signifying an
unnumbered title page.  Its border will be ODDLEFTBORDER
to be consistent with the way books are made.  However,
if you set PAGE←0 (but leave PAGE!=NULL to inhibit numbering)
then the title page will get an even left border.

If you find that your page images are too far to the right in
documents that used to look OK, this may be because the
default left borders used to be 1 inch.  The easiest fix
is to put at the top of the manuscript
or in your own DFS file the statement ODDLEFTBORDER ← EVENLEFTBORDER ← 1000.

.SEC(|!XGPINTRA|)

You can change the intra-line spacing on the XGP for the
entire document by setting !xgpintra to some value other
than its normal 3 raster units (.015 inch).
.BEGIN CENTER GROUP
---- if you want this feature: ---
--- pass 2 knows the value as INTRA ---
--- See how we tell our XGP and do something similar if you can ---
.end

.SEC(|PROCEDURE name(args,...) $( ... RETURN(value) ... )$|)

A procedure is a variety of macro.
The advantage of a procedure is that it may RETURN
at any time, with or without a value.  The default RETURN
is RETURN(NULL).

Example:
.BEGIN NOFILL GROUP
	.PROCEDURE DOUBLE(N) $( N ← N+N; RETURN("OK") )$
	.X ← 5 ;
	.TTY ← DOUBLE(X) ;
.end continue
This will set X to 10 and print OK on the terminal.
Good news: the restriction on recursive macros which sometimes
requires a double semicolon is not applicable to
procedures.  Bad news: procedures are as
slow as macros, i.e., very slow.

.SEC(|REPEAT $( ... DONE ... )$|)

The command REPEAT followed by a template will execute
that template repeatedly until the statement DONE is executed.
Example:
.BEGIN NOFILL GROUP
	.PROCEDURE FACTORIAL(↑F N)
	.$( << ↑F means N is a value parameter >>
	.ANS ← I ← 1 ;
	.REPEAT$( ANS←ANS*I ; I←I+1 ; IF I>N THEN DONE )$
	.RETURN(ANS)
	.)$
	.TTY←FACTORIAL(4)
.end continue
This will print 24 on the terminal.

.SEC(|WHILE(pretest,action), UNTIL(posttest,action)|)

These macros will execute the <action> repeatedly
while the <pretest> before each repetition is true or
until the <posttest> after some repetition is true.
Their arguments usually are enclosed in vertical bars.

.SEC(|PUB!DEBUG|)

The PUB!DEBUG command provides an interactive
debugging facility.  It allows  for both examination
of the state of a compilation and keyboard entry of commands.

PUB!DEBUG goes into a "read-eval-print" loop.

It prompts with # and waits for
you to type a segment of text terminated by <cr> or <esc>.
While typing the segment, ↑A deletes a character,
↑V accepts the next character literally,
↑S retypes the segment, and <del> starts over.
LF starts a continuation line, and the current
continuation line can be deleted by ↑Q.
.BEGIN CENTER GROUP
--- continuation lines are only implemented at PARC ---
--- they are handled by PUB's own INCHWL in PARSER.SAI ---
--- The edit control characters are those in your system ---
.end

PUB!DEBUG expects the first line
of the segment to be in one of the following forms:
.BEGIN NOFILL GROUP
	<expression>
	<expression> ; <commands>
	; <commands>
.end continue
The value of the <expression> is printed, and then the
<commands> are executed.

If there are continuation lines, they are expected to be in manuscript
format.  Command lines
start with the command character (usually period);
text lines do not.

It is legal to
include temporarily unmatched BEGINs, STARTs, and ENDs in the
segment, but unmatched template brackets will cause
havoc of a very unpleasant sort (for now anyway).

The read-eval-print loop is terminated as soon as an empty segment
is typed (i.e., just <cr>).

.SEC(|THISLINE|)

A useful variable to examine while debugging is THISLINE, which
is the current output line formed so far by PUB.  It is
NULLed out by every line break.  In it, word breaks are represented by
$ and forward references by ↑K<number>.

.SEC(|BURP INPUT|)

To discover your context while debugging, execute the
BURP INPUT command.  It types out some of the
yet unparsed input at the current level and at several previous
levels of macros and requires.  BURP INPUT VERBOSE may
type out more characters at each level, and always proceeds
to the outermost level.

.SEC(|BURP AREAS|)

If you are hopelessly fouled up with area
declarations, try BURP AREAS, which types out 10-30 lines of
information about all areas known by PUB, even those that are
inaccessible in outer blocks.  BURP AREAS VERBOSE
includes a picture of each
area that has text in it, with numbers that
reference the numbers found in the intermediate ".TXTn"
files.

.SEC(|DEBUG("herald"), DEBUGFLAG, BUGOFF|)

A convenient way to activate PUB!DEBUG is by planting calls
on the macro DEBUG("herald") throughout the manuscript.
The herald (if any) is printed, and then PUB!DEBUG is
called.  However, the macro is a no-op if the variable
DEBUGFLAG is FALSE.  An easy way to turn it off is by
calling the macro BUGOFF.

.SEC(|ERROR MESSAGE RESPONSES|)

Most SAIL and PUB error messages are now handled by a new error
handler providing somewhat more useful information than before.

In addition to the usual responses (CR to continue, LF to
continue automatically, X to exit, S to restart), you can now
type P to call PUB!DEBUG.
.begin center group
--- At SU-AI and CMU, E<cr> does the right thing. ---
--- T<cr> might work at SU-AI too. ---
.end

A LF to continue automatically sets the variable ERRLF to TRUE.
It can be
cancelled by the command ERRLF←FALSE either in the
manuscript or in a debug loop.

.SEC(|USERERR "message"|)

Thanks to Rich Johnsson, this command lets you
activate the error machinery yourself.

.SEC(|XLENGTH("string")|)

If in XGP mode, XLENGTH returns the raster width of the string in
the current font.  For other devices, it returns 0.

.SEC(|SCAN|)

Adopted from SAIL by request of Lee Erman, this function scans a string in
search of break characters and can divide the string into
a pre-break and a post-break substring.  The various forms of
call, in order of increasing complexity, are:

ANS←SCAN(STR,STOPPERS) scans the string STR in search of
any of the break characters listed in STOPPERS.
If one is found, then ANS← the substring before the break
character, and if STR is a variable then STR← the substring
that remains, retaining the break character.
If no break character is found, then ANS←STR, and if STR is a variable then
STR←NULL.

ANS←SCAN(STR,STOPPERS,OMITS) is similar but characters
in the string OMITS are dropped from ANS.

ANS←SCAN(STR,STOPPERS,OMITS,OPTIONS) where OPTIONS is a
string with an (R, A, or S) and an (I or X) varies
the behavior of SCAN as follows:
.BEGIN NOFILL GROUP
	R	Retain break character in STR (Default)
	A	Append break character to ANS instead
	S	Skip break character -- neither STR nor ANS

	I	"Inclusive": Break characters are
			those in STOPPERS (Default)
	X	"eXclusive": Break characters are all ascii
			characters EXCEPT those in STOPPERS
.end

ANS←SCAN(STR,STOPPERS,OMITS,OPTIONS,BRCVAR) where BRCVAR
is a variable name, sets BRCVAR to a one-character string
containing the break character which actually stopped the
scan.  If no break character was found, then BRCVAR←NULL.

The effect of SAIL break tables can be had (functionally,
not speedily) by the use of a macro to supply the middle
arguments of the function call.

.SEC(|OCTAL("string")|)

OCTAL returns the octal codes of the characters
in its argument, e.g.,
OCTAL("ABC")="'101'102'103".
If the value of OCTAL
is used in arithmetic, only the code of the first character
is involved.

.SEC(|BEWARE("'octal'values")|)

For generality, the inverse of OCTAL is
provided, i.e., BEWARE("'101'102'103")="ABC".  The function
is so named to remind you that the
insertion of a cr, lf, tab, vtab, altmode, rubout, or null
in a text line will hopelessly confuse PUB
and forfeit your right to aid or sympathy.

.SEC(|DECLARATION(identifier)|)

Borrowed from SAIL by request of Lee Erman,
this function takes an identifier as an
argument and returns its PUB internal type code.
The most useful value of DECLARATION(X) is 0 (FALSE) which
signifies that X is undeclared.

.SEC(|TABS PAST THE LAST TAB STOP|)

These used to produce an error message, but by request of
Ed Taft they now quietly emit a single space.

.SEC(|UNDERLINING IN XGP MODE|)

This will look slightly different -- usually better -- thanks
to a request by Dan Bobrow that PUB emit the sequence
underbar-backspace-character instead of character-backspace-underbar.

.SEC(|HEMLINES IN XGP MODE|)

These may also look a bit different, because Rich
Johnsson has fixed a bug in forward reference code.