Trailing-Edge
-
PDP-10 Archives
-
decuslib20-01
-
decus/20-0002/sail.doc
There are 2 other files named sail.doc in the archive. Click here to see a list.
SECTION 1
New Features
This section describes changes and additions to Sail since the August
1976 manual, AIM-289.
1.1 - Double Precision
Double precision floating-point arithmetic is available. Use the
<type!qualifier> LONG in declarations. For example,
LONG REAL X, Y, Z;
LONG REAL ARRAY XA[0:N];
Currently LONG has meaning only when it appears as part of LONG REAL.
(At some future time LONG INTEGERs may also exist.)
The runtime routines LREALIN and LREALSCAN operate the same as REALIN
and REALSCAN, except for returning LONG REAL values. The routine CVEL
takes a LONG REAL value and returns a string representation like that of
CVE, except that "@@" is used to signify LONG when delimiting the
exponent. Any of "@", "@@", "E", or "D" are acceptable exponent
delimiters to LREALIN and LREALSCAN.
Variables which are declared LONG REAL are represented in KI10 hardware
format double precision, take two consecutive words of storage, and
provide 62 bits of precision (approximately 18 decimal digits) to
represent the fraction part of a floating-point number. Regular REAL
variables occupy a single word and have 27 bits (8 decimal digits) of
precision. The exponent range of both REAL and LONG REAL variables is
from -128 to 127, where 2^127 is approximately 10^38.
LONG REAL is a dominant type in arithmetic operations +-*/%^ MAX MIN and
arithmetic relationals <>= LEQ GEQ NEQ. If one operand is LONG REAL
then both operands will be converted to LONG REAL (if necessary) before
performing the operation. An exponentiation involving a LONG REAL
raised to a positive integer constant is an exception to this rule. The
type coercion path is linear: STRING -> INTEGER -> REAL -> LONG REAL.
Conversion from REAL to LONG REAL is performed by assigning the (only)
word of the REAL to the most significant word of the LONG REAL and
setting the second (least significant) word of the LONG REAL to zero.
Conversion from LONG REAL to REAL is by UUO which rounds.
Arithmetic and assignment operations are compiled into DFAD, DFSB, DFMP,
DFDV, DMOVE, DMOVEM instructions. The Sail operations ASH, LSH, ROT,
LAND, LOR, EQV, XOR are performed on both words (ASHC, LSHC, ROTC, 2
ANDs, 2 IORs, etc.). LOCATION of a LONG REAL variable gives an address
E such that DMOVE AC,E fetches the appropriate words of memory. When
passed by value as an actual parameter to a procedure, both words are
placed on the P stack: PUSH P,X ; PUSH P,X+1. LONG REAL fields in
record classes are handled much like STRING fields, except that the
address in the record field points to the first word of a 2-word block
(rather than to the second word as in the case with STRINGs).
LONG REAL ARRAYs are stored as contiguous blocks of 2-word values.
ARRTRAN done on two LONG REAL arrays is a transparent operation, but for
ARRYIN, ARRYOUT, or ARRBLT the actual word count is specified; think
about whether you should multiply by 2! At runtime the array descriptor
for a LONG ARRAY has bit 12 (40,,0 bit) set in MULT(n), the multiplier
for the last dimension (which would otherwise be =1). Similarly, a LONG
ARRAY is allocated by setting bit 12 (40,,0) bit in the parameter which
specifies the number of dimensions to ARMAK.
Runtime support for LEAP items with LONG REAL datums does not yet exist,
although the compiler does generate suitable code. Runtime support for
double precision exponentiation is also limited for the moment. Any
exponentiation X^K where K is a positive integer constant is compiled
inline using the binary ("Russian peasant") method, regardless of the
type of X. Other exponentiations involving LONG REALs are merely
translated into procedure calls on
LONG REAL PROCEDURE DPOW (INTEGER EXPONENT; LONG REAL BASE);
LONG REAL PROCEDURE DLOGS (LONG REAL EXPONENT, BASE);
depending on the type of the exponent. The Sail runtime system does not
yet contain such procedures, so you will have to roll your own.
1.2 - Declarations and Scope
Sail declarations must occur before use. For example, in the following
program the argument to PRINT is interpreted as the K on line 2, even
though by the ALGOL60 notion of scope it should be interpreted as the K
on line 5.
BEGIN "FOO"
INTEGER K; COMMENT this is line 2;
BEGIN "RUB"
PROCEDURE BAR; BEGIN PRINT(K) END;
INTEGER K; COMMENT this is line 5;
<statements>
END "RUB"
END "FOO"
1.3 - Two-character Operators
The compiler now recognizes "**" for "^", ":=" for "_", "<=" for "LEQ",
and ">=" for "GEQ".
1.4 - Requires
REQUIRE OVERLAP!OK; will suppress the message which occurs at
initialization when two programs have declared items.
REQUIRE VERIFY!DATUMS; causes the compiler to generate three additional
instructions for each DATUM reference, to make sure (dynamically, at run
time) that the type of the item in the DATUM construct is the same as
the compiler expected. This is similar to (the unimplimented effect of)
declaring all itemvars CHECKED. It is planned that VERIFY!DATUMS will
soon be a bit in the /A switch and that the corresponding REQUIRE will
disappear.
REQUIRE PROCESSES; insures that MAINPR, the main process, is
initialized. You need not specify this REQUIRE if you use APPLY or
SPROUT, but if the only use of processes is via INTSET then you must
REQUIRE PROCESSES;.
1.5 - CASE statement
In an explicitly numbered CASE statement the word ELSE can appear where
a bracketed case number is normally used. The statement following the
ELSE is a catch-all for any case number not mentioned, including
anything which would otherwise generate a CASE index error. For
example,
CASE K OF BEGIN [3] J_3; ELSE J_4; [5] J_5 END
is another way of accomplishing
IF K=3 THEN J_3
ELSE IF K=5 THEN J_5
ELSE J_4
A CASE statement containing an ELSE case does not generate a call to the
CSERR runtime routine, and in addition the jump table usually contains
only max_case - min_case +1 words (rather than max_case +1).
1.6 - Circular RECORD!CLASSes
To define two record classes, both of which contain RECORD!POINTER
fields refering to the other class, say
FORWARD RECORD!CLASS BAR (RECORD!POINTER (ANY!CLASS) Q2);
RECORD!CLASS FOO (RECORD!POINTER (BAR) Q1);
RECORD!CLASS BAR (RECORD!POINTER (FOO) Q2);
In general, declare one class to be FORWARD and list its RECORD!POINTER
fields as pointers to ANY!CLASS. This breaks the circularity and allows
maximum compile-time type checking.
SECTION 2
Support for Tops-20
The "Tenex" version of SAIL has been modified slightly to support Tops-
20. In general SAIL should work the same on Tops-20 as it does on
Tenex. In particular, both the compiler and compiled SAIL programs can
be moved between vanilla Tenex and Tops-20 sites and do the equivalent
things. This is possible because all tests for Tops-20 or Tenex-
specific code are made at run-time. Code for both will be present in
all Tenex versions.
The one exception to this happy picture is with runtimes that are named
after JSYS's and are documented as simply doing that JSYS. SAIL makes
no attempt to insulate you from subtle differences in the meaning of
bits, or the fact that some of the JSYS's do not exist in one of the
systems. The most infamous of these problems is the removal of the
STDIR JSYS in Tops-20. That means that SAIL programs using STDIR will
blow up on Tops-20. (However similar results may be obtained using the
RCDIR and RCUSR routines, which support the corresponding JSYS's in
Tops-20.)
The following differences in behavior follow from the desire to make
SAIL on Tops-20 look like a "real" Tops-20 system:
The SAIL compiler's command scanner has been totally rewritten
for Tops-20. The old scanner will still be used for
Tenex. The most important feature of the new scanner is
that it links properly to the EXEC's commands COMPILE,
EXECUTE, LOAD, and DEBUG. Note that in order to make
DEBUG work, /BAIL:17 is forced for all compilations done
with the EXEC commands. The DEBUG command then causes
the program to be loaded with BAIL and a breakpoint
inserted at the start of the program.
If you run SAIL explicitly, you will find that the top-level
parser follows the conventions of recent Tops-20 command
interpreters. It will expect a list of source file
names, just as the Tenex one did, but switches are on the
same line, rather than appearing as subcommands. The
switch names have been lengthened for readability, but we
trust no one will have trouble matching the new names
with the manual. Arguments are now put after the switch
name and a colon, as usual. Instead of ^R and ^L to
select the output file names, the switches /BINARY,
/LIST, and /CREF can optionally take file names as
arguments. To suppress creation of an output file,
specify /NOBINARY, /NOLIST, or /NOCREF. The default is
/BINARY/NOLIST, as with Tenex. Switches that took octal
numbers to specify sets of features now allow keyword
arguments. If you do not find the new form self-
explanatory with a bit of usage of ?, you can still use
the old octal numbers.
On Tenex, certain files are expected to be on <SAIL> or
<SUBSYS>. The most important examples are <SAIL>T-6-
SAISG8.SAV and <SUBSYS>LOADER.SAV. On Tops-20, such
files are looked for on logical devices SAI: and SYS:
respectively. It is assumed that any site using SAIL
will define SAI: as a system-wide logical device,
probably referring to PS:<SAIL>. By using SAI: instead
of <SAIL>, we allow users to redefine SAI:, for testing
private versions of the sharable segment, etc. It also
means that it is not necessary to have a separate <SAIL>
directory on each mountable structure, as would be needed
if <SAIL> were used. Also, files having the extension
.SAV on Tenex are assumed to have .EXE on Tops-20. E.g.
the sharable segment is gotten from SAI:T-6-SAISG8.EXE,
and the loader from SYS:LINK.EXE.
On Tops-20, the default line-editors for TTY input use the
RDTTY JSYS. RDTTY will be used whether the user
specifies the "Tenex-style" or "Tops-10 style" line
editor, since RDTTY is sort of a merging of features of
both. The RDTTY JSYS implements the standard Tops-20
editing characters, for which we refer you to DEC's Tops-
20 User's Guide.
In some cases, user programs may wish to determine which operating
system they are running on. At startup time, the SAIL runtimes execute
a special GETTAB UUO that is supposed to return a code indicating the
operating system. This GETTAB is implemented on all known operating
systems that use PDP-10 hardware, except for the Stanford A.I. Lab
monitor, and possible certain out-of-date Tenex systems. It is even
implemented on ITS! The value returned by this UUO is put in a variable
$OS, which may be declared as an EXTERNAL INTEGER by your program so you
can look at it. The codes are returned in bits 18-23:
1 - Tops-10
2 - ITS
3 - Tenex
4 - Tops-20
5 - Stanford A.I. Lab monitor
The other bits in this word are reserved for indicating subversions of
these various operating systems.
For the Tenex SAIL system only, there is another EXTERNAL INTEGER
variable, $OSTYP. This is set to 0 for Tenex and 2 for anything else.
This is the variable actually used by the runtimes to determine whether
to execute Tenex or Tops-20 code.
2.1 - New runtimes for Tops-20
In an effort to support programming on Tops-20, the following runtimes
have been added. Note that they will result in errors if executed on
Tenex systems, since they call JSYS's that do not exist on Tenex. No
attempt is made to prevent these errors, on the theory that some Tenex
system might decide to implement one of them. So we recommend that
these be used only in programs that test $OS or $OSTYP and provide
special code for both Tenex and Tops-20.
******************************* ACCES ******************************;
SUCCESS __ ACCES("DIRECTORY","PASSWORD",FLAGS,JOBNO)
This runtime calls the ACCES JSYS. It gives the specified job access to
the requested directory. Only the first argument is required. Defaults
are
Password null
Flags '400 000 000 000 (Connect)
Jobno the current job.
Note that because of the implementation of defaults in SAIL, it is not
possible to specify a jobno of 0. However on Tops-20 job 0 is part of
the operating system, so this does not seem to be a serious limitation.
(A SAIL program running as part of job 0 would of course be able to
specify the current job.)
FLAGS are:
'400 000 000 000 Equivalent to CONNECT monitor command
'200 000 000 000 Equivalent to ACCESS monitor command
'100 000 000 000 Equivalent to END-ACCESS monitor command
JOBNO is the number of the job, or -1 for current job. (Requires
privileges to set for other jobs).
On success, returns true; on failure, false, with TENEX error code in
!SKIP!.
******************************* RCDIR ******************************;
DIRNUM __ RCDIR(@"DIRECTORY",@DIRNO,@FLAGS)
This procedure calls the RCDIR JSYS. A 36-bit directory number is
returned as the value of the call and also put in the reference
parameter DIRNO (useful for stepping through directories). If
recognition is not specifically disabled, the reference string DIRECTORY
is updated.
Input FLAGS are:
'10 000 000 Allow partial recognition
'4 000 000 Step to next directory in group (Previous
directory number is in DIRNO, and the
"wildcard" bit must be set)
'2 000 000 Allow wildcards in "DIRECTORY"
'1 000 000 Match given string exactly (suppresses
recognition)
The flags returned by the monitor are put in the reference parameter
FLAGS.
On failure, zero is returned with !SKIP! set to:
1 string does not match
2 string is ambiguous
3 no more in this group (while stepping)
On error, zero is returned with !SKIP! set to the TENEX error code.
(Note the subtle difference here: an error involves an illegal format
for a directory name, or some other invalid argument. Such an error
generates a Tenex error code of the usual sort. A directory name which
is valid, but just does not happen to exist on this system does not
generate a Tenex error code, but is simply called a failure.)
******************************* RCUSR ******************************;
USRNUM __ RCUSR(@"USER",@USRNO,@FLAGS)
This translates a user name string to its corresponding user number in
the identical manner as RCDIR does for directory strings. See RCDIR for
details. Note that a valid directory name always has < > around it,
while a user name does not.
******************************* RSCAN ******************************;
SUCCESS __ RSCAN(FUNCTION,STRING)
This procedure calls the RSCAN JSYS. This allows the program to replace
the string in the rescan buffer, set input to come from that buffer, or
determine how many characters are still to be read from that buffer.
Both arguments are optional. If omitted, the values used are
function 0
string null
The values of FUNCTION mean:
0 Set input to come from the rescan buffer.
1 Return number of characters still to be read from that
buffer.
The value returned by the call is the number of characters in the buffer
for FUNCTION 0, and number of characters left for FUNCTION 1.
If STRING is non-null, FUNCTION is ignored, the string is placed in the
rescan buffer, and the value returned by the call will be true on
success.
On failure or error, zero is returned and !SKIP! is set to the TENEX
error code.
****************************** ERSTRING ****************************;
errmessage _ ERSTRING(ERRNO, FORKNO)
This is similar to ERSTR. It will get the error message corresponding
to the given error number on the given fork. However instead of
printing it on the terminal, as ERSTR does, it returns it as a string.
!SKIP! will be set if the error number is illegal. In that case no
guarantee is made about what is returned. ERRNO and FORKNO are both
optional. The default values are the most recent error (-1) for ERRNO,
and the current fork for FORKNO.
2.2 - Changes to existing procedures to support Tops-20
******************************* CLOSF ******************************;
CLOSF now takes an optional extra argument, CLOSF(chan,bits). This
argument is an integer. Its left half will be put in the left half of
AC1 in the CLOSF jsys. The most useful option is bit '4 000 000 000.
This specifies that the file is to be aborted, rather than closed
normally. If the file is on disk, it will not appear (unless it has
been closed and reopened). If it is on tape, the 2 EOF's will not be
written.
Note that the SAIL runtimes have a strange habit of closing and
reopenning files, to try to get read/write mode. If you want to be able
to abort creation of a file, you will have to open it "RW". If you do,
then CLOSF with bit '4000000000 set will cause it not to show up on disk
at all. If you had specified only "W", SAIL would have created the
file, closed it, and reopened it, in order to get it in "RW" mode, which
the runtimes prefer to use. Then it would not be possible to abort
creation of the file by doing an abort close, since it has already been
closed normally.
Note that CLOSF always sets bit '400 000 000 000 (do not release the
jfn). To release the jfn, you can do a RLJFN after the CLOSF. If the
extra argument is omitted, no bits other than '400 000 000 000 are set.
******************************** DELF ******************************;
DELF now takes an extra optional argument, DELF(chan,bits). This
argument specifies bits to go in the left half of AC1 in the DELF jsys.
The most useful bit is '200 000 000 000. Setting this bit will cause
the file to be expunged as well as deleted. Note that DELF always sets
bit '400 000 000 000 (do not release the jfn). To release the jfn, you
can do a RLJFN after the DELF. If the extra argument is omitted, no
bits other than '400 000 000 000 are set.
******************************* IDTIM ******************************;
IDTIM now takes an extra optional argument, IDTIM(datime,bits). This
argument specifies certain details of the format expected by the jsys.
The default value if this argument is omitted is 0.
****************************** OPENFILE ****************************;
Openfile uses a somewhat obscure algorithm to determine the setting of
bit '400 000 000 000 in the GTJFN jsys. This is the bit that determines
whether an existing version will be used if there is one, or whether the
next higher version number will be used. If you specify "O" or "N",
this bit is never used, since it is meaningless in that case.
Otherwise, the next higher version is always used when "W" is set, and
the highest existing version when "W" is not set. (The one exception is
that "W" with "A" will still use an existing version, for obvious
reasons.) This causes problems for people who wish to open an existing
file for "RW" access, since "RW" will cause the bit to be set that moves
one to a new version. "ORW" will cause you to update an existing
version, but it will then give an error if there is no existing version.
In many cases you want to use the existing version if there is one, else
create a new file. This corresponds to setting no special bits in the
GTJFN at all.
To allow this useful case, we have added an option "U" (Update) to
OPENFILE. This is like "RW", except that it does not set the bit
causing the version number to be advanced. So it will use an existing
version if there is one, else create a new file.
******************************* RUNPRG *****************************;
RUNPRG will now supply a default extension if you leave it out in the
string. This is to allow people to write programs that will work on
both Tenex and Tops-20 without changing the file name, since the normal
extensions for executable files are different on these two systems. The
default extension supplied will be .SAV for Tenex and .EXE for Tops-20.
SECTION 3
New Tops-10 Features
Current versions of SAIL now support standard DEC Tops-10 systems more
fully than in the past. Tops-10 is no longer treated as a poor relation
of Stanford WAITS. Descriptions of the features specific to Tops-10
follow:
3.1 - SFD's
Any routine that accepts a file spec will allow SFD's as part of the
directory. Note that CVFIL has a problem in this regard, as it tries to
return the PPN in a reference integer parameter. If the file spec
includes SFD's, there is no obvious place to put them. I have taken the
quick and dirty route of returning a pointer to the path block in place
of a PPN. This strategy is reasonable because the monitor will accept
such a pointer in any context where it wants a PPN. Because old
programs may be expecting a real PPN, I do set !SKIP! in this case.
However I set it to +1 for SFD's, and -1 for a real error. Thus new
programs can be written to accept SFD's.
The project and programmer numbers can be omitted, as with PIP. Thus
[,,FOO] is the SFD FOO in your area. [,] is your area. But [] is 0,
i.e. your default path.
3.2 - Using SAIL from batch jobs
SAIL knows whether your job is a batch job or not. (It looks at a
GETTAB bit set up by the batch job controller.) This is desirable
because of SAIL's error handling. It normally goes into an interactive
error handler that asks the user what to do. This is obviously
undesirable in a batch job, because the error handler is liable to read
characters intended as input or commands. Thus the interactive error
handler is not called for batch jobs. In the compiler, SAIL assumes a
line feed response to the error handler. I.e. the compilation
continues. This allows you to see the maximum number of errors. In a
user program, SAIL aborts the program on the first error.
3.3 - USETI and USETO
There has been a problem previously with using USETI and USETO in
buffered I/O modes. The problem is that the corresponding monitor calls
do not clear your I/O buffers. Thus you can do a USETI, but you won't
see any data from the new block until you exhaust the data in you
current buffer ring. (Of course there is no easy way to know how much
data you would have to skip over.) Similarly, after a USETO, nothing
will go out to the block you specified until the current block is
filled. Under the new version of SAIL, USETI and USETO both clear the
buffer ring. USETI clears the input ring. USETI and USETO both force
out anything in the output ring that hasn't gone out yet, if any. Thus
the next SAIL I/O call will use the block you specified. Do USETI
before input and USETO before output.
Note that at Stanford the monitor clears the buffers as described above.
Thus this change is mostly simulating what would happen at Stanford.
However there output is only forced by a USETO. Thus I am not sure how
one would switch from output to input at Stanford. Here one would
simply do USETI to the desired block, but at Stanford that will not
work.
USETI -1 is a special case. It gets you to the end of the file under
TOPS-10. (At Stanford another method must be used for this.) If the
normal buffer clearing were done, USETI -1 would set your EOF variable.
Since it is normally used as a prelude to output, you do not want EOF
set, probably. Thus USETI -1, as a special case, does not clear the
buffer ring.
Mag tape positioning commands (MTAPE) have a problem with buffers that
is exactly the same as the problem solved by the USETI and USETO
patches. Nothing has been done about this, however. Should you be in
the middle of reading a tape and do a rewind, the next read would get
the next buffer in the ring, rather than the first thing on the tape.
This can apparently be solved by closing and reopening the device,
however, so it did not seem to be worth troubling about. (That would
not work for USETI and USETO because closing the disk also loses the
file one is working with.)
3.4 - Changes to buffering
It was discovered that SAIL gave a different interpretation to the byte
count in the routines intended for ASCII files (INPUT, OUT, NUMIN, etc.)
and those intended for binary files (WORDIN, ARRYIN, INOUT, etc.). This
meant that one could not mix those routines. E.g. one could not use
both INPUT and WORDIN for the same file. Trying to do so resulted in
losing characters from the file. This problem has been fixed, so it is
now OK to use WORDIN with ASCII files. It will return the next
character from the file, as an integer. Be warned that under TOPS-20
WORDIN will always return the next 36 bits, even for ASCII files, so use
of WORDIN to get a character will make your program incompatible with
TOPS-20 SAIL. (There is another function under TOPS-20 to return the
next character, however, so the incompatibility is not serious.)
3.5 - Non-blocking I/O
It should now be possible to do non-blocking I/O. The only problem
before was that you couldn't tell when an I/O operation had been
prematurely terminated due to no input being available. The runtimes
would think they had set EOF, but input failures in non-blocking I/O
don't set any error bits. Thus the runtimes carefully set EOF to zero!
I have fixed the runtimes to guarantee that EOF will be non-zero when an
I/O function takes the error return. If all of the error bits are zero
(bits 760000), I set bit 010000, which previously the runtimes always
cleared. Thus bit 010000 will always be set for a non-blocking failure.
Probably this will be the only case when it is set, though physical end
of tape may also do it. Note that it is perfectly possible for EOF to
be set in this way and for you to still have valid data. All it means
is that the operation was terminated prematurely (before your count was
exhausted) because an input failure occurred. You should save how much
you got and try to get the rest when the next input available interrupt
comes along.
3.6 - TMPIN and TMPOUT
TMPIN now deletes nulls and line numbers from the tempcore file being
read. TMPOUT has been fixed so it no longer randomly sets bit 35 in the
words outputted.
3.7 - /A
The default value of /A is /0A. This gives you the linkage appropriate
for F40 for FORTRAN PROCEDURES, and does not use KI or KL op codes.
This is probably wrong for most places, but is retained for
compatibility with the manual. An individual user can reset this by
specifying /nA in a REQUIRE COMPILER!SWITCHES statement. A site can
change the default by patching the compiler. To do this without
recompiling, just look at XINI4+7. You will find MOVEI TEMP,0; MOVEM
TEMP,ASWITCH. You can change the MOVEI TEMP,0 to use whatever value you
want as default. To change this in the source, see the file SAIL.
Users should consider setting /26A. In addition to F10 linkage, this
causes KI-10 instructions to be used for converting between integer and
real numbers. However it causes rounding to be used, while the default
is trucation (FLOOR).
3.8 - COMPIL
We are supplying a .COR file for COMPIL, to improve the handling of SAIL
by COMPILE-class commands. The following assumes that these changes
have been made.
******************************* /BAIL ******************************;
You may use the switch /BAIL:nn It will pass /nnB to the compiler in
the appropriate place. It will also cause COMPIL to look for a .SM1
file rather than a .REL file. Thus your program will be recompiled if
it had not originally been compiled with BAIL. If you use /BAIL alone,
i.e. without an argument, /BAIL:17 will be assumed.
******************************* DEBUG ******************************;
The DEBUG command now uses BAIL as its debugger by default. You need
not have any declarations or calls for BAIL in your program. My magic
linkage will automatically put a call to BAIL in your program before the
first executable instruction. When you get in this BAIL breakpoint you
can then set any other breakpoints you want. That breakpoint that I set
up is immediately removed, by the way. DEBUG forces /BAIL:17, which in
turn forces recompilation if your program had not originally been
compiled with /BAIL. To debug with DDT, specify DEBUG/DDT. Note that
the linkage to BAIL used by DEBUG causes the descriptors to be loaded
for all SAIL runtimes. Thus it simulates the 20 bit in the /B switch.
However, these descriptors are loaded only when the DEBUG command is
used, whereas /20b would have them in your core image even during normal
executions. Thus our implementation saves some core.
********************************* /Y *******************************;
Using /Y will cause your program to be loaded with the SAIL sharable
high segment (SAISG8). Note that /Y must appear before or after the
first program name in the command. Any later and it will not work. /Y
may be used with DEBUG as well as LOAD and EXECUTE. (It has no effect
for COMPILE, of course.)
SECTION 4
Documentation Errors
This is a list of known bugs in the August 1976 Sail manual, AIM-289.
PAGE DESCRIPTION
abstr. "varaiables" is a misspelling [JFR 10-22-76]
iiiL no period after LEAP (line 6 of paragraph) [LES 10-22-76]
162L "i.e" in the line "2. Recursive entry" [JFR 10-23-76]
1R "Nauer" for "Naur" (also References) [JFR 11-2-76]
22L,26L "disjunct" -> "conjunct" [JMC 11-12-76]
31L line -9 "its" -> "it's" [JMC 11-12-76]
162R The word PDA+'13 contains something other than indicated.
The parameter descriptor words actually start at PDA+'14,
but the way to find them is to follow the pointer in
the right half of PDA+7. [JFR 12-9-76]
9L Another restriction on SIMPLE procedures: They should not do
up-level addressing themselves (in addition to point 4.) unless
the user really understands what is going on with the stack.
It is possible to "screw up" without complaints from the
compiler. SIMPLE ought to mean "I know what I am doing, so let
me do it.". [JFR/DON 12-xx-76]
56L CRLF="('15 & '12)", not '12 & '15 [JFR 1-15-77]
10R It should be made clear that LET A=B; works even if
A is a reserved word. In particular, LET DEFINE=REDEFINE;
Also note that B can be any reserved
word except COMMENT. [COMMENT ALWAYS means "ignore through
the next semicolon".]
4R POLLING!POINTS is not a valid <require!spec> [WFW 1-21-77]
50R In FILEINFO, hidate2 occupies 3 bits [JFR 2-3-77]
152L CHNCDB and FILEINFO are defined everywhere except TENEX.
[JFR 2-3-77]
65R A better way of getting around the array problem is as follows:
REQUIRE "<><>" DELIMITERS;
DEFINE NewArray(type,name,bounds)=<
BEGIN
type ARRAY proxy bounds;
MEMORY[LOCATION(name)] _ MEMORY[LOCATION(proxy)];
MEMORY[LOCATION(proxy)] _ 0;
END>;
which hides all the hair of a poor facility and is perfectly
general. unlike the present scheme in the manual. A typical
call would be:
RECORD!CLASS RC(STRING ARRAY SA);
RECORD!POINTER (RC) rp;
rp _ NEW!RECORD(RC);
NewArray(STRING,RC:SA[rp],[0:1,-2:3]); [MWK for KS 01-13-77]
27L DIV and MOD use integer divide and are meant as a "integer
divide" and "integer divide and remainder". This is NOT the
real mod as written in Knuth volume 1. In fact, MOD would
better have been named REM. [MWK 01-13-77]