perm filename WRTON.JFR[DOC,AIL] blob sn#106779 filedate 1974-06-18 generic text, type T, neo UTF8
COMMENT ⊗   VALID 00002 PAGES 
RECORD PAGE   DESCRIPTION
 00001 00001
 00002 00002	.SEC |WRITEON|
 00020 ENDMK
⊗;
.SEC |WRITEON|
.FILL
Note. As of March 26, l974, the following feature is not available
from the SAIL system on [1,3], but does exist on [1,JFR] in files
SAIL.DMP and LIBSA7.REL.  The feature will become available from 
the system SAIL as soon as possible.

****** FURTHER NOTE: This feature may look somewhat different by the time it is actually
incorporated into the system -- RHT
**************

SAIL now has a WRITEON feature similar to the WRITEON statement of
ALGOLW.  SAIL WRITEON consists of a new key-word statement (WRITEON),
a pre-declared initialization procedure (WR_INI), and runtime support
routines.  The WRITEON statement takes an arbitrary number of SAIL
expressions as parameters, produces a string representation of each
expression, concatenates the strings, and writes the resulting string
to the terminal and to a file.

.SS |Definition|

The syntax of WRITEON is

.NOFILL

	WRITEON(<exp1>,<exp2>, ... ,<expn>)

.FILL

where <exp1>,<exp2>, ... ,<expn> are SAIL expressions.

A string representation of each expression is produced and then output.
The expressions are processed in order from left to right.

.BEGIN VERBATIM

Type of <exp>	String representaion of <exp>

    STRING	<exp> itself
    INTEGER	CVS(<exp>)
    REAL	CVG(<exp>)
    ITEM	the PNAME of the item, if it has one [the items
		ANY, BINDIT, MAINPI, and EVENT_TYPE are normally
		considered to have PNAMES];
		else "ITEM_"&CVS(CVN(<exp>))

    SET		if <exp>={} then "PHI" else "{"& <string
		representation of each item in the set> &"}"

    LIST	if <exp>={{}} then "NIL" else "{{"& <string
		representation of each item in the list> &"}}"

    array	concatenation of the string representation of 
		each element of the array; the elements are
		taken in ascending memory location order

.END VERBATIM

The initialization procedure is

.NOFILL

	WR_INI("DEVICE","FILE",CHANNEL,MAXLENGTH)

.FILL

where DEVICE is a device name, FILE is a file name, CHANNEL is a
system channel number, and MAXLENGTH is the number of characters
desired per line.

.fill

If FILE is not NULL, then DEVICE:FILE is OPENed for output on 
channel CHANNEL, and then ENTERed.  Subsequent WRITEON statements
will direct output to this channel/file, independent of whether 
output is also going to the terminal.  If FILE is NULL, then no
OPEN or ENTER is done, and subsequent WRITEON statements will not
direct output to any file except the terminal.

Remember to CLOSE(CHANNEL) if the file is to be made permanent.

.ss |Example|
.BEGIN VERBATIM

The following is an actual example of a program using WRITEON.

BEGIN "WRTEST"
EXTERNAL INTEGER WR_CHN;
EXTERNAL STRING WR_S1,WR_S2,WR_S3,WR_S4;
REQUIRE PNAMES; REQUIRE 10 NEW_ITEMS;
INTEGER J,K; ITEMVAR ITB; INTEGER ITEM ITA,ITB;
REAL PI; STRING GREET; SET S; LIST L;
STRING ARRAY ALPHABET[1:26]; INTEGER ARRAY EVENS[0:9];

DEFINE CRLF="('15&'12)", TAB="'11";

J←7; PI←3.14159265; ITVA←ITA; GREET←"HELLO"; DATUM(ITA)←117;
PUT ITB IN S; PUT ITA IN S;
PUT ITA IN L; PUT NEW IN L; PUT ITB IN L;
FOR K←0 STEP 1 UNTIL 9 DO EVENS[K]←K+K;
FOR K←1 STEP 1 UNTIL 26 DO 
	ALPHABET[K]←"ABCDEFGHIJKLMNOPQRSTUVWXYZ"[K FOR 1];

