perm filename TELLEM[S,AIL] blob sn#073852 filedate 1973-11-24 generic text, type T, neo UTF8
 00001 00001
 00004 00002	
 00005 00003	INTRODUCTION
 00006 00004	OPTIONS
 00010 00005	PARTS LIST (see appendix II for expanded explanations)
 00024 00009	
 00031 00011	RUN-TIME LIBRARY {LIB}
 00050 00015	
 00059 00017	
 00072 00020	
 00076 00021	
 00083 00022	
 00086 00023	
 00107 ENDMK


				Bob Sproull
				October 1970
				Revised May 1971 by D. Swinehart
				Revised Sept 1971 by D. Swinehart
				Revised Jan 1973 by D. Swinehart and J. Low
				Revised May 1973 by R. Taylor
				Revised June 1973 by H. Samet 

This document describes the various parts of the SAIL system, and how
they   might  be  combined  to  form  many  optional  manifestations.
Hopefully  not  only  the  methods  for  installing  SAIL,  but   the
motivations behind them will be explained.

The first sections are somewhat wordy, and describe in detail what is
going on.  Later sections may be used as checklists in performing the
actual    installation.    Appendices    follow,    explaining   less
commonly-needed facts.

You will probably not want a system with all  the  available  options
and configurations (especially since some are mutually exclusive). So
that you may readily ignore explanations of features you don't  want,
sections   which  represent  optional  things  are  labelled  in  the
following manner:

LEAP -- this section is of interest only if you want a runtime system
    with LEAP and PROCESS features. (The compiler always includes the
    LEAP and PROCESS features)
    It is advised that LEAP always be included as we have  maintained
    the system with the belief that LEAP will be around.
NOLEAP -- this section of interest only if you want one without LEAP.

TWOSEG--this section describes  the  sharable  (2d  segment)  runtime
     routines  configuration. 
NOTWOSEG -- of interest only in non-sharableconfigs etc.

LIB  --  describes the process for creating the LIBSAn library. 
NOLIB-- etc.

REENT -- describes the process for creating re-entrant SAIL programs,
     such  that not only the runtimes, but the entire user program is
     sharable; and the library (HLBSAn) that goes with such programs.

BIGRUN, NOBIGRUN -- describes the process  for  creating  RUNTIM.REL,
     all runtimes, non-sharable.