COMMENT SET SPACING BETWEEN WRITEONS; WR_S1←CRLF;
COMMENT SET SPACING BETWEEN EXPRESSIONS; WR_S2←" ";
COMMENT SET SPACING BETWEEN ARRAY ELEMENTS; WR_S3←TAB;
COMMENT SET SPACING BETWEEN SET & LIST ITEMS; WR_S4←", ";

WR_INI("DSK","OUTPUT.OUT",GETCHAN,50);
WRITEON(J,PI,ITV,GREET,DATUM(ITA);
WRITEON(S,L,25,SQRT(3.),{},GREET & GREET);
WRITEON EVENS,CRLF&"SAY YOUR ABC's",ALPHABET);
CLOSE(WR_CHN)
END "WRTEST"

The file OUTPUT.OUT, after the program is run:

7  3.141593     ITA HELLO 117
{ITA, ITB} {{ITA, ITB, ITEM_11}} 25  1.732051     
PHI HELLOHELLO
0	2	4	6	8	10	12
	14	16 	18 
SAY YOUR ABC's A	B	C	D	E
	F	G	H	I	J	K
	L	M	N	O	P	Q
	R	S	T	U	V	W
	X	Y	Z

.END VERBATIM
.ss |Runtime particulars|
.fill

The WRITEON runtime keeps track of the print length of the line
being assembled.  If a string to be concatenated to the end of 
the line would cause the print length to exceed MAXLENGTH characters,
then the runtime inserts a CRLF and resets its counter before
concatenating the string.

Example:  Suppose MAXLENGTH is 50, there are 35 characters already
in the line, and the runtime is asked to concatenate a string of 
21 characters to the end of the line.  Since 35+21>50, the runtime
concatenates a CRLF, zeroes its counter, and then concatenates the
21-character string.  This produces one line of 35 characters and
another (as yet partial) line of 21 characters.  Suppose the runtime
is then asked to concatenate strings of 58 characters and 10 characters.
Since 21+58>50, the runtime concatenates a CRLF, zeroes its count, and
concatenates the 58-character string.  Since 58+10>50, the runtime
concatenates a CRLF, zeroes its count, and concatenates the 10-character
string.  Thus there are lines of 35, 21, 58, and (a partial line of )
10 characters.

The runtime will recognize a CRLF contained in a string to be concatenated
if the CRLF appears as either the first two or the last two characters
(but it will recognize only one CRLF if CRLF appears at both the beginning
and end).  The runtime will recognize a TAB in a string to be concatenated
if the TAB is the first character of the string.

The runtime routine contains several INTERNAL variables which control
the WRITEON environment.  The user may declare these EXTERNAL to look
at them or change their values.  Variables are initialized to 
0(FALSE) if integers and to NULL if strings.

.BEGIN VERBATIM

Integer Variables	Function

    WR_TTK	Terminal kill flag.  If true, do not send 
		output to the terminal.

    WR_FIL	File flag.  If false, do not send output to 
		DEVICE:FILE of WR_INI.

    WR_LEN	Maximum line length before CRLF is inserted.
		(MAXLENGTH is copied to this location.)

    WR_CHN	Channel number for file output.
		(CHANNEL is copied to this location.)

    WR_ACT	Activation control--when to actually do the
		output to the terminal or file.
		=0   at the end of the WRITEON statement
		=1   after each inserted or recognized CRLF
		≥2   after each expression in the WRITEON
		≥3   after each element of an array, set, or list

    WR_USR	If ≠0, the location of a SIMPLE procedure to be
		called instead of OUTSTR and OUT to dispose of
		the current line.  This procedure should be
		declared like SIMPLE PROCEDURE GOBBLE(STRING S).
		Then say EXTERNAL INTEGER WR_USR;
		WR_USR←LOCATION(GOBBLE).

    WR_LPK	Leap name killer.  If true then the empty set
		prints as {}, the empty list as {{}}, and
		the items ANY, BINDIT, MAINPI, and EVENT_TYPE
		are not treated in any special manner.

    WR_CUR	"Cursor" position.  This variable holds the print
		length of the current line.

String Variables	Function

    WR_S1	Concatenated to the end of the line after
		each WRITEON statement.

    WR_S2	Inserted into the line between each expression
		appearing in the WRITEON statement.

    WR_S3	Inserted into the line between consecutive
		elements of the same array.

    WR_S4	Inserted into the line between consecutive
		items in the same set or list.

    WR_ST	This is the current line being assembled.
		If WR_USR≠0, then the call to the user
		procedure is   user_proc(WR_ST).

.END VERBATIM
.FILL

All CVS and CVG calls are done with the current settings or
WIDTH and DIGITS (see SETFORMAT).

To minimize the number of string concatenations (at the expense of calls
to OUTSTR and OUT), use WR_ACT←3.  To minimize the number of calls to 
OUTSTR and OUT (at the expense of string concatenations) use WR_ACT←0 
(the default).

To use multiple channels, non-Stanford I/O structures, etc:

.begin verbatim

A.  Do the I/O initializations for each file/channel.  A standard
    OPEN and ENTER sequence may be done for each file simply by
    calling WR_INI several times (once for each file/channel).

B.  Set WR_FIL←TRUE and WR_LEN←<length>.

C.  To switch channels, save and restore the values of parameters
    that are pecular to each channel, then do the WRITEON.  The
    values which normally will need to be saved and restored are
    WR_ST, WR_CUR, and WR_CHN.  Here is one way to do this:

    PROCEDURE SWITCH_CHAN(INTEGER NEWCHAN);
    BEGIN OWN INTEGER ARRAY CURSOR[0:20]; OWN STRING ARRAY STR[0:20];
    EXTERNAL INTEGER WR_CUR,WR_CHN; EXTERNAL STRING WR_ST;

    IF NEWCHAN=WR_CHN THEN RETURN;
    CURSOR[WR_CHN]←WR_CUR; STR[WR_CHN]←WR_ST;
    WR_CUR←CURSOR[NEWCHAN]; WR_ST←STR[NEWCHAN]; WR_CHN←NEWCHAN
    END;
	.
	.
	.
    SWITCH_CHAN(<new channel number>);
    WRITEON(<whatever>);

.end verbatim

.ss |Using WRITEON for other purposes|
.fill

At compile time SAIL constructs a one-word descriptor for each expression
appearing in the WRITEON statement.  These descriptors are fed one at a
time to the runtime routine WR_TON, which interprets the descriptors
in the appropriate manner.  After all the expressions appearing in the
WRITEON statement have been processed, the compiler inserts an extra 
call to WR_TON with an all zero descriptor to flag the end of the
WRITEON statement.

The descriptor of an expression is identical to the datum which would
be produced by REF_ITEM of the expression; WRITEON does not create new
items.  The format of a descriptor is:

.exa

Bits	Name	Comment

    1	REFB	"Reference" bit.  If this bit is on, then the
		address field points to a "permanent" location.
		If this bit is off, then the address field points
		to a temporary location.  Temporaries may be 
		reused by the compiler within the same WRITEON.

    2	QUESB	On if ? itemvar.

    3	BINDB	On if BINDING itemvar.

    4	PROCB	"Procedure" bit.

    5	ITEMB	On if item or itemvar.


    6	ARY2B	On if λ array itemvar array.

 7-12	MSK6BT	Type code, same as LEAP datum type (see TYPEIT).

13-35	ADDR	Effective address which points at the object 
		referred to.  String temporaries reside on top
		of the string stack (ADDR is  SP,,0).  All 
		other objects reside in fixed memory locations
		(ADDR is  0,,address).  The address of an array
		is the address of its HEAD word (see SAIL manual,
		p.106).

.endexa
.fill

By writing his own routine named WR_TON the user may do anything he
wants with the descriptors.

Caution.  In the case of a string temporary, the user must pop the stack.
The locations housing other temporaries may possibly be used more than once
within the same WRITEON.