GLOB,  NOGLOB  &  GLOC,  NOGLOC  &  EXPO-NOEXPO  --  These  refer  to
     differences between SAIL as it exists at Stanford & as it exists
     elsewhere.   These  differences  include  a  slightly  different
     interface  to  the (non-DEC-standard) Stanford operating system,
     and to the Stanford "global model", which requires special  UUOs
     found  only at Stanford.  In times past, the export sources were
     modified to omit Stanford-only features.  In accordance  with  a
     new  file  maintainence  policy,  they  are being left in.  They
     certainly will not work on a regular DEC or TENEX system, and we
     make no promises, either implicit or explicit, to those who feel
     like monkeying around with them.  To avoid problems,  leave  the
     switch  EXPORT  set  to  1  in  file HEAD (and don't go changing

When these tags appear, they will be between braces ({}) in the text.

PARTS LIST (see appendix II for expanded explanations)

A  Files needed to get initial compiler and operating system going
   FILES (list of files in order on tape)
   TELLEM (this listing)
   DDT.REL (currently can't use any configuration of DEC's DDT)
   LIBSAn.REL (n, a digit.Library of runtime routines for transfer to SYS:)
   BKTBL.BKT (needs to be on SYS when STDBRK is called)
   2OPS2.OPS (START_CODE opcode table, created by compiling and
		running MAKTAB)
   PROCES.DEF (a collection of SAIL macros for use with processes)

B. Source files for SAIL compiler and execs(runtimes)

E. Files to build parser tables (FAIL files for inclusion in SAIL)
   PROD.QQQ (output of PTRAN, input is HEL)

F. Source files for SAIL compiler
   (HEL, FOO2 as comments)
   PROD (output of PTRAN, input is HEL)
   RESTAB (output of RTRAN, input is PROD and FOO2)

G. Source files for Execs

H. Required software support, if any modifications are to be made
   FAIL.REL (a one-pass assembler)
   PTRAN.SAI (creates FAIL-readable parser tables from HEL)
   RTRAN.SAI (creates FAIL-readable symbol table (reserved wds) from FOO2)
    (above previously HYSS and HYRS, respectively)
   SCNCMD.SAI (gets REQUIRED as a source file by PTRAN and RTRAN)
   WNTSLS.SAI (gets REQUIRED as a source file by PTRAN and RTRAN)
   MAKTAB.SAI (creates 2OPS2.OPS)

I. Other useful files
   PROFIL.SAI -- This program lists the .KNT file and .LST file, giving a
   nice frequency profile of statement execution (See /K Switch in manual)
   LOADER.MAC (our slightly modified version 52)
   DDT.FAI (our slightly modified version -- block structure)
   CREF.MAC (modified for block structure)
   SCISS.SAI (makes a a library, two-segment HLBSAn {REENT} or one-segment
	LIBSAn. Uses the file ORDER as input with other exec sources)
   FAIL.PMP -- FAIL assembler manual
   SAIL.KVL-- SAIL manual -- restoration of these last two to DSK should
	      be inhibited if disk storage is scarce -- about 100K worth.

K. Some additional files of marginal usefulness.  They are either documents,
   or programs whose only documentation is self-contained, if at all.  You
   can take a look at them if you want to.  They are mostly SAIL programs
   and their manuals.



This  presents  no  problem. The files are stored on several DECtapes
with  the  directories  plainly  listed thereon. They are  stored  in
standard PDP-10 DECTAPE format.

B. Mag Tape, 7 track only


The file SAIL.REL should run on any  standard  DEC  10/50  system  of
recent  (year  or  two)  vintage.  Load it with the DDT.REL provided,
and the library (LIBSAn), with the /B loader switch, using version 54
or later of the LOADER, with SAILSW and FAILSW turned on, and save it
as SAIL.SAV (one segment) somewhere. Later descriptions will indicate
a method  for creating a version without DDT.

The  file  LIBSAn.REL  is  the  library  which  is  REQUIREd  by  all
SAIL-compiled programs.  It uses a  recently-installed  LOADER  block
type  to  cause the automatic search.  The LOADER will look on device
SYS for this file, and will not really let you go  on  until  such  a
file  is  put  there.   The  version  of  LIBSAn  supplied  should be
sufficient in all important  details  (at  least  till  you  get  the
bootstrapping done).

If  you have installed SAIL on your SYS device, CCL may be changed to
include SAIL as a standard processor by including the line


in  the  PROCESS  macro  in  COMPIL.MAC  (DEC  program). You may also 
include  "FAIL,FAI,FAIL"  if  you  want  to  promote  use of the FAIL

To  complete a SAIL system (if you're not going to investigate any of
the other, better options or make any  changes),  transfer  2OPS2.OPS
and  BKTBL.BKT  to  SYS.   Always  load  SAIL-compiled  programs with
version  54  of  the  LOADER  or  later (LOADER 52 may be used if the
compiler is reassembled with the  LOADVR  switch  in  file  SAIL  set
to =52), with SAILSW and FAILSW  turned  on (or  ours, which  has its
points), and always use our DDT (at least until we can get together
with DEC on it).

There is one additional thing you can do if you want  to  --  install
the  LOADER  provided  with  SAIL.  This LOADER uses the /Y switch to
make shared-segment  loading  more  convenient  (See  Operating  with
shared segments, below). In addition, it automatically invokes /B and
/K to cut core to reasonable sizes after loading.  It is by no  means
necessary to use our LOADER,  though. If  our  LOADER  is  used,  the 
LOADVR switch in file SAIL must be set to =52 and SAIL reassembled.


The comments which accompany the source  files are  fairly  extensive.
This,  however,  is  about  the  only  assistance  you  will  get  in
understanding the compiler,  except  for  the  Parser  discussion  in
appendix  IV.  Therefore,  this  section  is  not  intended to aid in
anything but the actual mechanics (assembly, etc.) of modifying SAIL.

A. If you have only modified FAIL code, the process is fairly simple:

  1. One Segment Compiler

  This  command  string  should  be  typed  to  FAIL  (or  the
  equivalent formulation given via CCL:


  SAIL.REL will be created.  This version is tailored for  slimness,
  and is not intended to be loaded with DDT.  It should be loaded
  with the LIBSAn library.A typical LOADER command string is

  2. One Segment Compiler, tailored for debugging.

  This version should  (sort  of  must)  be  loaded  with  DDT.   It
  contains  code  for  the  /nM options described in the SAIL manual
  (and slightly better in the file PARSE just ahead of the code that
  does  it).  With  this  compiler  it  is much easier to track down
  elusive "line 99500, page 47" bugs.

  The command string is the same, except that FTDEBUG should be made
  1  instead  of 0 (never -1, 3, or anything but 0 or 1!!!!!) in the
  file SAIL (or insert a file with FTDEBUG←←1 in it ahead of SAIL).

  This is the version which was sent to you as SAIL.REL.   If you  do
  not use our LOADER remember to include the /B switch in your LOADER
  string or you will get the wonderful warning:


  everytime you run the compiler.

  3. Two Segment Compiler, no debugging {TWOSEG}

  Set  FTDEBUG=0  in  HEAD,  and  use  the above command string, Load
  without DDT, but as if it were a two-segment SAIL-compiled  program
  (see  Two  Segment operation, below).   Save in ONE segment, always
  (as with any SAIL-compiled job, see below).   When it runs, it will
  pick up the shared stuff.

  4.  Two  segments,  debugging  mode  Same  as  version 3, but make
  FTDEBUG←←1, load with DDT.

B. Changes to HEL (parse table) or FOO2 (built-in procedures)

  If for any reason you change either of these files, more work  has
  to be done:

  NOTE -- PTRAN and RTRAN replace HYRS and HYSS, resp.

  1.  PTRAN  -- Production Translator (see Appendix IV) This program
  takes  the pseudo Floyd-Evans productions found in  file  HEL  (or
  any  other),  and  converts  it  to  FAIL  assembly  language data
  statements which define interpretation tables for  the  parser  of
  SAIL.   In  addition,  it issues an auxilliary file containing the
  names of  the  reserved  words,  for  use  in  the  RTRAN  program
  described below.

  Compile PTRAN.SAI with your slightly used copy of  SAIL,  load  it
  and  run  it.   It  will  respond  with a `*', to which you should
  counter:    PROD←HEL<cr>.   When another  `*'  appears,  PROD  and
  PROD.QQQ  have  been  created.   PROD  is the parse table (HEL  is
  included only as a comment in the assembly  above,  as  is  FOO2).
  PROD.QQQ is the list of reserved words for RTRAN.

  2. RTRAN -- Reserved Word Translator

  This  program  issues  FAIL  source code which defines the initial
  configuration of the SAIL internal symbol table, for the  reserved
  words  like  BEGIN  and  END,  and for the execution routines like
  INPUT, BREAKSET, etc.  Input for the  reserved  words  comes  from
  PROD.QQQ  via  PTRAN.   Input  for the executions is from the file
  FOO2.  Appendix IV describes the formats of these files in detail.
  The  command  string  is:    RESTAB←PROD,FOO2<cr>.  The  resultant
  RESTAB is the initial symbol table, expressed in FAIL.

  Now proceed as given in part A.

  PTRAN  will  read  commands from nnnPTR.TMP if started in CCL mode.
  RTRAN will read from nnnRTR.TMP. Make what you like of that.

C. Some particularly interesting conditional assembly switches

  FTDEBUG -- 1 for debug/mode, 0 for non-debug mode, as above.

  LEAPSW  {LEAP}  -- on for LEAP features in runtimes (standard), off

  RENSW -- usually 1 -- on if compiler is to be capable of generating
  re-entrant (two-segment) code.  To get it to do that, use /H in the
  command string.  Such a file will REQUIRE the HLBSAn library,  each
  file  of  which  has been HISEGed (see below).  Most of the program
  can thus be shared, if the program has reached CUSP status.

  SIXSW -- turn this on if you use sixbit project-programmer numbers.
  Otherwise, SAIL assumes octal ones.   Examine  all  SIXSW-dependent
  code if you use something else entirely, and make changes.

  TMPCSW -- turn this off if your system does not support the TEMPCOR

  LOADVR -- the decimal value of the loader version to be  used;  =52
  or >=52, typically - loader block type problems.


along  with  the macro and accumulator  definition  file  HEAD,  were
historically assembled in the order


to  create  a  file RUNTIM.REL which contained the storage allocator,
the initializer, the string garbage collector, and all the  execution
routines  (INPUT, BREAKSET, concatenation, CVS, LEAP, etc.).

This  method  may  still  be  used.   Simply assemble the files given
above, in  the  order  specified.  Specify   RUNTIM.REL, or  anything
else, for that  matter,  as  the  binary  file.   This  file,  loaded
with a SAIL-compiled program, will provide all the support necessary.
Unfortunately, it is about 9.5K long.


We  found  that  out.   However,  the  obvious  solution to the large
execution package revealed some drawbacks.  We  wanted  to  create  a
library  for  SAIL  in  the  manner of the FORTRAN library.  However,
given the DEC  library  file  conventions,  each  separately-loadable
entry  would  have  to be assembled separately.  This was not so bad,
but it would mean fragmenting GOGOL  and  friends  into  many  parts,
making the creation of RUNTIM.REL or the shared segment version hard.
It was crucial  that  there  not  be  multiple  copies  of  the  same
routines, because maintenance of one set is hard enough.......

The  current  solution  to the problem is the program SCISS.SAI, some
special macro constructs in GOGOL and friends, and a lot of luck.

SCISS operates in two passes, with a pass of FAIL  between.   On  the
first  pass, it extracts from HEAD and GOGOL some common code used by
all library entries (making  HDRFIL.FAI,  or  some  such).   Then  it
writes   one  FAIL  source  file  for  each  desired  library  entry,
extracting  its  code  from  the  file GOGOL, STRSER, or IOSER
which  it appears  (removing  comments  and blank lines), naming each
after its library entry.  In addition, it writes a command file
(CCL  file) to FAIL, then chains to FAIL. The file ORDER contains the
correspondence  between  library entries and the source files as well
as "n" the version of the library.

FAIL  assembles  all  the  little FAIL files, each preceded by HDRFIL,
into little .REL files, chaining back to SCISS, this time in CCL mode,
thus  indicating  pass 2.  On pass 2, SCISS copies all the .REL files
into LIBSAn.REL, removing local symbols and cleaning things up.   All
the  FAIL  and  .REL  files, along with the HDRFIL and CCL files, are
deleted if desired.

Here we will only discuss the STANDARD case.  The procedure is:

Read  into  GOGOL,  looking  for the COMPILE macro, the ENDCOM macro.
Also  look  at the file ORDER.  These should give you an idea of what
is going on inside to give SCISS a hand.

Compile  and load  SCISS.SAI, and save it as SCISS.SAV on the area on
which you intend to run it.

Run  SCISS.  It  will  read the file ORDER (from the current area) as
input. When  it  asks   "STANDARD?  ",   answer   "Y<cr>".   It  will
chatter for some time about what it intends to do, then about what it
is doing. Thereafter, FAIL will be invoked to compile all the  little
files.  Finally  SCISS  will  return  with  "STANDARD? ".  Answer Yes
again.  It will drone on some more about the files it is deleting and
copying.   Finally  it  will  report  that  LIBSAn.REL exists for the

Use  an  option  of  SCISS (see appendix VI) to  get the high segment
library (HLBSAn). Programs compiled with /H will use HLBSAn -- others
will  use  the  shared  segment  (see {TWOSEG} below) or LIBSAn.  You
should  create  only  a  LIBSAn  if you don't make a /H-type compiler 
(RENSW off in SAIL) when you assemble it.

If anything goes wrong,  you  will  probably  profit  from  the  more
complete discussion of SCISS in appendix VI.

This option represents the latest step  in  the  evolution  of  these
things. In this version, we are back to the 9.5K runtime package, but
this time it occupies the (entire) second segment of  any  number  of
jobs.   Linkage to routines in this segment is accomplished at LOADER
time by loading as the FIRST THING a file containing  the  name  of a
particular upper segment, as well as symbol names and  locations  for
that upper segment's routines.  In addition, this file  contains some
impure  data  for the SAIL job, along with the UUO trap locations and
the  code  necessary  to  attach via GETSEG to the specified segment.
In this way the upper and lower files are keyed to each other, and as
long as standard naming conventions are followed, an  old  .SAV file,
when run, will never link to a new segment with unmatching addresses.
A  transfer  vector in the upper segment,  through which all calls to
runtime routines go, also minimizes this possibility of dissynchroni-

To  create one of these clever beasts, first look at the file FILSPC.
It contains default values  for  this  lower  segment  name  (SAILOW,
typically),  the current upper segment name (SAISGn, n a digit) which
will be unique to this particular manifestation (or at  least  should
change  when  the transfer vector changes), and some parameters which
are probably meaningless in your installation, and should be left  as
they  are.   In  addition, the device (DSK or SYS) and PPN pair where
the  segment file will  be  found  is  also  defined  therein.   Thus
SAISGn.SHR is one file which need not reside on SYS.

Once you are satisfied that FILSPC is OK (modification should include
noting on page 2 the date, the version number if you must,  and  what
glorious  changes  warrant  the new version), Use FAIL on the command


LOWER.REL will be a binary file containing the desired upper  segment
name and location  (for  use  by  the GETSEG routine), and the lower-
segment  initialization  and  impure code, selected from GOGOL by the
conditional assembly in LOW.

Now use FAIL to assemble:

TAILOR←HEAD,FILSPC,TAILOR (or the CCL equivalent, of course).

TAILOR.REL contains the upper segment name and location,  along  with
the other useless parameters from FILSPC, this time in core locations
rather  than as assembly constants.  This could have been included in
the next assembly, but wasn't so  that  the names  and  other  things
could  be changed without re-assembling the body of the segment code.

The last assembly is:


UPPER.REL contains, after some initial messing around, code PHASEd to
400000 and succeeding locations, so that when it  is  fetched  as  an
upper  segment, it will be able to run there.  The trick is to get it
written out such that this can be done.  Some of that  which  follows
may  look  ridiculous and overly complex to some of you, but remember
that the code, with modifications, must also  be  used  at  Stanford,
where things are done that way.

First load TAILOR and UPPER together.  This tells UPPER what its name
will be.  There is code in UP, before the phase,  and  to  which  the
starting address of the UPPER assembly refers, which will now perform
some contortions:

Start the resultant core image.  The code in UP will first write  out
pure segment code onto the file SAISGn.SHR ON THE  CURRENT  DIRECTORY
AREA,  notwithstanding  its  ultimate destination.  Then it will copy
LOWER.REL to SAILOW.REL  (or  whatever  FILSPC  says),  imbedding  in
SAILOW , in LOADER INTERNAL symbol format, the symbol names and upper
segment addresses for all the runtime routines and other  data  which
SAIL  programs must reference.  These symbols are taken directly from
the current core image's symbol table, which contains all the symbols
and their values, because the UPPER file was loaded with it.

SAILOW.REL   and  SAISGn.SHR  should  be  copied  to  their  intended
destinations (usually SYS).

To  create  a  core  image  which will use the shared SAISGn segment,
whether it be the compiler (see above sections)  or  a  SAIL-compiled
program,  simply  load it with the most recent SAILOW.REL as the VERY
FIRST THING (locations 140 cc.) in the core image.  SAISGn KNOWS that
certain  data  in SAILOW will be at these locations. SAILOW, in turn,
"knows", via the implanted symbols, where the  runtime  routines  for
the  SAISGn  keyed  to  it are.  Therefore, all references to runtime
routines in the files loaded after SAILOW will be  properly  resolved
to upper segment addresses.

After  loading  SAILOW, DDT can be loaded if desired, followed by any
SAIL-compiled or FAIL/MACRO/FORTRAN-processed files.   When  the  job
(which  should  have  a  SAIL  main program) is started, it will do a
GETSEG on the appropriate SAISGn.SHR, and you will be in business.

Leave old versions of SAISGn's (where the n's differ) around, so that
old  .SAV  files  will still work.   In general, you should save core
images BEFORE running them  the  first  time.   Otherwise,  you  will
probably  save  your own copy of the segment and stuff like that.  It
is not really a problem here, because our system's  different;  so  I
don't really know what problems you'll encounter.

Our  LOADER contains the /Y switch,  causing  SYS:SAILOW to be loaded
immediately after the /Y has been scanned. In addition, our CCL  will
look  for .SAI extensions on any of its inputs, and will put out a /Y
first thing (even before /D if debugging, etc.) if it sees  any.   In
the near future, we will probably remove the /Y business, and let CCL
insert the SYS:SAILOW directly-- under a previous,  more  complicated
scheme, the /Y stuff made more sense.

That  should  do  it.  The LOWER, UPPER, and TAILOR .REL files can be
deleted as soon as SAILOW and SAISGn  have  been  made  --  they  are
purely intermediate entities.

A. Getting files from MTA
 ( )1. Use FAILSAFE.

B. Getting a SAIL system up
 ( )1. Load the SAIL.REL,/BDDT.REL,/LLIBSAn provided with our LOADER
 	or with any version 54 or later LOADER with FAILSW and SAILSW
	turned on.
 ( )2. Save as SAIL.SAV or something in a convenient place.
 ( )3. Transfer LIBSAn.REL, 2OPS2.OPS, PROCES.DEF, and BKTBL.BKT to SYS -- 
	also SAIL, and/or FAIL, and/or LOADER, and/or DDT, if desired.

C. Changing the productions (HEL) or built-in descriptions (FOO2)
 ( )1. Make the appropriate edits
 ( )2. Compile PTRAN.SAI, RTRAN.SAI (require SCNCMD,WNTSLS as source
 ( )3. Load and run PTRAN (formerly HYRS).
        Command string is PROD←HEL<cr>.
 ( )4. Load and run RTRAN (formerly HYSS). 
	Command string is RESTAB←PROD,FOO2<cr>.
 ( )5. Do one of parts D, E, F, or G.

D. Assembling Two-segment, no debugging compiler
 ( )1. Assemble with FAIL:
 ( )2. Load SAILOW,SAIL without DDT.
E. Assembling Two-segment, debugging compiler
 ( )1. Change FTDEBUG in SAIL to 1, or insert a file ahead of SAIL
 	in the command string  below (DB, say), with FTDEBUG a 1.
 ( )2. Assemble with FAIL:
 ( )3. Load as in part D with DDT

F. Assembling a One-segment, no debugging compiler
 ( )1. Assemble as in part D
 ( )2. Load as in part B without DDT

G. Assembling a One-segment, debugging compiler
 ( )1. Guess.

H. Assembling a great big RUNTIM.REL
 ( )1. Assemble with FAIL:
 ( )2. Load SAIL programs with RUNTIM.

I. Creating a standard LIBSAn.REL
 ( )1. Compile and load SCISS.SAI
 ( )2. Save as SCISS.SAV
 ( )4. Run SCISS.  Reply Y<cr> to all questions.
 ( )5. After much typeout, it should report that LIBSAn.REL exists
       so put it where you like, preferably on SYS.
 ( )6. {REENT}For creation of HLBSAn  see Appendix VI
 ( )7. If you get in trouble, Appendix VI may provide some shortcuts
       for getting out of it.

J. Creating shared segments
 ( )1. Modify FILSPC to taste
 ( )5. Load TAILOR and UPPER with a SAIL-compatible LOADER
 ( )6. Run result, getting SAILOW.REL and SAISGn.SHR
 ( )7. Transfer SAILOW to SYS, SAISGn.SHR to wherever FILSPC says.

K. Running with shared segments
 ( )1. Load SAILOW.REL FIRST!!!!!
 ( )2. Load DDT and programs
 ( )3. Save core image if you want.
 ( )4. Start job -- segment will hook up right away.

L. {REENT} Running with 2-segment programs (/H when compiling)
 ( )1. Compile with /H in command string
 ( )2. Load as usual (DO NOT LOAD SAILOW AT ALL)
 ( )3. The HLBSAn library will provide al(most al)l high-segment


-- a definition file, defines useful macros, accumulators etc.  There
are also definitions for the "user table", the table  of  good  stuff
which  contains  the  non-reentrant  information  for  use by runtime

--  initializer  for  the compiler, command line scanner.  Almost all
the CCL code is in here.

-- The syntax interpreter, the debugging routines (for looking at the
parse stack, symbol table entries, etc.)

--  This  is the file which contains the "english" of the productions
for SAIL.  It is included in the SAIL  assembly  as  a  comment.  The
actual production  interpreter  tables  are  generated from it by the
program PTRAN, which uses this file (HEL) as source, and  dumps  its
output into PROD.

-- Again included  in  the  assembly  as  a  comment.   This  is  the
"english" specification of the pre-defined procedures.  These are all
the procedures available at runtime.

-- Syntax tables, generated by PTRAN.

--  Reserved  word tables and pre-defined procedure tables, generated
by the program RTRAN, with FOO2 and PROD as input.

--  This is the scanner.  This has the code for inputting from source
files, producing a listing, expanding  macros,  looking  up  symbols,
entering symbols, and delivering and reclaiming symbol table blocks.

-- This is the first part  of  the  generators.   Contains  code  for
initialization,  declarations,  storage allocation in object program,
inline code, syntax error messages, etc.

-- Contains generators for array references.

--   Generators  for  expressions  --  arithmetic,  string,  boolean,
assignment statements.

--    Generators   for   statements:   LOOP   constructs,   procedure
declarations, etc.

-- Generators for LEAP, backtracking and procedure items.

-- Generators  for process,coroutine, event constructs.

--  This  file  contains  the  generator  subroutines  used  for type
conversion,  accumulator  management,  binary  file  output,   symbol
output, and miscellaneous other things.

-- Random service routines for the compiler (e.g. some string garbage
collector goodies).


-- Contains most of  the  runtime  environment  stuff  (also  compile
time).  Core  allocation,  UUO  handler,  string  garbage  collector,
allocation (i.e. of stacks, string space) stuff.

-- Contains trigonometric functions (SIN, COS, etc.) and an interupt
routine for processing floating underflow.

--   Contains   most   of   the  string  handling  routines  such  as
concatenation, substring, etc.

--  Contains  runtime routines for doing I/O a few other things.

-- Contains runtime routines for doing array allocation & deallocation,
run time "go to solving", and the apply construct.

--  Contains runtime routines for process handling

-- Runtime routines for LEAP.

-- Contains one-word,two-word and string descriptor  providers, as well
   as REMEMBER, FORGET and RESTORE routines.

-- Files used for making shareable runtime routines.


-- SAIL program for compiling syntax tables (see description below).

-- SAIL program for compiling tables for  reserved  word  definitions
and pre-declared procedure definitions.

-- SAIL sourcefiles required by PTRAN and RTRAN.

-- SAIL program to write the file 2OPS2.OPS, which  contains  op-code
definitions for the inline code generators (START_CODE).


-- An assembled version of SAIL, with FTDEBUG set (i.e. you must load
it with DDT).  If you are able to assemble your own .REL of SAIL, you
can save considerable space by turning FTDEBUG off.

-- A good library file.

-- The specification file for the STDBRK function.

-- The inline code opcode table.  Make a new one with MAKTAB.SAI.

-- A set of useful macros which a multiple process programmer may
require as a source file.


-- This is the assembler which will assemble all of the SAIL compiler
and runtime text files mentioned above. There  may  be  some  trouble
getting  this  to  run  on your system. If so, I suggest loading FAIL
with our DDT and looking around. Common problems are with the  APRENB
code.   FAIL asks for interrupts on ILL MEM REF so that it can assign
more core, link up free storage, etc.  If you  get  an  ILL  MEM  REF
message  on  your  console  while  running  FAIL, something is wrong:
either your system (this has been known to  happen  with  APRENB)  or
FAIL (there is a rumor that APRENB must be called after each trap).

-- This  loader is set up for SAIL, and contains the /Y (two segment,
see above) option.  It  can  be loaded by almost any previous loader.
If you have V52 or later, and don't need /Y, just use your own  (con-
figured for SAIL and FAIL, of course (of course!). Our  LOADER is set
up  also to provide the /B and /K features automatically, the desired
state for programs with SAIL stuff in them.

-- This is an improved DDT, and you might as well put it up  on  your
system.  There are many new features (see description below).

-- This is the cross-reference program which works for FAIL and SAIL.
(There  are  bugs  in the SAIL compiler output of CREF information --
wrong block names sometimes happen -- we will fix it sometime, but it
didn't seem like the most important thing in the world, also conditional
compilation is known to put out incorrect listing files).

-- This  program creates the LIBSAn and HLBSAn libraries, as described
in  varying degrees of detail in other parts of this document.

-- This program is applied to a SAIL listing file (with /K option) and
a  .KNT  file  created  by  a  program which was compiled using /K, as
described in the SAIL manual, to create a "program profile" listing.

The complete FAIL manual, and the
complete SAIL manual -- of little use to you if you don't have a lower-
case printer, probably.  They're big, so keep them off the disk unless
you have plenty of room.

These are stored after the EOT marks on the tape.  The section on getting
started describes how to get them off.  Take a look at them if you like
and decide whether they might be useful to you.  Otherwise forget them.

A. See HEAD for complete description of conditional assembly
   switches, the macros which simplify their use, and the files
   in which they are defined.

B. See SAIL for a complete listing of FAIL commands for creating
   various kinds of compilers (slightly invalid for non-Stanford

C. See GOGOL for a complete listing of FAIL commands for creating
   various kinds of runtime routines, libraries, etc. -- also for
   the COMPIL, ENDCOM, and ORDER constructs used by SCISS -- lastly
   for the usage of the HERE macro to conveniently create the upper
   segment transfer vector (HERE may be defined in HEAD).

D. See PARSE for a complete description of the features of the 
   debugging versions of the compiler -- features generally useful
   only to the maintainers of SAIL.

E. See NEWMAN for recent changes to the language.


The program  PTRAN   expects   an   input  file  of  a  very  special
format.  The ultimate aim of this input file is to specify a sequence
of productions, but we must first specify  the  production  alphabet,
both terminal and non-terminal.

The  meta  language for specifying productions consumes a few symbols
and conventions.  First, all alphabetic characters in the input  file
must be in upper case.  The only delimiters are space and tab, so →AG
does NOT get interpreted as two separate symbols.

1.  	For  various  undisclosed  reasons,  we  must  first  provide
alternate "names" for all single-letter delimiters we may need,  such
as  (  ) } ↑ [ ], etc.  The pseudo-op <SYMBOLS> is given, followed by
pairs of

	single-letter-delimiter crazy-alternate-name

See the example below for some  instances  of  this  phenomenon.  The
crazier  the  name  the  better.   This is so that the symbols can be
included in the  scanner  table.  Note  the  interaction  with  these
aliases and the reserved word scheme. Thus ≡ which is the same as EQV
is equivalenced by this scheme.

2. 	The terminal symbols of the language are then specfied in two
groups:  first, those which the scanner  knows  about  directly,  and
second,  the group of reserved words in the language (these look like
identifiers to the  scanner,  but  you  obviously  desire  a  special
interpretation).  The  first  group  is  initiated with the pseudo-op
<TERMINALS>, and must include all the single-letter-delimiters  cited
in 1 which do not have reserved word equivalents. The second group is
started with <RESERVED-WORDS>, and  is  merely  a  list  of  all  the
reserved words you desire.

3.	The non-terminal symbols are then declared.  These are things
which you may want to put on the  stack  as  "markers"  of  partially
completed   reductions.    The  pseudo-op  <NON-TERMINAL-SYMBOLS>  is
followed by a list of such symbols.

4.	For efficiency reasons, it is helpful to  define  CLASSES  of
symbols.  Then with one production, we can determine if a whole class
of productions are applicable, and we can often avoid stating all the
productions.   To  specify  classes,  we  start  with  the  pseudo-op
<CLASSES>, and then, on a one-class-to-a-line basis, we specify:

	class-name	class-element class-element ....

where class-name must begin with a @. All of the class-elements  must
have already been  defined  in  2  or 3 above or a previously defined
class-name. Note that two classes are predeclared. These are RESERVED 
which contains all the reserved words and TERMINAL which contains all
the terminal symbols.  
5.	Finally we are ready to state the productions.  We  give  the
pseudo-op  <PRODUCTIONS>  to  start  this off.  The name of the first
production is  BB0  (this  may be changed by altering the contents of
the cell PRODGO in file PARSE).

The  interpreter  will  start  AFTER ONE SCAN, so that the top of the
stack will already have the first "parse token" on it.

The syntax of each production is:

label:	LHS →→ RHS EXEC xxx SCAN α ¬yyy #zzz ↓↓ ↑www

This specifies a  production.   These  symbols  need  at  least  some
-- the label is the production "name". It is optional.  All labels in
        the program must be unique in their first 6 characters. There
	may not be a space between the label and the :.
	(If you plan to use the debugger (FTDEBUG← 1) it is advisable
	 to  have  only  3  character  label  names to avoid spurious
	 production breaks).

-- LHS is a left-hand-side-list.  That is, a list of symbols declared
        in 2,3, or 4 above which is to be matched against the current
        top elements of the stack.

--  RHS is a right-hand-side-list.  This is the list of symbols which
        will replace the LHS on the stack if the production succeeds.

--  EXEC  specifies  that a list of execs is to be called.  The names
        you give in this list of exec  routines  should be  the names
        of the procedures that you make up in your exec routine file.

-- SCAN specifies that we are to scan before going  on  to  the  next

--  the  # ¬ ↑ and ↓↓ parts specify where "control" of the production
        interpreter is to go.

The following things are omittable:

-- the label

-- the →→ and right-hand-side-list, in which case it is assumed  that
        if  the  production  succeeds,  the  stack is restored to its
        original condition.

-- the right-hand-side-list, in which case nothing is restored to the

-- EXEC and the list of exec routines which follows it.

--  SCAN  if  you do not want to scan.  Note that SCAN α means scan α
        times before going to the success spot.

-- the #zzz, ↓↓, and/or ↑www may be omitted.
Now for the interpretation.  When the interpreter is pointed at this
production, the stack is compared  against  the  left-hand-side-list.
The  last element in this list is compared against the current top of
the stack, and so on back the list and up the  stack.   Compares  are
equal if:

-- the symbols actually match.

-- the list element in the left-hand-side is  SG,  which  stands  for
        sigma, and compares equal to anything.  SG  is  thus  a  meta
        symbol of the production compiler, and may not be used in any
        other way. In fact, any identifier beginning  with  SG  is  a
        "sigma".   For  the purposes of stack restoring, however, SG1
        matches only SG1, etc.

--  the  list element in the left-hand-side is a class symbol and the
        corresponding stack element belongs to  that  class.  If  the
        left-hand-side-list  fails  to match the top positions of the
        stack, the production interpreter sees a failure and goes  to
        another  production.  The next production is normally the one
        following the one which failed.  If you want to specify  some
        other  failure  production, the #zzz construct is used, where
        zzz is the label of the production you want to go to.

If the left-hand-side-list matches the top of the stack, then:

1. These stack elements are popped off the stack temporarily.

2. If any exec routines have been specified, these  are  called.  The
        statement  EXEC FOOBAZ causes the subroutine called FOOBAZ to
        be  called.   The  statement  EXEC  @DCL  FOOBAZ  causes  the
        following  to happen: FOOBAZ is a routine which wants to know
        some  class  information  about  one  of  the  left-hand-side
        elements.   This  element  is specified by the @DCL (this was
        the same thing that occurred on the left-hand-side). Just how
        this  class information is passed is not important here. Upon
        return from all exec routines, we continue to:

3. The stack is  then  fixed  back  up,  reflecting  any  changes  as
        specified in the right-hand-side-list.

4. The scanner is called if SCAN was specified.

5.  The  production has now "succeeded".  We must cast around for the
        next   production.    Each   production   must   have    some
        specification  of  what  to  do  on  success.   If  you  only
        specified a ¬yyy , then we do a "jump" to the production with
        label yyy. If you specified a ↑aaa and a ¬yyy , we do a "push
        jump"  to  production  aaa.   When  we   return   from   that
        "subroutine,"  we  will go to production yyy.  The "pop jump"
        is specified by ↓↓.  It makes no sense to say: ¬aaa ↓↓  since
        these  two  operations  conflict  (in fact, the pop jump will
        take precedence).

6.  An  extension  has been made to production language to enable the 
implementation  of conditional compilation in SAIL.  This consists of 
maintaining  two  parser stacks.  When certain reserved words such as
IFC  are seen a "push jump" is done to a production which is accessed
by  an  index  to a table via the left hand entry of the words symbol
table  semantic  entry.  Parsing  then  continues in a coroutine-like
manner. The  PRESUME  construct has been added to production language
to  facilitate  a change in the current parser stack from conditional
compilation  to  SAIL-like  compilation.  Coroutine-like parser stack
switches  from  SAIL  to conditional compilation is done when certain
reserved  words  are  seen  such  as ELSEC.  A PRESUME followed by ↓↓
indicates that the conditional compilation process is finished.  Also
note  that  when DEFINE is seen, it is treated in the same way as IFC
with  the  exception  that  there is no need for an additional stack.  
If  you  do  not  understand  all  this  don't worry, you are in good 
The list of productions must be followed by the pseudo-op <END>

There  is  a  facility  for  passing  class-type  information to exec
routines.   The SAIL  production  interpreter  stores  a  number   in
accumulator  number  2  before executing  the   exec routine that you
specified. This number contains the type  information you  need.  The
problem   of   interpreting   that  number  is  complicated  but  not
impossible.  The  elementary  statement  is:  the number is the index
(starting  at 0) into the line of symbols in which that class type is
declared. So if you declare the class type


and if you wrote a production


then when ENTID is called, AC 2  will contain the following numbers:

	parse token which compared
	equal to @DCL
	INTEGER					0
	REAL					1
	BOOLEAN					2
	COMPLEX					3
	STRING					4

This simple explanation breaks down when, say BOOLEAN was declared to
be a member of another class, and THAT CLASS WAS DECLARED BEFORE @DCL
WAS.  So the easy rule is: declare the classes that will be  required
to  provide  class  information  to semantic routines first, and then
those classes which are used only for parsing purposes.

Numerical parameters can also be passed to exec routines.  This is 
done in the same manner as parsing class-type information.  The only 
difference being that the @ symbol is followed by an integer instead 
of a class name.  
III.  Pre-loaded symbol table input format (program RTRAN).

This file obeys many of the same conventions  as HEL  (no lower case,
delimiters  are  only  space and  tab,  comment  operator is  MUMBLE,
etc.). Don't  play with  <ASSIGN> or  <DEFINITIONS>  unless you  have
become a real wizard.  There isn't much content there anyway.

The functions  are all listed with  their parameter types.   There is
no  special  order, except  that the  first  function is  the default
program block.   Hence,  the default  program  name is  M. I  suggest
leaving this as is.

A function description is: (1) the first line has the  function  name
(this  is  what  will  go  out  to the loader as an external request)
followed by the value that the function returns. UNTYPE means it is a
procedure  and not a function (other types are specified by the names
of the semantic bits for them) followed by some  bits  specifying  to
the compiler how to interpret the rest of the symbol table entry. OWN
absolutely MUST  be  cited.    Reserved-functions  are  stored  in  a
compact  way,  and  OWN  specifes  this  special  packing.  BILTIN is
specified if the function will save accumulators (except  the  result
ac  if  any) over the function call.  (Most of these routines do save
accumulators, but for a special case, consider INPUT.   The  integers
BREAK and EOF referred to in the call on OPEN to open the channel may
be changed by a call to INPUT.  If  copies  of  these  integers  were
thought by the compiler to be in the ac's at the time, disaster would
(and did!) strike.) The bit name "FNYNAM" is used if the function  is
to  be  known  as  FCN  to  the  compiler  (and  hence  in the users'
programs), but as FCN$ to the loader.  This feature is used for  some
of  the  numerical  routines,  in  order to avoid conflict with LIB40
names. The last thing on the first line is the number  of  parameters
to  the  procedure.   Then  (2)  come  the parameters, one to a line.
There are four elements to a parameter description: (1) a  "type"  of
the  parameter,  an  artifact  left  over from an earlier scheme, and
ignored by RTRAN, (2) an optional comment about what the parameter is
--  must  be  a  single  word  (no spaces or tabs) surrounded by ( ).
Then (3,4) come the right and left halves of  the  semantic  word  to
specify  what  type  of  parameter  we  have.  Things here are pretty
obvious except for one particular feature -- reference parameters may
have  many  types.    If  the  routine  really  only needs an address
(ARRTRAN,ARRBLT, etc.) we don't care what  type  (INTEGER,REAL,  etc)
the parameter had.   So in this case, the actual-formal match is made
with the condition: "any bit which is on in the actual must be on  in
the  description of the formal," with the exception that if one is an
array (SBSCRP) they both must be.   There is one other  feature  that
may  be  useful.    If  a  "$"  is  placed before field (3), then the
parameter may be "defaulted" to its null value (ie integers to  zero,
itemvars  to  BINDIT,  etc)  if  the  actual  call  omits this actual
parameter. Such defaultable parameters must come at the  end  of  the
argument list and must be value parameters.


To  name  the  program,  type name$:  ($ stands for altmode).  To get
inside a "block", type blockname$& .  If you want to name a symbol in
another block without permanently entering that block (as above) type
block&symbol .

The following changes have been made to DDT:

1.   Halfword  printout  is  now  of  the  form A,,B instead of (A)B.
Either form may be used  on  input.   The  difference  is  that  A,,B
truncates A to 18 bits before swapping halves while (A)B does not.

2.  $U is a new output mode.  It is the same as $A$H.

3.   $F  mode  will  now  print normalized floating permit numbers as
decimal integers.  This means that FORTRAN users may, in general, use
$F to look at all variables and they will be printed correctly either
fixed or floating.

4.  If the address of a string of ASCIZ text is placed in $nB+3, then
whenever  breakpoint  n is reached, DDT will act as if the characters
in the string  were  being  read  from  the  teletype.   If  you  are
preparing  such a string in advance use either $ or ≠ (≠33 octal) for

5.   If a bytepointer to an asciz string is placed in $M-l, DDT  will
act  as  if  the  characters  in  the  string are being read from the

6.  $$7" <delimiter> characters <delimiter> will  act  just  like  an
asciz  statement  in  MACRO  or FAIL,i.e., more than one word will be
filled with asciz for the characters if necessary.  $$" will  have  a
similar effect but with sixbit.

7.   Typing  <number>$$P  will  cause  DDT to do an automatic proceed
<number> times instead of forever.

8.  When printing in $$S mode, no word will be printed out as  an I/O
instruction  (CONO, DATAO, CONI, etc.) unless the device number is in
a special table.  The table is 10 words long and is  in  $I-1,  $I-2,
etc.  Simply  put  device  number  here  to  have the appropriate I/O
instructions printed.

9.  If an address is placed in  $M-2  then  for  each  character  DDT
wishes  to  output,  a  pushj  1,@$M-2 will be executed.  This allows
output to be redirected to some  device  other  than  the  TTY.   The
character is in register 5.  The routine should preserve all AC's and
end with a POPJ l,.

10.  In byte mode output ($<number>0), if a size of 0  is  specified,
DDT will use a special mark in $M+2. The boundry between 1 and 0 bits
specifies the size of the bytes.  For example, a word containing

	11111111111 00000000000 11100010110001

would print 2 . 11 bit bytes, 2 3 bit bytes, 2 1 bit bytes, a  2  bit
bytes, a 3 bit byte, and a 1 bit byte.

11.   Bytes may be input of $<number>%.  This should be followed by a

by an altmode.  If number of bytes in a word is not integral the last
byte is treated as if the word were larger (bit number  greater  than
35).   This makes input compatible with output.  A size of O uses the
mark in $M+2 as above.

12.  It is now possible to print flag words and  T type  instructions
(TRNN, TLNN, etc.) with suitable names for the bit involved.  In $M+3
a pointer of the following form is placed:

			T0:	-------------
				|            |
     -------------  		|            |
$M+3 |  L1 | T0  |		| Table 0    | 
     -------------  		|            |

L1:  L2,,T1			-------------
				|            |
				| Table 1    |
				|            |

L2:  0,,T2			-------------
				|	     |                
				| Table 2    |
				|	     |                

As  many  tables as desired may be included.  The pointer to the last
table should have 0 in the left half. Each table contains  36  words.
The  nth word contains the RADIX50 for the name of bit n.  $<number>J
mode will cause a word to be printed out using the bit names in table
number.   If  an  entry  for  a  bit  is 0, the numeric value will be
printed.  A typical word might look like

foo! baz! 123,, fool! garp! 2

$J means $0J.  $nL causes the left half to be printed in symbolic and
the  right  half  to be printed in this bit mode, using the left-half
bits.  This is for printing out the instructions  like  TLNN,TLO,TLZ,
etc.   The corresponding command for TRNN,TRO,TRZ etc is $V. Needless
to say, the instructions do not have to be TRNN, TLNN etc.,  but  may
be anything.


This description attempts to  give  a  complete  description  of  the
possible  modes  of  operation  of  SCISS.   It  answers the pressing
question: What happens if I reply  NO  to  the  "STANDARD?  "  query.
Here's what happens --

1. The file ORDER consists of a comment (thus ignored by FAIL) of the
SCISS   reads  it  to  find  the  version  number  of   the   library
(the digit following "NAM," and the  list  of  all  possible  library
entries.   It  creates  files  of  the form SAILOR, SAISGC, .... when
operating.   The  SAILOR...  form  is  the  one  you  should  use  in
communicating with SCISS.

NOTE:  if  you  change  the version number of the library, be sure to
also change the library names  accordingly  in  FILSPC  so  that  the
compiler will generate library request for the current version of the

2. The COMPIL macro has as arguments, among others, the name  of  the
individual  entry  (3  letters,  like LOR), the list of ENTRIES to be
issued when in LIBRARY  mode,  any  EXTERNALS  and  INTERNALS  to  be
issued, and a short description.  When not in library mode,this macro
simply issues the ENTRY and INTERNAL lists as INTERNALS,  and  issues
the EXTERNALS.  When SCISS encounters it, it compares the name of the
entry with the list of those selected to be assembled this  run.   If
the  name matches an entry, it writes a file SAIccc.FAI, with all the
code between the COMPIL and the matching  ENDCOM  (which  expands  in
this  case  to  END)  in  it.   COMPIL  in this mode will expand when
assembled into the appropriate ENTRYs, TITLEs,  etc.     Notice  that
there is a COMPIL macro for each possible library entry, and an entry
in the ORDER list for every instance of COMPIL.   Thus  the  standard
case,  which  uses  the  whole ORDER list, makes the largest possible

3. SCISS will ask the question "STANDARD?" before PASS 1  and  before
PASS2  (unless  PASS  1  was totally suppressed). To get the standard
LIBSAn simply reply Y<cr> to both questions. Otherwise type N<cr> and
then you will get a list of options.



Type the indices of those options you wish to invoke:

1. PASS 2 NOW means don't create the SAIxxx.FAI files or  call  FAIL.
This makes sense only if SCISS has been run before and the SAIxxx.REL
files still exist. This option will cause the  copying  of  the  .REL
files  (which  ones,  may be specified by invoking options 5 or 6) to
form a library (unless inhibited by option 8) and then  deleting  the
.FAI  and .REL files (unless inhibited by option 7). The library will
be named HLBSAn if option 4 is requested (The .REL files should  have
been  created  by  running  SCISS  with a REENTRANT library requested
during the first pass).

2. DON'T CHAIN TO FAIL  means  just  create  the  .FAI  files.  Don't
assemble them.

3. DON'T CREATE INTERMEDIATE FILES.  Don't  create the .FAI files but
unless inhibited assemble the .FAI files generated previously.

4. MAKE REENTRANT LIBRARY means to make a HLBSAn instead of a LIBSAn.
	(command must be given to both PASS 1 and PASS 2)

5. SELECT ENTRIES FROM PROMPT-LIST  means  that  SCISS  will type the
library entries and let you indicate whether you desire that entry in
the  library.  This  option  and the next are very useful in avoiding
reassembling everything when an assembly error has occurred in one or
two library entries. SCISS will type the names of the library entries
like SAICOR, pausing for your response:
		Y<cr> retain this entry
		N<cr> omit this entry
		DONE  dispose  of  the rest of the entries as you did
			the last (all Y or N)

6.  SPECIFY  ENTRIES  EXPLICITLY  - type the names of the entries you
want (SAILOR etc) separated by <cr>. After all  the  names  you  want
type DONE<cr>

7.  DON'T  DELETE  INTERMEDIATE  FILES- don't delete the .FAI or .REL
files (only meaningful if doing PASS 2 now)

8. DON'T MAKE LIBRARY.(only meaningful doing PASS 2 now).


An important thing to remember is that SCISS  doesn't  remember  what
you  requested  at  the  beginning of PASS 1 so if you want something
unusual (e.g. a  reentrant  library  or  a  library  without  certain
entries) you are going to have to tell SCISS again.


These have the same meaning as they did in PASS 1.



Assemble  and  run  to  get  a new copy of 2OPS2.OPS, just for fun or
because you changed it.   This file  is  needed  on  SYS  before  the
START_CODE feature will work.