%begin
!$IF ECSVAX
{%conststring(51) title = %c
{"  EUCSD IMP Compiler for M68000.  VAX Version  2.2g"
!$IF APM
%conststring(51) title = %c
"  EUCSD IMP Compiler for M68000.  APM Version  2.2g"
!$FINISH
!
! Hamish Dewar  Computer Science   Edinburgh University  1982/83/84
!
%constinteger WHICH='.imp'

!<<BOTH [markers for parts common to Pascal]

!General notes:
!  The main data structure DICT is used for identifier, type, label
!  and expression representation (with some aliasing).  The fixedsize
!  cell has a number of advantages which outweigh the Procustean factor
!  (and the 16-byte size is efficiently addressed)
!
!  Major routines (like EVAL) which have variables heavily used by
!   nested routines are not placed below level 1 for efficiency of
!   addressing.  (Making the compiler an external procedure rather
!   than a main program would seriously impact this efficiency).
!
!!!!!!!!!!!!!!!!!!  File handling definitions  !!!!!!!!!!!!!!!!!!!!!
!
%constinteger MAXNAME=127
%string(maxname) MAINFILE,OBJFILE

! Editor-compatible file-mapping record:
%recordformat EDFILE(%integer start1,lim1, {part 1}
                              start2,lim2, {part 2}
                              lim, {VMLIM}
                              lbeg,fp,change,flag,
                              line  {line number of current pos},
                              diff  {diff between LINE and ROW},
                       %byte  top  {top row of sub_window},
                              win  {floating top},
                              bot  {bottom row of sub_window},
                              min  {minimum window size},
                              row  {last row position},
                              col  {last col position},
             %string(maxname) name)
!
%external%routine%spec EDI(%record(edfile)%name main,sec,
                         %string(255) message)
{PAM: parameter acquisition module}
%constinteger NEWGROUP=1, NODEFAULT=2
%external%routine%spec DEFINE PARAM %alias "PAM_DEFSTRING" %c
          (%string(255) name, %name variable, %integer flags)
%external%routine%spec DEFINE INT PARAM %alias "PAM_DEFINT" %c
          (%string(255) name, %name variable, %integer flags)
%external%routine%spec DEFINE BOOLEAN PARAMS %alias "PAM_DEFBOOL" %c
    (%string(255) name, %name variable, %integer flags)
%external%routine%spec PROCESS PARAMETERS %alias "PAM_PROCESS"(%string(255) parm)
%external%routine%spec CONNECT EDFILE(%record(edfile)%name f)
%external%routine%spec DISCONNECT EDFILE(%record(edfile)%name f)
%external%string(8)%fnspec DATE
%external%string(5)%fnspec TIME
!
%owninteger ITEM=0;                ![high-frequency]
%owninteger LISTOUT=0 {set to 2 if listing to file}
!!  Compiler control
%constinteger ARRBIT=   16_80000000 {array bound check},
              LOOPBIT=  16_40000000 {%for loop check},
              CAPBIT=   16_20000000 {capacity check},
              OVERBIT=  16_10000000 {overflow check},
              ASSBIT=   16_08000000 {integer-unassigned check},
              STRASSBIT=16_04000000 {string-unassigned check},
              SASSBIT=  16_02000000 {short-unassigned check},
              BASSBIT=  16_01000000 {byte-unassigned check},
              ASSMASK=assbit!strassbit!sassbit!bassbit,
              LINEBIT=  16_00800000 {set line number},
              DIAGBIT=  16_00400000,
              TRACEBIT= 16_00200000 {plant TRAP 15},
              STACKBIT= 16_00100000 {stack over-run check},
              CHECKBIT= 16_00080000 {for NOCHECK},
              SYSBIT=   16_00040000 {special treatment of SIGNAL},
              STRICTBIT=16_00020000,
              VOLBIT   =16_00010000,
              HALFBIT=  16_00008000 {halfword MULT/DIV},
              LOWBIT  = 16_00004000 {low-level features permitted},
              EDITBIT=  16_00002000,
              RUNBIT=   16_00001000,
              FORCEBIT= 16_00000800,
              LOGBIT=   16_00000400 {print log},
              WARNBIT=  16_00000200 {print warnings},
              NONSBIT=  16_00000100 {nonstandard features permitted},
              PERMBIT=  16_00000080 {for PRIM compilation},
              NEWBIT=   16_00000040 {Pascal: new treatment of pointers},
              CODELIST= 16_00000020 {list code},
              DICTLIST= 16_00000010 {list dict entries},
              EXPLIST=  16_00000008 {list EXP entries},
              MAPLIST=  16_00000004 {print space map},
              TTLIST=   16_00000002 {list to terminal},
              LIST=     16_00000001 {do list}
%constinteger LISTBITS=codelist+dictlist+explist+maplist+ttlist+list
%owninteger CONTROL=warnbit+checkbit+linebit+diagbit+editbit+volbit %c
                   +strassbit+assbit+arrbit+loopbit+capbit+stackbit
%integer INITCON,TIME1,TIME2
!Events:-
%constinteger OFLOW=1, FAIL=11, DONE=12, REDO=13, ABANDON=14
!
!
%constinteger MAXINT=16_7FFFFFFF, MININT=\MAXINT
%constinteger SIGN16=\16_7FFF, SIGN=\16_7FFFFFFF
!
!!!!!!!!!!!!!!!!   Operand Representation  !!!!!!!!!!!!!!!!!!!
! Operands (largely, Expressions) are denoted by integers in a
! contiguous range as follows:
! 
! <= 0  Literals (including 'addresses' within FINAL)
!       [see LITREF and LITVAL for interpretation]
!                                    Dictionary
!                   __16___16____16____8____8____32____16___16__
! [dummy @ 0] ->    |flags|type| link| reg|mode|value|text|hlink|
! D0 [@1]  ->  R    |     |    | size|    |    |     |    |    |
!                   |     |    |xtype|    |    |     |    |    |
! D7       ->       |     |    |     |    |    |     |    |    |
! A0       ->  E    |     |    |     |    |    |     |    |    |
!                   |     |    |     |    |    |     |    |    |
! A7       ->  G    |     |    |     |    |    |     |    |    |
! INDA0    ->       |     |    |     |    |    |     |    |    |
!              S    |     |    |     |    |    |     |    |    |
! PREA7    ->       |     |    |     |    |    |     |    |    |
!              I    |     |    |     |    |    |     |    |    |
!              D    |     |    |     |    |    |     |    |    |
!              E    |     |    |     |    |    |     |    |    |
!              N    |     |    |     |    |    |     |    |    |
!              T    |     |    |     |    |    |     |    |    |
!              S    |     |    |     |    |    |     |    |    |
!                   |_____|____|_____|____|____|_____|____|____|
! DICTLIM  ->       | --  |--  |  -- | -- |mode|value| -- | -- |
!              C L  |     |    |     |    |    |     |    |    |
!              O A  |     |    |     |    |    |     |    |    |
!              M B  |     |    |     |    |    |     |    |    |
!              P S  |     |    |     |    |    |     |    |    |
!                   |_____|____|_____|____|____|_____|____|____|
! LABLIM   ->       |flags|type| act |----|mode|value|arg1|arg2|
!              C    |     |    |     |    |    |     |    |    |
!              O    |     |    |     |    |    |     |    |    |
!              M E  |     |    |     |    |    |     |    |    |
!              P X  |     |    |     |    |    |     |    |    |
!              L P  |     |    |     |    |    |     |    |    |
!              E S  |     |    |     |    |    |     |    |    |
!              X    |_____|____|_____|____|____|_____|____|____|
! EXPLIM   ->

%constinteger SMALLMIN=-1024, SMALLMAX=1023,
              LITMAX=smallmin-(smallmax+1), LITMIN=litmax-199,
              LITMITE=-255, LITQUICK=-16, ONE=-(1<<1)
%constinteger D0=1, D1=d0+1, D2=d0+2, D7=d0+7,
              A0=d0+8, A1=a0+1, A6=a0+6, A7=a0+7,
              INDA0=a0+8, INDA7=inda0+7,
              POSTA0=inda0+8, POSTA7=posta0+7,
              PREA0=posta0+8, PREA7=prea0+7,
              UNDEF=a7
%owninteger   DICTLIM=1000, FINALBOUND=64  {see Init for adjustment}
%integer      LABLIM,NP0,EXPLIM {continuing from DICTLIM}
%integer      CHARBOUND         {derived from DICTLIM}
%constinteger LABELS=42 {enough for Pascal reserveds},
              TRIPLES=200
%constinteger AD=16384  {any item + AD >= EXPLIM}

%constinteger BREG=D0+4, LINELOC=d0+5
%constinteger F1=a0+6, GB=a0+5, MB=a0+4;  !level 1, global base, main base
%constinteger MAXDREG=d0+3, MAXAREG=a0+3
%constinteger D0B=1, D1B=2, D2B=4, BREGB=16,
              A0B=16_100, A1B=16_200, A2B=16_400
%constinteger ANYDREG=16_00FF-bregb, ANYAREG=16_FF00,
              ANYREG=16_FFFF
%constinteger DEFAULTFREE=2<<(maxdreg-d0)-1+(2<<(maxareg-a0)-1)<<8+bregb
%integer MAXCALLDREG, MAXCALLAREG
%integer FREE

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!   Big Literals  !!!!!!!!!!!!!!!!!!!!!!!
%integer LITPOS
%integerarray LITSTORE(litmin:litmax)
!
!!!!!!!!!  Registers, Identifiers, Labels, Expressions  !!!!!!!!!
!
!   Operand attributes:
%recordformat OBJINFO %C
  (%short FLAGS,TYPE,
   (%short LINK %or %short XTYPE %or %short SIZE %or %short ACT),
   %byte REG,MODE,
   %integer VAL)
%recordformat IDENTINFO %C
  ((%short FLAGS,TYPE,
   (%short LINK %or %short XTYPE %or %short SIZE %or %short ACT),
    %byte REG,MODE,
    %integer VAL %or %record(objinfo) DETAILS),
   (%short   TEXT,HLINK %or %short X,Y))
!
!Machine addressing modes:
%constinteger AREGMODE=2_001000,
              DISPMODE=2_101000, INDEXMODE=2_110000, ABSMODE=2_111000,
              PCMODE=2_111010, LITMODE=2_111100
!Conversion factors for address register modes (from AREGMODE)
%constinteger INDIR=8, POST=16, PRE=24
!Additional source-related modes:
%constinteger LABMODE=2_10000000+pcmode,
              PROCMODE=2_11000000+pcmode,
              GLOBALMODE=dispmode+(gb-a0),
              OWNMODE=2_01000000+dispmode+(mb-a0),
              CONSTMODE=2_01000000+pcmode,
              FRAMEMODE=2_10000000+dispmode
!                      +  01000000 for dynamic array
!
! MODE,VAL:
!  %const simple       : LITMODE     the actual value
!  %const structure    : CONSTMODE   address in code area
!  variable etc        : mode        byte address/displacement
!  undefined label     : LABMODE     reference chain
!  undefined procedure : PROCMODE    reference chain
!  record format       : 0           size of record in bytes
!
! Significance of FLAGS:
%constinteger CAT     =16_000F, {category: typeid only}
              WRITABLE=16_0001,
              READABLE=16_0002, {not write only}
              VOLATILE=16_0004,
              ARRFLAG =16_0008, {bound check needed}
                ALT   =16_0008, {alternative proc}
              WFLAG   =16_0010, {has been written to}
              RFLAG   =16_0020, {has been read from}
              OKFLAG  =16_0040, {no unassigned check needed, CC OK for fun}
                NORET =16_0040, {routine does not return}
              MFLAG   =16_0080, {has had mem access}
              SPEC    =16_0100, {unbodied spec or forward label}
              TYPEID  =16_0200, {type identifier}
              PACKED  =16_0400,
              INDIRECT=16_0800,
              PROC    =16_3000, {procedure not data}
                PROC1 =16_1000,
                PROC2 =16_2000,
              EXT     =16_4000, {external}
              NAME    =sign16
%constinteger HERITABLE=writable+readable+volatile %c
                       +wflag+rflag+okflag+arrflag
!
!CATegories (type identifiers only):
%constinteger INTY=0, CHARY=1, BOOLY=2, ENUMY=3,
              POINTY=4, REALY=5,
              STRINGY=8, ARRY=9, SETY=10,
              RECY=12, FILEY=13,
              NONORD=12

%ownrecord(objinfo) DEFINEDLABEL=0,
                    FORWARDLABEL=0,
                    BEGINBLOCK=0,
                    TYPEIDENT=0
!!!!!!!!!!!!!!!!!  File and control initialisation  !!!!!!!!!!!!!!!
!
%constinteger MAIN=1
%record(edfile)%array FILE(1:3)
%record(edfile)%name CUR
%integerarray FCONTROL(1:3)
%integer CURFILE,LASTFILE;      !current source file no (0:3)
%integer CURSTART,CURLIM;        !current source file bounds

%routine SET OPTIONS(%string(255) parm)
%constinteger CHECKS=assmask+arrbit+loopbit+capbit+overbit
  define boolean params( %c
  "ARR,LOOP,CAP,OVER,ASS,STRASS,SASS,BASS,LINE,DIAG,TRACE,STACK,".%C
  "CHECK,SYS,STRICT,VOL,HALF,LOW,EDIT,RUN,FORCE,LOG,WARN,NONS,PERM,NEW,".%C
  "CODE,DICT,EXP,MAP,TT,LIST",control,0)
  process parameters(parm)
 !NOCHECK => removal of checkbits
  control = control&(\checks) %if control&checkbit = 0
  control = control&(\editbit) %if control&listbits # 0
%end

%routine SET EXTENSION(%string(maxname)%name f,%string(4) ext)
%integer strip
%integer%fn last4(%string(*)%name s)
%integer i,e
  i = 0;  e = 0
  %while i < length(s) %cycle
    i = i+1;  e = e<<8+charno(s,i)
  %repeat
  %result = e
%end
  strip = last4(ext)
  f = mainfile %and strip = which %if f = ""
  length(f) = length(f)-4 %if last4(f)!16_202020 = strip
  f = f.ext
%end

%routine OPEN FILES
%string(maxname) LISTFILE=""
  objfile = ""
  define param("SOURCE",mainfile,nodefault)
  define param("OFILE",objfile,newgroup)
  define param("LFILE",listfile,0)
  define int param("IDents",dictlim,newgroup)
  define int param("KBytes",finalbound,0)
  file(main) = 0
  set options(cliparam)
  control = control&(\linebit) %if control&diagbit = 0;  !*temp*
!Main file
  file(main)_name = mainfile;  file(main)_flag = 32768
  time1 = time1-cputime
  connect edfile(file(main))
  time1 = time1+cputime
  %stop %if file(main)_flag # 0

!Listing file
  %if listfile # "" %or control&(list+ttlist) # 0 %start
    %if control&ttlist = 0 %start
      set extension(listfile,".lis")
      listout = 2
      open output(listout,listfile)
    %finish
    control = control&(\(editbit+ttlist))
    control = control!list %if control&listbits = 0
  %finish
  select output(listout)
  %if control&listbits # 0 %start
    control = control!list %if control&listbits # maplist
    newlines(2)
    printstring(title)
    newlines(2)
    printstring("   ");  printstring(file(main)_name)
    printstring("  compiled on ");  printstring(date)
    printstring("  at  ");  printstring(time)
    newlines(2)
  %finish
  initcon = control
%end

  time1 = 0
  open files
  dictlim = dictlim+300;  !allow for presets
  charbound = dictlim*8
  finalbound = finalbound<<10+4095;  !kilobytes -> bytes + (min) owns
  lablim = dictlim+labels
  explim = lablim+triples
  np0 = lablim+4
  file(main)_change = 16_7FFFFFFF
  forwardlabel_flags = spec;  forwardlabel_mode = labmode
  definedlabel_mode = labmode
  beginblock_mode = procmode
  typeident_flags = typeid+recy
!
!!!!!!!!!!!!!!!!  end of file and control initialisation  !!!!!!!!
!
%record(identinfo)%array DICT(0:explim-1)
!  indexing DICT:
%integer DLIM;         !dict limit (up)
%integer DLIM0
%integer DMIN;       !dict upper limit (down)
%integer DMIN0
%integer DICTSHOWN
%integer INCLIM
%record(identinfo)%name DLINK,DFORMAT,DTEMP,DTEMP2,DTSPREL,DINT
%integer SUBBED
%integer RANGES

! The identifier dictionary grows as declarations are
! encountered, sequentially from 0 up, so that the
! identifiers within a declaration group and within any block
! are contiguous and may be processed thus (eg at block end).
! However, searching is always through the hash links, with a
! start-point given by the array HASHINDEX.  The final link
! value is zero.
!  Identifiers are normally added at the start of the hash list
! (hence pushing down any global instance of the same name),
! but identifiers which have been reported as 'not declared'
! are added at the end of the list, using a negative link value.
! This tail section is used to avoid repeated reports for the
! same name (and is ultra-global, ie never removed).
!
! For record formats, the format name is stored in the usual way
! and contains in LINK a pointer to the field-names which are linked
! through what is normally the hash link.  Searching for field-names
! proceeds along this chain, as if following hash links.
!
!  HLINK is the hash link (index to DICT)
!
!  TEXT is the pointer (index to CHAR) to the text of the identifier
!       stored as a standard string

!  Text of identifiers (indexed by _TEXT):
%bytearray CHAR(0:charbound)
%integer CHAR0,CHARLIM,CHARMIN;  !pointers
%integer NEWLEN

!  Hash index to DICT:
%shortarray HASHINDEX(0:255)
%shortname HEAD;                  !head of ident search list
!
!
!<<IMP

!* PRIMGEN marker 1
%constinteger NULL=41,
              PROCSTAR=42,
              INTTYPE=43,
              SHORTTYPE=46,
              HALFTYPE=49,
              BYTETYPE=52,
              MITETYPE=55,
              BOOLTYPE=58,
              CHARTYPE=61,
              STRINGSTAR=62,
              STRING1=63,
              STRINGTYPE=64,
              ARRSTAR=65,
              NULLSETTYPE=66,
              RECSTAR=67,
              REALTYPE=69,
              SIGNAL=73,
              DADDR=74,
              DSIZEOF=77,
              INDEX=78,
              LENREF=79,
              SINDEX=82,
              IMUL=86,
              IDIV=87,
              IPOW=88,
              FNEG=89,
              FADD=90,
              FSUB=91,
              FMUL=92,
              FDIV=93,
              FPOW=94,
              FLOAT=95,
              DREM=98,
              UNASS=102,
              ADOK=103,
              STACKOK=104,
              ASIZE=105,
              CONCAT=106,
              DTOSTRING=107,
              AGET=109,
              FOROK=110,
              CHECK=111,
              SCOMP=112,
              STRCOPY=113,
              STRTOSTK=114,
              DNEW=115,
              RESOLVES=117,
              DEVENTF=128,
              DEVENT=134,
              DNIL=137,
              DPRINTSTR=155,
              DWRITE=183

%constinteger OPMAX=resolves

%routine SET HASHHEAD(%string(*)%name s)
%integer h,i
  h = 0
  h = h<<1!!charno(s,i) %for i = 1,1,length(s)
  head == hashindex(h&255)
%end

%routine PRESET
!* PRIMGEN marker 2
%const%integer CMAX=775
%const%byte%array CHARINIT(0:CMAX) = 
  0,
  2,'d','0',
  2,'d','1',
  2,'d','2',
  2,'d','3',
  2,'d','4',
  2,'d','5',
  2,'d','6',
  2,'d','7',
  2,'a','0',
  2,'a','1',
  2,'a','2',
  2,'a','3',
  2,'a','4',
  2,'a','5',
  2,'a','6',
  2,'a','7',
  7,'i','n','t','e','g','e','r',
  6,'M','A','X','I','N','T',
  12,'s','h','o','r','t','i','n','t','e','g','e','r',
  11,'h','a','l','f','i','n','t','e','g','e','r',
  11,'b','y','t','e','i','n','t','e','g','e','r',
  11,'m','i','t','e','i','n','t','e','g','e','r',
  7,'B','O','O','L','E','A','N',
  5,'F','A','L','S','E',
  4,'T','R','U','E',
  4,'c','h','a','r',
  6,'s','t','r','i','n','g',
  5,'a','r','r','a','y',
  6,'r','e','c','o','r','d',
  4,'T','E','X','T',
  4,'r','e','a','l',
  8,'l','o','n','g','r','e','a','l',
  6,'S','I','G','N','A','L',
  4,'a','d','d','r',
  6,'s','i','z','e','o','f',
  5,'I','N','D','E','X',
  6,'l','e','n','g','t','h',
  6,'c','h','a','r','n','o',
  4,'I','M','U','L',
  4,'I','D','I','V',
  4,'I','P','O','W',
  4,'F','N','E','G',
  4,'F','A','D','D',
  4,'F','S','U','B',
  4,'F','M','U','L',
  4,'F','D','I','V',
  4,'F','P','O','W',
  5,'f','l','o','a','t',
  3,'r','e','m',
  5,'U','N','A','S','S',
  4,'A','D','O','K',
  7,'S','T','A','C','K','O','K',
  5,'A','S','I','Z','E',
  6,'C','O','N','C','A','T',
  8,'t','o','s','t','r','i','n','g',
  4,'A','G','E','T',
  5,'F','O','R','O','K',
  5,'C','H','E','C','K',
  5,'S','C','O','M','P',
  7,'S','T','R','C','O','P','Y',
  8,'S','T','R','T','O','S','T','K',
  3,'n','e','w',
  8,'r','e','s','o','l','v','e','s',
  9,'s','u','b','s','t','r','i','n','g',
  7,'e','v','e','n','t','f','m',
  5,'e','v','e','n','t',
  3,'s','u','b',
  4,'l','i','n','e',
  5,'e','x','t','r','a',
  7,'m','e','s','s','a','g','e',
  5,'e','v','e','n','t',
  2,'n','l',
  3,'s','n','l',
  3,'n','i','l',
  7,'d','i','s','p','o','s','e',
  5,'r','o','u','n','d',
  5,'t','r','u','n','c',
  8,'f','r','a','c','t','i','o','n',
  3,'i','n','t',
  5,'i','n','t','p','t',
  6,'f','r','a','c','p','t',
  4,'s','q','r','t',
  10,'n','e','x','t','s','y','m','b','o','l',
  10,'r','e','a','d','s','y','m','b','o','l',
  10,'s','k','i','p','s','y','m','b','o','l',
  11,'p','r','i','n','t','s','y','m','b','o','l',
  11,'p','r','i','n','t','s','t','r','i','n','g',
  9,'o','p','e','n','i','n','p','u','t',
  10,'o','p','e','n','o','u','t','p','u','t',
  11,'s','e','l','e','c','t','i','n','p','u','t',
  12,'s','e','l','e','c','t','o','u','t','p','u','t',
  8,'s','e','t','i','n','p','u','t',
  9,'s','e','t','o','u','t','p','u','t',
  10,'r','e','s','e','t','i','n','p','u','t',
  11,'r','e','s','e','t','o','u','t','p','u','t',
  10,'c','l','o','s','e','i','n','p','u','t',
  11,'c','l','o','s','e','o','u','t','p','u','t',
  6,'p','r','o','m','p','t',
  7,'n','e','w','l','i','n','e',
  5,'s','p','a','c','e',
  6,'s','p','a','c','e','s',
  8,'n','e','w','l','i','n','e','s',
  4,'r','e','a','d', 138,'r','e','a','d','s','t','r','i','n','g',
  4,'r','e','a','d', 136,'r','e','a','d','r','e','a','l',
  4,'r','e','a','d',
  5,'w','r','i','t','e',
  7,'c','p','u','t','i','m','e',
  5,'p','r','i','n','t',
  7,'p','r','i','n','t','f','l',
  8,'i','n','s','t','r','e','a','m',
  9,'o','u','t','s','t','r','e','a','m',
  8,'c','l','i','p','a','r','a','m',
0
%constinteger PREMAX=196
%const%short%array DICTINIT(41*6:PREMAX*6+5) = 
 516,-1,0,0,0,0,
 527,-1,0,0,0,4,
 512,43,4,56,-32768,0,
 0,-44,4,60,-32768,0,
 0,43,4,60,32767,-1,
 512,43,2,56,-32768,0,
 0,-44,2,60,-1,-32768,
 0,-44,2,60,0,32767,
 512,43,2,56,-32768,0,
 0,-44,2,60,0,0,
 0,-44,2,60,0,-1,
 512,43,1,56,-32768,0,
 0,-44,1,60,0,0,
 0,-44,1,60,0,255,
 512,43,1,56,-32768,0,
 0,-44,1,60,-1,-128,
 0,-44,1,60,0,127,
 514,58,1,0,0,0,
 0,58,1,60,0,0,
 0,58,1,60,0,1,
 513,61,255,0,0,0,
 520,61,0,0,0,0,
 520,-62,-2,0,0,0,
 520,-62,-256,0,0,0,
 521,0,0,0,0,0,
 522,-1,0,0,0,0,
 524,0,0,0,0,0,
 525,61,4,0,0,0,
 517,0,4,0,0,0,
 517,0,4,0,0,0,
 0,-1,0,0,0,0,
 0,-1,0,0,0,0,
 4256,42,0,56,0,16122,
 4098,75,0,56,0,0,
 0,-44,76,0,0,4,
 -32701,-1,0,6313,-1,-4,
 4098,75,0,56,0,0,
 4096,42,0,56,-32767,2861,
 4099,80,0,56,0,0,
 0,-53,81,6144,0,4,
 -32701,-63,0,6313,-1,-4,
 4099,83,0,56,0,0,
 0,-53,84,6144,0,4,
 -32701,-63,85,6313,-1,-4,
 67,-44,0,169,-1,-8,
 4256,42,0,56,0,16116,
 4256,42,0,56,0,16110,
 4096,42,0,56,0,16098,
 4096,42,0,56,0,16092,
 4096,42,0,56,0,16086,
 4096,42,0,56,0,16080,
 4096,42,0,56,0,16074,
 4096,42,0,56,0,16068,
 4096,42,0,56,0,16062,
 4098,96,0,56,0,16056,
 0,-70,97,0,0,4,
 67,-44,0,169,-1,-4,
 4098,99,0,56,0,0,
 0,-44,100,0,0,4,
 67,-44,101,169,-1,-4,
 67,-44,0,425,-1,-8,
 4096,42,0,56,-32722,2578,
 4096,42,0,56,-32704,2064,
 4096,42,0,56,-32688,2839,
 4096,42,0,56,-32665,3097,
 4096,42,0,56,-32640,2077,
 4098,108,0,56,-32611,6,
 0,-64,97,6144,0,4,
 4096,42,0,56,-32605,2597,
 4096,42,0,56,-32568,2334,
 4096,42,0,56,-32538,1806,
 4096,42,0,56,-32524,2626,
 4096,42,0,56,-32458,2070,
 4096,42,0,56,-32436,2090,
 4103,116,0,56,0,16008,
 0,-68,76,6144,0,4,
 22786,118,0,108,0,0,
 0,-59,119,0,0,0,
 -32701,-63,120,6313,-1,-4,
 67,-65,121,6569,-1,-260,
 -32701,-63,122,6825,-1,-264,
 -32701,-63,0,7081,-1,-268,
 4098,124,0,56,-32394,15,
 0,-65,125,6144,0,4,
 -32701,-63,126,6313,-1,-4,
 67,-44,127,169,-1,-8,
 67,-44,0,425,-1,-12,
 524,0,129,0,-1,-264,
 3,52,0,0,0,0,
 3,52,0,0,0,1,
 3,46,0,0,0,2,
 3,43,0,0,0,4,
 3,64,0,0,0,8,
 67,128,0,45,0,32,
 66,43,0,60,0,10,
 66,61,0,60,0,10,
 67,67,0,56,0,0,
 4096,139,0,56,0,16002,
 0,-1,76,0,0,4,
 4098,141,0,56,0,16050,
 0,-44,142,0,0,4,
 67,-70,0,169,-1,-4,
 4098,141,0,56,0,16044,
 4098,145,0,56,0,16038,
 0,-70,142,0,0,4,
 4098,141,0,56,0,16032,
 4098,141,0,56,0,16026,
 4098,145,0,56,0,16020,
 4098,145,0,56,0,16014,
 4098,132,0,56,0,15996,
 4098,132,0,56,0,15990,
 4096,42,0,56,0,15990,
 4256,154,0,56,0,15984,
 0,-1,97,0,0,4,
 4096,156,0,56,0,15978,
 0,-1,157,0,0,4,
 67,-65,0,6313,-1,-256,
 26880,159,0,108,0,0,
 0,-1,160,0,0,0,
 67,-44,161,169,-1,-4,
 67,-65,0,6313,-1,-260,
 26880,159,0,108,0,0,
 4096,154,0,56,0,15960,
 4096,154,0,56,0,15954,
 26880,166,0,108,0,0,
 0,-1,97,0,0,0,
 26880,166,0,108,0,0,
 26880,0,0,108,0,0,
 26880,0,0,108,0,0,
 4096,42,0,56,0,15936,
 4096,42,0,56,0,15930,
 26880,173,0,108,0,0,
 0,-1,157,0,0,0,
 4096,42,0,56,-32379,4,
 4096,42,0,56,-32375,4,
 22784,166,0,108,0,0,
 22784,166,0,108,0,0,
 22790,179,0,108,0,0,
 0,-65,0,6144,0,0,
 22798,181,0,108,0,0,
 0,-70,0,0,0,0,
 22798,1,0,108,0,0,
 22784,184,0,108,0,0,
 0,-1,100,0,0,0,
 26886,1,0,108,0,0,
 22784,187,0,108,0,0,
 0,-1,188,0,0,0,
 67,-70,189,169,-1,-4,
 67,-44,190,425,-1,-8,
 67,-44,0,681,-1,-12,
 22784,192,0,108,0,0,
 0,-1,193,0,0,0,
 67,-70,101,169,-1,-4,
 67,43,0,45,0,392,
 67,43,0,45,0,396,
 67,64,0,45,0,464

%integer i,ci,anons
%record(identinfo)%name dp

%routine PUT CHAR
  byteinteger(charlim) = charinit(ci)
  charlim = charlim+1;  ci = ci+1
%end

%routine TEXTSET(%record(identinfo)%name dp)
%integer len
  dp_hlink = 0
  %if dp_type < 0 %start;     !convention for *anon*
    dp_type = \dp_type
    dp_text = 0
    anons = anons-1
    dp_hlink = ranges %and ranges = dlim %if anons = 0 %and dlim <= mitetype+2
  %else
    dp_text = ci
    %if charinit(ci+1)&32 # 0 %start;  !not upper-case
      %if deventf < dlim < devent %start
        head = dlim;  head == dp_hlink
      %else
        set hashhead(string(addr(charinit(ci))))
        dp_hlink = head;  head = dlim
        head == dp_link %if dlim = deventf
      %finish
    %finish
    len = charinit(ci)
    put char %and len = len-1 %until len < 0
    len = charinit(ci)-128
    put char %and len = len-1 %while len >= 0
    anons = 2
  %finish
%end

  hashindex(i) = 0 %for i = 0,1,255;  !hash table empty
  byteinteger(char0) = 0;  !for anon ident
  charlim = char0+1
  charmin = charlim+charbound;  !(1 over top)
  ranges = 0

  ci = 1
  anons = 100
  dict(0) = 0
  dlim = d0
  %cycle
    dp == dict(dlim)
    %if dlim <= prea7 %start
      dp = 0
      dp_flags = okflag+writable+readable;  dp_mode = dlim-d0
      dp_type = inttype
      textset(dp) %if dlim <= a7
    %else
      dp_details = record(addr(dictinit(dlim*6)))
      textset(dp)
    %finish
    dlim = dlim+1
    %exit %if control&permbit # 0 %and dlim >= signal
  %repeat %until dlim > premax
  dictshown = dlim
  i = dictlim
  %cycle
    dp == dict(i)
    dp = 0
    dp_mode = labmode
    i = i+1
  %repeat %until i = np0
%end;  !preset

!<<BOTH

!  The last part of DICT (from LABLIM to EXPLIM) is used for
! the intermediate representation of the components of source
! statements between the recognition stage and the code generation
! stage.
!  The part from LABLIM+4 (NP0) up is used as a temporary pipeline
! for non-expression cells (instructions, conditions, etc)
! and the part down from EXPLIM for the canonical and
! persistent representation of expressions (including name
! expressions).
! In this part of the array the ident components PLIST (etc), TEXT
!  and HLINK are replaced by ACT, X and Y representing an operation
!  and (up to) two operands.
%integer EXPLO,OLDEXPLO
%integer NP,STARTNP

!Operator codes:
! Machine operator index values 1-31:
%constinteger MOVE=1, ADD=2, SUB=3,
              CMP=4, AND=5, OR=6, EOR=7,
              NOT=8, NEG=9, LSL=10, LSR=11,
              MULS=12, DIVS=13, MULU=14, DIVU=15,
              BRA=16, BSR=17,
              BCC=20, BCS=21, BNE=22, BEQ=23,
              BVC=24, BVS=25,
              BGE=28, BLT=29, BGT=30, BLE=31
%constinteger COMPARE=cmp, GOTO=bra
! Other built-in operators
%constinteger JAMASS=32, OKASS=33, ASSIGN=34, INCASS=35,
              FORASS=36, STOP=37, RETURN=38, REPEAT=39,
              ELSE=40, JUMPOUT=41, SETTRAP=42, SWGOTO=43,
              LABEL=44, RECREF=45, PREL=46, STOREMAP=47,
              IABS=48, FABS=49, END=50
! PLUS OPERATORS DEFINED IN DICTIONARY > BOPMAX <= OPMAX
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

%integer STARTS, CYCLES
%integer CURLAB
%integer PENDOUT, PENDCOND, PENDIN, POLARITY, CONDOP
%ownshortinteger EXTSPECS=0, EXTERNS=0
!
%recordformat CONTENTINFO(%short ccx,ccy,line,
                          %shortarray content(d0:a7))
%recordformat BLOCKINF(%integer sp, stack, extra, totstack, free, status,
                type, localdpos, parlim, localtext, localad, vintage,
                localpc, localswpc, pid, access, forward, lab1, looplab,
                eventsp, faults, return, shorts, temps,
                dynarray, oldcontrol, mode,val,
                %record(identinfo)%name dpid,
                %record(contentinfo) reg)
!STATUS flag bits
%constinteger UNKNOWN    =16_0002,
              WRONGCC    =16_0004,
              ONSTACK    =16_0008,
              GLOBBED    =16_0010,
              LABGLOBBED =16_0020, {Pascal}
              HADSPEC    =16_0040,
              HADSWITCH  =16_0080,
              HADON      =16_1000,
              HADORDERERR=16_2000,
              HADINST    =16_4000  {max flag}

%constinteger OUTERLEVEL=0, MAXLEVEL=7
%integer LEVEL;           !current block level
%integer VINTAGE;         !current block number
%record(blockinf) C;      !info for current block
%record(blockinf)%array HOLD(0:maxlevel-1); !info for global blocks
%record(contentinfo)%array LREG(0:labels)

! Code storage for currently open blocks
%constinteger PROGBOUND=16383
%shortarray PROG(0:progbound)
%bytearray PFLAG(0:progbound)
%constinteger SHORTJUMP=1, JUMP=2, LONGJUMP=3,
              GLOBAL=4, {NEGGLOBAL=5, BIGGLOBAL=6,} INDGLOBAL=7,
              ZEROSHORTS=8
%integer PC,SWPC
! Final core image
%bytearray FINAL(0:finalbound)
! Declaration records (to select relevant context)
%integer CAD,OWNAD,JOKERAD,OWNBASE
%integer FINAL0,ACCOUNTED
!
%integer FIRSTENTRY, FIRSTPOS

!Memo variables for current statement:-
%own%integer {ITEM,}TYPE=0,VALUE=0;      !current operand
%record(identinfo)%name DITEM
%integer SPECCING
%integer DUMP

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

!!  Source file input and listing
%owninteger ATOM=0;       !current lexical atom
%integer MATCHED;         !indic that atom has been matched
%integer SYM;             !current input symbol
%integer LINE;            !current line number
%owninteger CODEFLAG=' '; !or ^
%integer LISTFLAG;        !' ' or '&' or '+' or '"'
!   Pointers to source file:
%integer LINESTART
%integer FP;              !(file pointer) current position
%integer ATOMP;           !start of current atom
%integer EXPP
!
!! Utility routines

%predicate IS SHORT(%integer v)
  %true %if -32768 <= v <= 32767
  %false
%end

%predicate IS MITE(%integer v)
  %true %if -128 <= v <= 127
  %false
%end

%integer%fn MITE(%integer v)
  v = v&255;  v = v-256 %if v&128 # 0
  %result = v
%end

%record(identinfo)%map TYPECELL(%integer t)
  %result == dict(t)
%end

%integer%fn CATEGORY(%integer t)
  %result = dict(t)_flags&(packed+cat)
%end

%integer%fn LITVAL(%integer v)
  %result = v %if v = 0
  %if v > litmax %start;  !not stored literal
    %result = (-v)>>1 %if v&1 = 0
    %result = \((-v)>>1)
  %finish
  %result = litstore(v)
%end
!
!!!!!!!!!!!!!! Listing, diagnostic and report routines  !!!!!!!!!!!!!!
!
%integer FAULTS, OTHERS, FAULTNUM, FAULTP
!
!!  Program statistics
%integer STATEMENTS;           !statement count
%integer COMMENTS;             !comment count
%integer ATOMS;                !atom count
%integer IDENTATOMS;           !identifier count
%integer LITATOMS;             !numeric atom count
%integer ZAPS;                 !enforced cleardown of lits/exps
%integer STEPS;                !stepping stones inserted
!%integer MAXIDENTS, MAXCHARS, MAXLITS
%integer JUMPS,SHORTS
!
%string(255) REP
!
%routine PRINT LINE
  print string(rep);  print symbol(nl)
  rep = ""
%end
!
%routine PUT SYM(%integer k)
  rep = rep.tostring(k)
%end
!
%routine PUT STRING(%string(255) s)
  rep = rep.s
%end
!
!
%routine PUT NUM(%integer val)
%routine PD(%integer v)
  pd(v//10) %and v = v-v//10*10 %if v <= -10
  put sym('0'-v)
%end
  %if val < 0 %then put sym('-') %and pd(val) %c
  %else pd(-val)
%end
!
%routine PUT IDENT(%integer p,mode)
%record(identinfo)%name dp
  %cycle
    print line %if length(rep) > 50
    spaces(6) %if rep = ""
    dp == dict(p)
    put sym(' ') %and put sym('"') %if mode # 0
    %if dp_text > 0 %then put string(string(char0+dp_text)) %c
    %else %if dp_text < 0 %then put num(\dp_text) %c
    %else put num(p)
    put sym('"') %if mode # 0
    %return %if mode <= 0
    p = dp_hlink
  %repeat %until p = 0
%end
!
{?}%routine SPACES(%integer n)
{?}  %while n > 0 %cycle
{?}    put sym(' ');  n = n-1
{?}  %repeat
{?}%end
{?}!
{?}%routine PUT SPNUM(%integer val)
{?}  put sym(' ') %if val >= 0
{?}  put num(val)
{?}%end
{?}
{?}%constbytearray hexsym(0:15) =
{?}'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
{?}
{?}%routine PUT HEX(%integer val)
{?}%integer i
{?}  put sym(hexsym(val>>i&15)) %for i = 12,-4,0
{?}%end
{?}!
{?}%routine PUT OPERAND(%integer v)
{?}%integer i
{?}%routine INTERPRET(%integer mode)
{?}%switch s(0:7)
{?}  ->s(mode>>3&7)
{?}s(0):                 !DREG
{?}  put sym('D')
{?}putrno:
{?}  put sym(mode&7+'0')
{?}  %return
{?}s(1):                 !AREG
{?}  %if mode >= framemode-dispmode %then put sym('F') %else put sym('A')
{?}  -> putrno
{?}s(4):                 !PRE
{?}  put sym('-')
{?}s(2):                 !INDIRECT
{?}ind:
{?}  put sym('(')
{?}  interpret(mode&2_11000111+aregmode)
{?}  put sym(')')
{?}  %return
{?}s(3):                 !POST
{?}  interpret(mode-8);  !ind
{?}  put sym('+')
{?}  %return
{?}s(5):                 !DISP
{?}  put num(i)
{?}  ->ind
{?}s(6):                 !INDEX
{?}  put num(mite(i))
{?}  put sym('(')
{?}  interpret(mode+(aregmode-indexmode))
{?}  put sym(',')
{?}  interpret(i>>12&15)
{?}  put sym('.')
{?}  %if i&16_800 = 0 %then put sym('W') %else put sym('L')
{?}  put sym(')')
{?}  %return
{?}s(7):                 !MISC
{?}  %if mode&63 = pcmode %start
{?}    put num(i) %if mode = pcmode;  !suppress if not explicit
{?}    put string("(PC)")
{?}    %return
{?}  %finish
{?}  %if mode <= absmode+1 %start
{?}    put sym('$')
{?}    put hex(i>>16) %if mode = absmode+1 %or %not is short(i)
{?}  %else
{?}    put sym(hexsym(mode>>4&3))
{?}    put sym(hexsym(mode&15))
{?}    put sym('_')
{?}  %finish
{?}  put hex(i)
{?}%end
{?}
{?}  %if v <= 0 %start;               !literal
{?}    v = litval(v)
{?}    put sym('#')
{?}    %if is mite(v) %then put num(v) %else %start
{?}      put sym('$')
{?}      put hex(v>>16) %if v>>16 # 0
{?}      put hex(v&16_FFFF)
{?}    %finish
{?}  %else %if v <= prea7;    !register
{?}    interpret(v-d0)
{?}  %else %if v < dictlim;  !identifier
{?}    put ident(v,0)
{?}  %else %if v < lablim;  !internal label
{?}    put sym('L')
{?}    put num(v-dictlim)
{?}  %else;                 !complex
{?}    i = dict(v)_val
{?}    interpret(dict(v)_mode)
{?}  %finish
{?}%end;  !put operand
{?}
{?}%routine MARK AT(%integer col)
{?}  put sym(' ') %while length(rep) < col;  put sym('|')
{?}%end
{?}!
{?}%routine SHOW DICT(%integer from)
{?}%integer i
{?}%record(identinfo) d
{?}%constbytearray flagsym(0:15) =
{?}  'W','R','V','A','w','r','o','m','S','T','K','?','P','p','E','*'
{?}%constbytearray catsym(0:15) =
{?}  'I', 'C', 'B', 'E', '@', 'X', '?', '?',
{?}  'S', 'A', 'Z', '?', 'R', 'F', '?', '?'
{?}
{?}  %return %if from >= dlim
!<<IMP
{?}  print line %if rep # ""
{?}  byteinteger(charlim) = 0
{?}  spaces(6)
{?}  put string("___identifier____flags___type__link__par_mode___value____")
{?}  print line
{?}  %cycle
{?}    put spnum(from);  mark at(6)
{?}    d = dict(from)
{?}    put sym(' ');  put ident(from,0)
{?}    %if d_text > 0 %start
{?}      i = char0+d_text;  i = i+byteinteger(i)+1
{?}      %if byteinteger(i)&128 # 0 %start
{?}        byteinteger(i) = byteinteger(i)-128
{?}        put sym(':');  put string(string(i))
{?}        byteinteger(i) = byteinteger(i)+128
{?}      %finish
{?}    %finish
{?}    mark at(22)
{?}    %if d_flags&typeid # 0 %then put sym(catsym(d_flags&cat)) %and i = 4 %c
{?}    %else put sym(' ') %and i = 0
{?}    %cycle
{?}      put sym(flagsym(i)) %if d_flags>>i&1 # 0
{?}      i = i+1
{?}    %repeat %until i > 15
{?}    mark at(30)
{?}    put spnum(d_type);  mark at(35)
{?}    put spnum(d_link);  mark at(42)
{?}    put spnum(d_reg);  mark at(46)
{?}    put spnum(d_mode);  mark at(51)
{?}    put spnum(d_val);  mark at(63)
{?}    print line
{?}    from = from+1
{?}  %repeat %until from = dlim
{?}  spaces(6)
{?}  put string("+-------------------------------------------------------+")
{?}  print line
!<<BOTH
{?}%end
{?}%routine PUT MNEMONIC(%integer m)
{?}  m = m<<2
{?}  %cycle
{?}    put sym(m>>27+'A'-1)
{?}    m = m<<5
{?}  %repeat %until m = 0
{?}%end
{?}%routine%spec PUT OPCODE(%integer op)
{?}%routine SHOW EXP(%integer startp)
{?}%integer p,q
{?}%record(identinfo)%name dp
{?}
%constinteger bopmax=51
%constintegerarray EXTRA(32:bopmax) =
'j'<<25+('a'&31)<<20+('m'&31)<<15+('a'&31)<<10+('s'&31)<<5+('s'&31),
'o'<<25+('k'&31)<<20+('a'&31)<<15+('s'&31)<<10+('s'&31)<<5,
'a'<<25+('s'&31)<<20+('s'&31)<<15+('i'&31)<<10+('g'&31)<<5+('n'&31),
'i'<<25+('n'&31)<<20+('c'&31)<<15+('a'&31)<<10+('s'&31)<<5+('s'&31),
'f'<<25+('o'&31)<<20+('r'&31)<<15+('a'&31)<<10+('s'&31)<<5+('s'&31),
's'<<25+('t'&31)<<20+('o'&31)<<15+('p'&31)<<10,
'r'<<25+('e'&31)<<20+('t'&31)<<15+('u'&31)<<10+('r'&31)<<5+('n'&31),
'r'<<25+('e'&31)<<20+('p'&31)<<15+('e'&31)<<10+('a'&31)<<5+('t'&31),
'e'<<25+('l'&31)<<20+('s'&31)<<15+('e'&31)<<10,
'e'<<25+('x'&31)<<20+('i'&31)<<15+('t'&31)<<10,
't'<<25+('r'&31)<<20+('a'&31)<<15+('p'&31)<<10,
's'<<25+('w'&31)<<20+('g'&31)<<15+('o'&31)<<10+('t'&31)<<5+('o'&31),
'l'<<25+('a'&31)<<20+('b'&31)<<15+('e'&31)<<10+('l'&31)<<5,
'r'<<25+('e'&31)<<20+('c'&31)<<15+('r'&31)<<10+('e'&31)<<5+('f'&31),
'p'<<25+('r'&31)<<20+('e'&31)<<15+('l'&31)<<10,
's'<<25+('t'&31)<<20+('r'&31)<<15+('m'&31)<<10+('a'&31)<<5+('p'&31),
'i'<<25+('a'&31)<<20+('b'&31)<<15+('s'&31)<<10,
'f'<<25+('a'&31)<<20+('b'&31)<<15+('s'&31)<<10,
'e'<<25+('n'&31)<<20+('d'&31)<<15,
'l'<<25+('o'&31)<<20+('g'&31)<<15+('s'&31)<<10+('u'&31)<<5+('b'&31)

{?}%routine PUT OPRAND(%integer v)
{?}  put sym('#') %and v = v-ad %if v >= explim
{?}  %if v < np0 %then put operand(v) %else put num(v)
{?}%end
{?}  print line %if rep # ""
{?}  %return %unless np > np0
{?}  put string("      ______action_______first_______second____")
{?}  print line
{?}  p = np0
{?}  %cycle
{?}    %if p = np %start
{?}      p = explo
{?}      %exit %if p >= oldexplo
{?}      put string("      |---------------------------------------|")
{?}      print line
{?}    %finish
{?}    %if p = startp %then put sym('>') %else put sym(' ')
{?}    put num(p);  mark at(6)
{?}    dp == dict(p)
{?}    put sym(' ')
{?}    q = dp_act
{?}    %if q <= 31 %then put opcode(q) %c
{?}    %else %if q <= bopmax %then put mnemonic(extra(q)) %c
{?}    %else put ident(q,0)
{?}    mark at(22)
{?}    put sym(' ');  put oprand(dp_x);  mark at(34)
{?}    put sym(' ');  put oprand(dp_y);  mark at(46)
{?}    %if p >= explo %start
{?}      put spnum(dp_type)
{?}      put sym('*') %if dp_flags < 0
{?}    %finish
{?}    print line
{?}    p = p+1
{?}  %repeat %until p >= oldexplo
{?}  oldexplo = explo
{?}  put string("      +---------------------------------------+")
{?}  print line
{?}%end
{?}!
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!! Fault reporting  !!!!!!!!!!!!!!!!!!!!!!!!!!!
!
%routine CROAK(%string(255) s)
  select output(0)
  put string("** ");  put string(s)
  put string(".  Compilation abandoned at line ");  put num(line)
  print line
  %signal abandon
%end

!<<IMP

!!  Fault numbers
%constinteger INTERNERR=1, PLEXERR=2, CREACHERR=3, REACHERR=4,
              NORESULT=5, DREACHERR=6,
              FORMERR=7, ATOMERR=8, NAMERR=9, CLASSERR=10,
              SIZERR=11, TYPERR=12, BOUNDSERR=13, UNENDING=14,
              LOWLEVEL=15, ACCESSERR=16, NOTINLOOP=17, NOTINROUT=18,
              NOTINFUN=19, NOTINPRED=20, DUPERR=21,
              ORDERERR=22, MATCHERR=23, RANGERR=24, NONLITERAL=25,
              MOPERR=26, NOCYCLE=27,
              NOSTART=28, NOIF=29, ILLSTARRED=30, NONSTARTER=31,
              NONVAR=32, NONREF=33, TOOFEW=34, TOOMANY=35,
              NOBEGIN=36, DUBIOUS=37, NOTINBLOCK=38,
              NONSTAND=39, NOTIN=40, ASSERR=41,
              NOEND=42, NOFINISH=43, NOREPEAT=44
%constinteger COUNTERR=45, SLABMISSING=46, IDMISSING=47
%constinteger POINT=64, WARN=-128, NOW=128
!
%routine REPORT(%integer n,id,num)
%owninteger lastchange=0
%integer mark,start,errline

%routine PRINT TEXT(%integer stream)
%constinteger esc=27
%integer k,p

%conststring(15)%array MESSAGE(1:44) =
  "Internal error ", "Reg not free",
  "Out of reach ",  " out of reach!",
  "RESULT missing", "Out of reach",
  "Faulty form", "Unknown atom",
  "Unknown name", "Wrong class",
  "Wrong size", "Wrong type",
  "Inside out", "Endless loop",
  "Low level", "Not accessible",
  "Not in loop", "Not in routine",
  "Not in fn/map", "Not in pred",
  "Duplicate",
  "Out of order", "Mismatch",
  "Out of range", "Not literal",
  "Faulty operand", "%CYCLE missing",
  "%START missing", "Extra %ELSE",
  "Ill-starred", "Non-starter",
  "Not variable", "Not reference",
  "Too few args", "Too many args",
  "%BEGIN missing",
  "Dubious usage", "Not in block",
  "Nonstandard ", "Not supported",
  " void",
  "%END missing",
  "%FINISH missing", "%REPEAT missing"

!<<BOTH

  put sym(mark)
  put sym(' ') %if errline < 1000
  put sym(' ') %if errline < 100
  put sym(' ') %if errline < 10
  put num(errline)
  put sym(listflag);  put sym(' ')
  k = n&63
  %if k >= counterr %start
    %if k = counterr %start
      %if num < 0 %start
        put num(-num);  put string(" extra")
      %else
        put num(num) %if num # 0;  put string(" missing")
      %finish
      put string(" value(s) for ")
      put ident(id,0)
      %return
    %finish
    %if k # slabmissing %start
      put ident(id,1)
    %else
      put ident(id,0)
      put sym('(');  put num(num);  put sym(')')
    %finish
    put string(" missing")
mend:
    %if c_dpid_text # 0 %start
      put string(" in ")
      put ident(c_pid,-1)
    %finish
    %return
  %finish
  put ident(id,0) %if id > 0
  put string(message(k))
  put num(num) %if num > 0
  -> mend %if creacherr <= k <= noresult
  spaces(22-length(rep))
  p = start
  p = p+1 %while byteinteger(p) = ' '
  %if p < faultp-50 %then p = faultp-47 %and put string("...") %c
  %else put sym(' ')
  %cycle
    k = byteintegeR(p);  p = p+1
    %if p = faultp %start
!      %if stream # 0 %then put sym('|') %else %start
!       !**V200**
!        put sym(esc);  put sym('F');  !graphics
!        put sym('~')
!        put sym(esc);  put sym('G');  !normal
!      %finish
      put sym('|')
    %finish
    %exit %if k = nl
    put sym(k)
!    %if ' ' <= k <= '~' %then put sym(k) %c
!    %else put sym('[') %and put num(k) %and put sym(']')
  %repeat
  %return
%end

!Warning or error
  mark = '?'
  %if n > 0 %start
    mark = '*'
    c_faults = c_faults+1;  faults = faults+1
  %finish
  faultnum = 0;  c_access = -1
!Ignore uncorrected earlier error
  %return %if file(main)_start1 <= fp < lastchange
!Establish what to print
  start = linestart;  errline = line
  %if n&point = 0 %start
    faultp = 0;  !no pointing
  %else
    %while start >= faultp %cycle;  !before current line
      start = start-1
      errline = errline-1 %if byteintegeR(start) = nl
    %repeat
    start = start-1 %while start # curstart %and byteintegeR(start-1) # nl
  %finish
  time1 = time1-cputime
  %if listout # 0 %start;  !listing file
    print text(listout);  print line
  %finish
  select output(0)
  %if curfile # lastfile %start
    lastfile = curfile;  put string(cur_name);  print line
  %finish
  print text(0)
  %if n > reacherr %and curfile = main %and control&editbit # 0 %start
    start = faultp-1 %if faultp > start
    cur_fp = start;  cur_line = line
    cur_change = 16_7FFFFFFE %if lastchange # 0
    select input(0)
    file(main+1) = 0
    edi(file(main),file(main+1),rep);  !main+1 to keep editor happy
    rep = ""
    select output(listout)
    time1 = time1+cputime
    %signal abandon %if cur_flag < 0 {abandoned}
    control = control&(\editbit) %if cur_flag = 'I'
    lastchange = cur_change %and %signal redo %if cur_change < 16_7FFFFFFE
  %else
    print line
    select output(listout)
    time1 = time1+cputime
  %finish
%end;  !report

%routine FAULT(%integer n)
!Note fault number and position of (earliest) fault
! for subsequent reporting (warnings and weak errors)
  %if faultnum = 0 %or (n > 0 %and faultnum < 0) %start
    faultnum = n;  faultp = atomp
    report(faultnum&127,0,0) %if faultnum >= now
  %finish
%end

%routine INTERN(%integer n)
  report(internerr,0,n)
%end

!!!!!!!!!!!!!!!!!!!!   CELL  CONSTRUCTORS  !!!!!!!!!!!!!!!!!!!
!
%integer%fn LITREF(%integer v)
%integer i
  %result = v %if v = 0
  %if v > 0 %start
    %result = -(v<<1) %if v <= smallmax
  %else
    %result = v<<1+1 %if v >= smallmin
  %finish
  litstore(litpos) = v
  i = litmin-1
  i = i+1 %until litstore(i) = v
  %if i = litpos %start
    litpos = litpos+1
    croak("Too many literals") %if litpos >= litmax
  %finish
  %result = i
%end
!
%routine PUTEXP(%integer act,x,y,t)
  type = t
  item = explim
  item = x %if explo <= x < item
  item = y %if explo <= y < item
  %cycle
    item = item-1
    ditem == dict(item)
    %if item < explo %start
      explo = item
      ditem_act = act;  ditem_x = x;  ditem_y = y
      ditem_flags = 0;  ditem_type = t;  ditem_mode = 0
      %exit
    %finish
  %repeat %until ditem_act = act %and ditem_x = x %and ditem_y = y
%end

!$IF VAX
{%integer%fn IEEE(%integer v)
{  %result = 0 %if v = 0
{  %result = v<<16+v>>16-16_01000000
{%end
!$FINISH

%routine PUTEXP2(%integer op,first,t)
  %if item = 0 %start
!$IF VAX
{  value = ieee(value) %if type = realtype;  !vax->ieee
!$FINISH
    item = litref(value)
  %finish
  putexp(op,first,item,t)
%end

%integer%fn NORMITEM
  %result = item %if item # 0
!$IF VAX
{  value = ieee(value) %if type = realtype;  !vax->ieee
!$FINISH
  %result = litref(value)
%end

%routine TOREAL
  %if item # 0 %then putexp(float,item,0,realtype) %c
  %else real(addr(value)) = value %and type = realtype
%end

%integer%fn TEMP(%integer m,v)
  dtemp_mode = m;  dtemp_val = v
  %result = lablim
%end
%integer%fn TEMPX(%integer r1,r2)
  dtemp_mode = r1+(indexmode-a0);  dtemp_val = (r2-d0)<<12+16_0800
  %result = lablim
%end
%integer%fn TEMPD(%integer a,disp)
  dtemp_mode = a+(dispmode-a0);  dtemp_val = disp
  %result = lablim
%end
%integer%fn TEMPX2(%integer r1,r2)
  dtemp2_mode = r1+(indexmode-a0);  dtemp2_val = (r2-d0)<<12+16_0800
  %result = lablim+1
%end

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!    CODE  GENERATION   !!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
!  The array DEF contains packed mnemonics for M68000 machine
! instructions and, for each mnemonic, the basic opcode and
! a type indicator.
!  The type indicator contains flag bits for various special cases
! and two 6-bit fields defining the operand types
! [should be const record array]
!  The mnemonics and variant distinctions broadly follow the
!  manufacturer's Assembly Language conventions
!
! Opcode index values needed globally:-
%constinteger LEA=78, PEA=55, CLR=52, DBRA=81, JSR=56,
              LINK=72, UNLK=73, RTS=68,
              MOVEM=100, TRAPI=101, DC=102

!Machine-code operand types
![EA needs to be further distinguished]
%constinteger SHIFT=32
%constinteger REG=1, AREG=2, IREG=3, QUICK=4, MQUICK=5,
              EA=6, RWEA=7, WEA=8,
              IMM=9, TQUICK=10, REL=11, LONGREL=12,
              QREG=13, POSTAREG=14, QEA=15,
              REVEA=16, XIMM=17, DATA=18, PREAREG=19, QPRE=20,
              EXREG=21+shift
%constinteger REG9=reg+shift, QREG9=qreg+shift, IREG9=ireg+shift,
              POSTAREG9=postareg+shift,
              QUICK9=quick+shift, AREG9=areg+shift
%constinteger SIZED=1<<15, ASIZED=1<<14;  !2 spare bits
%constinteger REVERSIBLE=revea<<6+reg9+sized, MULTIPLE=ximm<<6+ea+asized
%constinteger DEFMAX=129
%constintegerarray DEF(0:defmax+defmax) =
  0,
 {MOVE} 16_0000<<16+ ea<<6+wea+shift +sized,
  'm'<<25+('o'&31)<<20+('v'&31)<<15+('e'&31)<<10,
 {ADD} 16_D000<<16+ reversible,
  'a'<<25+('d'&31)<<20+('d'&31)<<15,
 {SUB} 16_9000<<16+ reversible,
  's'<<25+('u'&31)<<20+('b'&31)<<15,
 {CMP} 16_B000<<16+ ea<<6+reg9 +sized,
  'c'<<25+('m'&31)<<20+('p'&31)<<15,
 {AND} 16_C000<<16+ reversible,
  'a'<<25+('n'&31)<<20+('d'&31)<<15,
 {OR} 16_8000<<16+ reversible,
  'o'<<25+('r'&31)<<20,
 {EOR} 16_B100<<16+ reg9<<6+rwea +sized,
  'e'<<25+('o'&31)<<20+('r'&31)<<15,
 {NOT} 16_4600<<16+ rwea +sized,
  'n'<<25+('o'&31)<<20+('t'&31)<<15,
 {NEG} 16_4400<<16+ rwea +sized,
  'n'<<25+('e'&31)<<20+('g'&31)<<15,
 {LSL} 16_E108<<16+ qreg9<<6+reg +sized,
  'l'<<25+('s'&31)<<20+('l'&31)<<15,
 {LSR} 16_E008<<16+ qreg9<<6+reg +sized,
  'l'<<25+('s'&31)<<20+('r'&31)<<15,
 {MULS} 16_C1C0<<16+ ea<<6+reg9,
  'm'<<25+('u'&31)<<20+('l'&31)<<15+('s'&31)<<10,
 {DIVS} 16_81C0<<16+ ea<<6+reg9,
  'd'<<25+('i'&31)<<20+('v'&31)<<15+('s'&31)<<10,
 {MULU} 16_C0C0<<16+ ea<<6+reg9,
  'm'<<25+('u'&31)<<20+('l'&31)<<15+('u'&31)<<10,
 {DIVU} 16_80C0<<16+ ea<<6+reg9,
  'd'<<25+('i'&31)<<20+('v'&31)<<15+('u'&31)<<10,
 {BRA} 16_6000<<16+ rel,
  'b'<<25+('r'&31)<<20+('a'&31)<<15,
 {BSR} 16_6100<<16+ rel,
  'b'<<25+('s'&31)<<20+('r'&31)<<15,
 {BHI} 16_6200<<16+ rel,
  'b'<<25+('h'&31)<<20+('i'&31)<<15,
 {BLS} 16_6300<<16+ rel,
  'b'<<25+('l'&31)<<20+('s'&31)<<15,
 {BCC} 16_6400<<16+ rel,
  'b'<<25+('c'&31)<<20+('c'&31)<<15,
 {BCS} 16_6500<<16+ rel,
  'b'<<25+('c'&31)<<20+('s'&31)<<15,
 {BNE} 16_6600<<16+ rel,
  'b'<<25+('n'&31)<<20+('e'&31)<<15,
 {BEQ} 16_6700<<16+ rel,
  'b'<<25+('e'&31)<<20+('q'&31)<<15,
 {BVC} 16_6800<<16+ rel,
  'b'<<25+('v'&31)<<20+('c'&31)<<15,
 {BVS} 16_6900<<16+ rel,
  'b'<<25+('v'&31)<<20+('s'&31)<<15,
 {BPL} 16_6A00<<16+ rel,
  'b'<<25+('p'&31)<<20+('l'&31)<<15,
 {BMI} 16_6B00<<16+ rel,
  'b'<<25+('m'&31)<<20+('i'&31)<<15,
 {BGE} 16_6C00<<16+ rel,
  'b'<<25+('g'&31)<<20+('e'&31)<<15,
 {BLT} 16_6D00<<16+ rel,
  'b'<<25+('l'&31)<<20+('t'&31)<<15,
 {BGT} 16_6E00<<16+ rel,
  'b'<<25+('g'&31)<<20+('t'&31)<<15,
 {BLE} 16_6F00<<16+ rel,
  'b'<<25+('l'&31)<<20+('e'&31)<<15,
 {ASL} 16_E100<<16+ qreg9<<6+reg +sized,
  'a'<<25+('s'&31)<<20+('l'&31)<<15,
 {ASR} 16_E000<<16+ qreg9<<6+reg +sized,
  'a'<<25+('s'&31)<<20+('r'&31)<<15,
 {ROL} 16_E118<<16+ qreg9<<6+reg +sized,
  'r'<<25+('o'&31)<<20+('l'&31)<<15,
 {ROR} 16_E018<<16+ qreg9<<6+reg +sized,
  'r'<<25+('o'&31)<<20+('r'&31)<<15,
 {MOVEQ} 16_7000<<16+ mquick<<6+reg9,
  'm'<<25+('o'&31)<<20+('v'&31)<<15+('e'&31)<<10+('q'&31)<<5,
 {ADDQ} 16_5000<<16+ quick9<<6+rwea +sized,
  'a'<<25+('d'&31)<<20+('d'&31)<<15+('q'&31)<<10,
 {SUBQ} 16_5100<<16+ quick9<<6+rwea +sized,
  's'<<25+('u'&31)<<20+('b'&31)<<15+('q'&31)<<10,
 {MOVEA} 16_3040<<16+ ea<<6+areg9 +asized,
  'm'<<25+('o'&31)<<20+('v'&31)<<15+('e'&31)<<10+('a'&31)<<5,
 {ADDA} 16_D0C0<<16+ ea<<6+areg9 +asized,
  'a'<<25+('d'&31)<<20+('d'&31)<<15+('a'&31)<<10,
 {SUBA} 16_90C0<<16+ ea<<6+areg9 +asized,
  's'<<25+('u'&31)<<20+('b'&31)<<15+('a'&31)<<10,
 {CMPA} 16_B0C0<<16+ ea<<6+areg9 +asized,
  'c'<<25+('m'&31)<<20+('p'&31)<<15+('a'&31)<<10,
 {CMPM} 16_B108<<16+ postareg<<6+postareg9,
  'c'<<25+('m'&31)<<20+('p'&31)<<15+('m'&31)<<10,
 {ADDI} 16_0600<<16+ imm<<6+rwea +sized,
  'a'<<25+('d'&31)<<20+('d'&31)<<15+('i'&31)<<10,
 {SUBI} 16_0400<<16+ imm<<6+rwea +sized,
  's'<<25+('u'&31)<<20+('b'&31)<<15+('i'&31)<<10,
 {CMPI} 16_0C00<<16+ imm<<6+ea +sized,
  'c'<<25+('m'&31)<<20+('p'&31)<<15+('i'&31)<<10,
 {ANDI} 16_0200<<16+ imm<<6+rwea +sized,
  'a'<<25+('n'&31)<<20+('d'&31)<<15+('i'&31)<<10,
 {ORI} 16_0000<<16+ imm<<6+rwea +sized,
  'o'<<25+('r'&31)<<20+('i'&31)<<15,
 {EORI} 16_0A00<<16+ imm<<6+rwea +sized,
  'e'<<25+('o'&31)<<20+('r'&31)<<15+('i'&31)<<10,
 {ROXL} 16_E110<<16+ qreg9<<6+reg +sized,
  'r'<<25+('o'&31)<<20+('x'&31)<<15+('l'&31)<<10,
 {ROXR} 16_E010<<16+ qreg9<<6+reg +sized,
  'r'<<25+('o'&31)<<20+('x'&31)<<15+('r'&31)<<10,
 {CLR} 16_4200<<16+ wea +sized,
  'c'<<25+('l'&31)<<20+('r'&31)<<15,
 {NEGX} 16_4000<<16+ rwea +sized,
  'n'<<25+('e'&31)<<20+('g'&31)<<15+('x'&31)<<10,
 {NBCD} 16_4800<<16+ rwea,
  'n'<<25+('b'&31)<<20+('c'&31)<<15+('d'&31)<<10,
 {PEA} 16_4840<<16+ ea,
  'p'<<25+('e'&31)<<20+('a'&31)<<15,
 {JSR} 16_4E80<<16+ ea,
  'j'<<25+('s'&31)<<20+('r'&31)<<15,
 {JMP} 16_4EC0<<16+ ea,
  'j'<<25+('m'&31)<<20+('p'&31)<<15,
 {TAS} 16_4AC0<<16+ rwea,
  't'<<25+('a'&31)<<20+('s'&31)<<15,
 {TST} 16_4A00<<16+ ea +sized,
  't'<<25+('s'&31)<<20+('t'&31)<<15,
 {ABCD} 16_C100<<16+ qpre<<6+reg9,
  'a'<<25+('b'&31)<<20+('c'&31)<<15+('d'&31)<<10,
 {SBCD} 16_8100<<16+ qpre<<6+reg9,
  's'<<25+('b'&31)<<20+('c'&31)<<15+('d'&31)<<10,
 {ADDX} 16_D100<<16+ qpre<<6+reg9 +sized,
  'a'<<25+('d'&31)<<20+('d'&31)<<15+('x'&31)<<10,
 {SUBX} 16_9100<<16+ qpre<<6+reg9 +sized,
  's'<<25+('u'&31)<<20+('b'&31)<<15+('x'&31)<<10,
 {NOP} 16_4E71<<16,
  'n'<<25+('o'&31)<<20+('p'&31)<<15,
 {RESET} 16_4E70<<16,
  'r'<<25+('e'&31)<<20+('s'&31)<<15+('e'&31)<<10+('t'&31)<<5,
 {RTE} 16_4E73<<16,
  'r'<<25+('t'&31)<<20+('e'&31)<<15,
 {RTR} 16_4E77<<16,
  'r'<<25+('t'&31)<<20+('r'&31)<<15,
 {RTS} 16_4E75<<16,
  'r'<<25+('t'&31)<<20+('s'&31)<<15,
 {STOP} 16_4E72<<16 +imm,
  's'<<25+('t'&31)<<20+('o'&31)<<15+('p'&31)<<10,
 {TRAPV} 16_4E76<<16,
  't'<<25+('r'&31)<<20+('a'&31)<<15+('p'&31)<<10+('v'&31)<<5,
 {TRAP} 16_4E40<<16+ tquick,
  't'<<25+('r'&31)<<20+('a'&31)<<15+('p'&31)<<10,
 {LINK} 16_4E50<<16+ imm<<6+areg,
  'l'<<25+('i'&31)<<20+('n'&31)<<15+('k'&31)<<10,
 {UNLK} 16_4E58<<16+ areg,
  'u'<<25+('n'&31)<<20+('l'&31)<<15+('k'&31)<<10,
 {SWAP} 16_4840<<16+ reg,
  's'<<25+('w'&31)<<20+('a'&31)<<15+('p'&31)<<10,
 {EXTW} 16_4880<<16+ reg,
  'e'<<25+('x'&31)<<20+('t'&31)<<15+('w'&31)<<10,
 {EXTL} 16_48C0<<16+ reg,
  'e'<<25+('x'&31)<<20+('t'&31)<<15+('l'&31)<<10,
 {EXG} 16_C140<<16+ exreg<<6+reg,
  'e'<<25+('x'&31)<<20+('g'&31)<<15,
 {LEA} 16_41C0<<16+ qea<<6+areg9,
  'l'<<25+('e'&31)<<20+('a'&31)<<15,
 {CHK} 16_4180<<16+ ea<<6+reg9,
  'c'<<25+('h'&31)<<20+('k'&31)<<15,
 {DBXX} 16_50C8<<16+ reg<<6+longrel,
  'd'<<25+('b'&31)<<20+('x'&31)<<15+('x'&31)<<10,
 {DBRA} 16_51C8<<16+ reg<<6+longrel,
  'd'<<25+('b'&31)<<20+('r'&31)<<15+('a'&31)<<10,
 {DBHI} 16_52C8<<16+ reg<<6+longrel,
  'd'<<25+('b'&31)<<20+('h'&31)<<15+('i'&31)<<10,
 {DBLS} 16_53C8<<16+ reg<<6+longrel,
  'd'<<25+('b'&31)<<20+('l'&31)<<15+('s'&31)<<10,
 {DBCC} 16_54C8<<16+ reg<<6+longrel,
  'd'<<25+('b'&31)<<20+('c'&31)<<15+('c'&31)<<10,
 {DBCS} 16_55C8<<16+ reg<<6+longrel,
  'd'<<25+('b'&31)<<20+('c'&31)<<15+('s'&31)<<10,
 {DBNE} 16_56C8<<16+ reg<<6+longrel,
  'd'<<25+('b'&31)<<20+('n'&31)<<15+('e'&31)<<10,
 {DBEQ} 16_57C8<<16+ reg<<6+longrel,
  'd'<<25+('b'&31)<<20+('e'&31)<<15+('q'&31)<<10,
 {DBVC} 16_58C8<<16+ reg<<6+longrel,
  'd'<<25+('b'&31)<<20+('v'&31)<<15+('c'&31)<<10,
 {DBVS} 16_59C8<<16+ reg<<6+longrel,
  'd'<<25+('b'&31)<<20+('v'&31)<<15+('s'&31)<<10,
 {DBPL} 16_5AC8<<16+ reg<<6+longrel,
  'd'<<25+('b'&31)<<20+('p'&31)<<15+('l'&31)<<10,
 {DBMI} 16_5BC8<<16+ reg<<6+longrel,
  'd'<<25+('b'&31)<<20+('m'&31)<<15+('i'&31)<<10,
 {DBGE} 16_5CC8<<16+ reg<<6+longrel,
  'd'<<25+('b'&31)<<20+('g'&31)<<15+('e'&31)<<10,
 {DBLT} 16_5DC8<<16+ reg<<6+longrel,
  'd'<<25+('b'&31)<<20+('l'&31)<<15+('t'&31)<<10,
 {DBGT} 16_5EC8<<16+ reg<<6+longrel,
  'd'<<25+('b'&31)<<20+('g'&31)<<15+('t'&31)<<10,
 {DBLE} 16_5FC8<<16+ reg<<6+longrel,
  'd'<<25+('b'&31)<<20+('l'&31)<<15+('e'&31)<<10,
 {BCHG} 16_0140<<16+ ireg9<<6+rwea,
  'b'<<25+('c'&31)<<20+('h'&31)<<15+('g'&31)<<10,
 {BCLR} 16_0180<<16+ ireg9<<6+wea,
  'b'<<25+('c'&31)<<20+('l'&31)<<15+('r'&31)<<10,
 {BSET} 16_01C0<<16+ ireg9<<6+wea,
  'b'<<25+('s'&31)<<20+('e'&31)<<15+('t'&31)<<10,
 {BTST} 16_0100<<16+ ireg9<<6+ea,
  'b'<<25+('t'&31)<<20+('s'&31)<<15+('t'&31)<<10,
 {MOVEM} 16_4880<<16+ multiple,
  'm'<<25+('o'&31)<<20+('v'&31)<<15+('e'&31)<<10+('m'&31)<<5,
 {TRAPI} 16_4E40<<16+ imm<<6+tquick,
  't'<<25+('r'&31)<<20+('a'&31)<<15+('p'&31)<<10+('i'&31)<<5,
 {DC}         data,
     'd'<<25+('c'&31)<<20,
 {ST} 16_50C0<<16+ wea,
  's'<<25+('t'&31)<<20,
 {SF} 16_51C0<<16+ wea,
  's'<<25+('f'&31)<<20,
 {SHI} 16_52C0<<16+ wea,
  's'<<25+('h'&31)<<20+('i'&31)<<15,
 {SLS} 16_53C0<<16+ wea,
  's'<<25+('l'&31)<<20+('s'&31)<<15,
 {SCC} 16_54C0<<16+ wea,
  's'<<25+('c'&31)<<20+('c'&31)<<15,
 {SCS} 16_55C0<<16+ wea,
  's'<<25+('c'&31)<<20+('s'&31)<<15,
 {SNE} 16_56C0<<16+ wea,
  's'<<25+('n'&31)<<20+('e'&31)<<15,
 {SEQ} 16_57C0<<16+ wea,
  's'<<25+('e'&31)<<20+('q'&31)<<15,
 {SVC} 16_58C0<<16+ wea,
  's'<<25+('v'&31)<<20+('c'&31)<<15,
 {SVS} 16_59C0<<16+ wea,
  's'<<25+('v'&31)<<20+('s'&31)<<15,
 {SPL} 16_5AC0<<16+ wea,
  's'<<25+('p'&31)<<20+('l'&31)<<15,
 {SMI} 16_5BC0<<16+ wea,
  's'<<25+('m'&31)<<20+('i'&31)<<15,
 {SGE} 16_5CC0<<16+ wea,
  's'<<25+('g'&31)<<20+('e'&31)<<15,
 {SLT} 16_5DC0<<16+ wea,
  's'<<25+('l'&31)<<20+('t'&31)<<15,
 {SGT} 16_5EC0<<16+ wea,
  's'<<25+('g'&31)<<20+('t'&31)<<15,
 {SLE} 16_5FC0<<16+ wea,
  's'<<25+('l'&31)<<20+('e'&31)<<15,
 {MTCCR} 16_44C0<<16+ ea<<6,
  'm'<<25+('t'&31)<<20+('c'&31)<<15+('c'&31)<<10+('r'&31)<<5,
 {MTSR} 16_46C0<<16+ ea<<6,
  'm'<<25+('t'&31)<<20+('s'&31)<<15+('r'&31)<<10,
 {MFSR} 16_40C0<<16+ wea,
  'm'<<25+('f'&31)<<20+('s'&31)<<15+('r'&31)<<10,
 {MTUSP} 16_4E60<<16+ areg,
  'm'<<25+('t'&31)<<20+('u'&31)<<15+('s'&31)<<10+('p'&31)<<5,
 {MFUSP} 16_4E68<<16+ areg,
  'm'<<25+('f'&31)<<20+('u'&31)<<15+('s'&31)<<10+('p'&31)<<5,
 {ATCCR} 16_023C<<16+ imm,
  'a'<<25+('t'&31)<<20+('c'&31)<<15+('c'&31)<<10+('r'&31)<<5,
 {ATSR} 16_027C<<16+ imm,
  'a'<<25+('t'&31)<<20+('s'&31)<<15+('r'&31)<<10,
 {ETCCR} 16_0A3C<<16+ imm,
  'e'<<25+('t'&31)<<20+('c'&31)<<15+('c'&31)<<10+('r'&31)<<5,
 {ETSR} 16_0A7C<<16+ imm,
  'e'<<25+('t'&31)<<20+('s'&31)<<15+('r'&31)<<10,
 {OTCCR} 16_003C<<16+ imm,
  'o'<<25+('t'&31)<<20+('c'&31)<<15+('c'&31)<<10+('r'&31)<<5,
 {OTSR} 16_007C<<16+ imm,
  'o'<<25+('t'&31)<<20+('s'&31)<<15+('r'&31)<<10

{?}%routine PUT OPCODE(%integer op)
{?}  put mnemonic(def(op+op))
{?}%end

%routine STORE(%integer v,f)
!$IF VAX
{  v = v&16_FFFF;  v = v!sign16 %if v&sign16 # 0
!$FINISH
  prog(pc) <- v;  pflag(pc) = f;  pc = pc+1
%end

%routine MAKE ROOM(%integer size)
%integer newbase,newlim
  size = (size+127)&(\127)
  ownbase = ownbase-size
  croak("Program too big") %if ownbase <= cad
  newbase = ownbase;  newlim = newbase+ownad
  %cycle
    final(newbase) = final(newbase+size)
    newbase = newbase+1
  %repeat %until newbase >= newlim
%end

%routine FILL CODE(%integer n)
%integer i
  i = cad;  cad = cad+n
  %while n > 0 %cycle
    final(i) = 16_80;  i = i+1;  n = n-1
  %repeat
%end
%routine FILL OWN(%integer n)
%integer i
  make room(n)
  i = ownbase+ownad;  ownad = ownad+n
  %while n > 0 %cycle
    final(i) = 16_80;  i = i+1;  n = n-1
  %repeat
%end

%routine SET CODE WORD(%integer v)
!$IF VAX (works irrespective of host byte sex)
{  final(cad) <- v>>8;  final(cad+1) <- v
!$IF APM (for efficiency)
  shortinteger(final0+cad) <- v
!$FINISH
  cad = cad+2
%end

%integer%fn CODE WORD(%integer cad)
!$IF VAX (works irrespective of host byte sex)
{  %result = final(cad)<<8+final(cad+1)
!$IF APM (for efficiency)
  %result = shortinteger(final0+cad)
!$FINISH
%end

%routine SET CODE LONGWORD(%integer v)
  set code word(v>>16);  set code word(v)
%end

%routine SET OWN WORD(%integer v)
  make room(2) %if ownbase+ownad > finalbound
!$IF VAX
{  final(ownbase+ownad) <- v>>8;  final(ownbase+ownad+1) <- v
!$IF APM
  shortinteger(final0+ownbase+ownad) <- v
!$FINISH
  ownad = ownad+2
%end

%routine EXTEND STACK(%integer delta)
  c_sp = c_sp-delta
  %if c_sp < c_stack %start
    c_stack = c_sp
    c_totstack = c_stack %if c_stack < c_totstack
  %finish
%end

%routine PLANT(%integer op,y,x)
!Basic code planting procedure
! OP is an index to the array defining op-codes
!  (it can be flagged to force SIZE)
! For unary operations the operand is given by X (Y zero)
! For binary operations the operands are Y (source) and X (dest)
%integer OPCODE,PC1,I,F,EXTWORD,INFO,KIND,MODE,MODEX,SIZE
%record(identinfo)%name DX,DY
%switch S(0:21)
%constbytearray SIZESYM(0:3) = 'L','B','W','?'

%integer%fn NONLOCAL(%integer l)
%integer r
  %result = mb %if l = outerlevel
  hold(l)_status = hold(l)_status!globbed %if l # level
  %result = f1 %if l = outerlevel+1
  r = maxareg
  %cycle
    %result = r %if c_reg_content(r) = d7+l;  ![unique]
    r = r-1
  %repeat %until r < a0
![not good enough: 1. may need two
!                  2. FREE updated elsewhere without regard to this]
  r = maxareg
  %while a0b<<(r-a0)&free = 0 %cycle
    fault(plexerr) %and %exit %if r = a0
    r = r-1
  %repeat
  c_reg_content(r) = d7+l
  dtsprel_mode = globalmode;  dtsprel_val = l<<2
  plant(move,lablim+2,r)
  %result = r
%end

%constinteger MOVEQ=36, ADDQ=37, MOVEA=39,
              ADDA=40, ADDI=44

  %if x > 0 %start
    intern(1) %and %return %if x >= explim
    dx == dict(x)
    modex = dx_mode
    %if modex >= framemode %and modex # c_mode %c
    %and modex&2_111000 # 2_111000 %start
      modex = nonlocal(modex&7)-a0+(modex&(7<<3))
    %finish
  %finish %else modex = litmode %and dx == dint
  %if y > 0 %start
    intern(1) %and %return %if y >= explim
    dy == dict(y)
    mode = dy_mode
    %if mode >= framemode %and mode # c_mode %c
    %and mode&2_111000 # 2_111000 %start
      mode = nonlocal(mode&7)-a0+(mode&(7<<3))
    %finish
  %finish %else mode = litmode %and dy == dint
  size = op>>8;  op = op&255
  %if op = move %start
    %if modex&2_111000 = 0 %start;  !D
      op = moveq %if y <= 0 %and y >= litmite %and size&3 = 0
    %else %if modex&2_110000 = 0;   !A
      op = movea
    %finish
  %else %if op <= cmp
    %if op < cmp %and y < 0 %and y >= litquick %and y&1 = 0 %c
    %then op=op+(addq-add) {ADDQ,SUBQ} %c
    %else %if modex&2_111000 = aregmode %c
    %then op=op+(adda-add) {ADDA,SUBA,CMPA} %c
    %else %if y <= 0 %c
    %then op=op+(addi-add) {ADDI,SUBI,CMPI}
  %else %if op <= eor
    op = op+(addi-add) %if y <= 0 {ANDI,ORI,EORI}
  %finish
  info = def(op+op-1)
  opcode = info>>16
  %if info&sized # 0 %start;  !data size required
    size = 4 %if size = 0
    %if op = move %start
      %if size = 4 %then opcode = opcode+16_2000 %c
      %else %if size = 2 %then opcode = opcode+16_3000 %c
      %else opcode = opcode+16_1000
    %else
      %if size = 4 %then opcode = opcode+16_80 %c
      %else %if size = 2 %then opcode = opcode+16_40
    %finish
  %else %if info&asized # 0;  !areg size required
    fault(sizerr) %if size = 1
    %if op # movem %start
      %if size = 0 %start
        size = 4 %unless y <= 0 %and is short(litval(y))
      %finish
      %if size = 4 %start
        %if op = movea %then opcode = opcode!!16_1000 %c
        %else opcode = opcode+16_0100
      %finish
    %else;  !MOVEM
      size = 4 %if size = 0
      opcode = opcode+16_0040 %if size = 4
    %finish
  %finish
{?}  %if control&codelist # 0 %and control&list # 0 %start
{?}    print line %if length(rep) >= 4
{?}    put sym(codeflag);  spaces(4-length(rep))
{?}    put opcode(op)
{?}    %if size # 0 %start
{?}      put sym('.')
{?}      put sym(sizesym(size&3))
{?}    %finish
{?}    spaces(12-length(rep))
{?}    %if info&(63<<6) # 0 %start
{?}      put operand(y)
{?}      put sym(',') %if info&63 # 0
{?}    %finish
{?}    put operand(x) %if info&63 # 0
{?}    spaces(33-length(rep));  put sym(':')
{?}  %finish

  pc1 = pc;  pflag(pc1) = c_shorts;  !op-code word
  pc = pc+1
  croak("Code space exhausted") %if pc >= swpc-8
  kind = info>>6
again:
  ->s(kind&31)
s(0):
next:
  kind = info
  %if kind # 0 %start
    dy == dx;  y = x;  mode = modex
    info = 0
    ->again
  %finish
!
!$IF VAX
{  opcode = opcode!sign16 %if opcode&sign16 # 0
!$FINISH
  prog(pc1) <- opcode
{?}  %if control&codelist # 0 %and control&list # 0 %start
{?}    %cycle
{?}      put sym(' ')
{?}      put hex(prog(pc1))
{?}      pc1 = pc1+1
{?}    %repeat %until pc1 >= pc
{?}    print line
{?}  %finish
  %return

!Set flag value for PC-relative reference
! distinguishing GLOBAL (const access), INDIRECT GLOBAL (procedure),
! and LOCAL (label) -- the last further distinguished according to
! whether the instruction permits shortening
%routine PCREL(%integer shorten)
  %if dy_mode = labmode %start
    f = jump;  f = longjump %if shorten = 0
    %if extword > 0 %start;  !label defined
      %if shorten # 0 %and (extword-pflag(extword)-pc+c_shorts)<<1 >= -128 %start
        %if c_shorts = 255 %start
          zaps = zaps+100
        %else
          shorts = shorts+1;  c_shorts = c_shorts+1
          f = shortjump
        %finish
      %finish
    %else
      extword = -extword
      dy_val = -pc
    %finish
  %else %if dy_mode = procmode;  !procedure
    f = indglobal;  extword = y;  !rather than DY_VAL
  %else %if dy_mode = constmode;  !constant data ref
    f = global
    f = f+1 %if extword < 0
    f = f+2 %if extword > 65535
  %else %if dy_mode # pcmode
    fault(moperr)
  %finish
%end

s(qea):  !LEA
  -> ea0 %unless mode&63 = x-(a0-indexmode) %and dy_val&255 = 0
  !  LEA 0(Ax,Dy)  =>  ADDA Dy,Ax
  opcode = 16_D1C0+dy_val>>12&15
  -> next

s(wea):
  dy_flags = dy_flags!(mflag!wflag)
  -> wea1
s(rwea):  ![for our purposes, read&write counts as neither]
  dy_flags = dy_flags!mflag
wea1:
  -> err %if y <= 0 %or mode&63 >= pcmode
  -> ea1
s(revea):  !reversible cases (EA,REG or REG,EA)
  %if modex&2_111000 # 0 %start;  !dest not D
    kind = shift;  info = rwea
    opcode = opcode!!16_0100
    ->sreg
  %finish
s(ea): ea0:
  %if y <= 0 %start
    opcode = opcode+litmode;  !immediate
    ->simm
  %finish
  %if dy_flags&(ext+spec+rflag+wflag) = ext+spec %c
  %and dy_flags&proc # 0 %start
    ! Create transfer vector for external procedure
    fill own(1) %if ownad&1 # 0
    dy_val = ownad
    set own word(16_207C+(mb-a0)<<9);  !MOVE.L #xxxxxxxx,MB
    set own word(0);  set own word(0)
    set own word(16_4EF9);  !JMP xxxxxxxx
    set own word(0);  set own word(0)
  %finish
  %if (op = lea %or op = pea) %and mode&63 # pcmode %start
    !taking address: might read or write
    dy_flags = dy_flags!(mflag+rflag+wflag)
    ->err %if mode&2_111000 < aregmode+indir
  %else
    dy_flags = dy_flags!(mflag+rflag)
  %finish
ea1:
  extword = dy_val
  %if mode = c_mode %start;  !local
    mode = dispmode+7;  extword = extword-c_sp;  !convert to use SP
    %if extword < 0 %start
      intern(4) %if extword < -4
      mode = aregmode+pre+7
      extend stack(-extword)
      extword = 0
    %finish
  %finish
  mode = mode&63;   !strip extra flags
  %if mode >= dispmode %start;  !+extra
    f = 0
    %if mode = pcmode %start
      pcrel(0)
    %finish
    %if mode <= dispmode+7 %start
      %if extword = 0 %start
        ! Premode (just created) or Dispmode (=>Indmode)
        mode = mode+(aregmode+indir-dispmode) %if mode >= dispmode
      %else
        fault(dreacherr) %unless -32768 <= extword <= 32767
        store(extword,f)
      %finish
    %else
      mode = absmode+1 %if mode = absmode %and %not is short(extword)
      store(extword>>16,0) %if mode = absmode+1
      store(extword,f)
    %finish
  %finish
  mode = ((mode&7)<<3 + mode>>3)<<6 %if kind&shift # 0
  opcode = opcode+mode
  ->next

s(exreg&31):  !EXG (D,D / A,A / D,A)
  %if mode&2_111000 = 0 %start;  !D
    %if modex&2_111000 # 0 %start;  !not D
      opcode = opcode!!16_C8;  info = areg
    %finish
    -> sreg
  %finish
  opcode = opcode+8;  info = areg
  -> sareg
s(qpre):
  -> sreg %if mode&2_111000 = 0;  !D
  opcode = opcode+8;  info = preareg+shift
s(preareg):
  mode = mode+(post-pre)
s(postareg):
  mode = mode-post
s(areg): sareg:
  mode = mode-8
s(reg): sreg:
  -> err %unless mode&2_111000 = 0
  mode = mode&7
  mode = mode<<9 %if kind&shift # 0
  opcode = opcode+mode
  ->next

s(qreg):  !Shift formats -- quick,Dx / Dy,Dx / 1,<ea> (W)
  opcode = opcode+16_20 %and ->sreg %if y > 0
  %if y = one %and size = 2 %and modex&2_111000 # 0 %start
    opcode = opcode!!16_290
    ->next
     %finish
s(quick):
  -> err %if y >= 0
  y = litval(y)
  ->err %unless y <= 8
  opcode = opcode+(y&7)<<9;  !(always aligned to bit9)
  ->next

s(tquick):  !(TRAP)
  -> err %unless -30 <= y %and y&1 = 0;  !{0<=}litval(y)<=15
s(mquick):
  ->err %unless y <= 0 %and y >= litmite
  y = litval(y)
  opcode = opcode+y&255
  ->next
s(rel):
  ->s(mquick) %if y <= 0 %and y >= litmite
s(longrel):
  ->simm %if y <= 0
  dy_flags = dy_flags!rflag
  extword = dy_val
  f = 0
  pcrel(longrel-kind&31)
  store(extword,f)
  ->next

s(ireg):  !immediate or reg
  ->sreg %if y > 0
  opcode = opcode!!16_900
s(imm):
  ->err %if y > 0
simm:
  y = litval(y)
  store(y>>16,0) %if size = 4
put:
  store(y,0)
  ->next
s(ximm):  !MOVEM (IMM,EA or EA,IMM)
  %if y > 0 %start;  !EA,IMM
    opcode = opcode!!16_0400
    i = x;  x = y;  y = i
    dx == dy;  modex = mode
  %finish
  y = litval(y)
  %if prea0 <= x <= prea7 %start;  !-(SP)
    i = 0;  !Reverse bits
    i = i<<1+y&1 %and y = y>>1 %for extword = 1,1,16
    y = i
  %finish
  ->put
s(data):
  -> err %if y <= 0
  -> err %if mode # absmode
  opcode = dy_val
  ->next
err:
  fault(moperr)
  ->next
%end;  !plant

%routine PLANTLIT(%integer op,v,x)
  %if v >= 0 %start
    %if v > smallmax %then litstore(litmax) = v %and v = litmax %c
    %else v = -(v<<1)
  %else
    %if v < smallmin %then litstore(litmax) = v %and v = litmax %c
    %else v = v<<1+1
  %finish
  plant(op,v,x)
%end

%routine PLANTLIT2(%integer op,y,v)
  %if v >= 0 %start
    %if v > smallmax %then litstore(litmax) = v %and v = litmax %c
    %else v = -(v<<1)
  %else
    %if v < smallmin %then litstore(litmax) = v %and v = litmax %c
    %else v = v<<1+1
  %finish
  plant(op,y,v)
%end

%routine ALIGN(%integername AD, %integer size)
!Impose alignment requirements on address AD for
! operand of length SIZE
!provisional basis for bit addressing
! -- multiples of 16 on Word boundary
! -- multiples of 8 on Byte boundary
! -- other < 32 within one Longword
!%constinteger BITMASK=16_E0000000
!  %if size&7 = 0 %start
!    ad = (ad&(\bitmask))+1 %if ad&bitmask # 0;  !ensure on byte boundary
!    %return %if size&8 # 0
!  %else
!    %return %if size < 16
!    %return %if ad>>29+(ad&1)<<3+size <= 32
!    ad = (ad&(\bitmask))+1 %if ad&bitmask # 0
!  %finish
  ad = ad+1 %if size # 1 %and ad&1 # 0
%end

%routine ADDIMM(%integer bytes,dest)
  %if bytes <= 0 %start
    %return %if bytes = 0
    %if bytes >= -8 %start
      plantlit(sub,-bytes,dest)
      %return
    %finish
  %else %if bytes <= 8
    plantlit(add,bytes,dest)
    %return
  %finish
  %if a0 <= dest <= a7 %and is short(bytes) %start
    plant(lea,tempd(dest,bytes),dest)
    %return
  %finish
  plantlit(add,bytes,dest)
%end

%integer%fn FREE REG(%integer rset)
%integer r,r1
  r = d0;  rset = rset&free
  %if rset = 0 %then fault(plexerr) %else %start
    r = r+1 %and rset = rset>>1 %while rset&1 = 0
    r1 = r
    %while c_reg_content(r) # undef %cycle
      r = r+1;  rset = rset>>1
      r = r1 %and %exit %if rset = 0
      r = r+1 %and rset = rset>>1 %while rset&1 = 0
    %repeat
    free = free-d0b<<(r-d0)
  %finish
  %result = r
%end

%routine MOVE BLOCK(%integer source,dest,bytes)
!Generate code to move a fixed number of bytes
! from SOURCE (0,reg,pre,post) to DEST (pre,post)
! -- source & dest addresses both even if BYTES even
%integer op,f,r,pc1
  op = move;  op = clr %if source = 0
  %if bytes <= 16 %and bytes&1 = 0 %start
    plant(op,source,dest) %and bytes = bytes-4 %while bytes >= 4
    plant(op+2<<8,source,dest) %if bytes >= 2
  %else;  !use loop
    op = op+1<<8
    %if bytes&1 = 0 %start
      bytes = bytes>>1;  op = op+1<<8;  !.B -> .W
      %if bytes&1 = 0 %start
        bytes = bytes>>1;  op = op+2<<8;  !.W -> .L
      %finish
    %finish
    f = free
    %if bytes <= 32768 %and free&anydreg # 0 %start
      r = free reg(anydreg)
      plantlit(move,bytes-1,r)
      pc1 = pc
      plant(op,source,dest)
      plantlit2(dbra,r,(pc1-pc-1)<<1)
      bytes = undef
    %else
      r = free reg(anydreg!bregb)
      plantlit(move,bytes,r)
      pc1 = pc
      plant(op,source,dest)
      plant(sub,one,r)
      plantlit2(bne,0,(pc1-pc-1)<<1)
      bytes = 0
    %finish
    c_reg_content(r) = bytes;  free = f
  %finish
%end

%routine UPDATE SP
  %return %if c_val = 0
  %if c_val < 0 %start
    addimm(-c_val,a7);  c_sp = c_sp-c_val
  %else
    %if control&assmask = 0 %then addimm(-c_val,a7) {no unass check} %c
    %else move block(d7,prea7,c_val)
    extend stack(c_val)
  %finish
  c_val = 0
%end

%routine GET BOUNDS(%integer t,%integername lo,hi)
![Note: sets HI after LO -- see dummy params in VALOK]
%record(identinfo)%name tp==typecell(t)
  %if tp_type = t # inttype %start;  !basetype
    lo = 0;  hi = tp_size
  %else
    %if tp[1]_mode # litmode %then lo = minint %c
    %else lo = tp[1]_val
    %if tp[2]_mode # litmode %then hi = maxint %c
    %else hi = tp[2]_val
  %finish
%end

%integer%fn SIZE(%integer t)
!Storage size for given object type in bytes
! > 0 for operand passable in register
! < 0 otherwise
%integer s,ss,lo,hi
%record(identinfo)%name tp
  tp == dict(t)
  %if tp_flags&nonord = 0 %start
    %result = tp_size %if tp_type # t;  !subrange
    %result = 4 %if tp_type = inttype
    %result = 1 %if tp_size <= 255
    %result = 2
  %finish
  %result = tp_val %if tp_flags&cat = recy
  %result = tp_size %if tp_flags&cat # arry
  %result = 0 %if tp_mode >= framemode;  !dynamic bounds
  s = 4;  s = size(tp_type) %if tp_flags >= 0
  get bounds(tp_xtype,lo,hi)
  %result = 0 %if lo = minint %or hi = maxint
  ss = (hi-lo+1)*s
  %result = ss %if ss <= 0
  %if s = 1 %start;  !byte element size (not nec aligned)
    %result = ss %if ss = 1
  %else;  !word,long element size (aligned)
    %result = ss %if ss <= 4
  %finish
  %result = -ss
%end

%integer%fn NSIZE(%record(identinfo)%name dp)
  %result = 4 %if dp_flags&(name+indirect) # 0
  %result = 0 %if dp_flags&proc # 0;       ![??]
  %result = size(dp_type)
%end

%integer%fn TSIZE(%integer t)
  %result = size(dict(t)_type)
%end

%routine FORGET(%integer r)
  c_reg_content(r) = undef
%end
%routine FORGET CC
  c_reg_ccy = undef
%end
%routine FORGET REGS
%shortname cc==c_reg_content(maxareg)
  %cycle
    cc = undef
    %exit %if cc == c_reg_content(d0)
    cc == cc[-1]
  %repeat
  c_reg_ccy = undef;  c_reg_line = -9
%end
%routine FORGET TRIPLES
  litpos = litmin;  explo = explim;  oldexplo = explim
%end
%routine FORGET ALL
%integer i,j
%record(contentinfo)%name lr
  forget regs
  j = dictlim
  %cycle
    j = j+1
    %exit %if j >= curlab
    lr == lreg(j-dictlim)
    lr_content(i) = undef %for i = d0,1,maxareg
    lr_ccx = undef
  %repeat
  forget triples
%end

%routine DEFINE JUMPS(%integer chain)
%integer i,j,k
  chain = -chain
  %return %if chain <= 0;  !no jumps to this label
  c_forward = c_forward-1;  c_access = 1
  %cycle
    i = prog(chain)
    %if pflag(chain) = jump %start;  !shortenable
      j = chain-pflag(chain-1);  !adjusted jump position
      k = (pc-c_shorts-j)<<1;  !displacement
      %if k > 2 %and k <= 127 %start
        %if c_shorts = 255 %start
          zaps = zaps+100
        %else
          c_shorts = c_shorts+1;  shorts = shorts+1
          pflag(chain) = shortjump
          j = chain
          %cycle
            pflag(j) = pflag(j)+1 %if pflag(j) >= zeroshorts
            j = j+1
          %repeat %until j = pc
        %finish
      %finish
    %finish
    prog(chain) = pc
    chain = i
  %repeat %until chain <= 0
%end

%routine SAVE CONTEXT(%integer l)
!Store register content associated with label L
! (prior to generating forward branch)
%integer r
%record(contentinfo)%name lr
  %return %if l-dictlim < 0    {user label}
  lr == lreg(l-dictlim)
  %if dict(l)_val >= 0 %start;  !first jump to this label
    dict(l)_val = 0
    lr = c_reg
    c_forward = c_forward+1
  %else
    %for r = d0,1,maxareg %cycle
      lr_content(r) = undef %if lr_content(r) # c_reg_content(r)
    %repeat
    lr_ccy = undef %if lr_ccx # c_reg_ccx %or lr_ccy # c_reg_ccy
    lr_line = -9 %if lr_line # c_reg_line
  %finish
%end

%routine SRCALL(%integer x)
%routine PUT PRIM(%record(identinfo)%name DX)
!<<IMP
!* PRIMGEN marker 3
%const%short%array PRIMCODE(1:396) <- 
16_1541,16_7272,16_6179,16_2062,16_6F75,16_6E64,16_7320,16_6578,
16_6365,16_6564,16_6564,16_B098,16_6E06,16_9098,16_6C10,16_D0A0,
16_41FA,16_FFDE,16_2400,16_7202,16_7076,16_4EF8,16_3EFA,16_4A58,
16_660C,16_4840,16_4A40,16_6610,16_4840,16_C0D8,16_4E75,
16_2F01,16_2200,16_C2E8,16_FFFE,16_6008,16_2F01,16_2200,16_4840,
16_C2D0,16_4841,16_C0D8,16_D081,16_221F,16_4E75,
16_1355,16_6E61,16_7373,16_6967,16_6E65,16_6420,16_7661,16_7269,
16_6162,16_6C65,16_660C,16_41FA,16_FFE8,16_7201,16_7058,16_4EF8,
16_3EFA,16_4E75,
16_0F49,16_6E76,16_616C,16_6964,16_2061,16_6464,16_7265,16_7373,
16_6E0C,16_41FA,16_FFEC,16_7201,16_7058,16_4EF8,16_3EFA,16_4E75,
16_1553,16_7461,16_636B,16_2073,16_7061,16_6365,16_2065,16_7868,
16_6175,16_7374,16_6564,16_D88F,16_B886,16_6C0E,16_4284,16_41FA,
16_FFE0,16_7203,16_7055,16_4EF8,16_3EFA,16_4284,16_4E75,
16_1741,16_7272,16_6179,16_2062,16_6F75,16_6E64,16_7320,16_696E,
16_7369,16_6465,16_206F,16_7574,16_9282,16_6F0C,16_41FA,16_FFE2,
16_7203,16_7055,16_4EF8,16_3EFA,16_4481,16_5281,16_4EF8,16_3EF4,
16_4E75,
16_0E53,16_7472,16_696E,16_6720,16_746F,16_6F20,16_6269,16_6780,
16_1811,16_9004,16_6504,16_9010,16_640C,16_41FA,16_FFE4,16_7203,
16_7051,16_4EF8,16_3EFA,16_1018,16_670C,16_D111,16_1398,16_4801,
16_5204,16_5300,16_66F6,16_2049,16_4E75,
16_3F00,16_7001,16_1E80,16_204F,16_548F,16_4E75,
16_124E,16_6F20,16_7370,16_6163,16_6520,16_666F,16_7220,16_6172,
16_7261,16_7980,16_5680,16_E480,16_E588,16_6D08,16_204F,16_91C0,
16_B1C6,16_6C0E,16_2400,16_41FA,16_FFD8,16_7201,16_7072,16_4EF8,
16_3EFA,16_205F,16_E488,16_6004,16_4840,16_2F07,16_51C8,16_FFFC,
16_4840,16_51C8,16_FFF4,16_4ED0,16_4E75,
16_1149,16_6E76,16_616C,16_6964,16_2025,16_666F,16_7220,16_6C6F,
16_6F70,16_2F00,16_9082,16_6720,16_2F01,16_6708,16_4EB8,16_3EEE,
16_4A80,16_6D0E,16_508F,16_41FA,16_FFD8,16_7201,16_7055,16_4EF8,
16_3EFA,16_4A81,16_66EE,16_221F,16_201F,16_4E75,
16_0C4F,16_7574,16_206F,16_6620,16_7261,16_6E67,16_6580,16_41FA,
16_FFF0,16_7201,16_7056,16_4EF8,16_3EFA,16_4E75,
16_1355,16_6E61,16_7373,16_6967,16_6E65,16_6420,16_7661,16_7269,
16_6162,16_6C65,16_B0FC,16_0000,16_6F1A,16_B2FC,16_0000,16_6F14,
16_BE10,16_6606,16_BE28,16_0001,16_670A,16_BE11,16_6612,16_BE29,
16_0001,16_660C,16_41FA,16_FFCA,16_7202,16_7054,16_4EF8,16_3EFA,
16_48E7,16_C0C0,16_4240,16_1018,16_6730,16_4241,16_1219,16_6722,
16_5380,16_5381,16_B041,16_6E12,16_9240,16_B109,16_56C8,16_FFFC,
16_6602,16_4441,16_4CDF,16_0303,16_4E75,
16_B109,16_56C9,16_FFFC,16_66F2,16_7201,16_4CDF,16_0303,16_4E75,
16_1011,16_4440,16_4CDF,16_0303,16_4E75,
16_0E53,16_7472,16_696E,16_6720,16_746F,16_6F20,16_6269,16_6780,
16_B010,16_640C,16_41FA,16_FFEA,16_7203,16_7051,16_4EF8,16_3EFA,
16_4280,16_1010,16_12D8,16_51C8,16_FFFC,16_4E75,
16_0E53,16_7472,16_696E,16_6720,16_746F,16_6F20,16_6269,16_6780,
16_B010,16_640C,16_41FA,16_FFEA,16_7201,16_7056,16_4EF8,16_3EFA,
16_0240,16_00FE,16_245F,16_9EC0,16_558F,16_224F,16_BFC8,16_6E0E,
16_1010,16_12D8,16_51C8,16_FFFC,16_204F,16_224F,16_4ED2,16_1018,
16_5289,16_D0C0,16_D2C0,16_1320,16_51C8,16_FFFC,16_204F,16_224F,
16_4ED2,16_4E75,
16_43EF,16_FF00,16_2448,16_D5C0,16_2049,16_9280,16_6C04,16_4211,
16_4E75,
16_1281,16_5219,16_12DA,16_51C9,16_FFFC,16_4E75,
16_700A,16_4EF8,16_3E70,16_4E75,
16_7020,16_4EF8,16_3E70,16_4E75

!<<BOTH
%integer start,limit
%record(identinfo)%name DDX
  fill code(1) %if cad&1 # 0
  start = dx_val>>16&511;  limit = start+dx_val&255
  dx_val = cad+dx_val>>7&(255<<1);  !entry
  dx_mode = procmode
  %if start = limit %start;  !range check
    ddx == dict(check)
    put prim(ddx) %and dx_val = cad %if ddx_mode = absmode
    set code word(16_0C80);  !CMPI.L #?,D0
    set code longword(dx[1]_val);  !lower
    set code word(16_6D00);  !BLT
    set code word(ddx_val-cad)
    set code word(16_0C80);  !CMPI.L #?,D0
    set code longword(dx[2]_val);  !upper
    set code word(16_6E00);  !BGT
    set code word(ddx_val-cad)
    set code word(16_4E75);  !RTS
  %else
    set code word(primcode(start)) %and start=start+1 %until start >= limit
  %finish
%end

%record(identinfo)%name dx==dict(x),tp==typecell(dx_type)
  %if dx_mode = absmode %and dx_val < 0 %start;  !prim routine
   ![**for now**: the convention is inadequate because excludes abs neg]
    put prim(dx)
  %else
    c_status = c_status!unknown %if tp_val <= 0
    c_totstack = c_sp-|tp_val| %if c_sp-|tp_val| < c_totstack
  %finish
  %if dx_mode&63 = pcmode %start;  !internal
    c_forward = c_forward+1 %if dx_flags&spec # 0 %and dx_flags&rflag = 0
    plant(bsr,0,x)
  %else %if dx_flags&(name+indirect) = 0 %or dx_flags&ext # 0 {temp}
    plant(jsr,0,x)
  %else %if free&a0b<<3 # 0
    plant(move,x,a0+3)
    plant(jsr,0,a0+3+indir)
    forget(a0+3)
  %else
    plant(move,x,tempd(a7,-4))
    plantlit(move,16_4EF9,tempd(a7,-6))
    plant(jsr,0,lablim)
  %finish
%end;  !srcall
!
%routine DEFINE LABEL(%integer lab)
%integer r,chain
%record(contentinfo)%name lr
  chain = dict(lab)_val
  %if chain >= 0 %start;  !label before jumps
    update sp
    forget regs
  %else
    lr == lreg(lab-dictlim)
    %if c_access = 0 %start;  !no fall-through
      c_reg = lr;  !so just incoming context
    %else;  !join
      %for r = d0,1,maxareg %cycle
        forget(r) %if c_reg_content(r) # lr_content(r)
      %repeat
      forget cc %if c_reg_ccx # lr_ccx %or c_reg_ccy # lr_ccy
      c_reg_line = -9 %if lr_line # c_reg_line
    %finish
  %finish
  define jumps(chain)
  dict(lab)_val = pc
{?}  put operand(lab) %if control&codelist # 0 %and control&list # 0
%end;  !define label

%routine SET USER LABEL(%integername chain)
  update sp
  addimm(c_temps,a7) %if c_temps # 0 %and c_access # 0  {remove temps}
  define jumps(chain)
  chain = pc
  c_access = 1;  !anyway
  addimm(-c_temps,a7) %if c_temps # 0  {restore temps}
  forget regs
  forget triples %if curlab = c_lab1
%end

%routine FLUSH
  %if pendcond < 0 %start;  !indicator for line num update
    litstore(litpos) = line
    %if control&tracebit # 0 %then plantlit2(trapi,litpos,15) %c
    %else %if line-c_reg_line > 8 %then plant(move+2<<8,litpos,lineloc) %c
    %else plantlit(add+2<<8,line-c_reg_line,lineloc)
    forget cc;  c_reg_line = line
  %else
    %if pendout # 0 %start
      pendcond = pendcond&15
      c_access = 0 %if pendcond = 0
      %if pendcond # 1 %start
        save context(pendout)
        plant(bra+pendcond,0,pendout)
      %finish
    %finish
    define label(pendin) %if pendin # 0
  %finish
  pendcond = 0
%end

!!!!!!!!!!!!!!!!   Main code generation procedure  !!!!!!!!!!!!!!!!!!!!!

%constinteger INST=1<<30

%routine EVAL(%integername pp, %integer rset)
!Evaluate the operand identified by PP as defined by RSET:
!  RSET = boolean vector of acceptable registers
!  + SIGN to indicate that stopping at EA is acceptable
!  + 1<<16 to indicate byte value ok
!  + 2<<16 to indicate short value ok
!  + STACK if stack ok [not yet: too complex]
%constinteger ASL=32,
              CMPM=43,
              TRAPV=70,
              SWAP=74, EXTL=76,
              JMP=57, TST=59, DBNE=86
              
%constinteger MOVEW=move+2<<8, ADDW=add+2<<8,
              MOVEB=move+1<<8, ADDB=add+1<<8,
              SUBB=sub+1<<8, CMPB=cmp+1<<8,
              CMPMB=cmpm+1<<8

%constinteger VAL=sign+anyreg, REF=sign,
              SIZESHIFT=16,
              TOBYTE=1<<16, TOSHORT=1<<17, {1<<18 not sig}
              TOSTACK=1<<19, ASAD=1<<20

%switch DO(0:opmax)
%owninteger STSIZ=0;  !this variable is used to convey a
    !rarely required 3rd parameter to EVAL
    !Its value is captured into STSIZE on entry
    !A negative value indicates a string;
    ! a positive value a fixed length structure
    ! * CF normal use of negative/positive size *
%integer I,J,P,ACT,X,Y,XX,YY,WX,WY,SX,SY,R,OLDFREE,FREED
%integer M,V,SP,STSIZE,OP,CASE
%record(identinfo)%name DP,DX,DY,TX

%integer%fn FREE DREG
  %result = free reg(anydreg)
%end

%integer%fn FREE AREG(%integer content)
%integer r
  r = free reg(anyareg)
  c_reg_content(r) = content
  %result = r
%end

%routine PUSH(%integer x)
  plant(move,x,prea7);  extend stack(4)
%end
%routine POP(%integer x)
  plant(move,posta7,x);  c_sp = c_sp+4
%end
%routine PUSHS(%integer x,s)
  plant(move+s<<8,x,prea7)
  %if s < 4 %then extend stack(2) %else extend stack(4)
%end

%routine PUSH BLOCK(%integer areg,bytes)
  %if bytes <= 4 %then move block(areg+indir,prea7,bytes) %c
  %else addimm(bytes,areg) %and move block(areg+pre,prea7,bytes)
  extend stack(bytes)
%end

%routine COMPILE UNCOND BRANCH(%integer l)
  %if pendcond # 0 %start
    %if pendcond < 0 %start
      pendcond = 0;  !ok?
    %else %if pendin # 0
      flush;                ![safe - improvable?]
    %else
      pendcond = pendcond!!1
      c_access = -2 %if pp+1 < np %and dict(pp+1)_act = else
    %finish
  %finish
  pendcond = pendcond&15
  c_access = 0 %if pendcond = 0
  plant(bra+pendcond,0,l) %if pendcond # 1
  pendcond = 0
%end

%integer%fn CLEAN REG
%integer r
  free = free-bregb %and %result = breg %if free&bregb # 0
  r = free dreg
  plant(clr,0,r)
  %result = r
%end

%integer%fn WEIGHT(%integer p)
!(Heuristic: can't anticipate all generation decisions)
%integer a,wy
%record(identinfo)%name dp
  p = p-ad %if p >= explim
  %result = 1 %if p < np0
  dp == dict(p)
  a = dp_act
  %result = 999 %if a >= imul;  !funcall,mapcall
  wy = weight(dp_y)
  %result = wy %if wy >= 999
  wy = wy-1 %if a = recref %and dict(dp_x)_flags >= 0
  %result = wy+weight(dp_x)
%end

%routine CHECK ADDRESS(%integer v)
  %if a0 <= v <= a7 %then plant(cmp+2<<8,0,v) %else plant(tst,0,v)
  srcall(adok)
  forget cc
%end

!!!!!!!!!!!!!!!!!!!  Procedure call  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
!      _____ACT_________X__________Y____
! P -> | procident | param 1 | param 2 |
!      |     0     | param 3 | param 4 |
!      .           .         .         .
!
%routine CALL
!Load parameters following P and call procedure ACT (DX)
! Update PP for RCALL
%integer sp,stage,maxq,awkward

%routine EVAL PARLIST(%integer arg,q)
%record(identinfo)%name darg,dv
%integer v,w,f,r,s
!Stage 0 (forward):
!Stage 0 (returning):
!Stage 1 (forward):
!Stage 1 (returning):
  %return %if arg = 0
  darg == dict(arg)
  q = q+1;  maxq = q %if q > maxq
  %if q&1 = 0 %then v = dict(p+q>>1)_x %else v = dict(p+q>>1)_y
  r = darg_reg&15
  s = size(darg_type)
  %if darg_flags&proc # 0 %start
    s = 0
    %if awkward # 0 %start
      f = v;  f = f-ad %if f >= explim
      dv == dict(f)
      %if dv_flags&(ext+spec) # ext+spec %start
      !non-external to (maybe) external
        eval parlist(darg_link,q) %and %return %if stage # 0
        %if dv_flags&(name+indirect) # 0 %then plant(move,f,prea7) -
        %else plant(pea,0,f)
        plantlit(move+2<<8,16_4EF9,prea7)  {JMP entry}
        plant(move,mb,prea7)
        plantlit(move+2<<8,16_287C,prea7)  {MOVE #xxxx,mb}
        extend stack(12)
        s = c_sp
        eval parlist(darg_link,q)
        %if darg_val > 0 %start
          plant(pea,0,temp(c_mode,s))
        %else
          plant(lea,temp(c_mode,s),r+d0)
          free = free&(\(d0b<<r))
        %finish
        %return
      %finish
    %finish
  %finish
  %if darg_val > 0 %start;  !passed on stack
    eval parlist(darg_link,q)
    %return %if stage # 0
    %if darg_flags < 0 %start;     !name
      f = free
!      eval(v,ref)
!      plant(pea,0,v);  extend stack(4)
      eval(v,anyareg)
      push(v)
      free = f
      %return
    %finish
    %if s > 0 %start;              !simple value
      f = free;  eval(v,val)
      pushs(v,s)
      free = f
    %else;                        !structure by value
      stsiz = s
      stsiz = -stsiz %if category(darg_type) # stringy
      eval(v,tostack)
    %finish
    %return
  %finish
  %if s <= 0 %and darg_flags >= 0 %start
    !structure by value -- ad in reg
    v = v-ad %if v >= explim
    %if v >= np0 %start
      dv == dict(v)
      %if dv_act >= concat %and dv_mode = 0 %start
        !string/record function
        %if stage = 0 %start
          stsiz = s
          stsiz = -stsiz %if category(darg_type) # stringy
          r = v;  eval(r,tostack);  free = free!a0b;  ![?here?]
          c_reg_content(a0) = v+ad
          dv_val = c_sp
          eval parlist(darg_link,q)
        %else
          eval parlist(darg_link,q)
          %if c_reg_content(r+d0) # v+ad %start
            dv_mode = c_mode
            plant(lea,v,r+d0)
            dv_mode = 0
          %finish
          free = free&(\(d0b<<r))
        %finish
        %return
      %finish
    %finish
    v = v+ad
  %finish
  w = weight(v)
  %if w >= 999 %start
    eval parlist(darg_link,q)
    %return %if stage # 0
  %else
    %if w >= 2 %and stage # 0 %start
      eval(v,d0b<<r)
      eval parlist(darg_link,q)
      %return
    %finish
    eval parlist(darg_link,q)
    %return %if stage = 0
  %finish
  eval(v,d0b<<r)
%end

  awkward = 0
  awkward = 1 %and push(mb) %if dx_flags&proc2 # 0 %c
           %and (dx_flags&ext = 0 %or dx_flags&spec # 0);  !param or external
  sp = c_sp
  maxq = 0
  stage = 0
  eval parlist(dict(dx_type)_link,-1)
  stage = 1
  eval parlist(dict(dx_type)_link,-1)
  srcall(act)
  %if c_sp # sp %start
    addimm(sp-c_sp,a7);  c_sp = sp
  %finish
  pop(mb) %if awkward # 0
  pp = p+maxq>>1 %if p < np;  !update for RCALL + RESOL
  forget regs
  c_reg_line = line %if dx_flags&(ext+proc) = ext+proc1;  !%system
%end;  !call
!
%routine STRUCTCALL(%integer entry,size)
  size = mite(-size-1) %and forget(breg) %if size <= 0;  !string
  plantlit(move,size,d0)
  srcall(entry)
  forget(d0)
%end

%routine PUSH STRUCTURE
  %if stsize <= 0 %start;               !string
    structcall(strtostk,stsize)
    forget(a0);  forget(a1);  forget(a0+2)
    extend stack(256-(stsize&254))
  %else;                               !fixed size structure
    push block(a0,(stsize+1)&(\1))
  %finish
%end

%routine OK REG(%integer got)
  r = got
  %if d0b<<(got-d0)&rset = 0 %start
    c_reg_content(got) = pp
    %if rset&free = 0 %and rset&tostack # 0 %start
      push structure;  r = a7
!      push(got);  r = a7
!      c_reg_ccx = pp;  c_reg_ccy = 0
    %else
      r = free reg(rset&(\bregb));  plant(move,got,r)
      c_reg_ccx = pp %and c_reg_ccy = 0 %if r < a0
    %finish
  %finish
%end

%routine OK AREG(%integer got,ok)
  r = got
  %if a0b<<(got-a0)&ok = 0 %start
    r = free reg(ok);  plant(move,got,r)
  %finish
%end

%routine LOAD ADDRESS(%integer p)
%integer i,f
  %if rset&anyareg&free # 0 %start
    %if dp_mode&2_111000 = indexmode %and dp_val&255 = 0 %start
      i = a0b<<(dp_mode&7)
      rset = i %if rset&free&i # 0
    %finish
    r = free reg(rset&anyareg)
    plant(lea,p,r)
  %else
    f = free
    i = free areg(p+ad);  plant(lea,p,i)
    free = f
    r = free reg(rset&(\bregb));  plant(move,i,r)
  %finish
%end

%routine COMMANDEER(%integer regs)
%integer r
  freed = \free&regs
  %if freed # 0 %start
    regs = freed;  r = d0
    %while regs # 0 %cycle
      push(r) %and forget cc %if regs&1 # 0
      regs = regs>>1;  r = r+1
    %repeat
    free = free!freed;  rset = rset&(\freed)
  %finish
%end
%routine RESTORE(%integer regs)
%integer r
  r = a7
  %while regs # 0 %cycle
    %if regs&16_8000 # 0 %start
      pop(r);  forget(r);  !*should have remembered it*
      forget cc
    %finish
    regs = regs<<1&16_FFFF;  r = r-1
  %repeat
%end

%routine PARTREG
! Something smaller than integer has been loaded to R
! Determine what else to do (using SX,SY)
  sy = 4 %if r = breg %or r >= a0
  %while |sy| < sx %cycle
    %if sy > 0 %start;  !signed
      plant(extl-2+sy,0,r);  !ext.w,ext.l
      sy = sy+sy
    %else
      %if sy = -1 %start;  !unsigned byte
        plantlit(and,255,r)
      %else;            !unsigned word (half)
        plantlit(and,16_FFFF,r)
      %finish
      sy = 4
    %finish
  %repeat
%end

!!Start of EVAL

  stsize = stsiz;  !additional parameter (for TOSTACK cases)
  rset = rset&(\anyareg) %if rset&tobyte # 0;  ![1 bit]
  p = pp;  p = p-ad %if p >= explim
  rset = rset-asad %and pp = p+ad %if rset&asad # 0
  %if p <= 0 %then dp == dint %else dp == dict(p)
  oldfree = free;  freed = 0

%if rset # inst %start
  %unless dp_mode&2_110000 = 0 %and pp < np0 %start;  !not already reg
    j = pp
    %if rset&(anydreg!bregb{+tostack}) # 0 %start;  !data reg acceptable
      i = d0
      %cycle;  !See if available
        j = i %and %exit %if c_reg_content(i) = j
        i = i+1;  i = a0 %if i = maxdreg+1
      %repeat %until i > maxareg
    %else %if rset&anyareg # 0;  !try address regs first
      i = maxareg
      %cycle
        j = i %and %exit %if c_reg_content(i) = j
        i = i-1;  i = maxdreg %if i = a0-1
      %repeat %until i < d0
    %else %if j < explim %and rset # tostack;  !REF: try for address
      i = a0
      %cycle
        %if c_reg_content(i) = j+ad %start
          free = free&(\(a0b<<(i-a0)))
          dp_flags = dp_flags!(rflag+wflag)
          pp = i+indir
          %return
        %finish
        i = i+1
      %repeat %until i > maxareg
    %finish
  %else;  !already reg
    j = dp_mode+d0;       !in case reg alias
    %if rset < 0 %start;  !EA ok means any reg ok
      pp = j
      %return
    %finish
    pp = c_reg_content(j); !fiddle for update
  %finish

  %if 0 < j <= a7 %start;  !operand (now) in reg
    ok reg(j)
    dp_flags = dp_flags!rflag
    -> endload
  %finish

  %if p <= 0 %start;  !literal
    %return %if rset < 0
    %if rset = tostack %start
      i = constmode;  i = pcmode %if p = 0;  !null string [sneaky]
      plant(lea,temp(i,litval(p)),a0);           !A0 must be free
      forget(a0)
      push structure
      %return
    %finish
    %if pp < explim %start;  !normal value
      rset = rset&(\bregb) %if p < -(255<<1) %or p&1 # 0;  !0:255 ok
      r = free reg(rset)
      %if r < a0 %or p # 0 %then plant(move,p,r) %c
      %else plant(sub,r,r)
    %else;                    !address within FINAL
      i = constmode;  i = pcmode %if p = 0;  !null string [sneaky]
      load address(temp(i,litval(p)))
    %finish
    c_reg_ccx = pp %and c_reg_ccy = 0 %if r < a0
    ->endload
  %finish
%finish
  %if p >= np0 %start;  !complex
more:
    act = dp_act;  x = dp_x;  y = dp_y
    xx = x;  yy = y
    -> proccall %if act > opmax
    -> do(act)
  %finish

do(move):
load:
  i = 0
  i = i+1 %if dp_flags&indirect # 0
  i = i+2 %if dp_flags < 0
  %if pp >= explim %start {address wanted}
    %if i = 0 %start
      free = oldfree
      load address(p)
    %else
      %if i = 3 %start;  !indirect name
        free = oldfree
        r = free areg(undef);  plant(move,p,r)
        p = r+indir
      %finish
      pp = p %and %return %if rset < 0
      free = oldfree
      r = free reg(rset);  plant(move,p,r)
    %finish
    c_reg_ccx = pp %and c_reg_ccy = 0 %if r < a0
  %else
    %if i > 0 %start
      free = oldfree
      r = maxareg+1
      %cycle
        r = r-1
        %if r < a0 %start
          r = free areg(p+ad);  plant(move,p,r)
          plant(move,r+indir,r) %if i = 3
          check address(r) %if i > 1 %and control&assbit # 0
        %finish
      %repeat %until c_reg_content(r) = p+ad
      free = free&(\(a0b<<(r-a0)))
      p = r+indir
    %finish
    pp = p %and %return %if rset = ref
    sx = rset>>sizeshift&3;  sx = 4 %if sx = 0
    i = dp_flags
    sy = size(dp_type)
    %if c_localdpos <= p < dictlim %and i&okflag = 0 %and c_forward = 0 %start
      !local, simple, always accessed
      %if i&wflag = 0 %start;  !unassigned
        report(asserr+warn,p,0) %if c_faults = 0
      %finish
      dp_flags = dp_flags+okflag %if dp_flags >= 0 %and sy > 0
    %finish
    %if rset = tostack %start
      free = oldfree
      plant(lea,p,a0);           !A0 must be free
      forget(a0)
      push structure
      %return
    %finish
    intern(5) %and %return %if sy <= 0
    i = i!okflag %if control&bassbit>>1<<sy = 0
    %if i&okflag # 0 %and rset < 0 %start;  !not necessary to load?
      %if sy = sx %start;  !same size
         pp = p
        %return
      %finish
    %finish
    free = oldfree
    %if i&okflag # 0 %then i = -1 %else i = sy
    sy = -sy %if sy # 4 %and (dict(dp_type)_flags&nonord # 0 %c
                        %or dict(dp_type+1)_val = 0);  !unsigned
    %if sy = -1 %start;  !unsigned byte
      %if free&bregb # 0 %start
        %if rset&bregb # 0 %start
          rset = bregb
        %else
          plant(moveb,p,breg)
          forget(breg)
          p = breg;  sy = 4
        %finish
      %finish
    %finish %else rset = rset&(\bregb)
    %if sy < 2 %or sx = 1 %start
      %if rset&(anydreg!bregb) = 0 %start
      !Can't load bytes,halfs to address regs
      ! or store bytes from them
        r = free dreg
        plant(move+|sy|<<8,p,r)
        partreg
        p = r;  free = oldfree
      %finish %else rset = rset&(\anyareg)
    %finish
    %if sy = 2 %and rset&anyareg&free # 0 %start
      rset = rset&(\anydreg);  !prefer areg for word (auto-extend)
    %finish
    r = free reg(rset)
    plant(move+|sy|<<8,p,r)
    c_reg_ccx = pp %and c_reg_ccy = 0 %if r < a0
    %if sy # 4 %start
      partreg
    %finish
    %if i >= 0 %start
      plant(cmp+i<<8,r,d7);  !check unassigned
      srcall(unass)
      forget cc
    %finish
    %if sy # 4 %and r # breg %start;  !not full reg
      forget(r)
      -> endload1
    %finish
  %finish
endload:
  c_reg_content(r) = pp
endload1:
  free = free&(\(d0b<<(r-d0)))
  r = r+indir %if rset = ref
  pp = r
  %return

dataload:
  eval(p,anydreg)
  ok reg(p)
  -> endload

!!!!!!!!!!!!!!!!   Array   /   Record    /   Map   !!!!!!!!!!!!!!!!!!

%integer%fn FREEISH AREG(%integer for)
!Use the register component of M if alterable
! to avoid excessive dissipation of address registers
%integer i
  i = m&7
  %result = free areg(for) %if a0b<<i&oldfree = 0 %or m >= framemode
  free = free&(\(a0b<<i))
  i = i+a0;  c_reg_content(i) = for
  %result = i
%end
%routine ADEVAL(%integer x,y,q)
!Base X, scaled index Y, displacement Q
%integer i,j
  %if x <= 0 %start;  !%const
    m = constmode;  v = litval(x)
  %else
    eval(x,ref)
    m = dict(x)_mode;  v = dict(x)_val
    %if m = c_mode %and v < 0 %start
     !*Assertion: SP will have same value when address used
      m = dispmode+7;  v = v-c_sp
    %else %if m&2_111000 = aregmode+indir
      m = m+(dispmode-(aregmode+indir))
    %finish
  %finish
  eval(y,anyreg) %if y # 0;  !subscript
  %if m&2_111000 = indexmode %start;  !X already involves index
    %if y = 0 %start
     !See if Q can be combined with existing disp
      j = mite(v)
      i = j+q
      %if is mite(i) %start
        v = v-j+i&255
        %return
      %finish
    %finish
    i = freeish areg(x+ad)
    plant(lea,x,i)
    m = i+(dispmode-a0);  v = 0
  %finish
  %if y # 0 %start
    %if m&63 = pcmode %start
      i = free areg(undef);  plant(lea,temp(m,v+q),i)
      m = i+(dispmode-a0);  v = 0;  q = 0
    %else %if %not is mite(v+q);  !indexmode out
      %if %not is mite(q) %start; !& out even if V absorbed
        i = freeish areg(undef)
        %if is short(v+q) %start
          plant(lea,temp(m,v+q),i)
        %else
          plant(lea,x,i);  addimm(q,i)
        %finish
        q = 0
      %else
        i = freeish areg(x+ad)
        plant(lea,x,i)
      %finish
      m = i+(dispmode-a0);  v = 0
    %finish
  %finish
  v = v+q
  %if y # 0 %start
    m = m+(indexmode-dispmode)
    v = (y-d0)<<12+16_0800+v&255
  %finish
%end

do(index):
!  P      => {index,ARRAY,SUBSCRIPT}
!  ARRAY  => ARRID
!         or {index,ARRAY,SUBSCRIPT}
!         or {recref,RECORD,ARRAY}
!  TYPE INFO : TYPE = ELTYPE, XTYPE = INDEX-TYPE
!              MODE,VAL = DOPE ADDRESS
  dx == dict(x)
  i = dx_type;                   !array type cell
  tx == dict(i)
  get bounds(tx_xtype,sx,sy)
 !establish multiplier (element size)
  m = |nsize(tx)|
 !ARRFLAG is set for either ABC requested or dynamic
  %if dx_flags&arrflag # 0 %and (y > 0 %or sx = minint %or m = 0) %start
    commandeer(d0b+d1b+a0b);  ![D1 ??]
   ! subscript
    eval(y,d0b)
   ! dope vector
    j = 0
    j = j+12 %and i = i+1 %and tx == dict(i) %while tx_mode = 0
    %if tx_flags&indirect # 0 %start
      plant(move,i,a0)
      addimm(j,a0) %if j # 0
    %else
      %if tx_val = 0 %and tx_mode = constmode %start
      ! dope info not yet created
        fill code(1) %if cad&1 # 0
        tx_val = cad
        set code longword(sy)
        set code longword(sx)
        set code longword(m)
      %finish
      plant(lea,i,a0)
    %finish
    srcall(index)
    forget(d0);  forget(a0)
    restore(freed&(\d0b))
    free = oldfree&(\d0b)
    freed = freed&d0b
    i = x;  eval(i,anyareg&free+asad)
    plant(add,d0,i)
    %if dp_flags < 0 %then forget(i) {ad of ad of P} %c
    %else c_reg_content(i) = p+ad
    free = free!d0b %if freed = 0
    restore(freed)
    m = i+(dispmode-a0);  v = 0
    -> setflags
  %finish
index1:
  !deal with subscript
  j = 0
  %if y <= 0 %start;  !literal subscript
    j = litval(y);  y = 0
  %finish
  %if y >= np0 %and dict(y)_act = add %c
   %and dict(y)_y <= 0 %start;  !Y => {add,exp,lit}
    j = litval(dict(y)_y);  y = dict(y)_x
  %finish
  %if m > 1 %start
    %if y # 0 %start
      %if m&(m-1) # 0 %and m <= 32767 %and sy <= 32767 %and sx >= -32768 %start
        putexp(muls,y,litref(m),inttype)
      %else
        putexp(imul,y,litref(m),inttype)
      %finish
      y = item
    %finish
  %finish
  %if dx_flags&(name+ext+arrflag+indirect) = indirect %and sx # 0 %start
    dx_val = dx_val+4;  !0-based
    adeval(x,y,j*m)
    dx_val = dx_val-4
  %else
    j = j-sx;  j = j*m %if m > 1
    adeval(x,y,j);  !array,index,displacement
  %finish
setflags:
  dx_flags = dx_flags!(mflag+wflag+rflag);  !don't know
setmode:
![what about FRAMEMODE?]
  %if dispmode <= m < indexmode %start
    %unless isshort(v) %start
      ok areg(m+(a0-dispmode),oldfree&anyareg)
      addimm(v,r);  forget(r)
      m = r-(a0-dispmode);  v = 0
    %finish
    %if pp >= explim %and v = 0 %and rset # ref %and dp_flags >= 0 %start
    !address wanted, disp zero, as value, not name
    ! so the address is simply in the register
      ok reg(m+(a0-dispmode))
      free = oldfree
      -> endload
    %finish
  %finish
  dp_mode = m;  dp_val = v
  ->load

do(recref):
!  P => {recref,RECORD,SUBEL}
  dx == dict(x)
  adeval(x,0,dict(y)_val);  !record,subscript,displacement
  ->setflags

do(storemap):
  v = 0
  %if y >= explim %start
    y = y-ad;  eval(y,ref)
    m = dict(y)_mode;  v = dict(y)_val
  %else
    %if y >= np0 %start
      %if dict(y)_act = add %start
        m = dict(y)_y
        y = dict(y)_x %and v = litval(m) %if m <= 0
!       eval(y,val) %if y >= dictlim
      %finish;! %else eval(y,val)
    %finish
    eval(y,anyareg)
    check address(y) %if control&assbit # 0  %and pp < explim
    m = y+(dispmode-a0)
  %finish
  -> setmode

do(lenref):
do(sindex):
  x = x-ad %if x >= explim
  dx == dict(x)
  %if y <= 0 %then adeval(x,0,litval(y)) %c
  %else eval(y,anydreg) %and adeval(x,y,0)
  -> setflags

do(dnew):
  commandeer(c_free)
  plant(move,y,d0)
  srcall(act)
  forget regs
  c_reg_line = line
  -> endmap

do(dtostring):
proccall:
  dx == dict(act)
  -> rcall %if p < np
  -> funcall %if dx_flags&writable = 0
!mapcall
  commandeer(c_free)
  call
endmap:
  free = oldfree
  r = a0
  ok areg(a0,\freed&anyareg) %if rset # ref
  restore(freed)
  free = free&(\(a0b<<(r-a0)))
  c_reg_content(r) = p+ad
  m = r+(dispmode-a0);  v = 0;  !0(A?)
  ->setmode

funcall:
  commandeer(c_free)
  call
  r = typecell(dx_type)_reg&15+d0
  c_reg_ccx = pp %and c_reg_ccy = 0 %if dx_flags&okflag # 0
endloadr:
  free = oldfree
  %if rset # ref %then ok reg(r)
  restore(freed)
  ->endload

rcall:
  flush %if pendcond # 0
  update sp
!<<IMP
  %while act = dprintstr %and x >= np0 %and dict(x)_act = concat %cycle
    dp_x = dict(x)_x;  !first of pair
    call;  free = c_free
    x = dict(x)_y;  dp_x = x
  %repeat
!<<BOTH
  call
  c_access = 0 %if dx_flags&noret # 0
  forget triples %if pp+1 = np %and curlab = c_lab1 %c
                 %and dict(curlab)_val >= 0 %and dict(curlab+1)_val >= 0
  %return

!!!!!!!!!!!!!!!!!!!!!!!!!   Operators   !!!!!!!!!!!!!!!!!!!!!!!!!!!

%routine EVALXY
  rset = rset&(\bregb)
  commandeer(d0b+d1b)
  %if 999 > weight(x) < weight(y) %start
    eval(y,d1b);  eval(x,d0b)
  %else
    eval(x,d0b);  eval(y,d1b)
  %finish
%end

%routine STACKOP(%integer s)
  stsiz = s
  sp = c_sp
  eval(x,tostack);  free = free!a0b
  eval(y,a0b+asad)
  plant(move,a7,a1);      !dest (stack)
  structcall(act,s)
  forget(a0);  forget(a1);  forget(a0+2)
%end

!<<IMP
do(prel):
!  P => {prel,BASENAME,INDEX}
  dx == dict(x)
  m = |size(dx_type)|
  sx = 0;  sy = 999999
  -> index1

!<<BOTH

do(check):        !CHECK rangetype,value
  commandeer(d0b)
  eval(y,d0b)
  srcall(x)
  r = d0
  -> endloadr

![Note that all literal subtraction comes through as ADD]
do(add):
  %if control&overbit # 0 %start
    -> dataload %if rset&(\anyareg) = 0
    rset = rset&(\anyareg)
  %finish
  -> dataload %if rset&(\bregb) = 0
  rset = rset&(\bregb)
  %if y < 0 %start
    %if y >= litquick %start;  !(ADDQ,SUBQ)
      y = y-1 %and act = sub %if y&1 # 0;  !'negate' if 'negative'
      eval(x,rset&free)
      ->fin1
    %finish
    %if y = -(128<<1) %start;  !+128
      act = sub;  y = y+1;  !- -128 (MOVEQ)
      -> op2
    %finish
  %finish
  -> op1
do(eor):
  -> dataload %if rset&(\bregb) = 0
  rset = rset&(\bregb)
do(or):
do(and):
  -> dataload %if rset&(\anyareg) = 0
  rset = rset&(\anyareg)
op1:
  wx = weight(x)
  %if wx <= 1 %and y <= 0 %and y >= litmite %and rset&(\anyareg) # 0 %start
    rset = rset&(\anyareg)
    i = x;  x = y;  y = i
  %else %if 999 > wx < weight(y)
    i = x;  x = y;  y = i
  %finish
  -> op2
do(sub):
  %if control&overbit # 0 %start
    -> dataload %if rset&(\anyareg) = 0
    rset = rset&(\anyareg)
  %finish
  rset = rset&(\bregb)
op2:
  eval(x,rset&free)
op3:
  oldfree = free
  %if y <= 0 %and y >= litmite %and free&(anydreg!bregb) # 0 %start
    eval(y,anydreg!bregb);           !bring Y to reg
  %else %if act = eor %and y > 0
    eval(y,anydreg)
  %else %if act > sub
    %if x = breg %and y > 0 %start
      sy = tsize(y)
      %if sy = 1 %or (sy = 2 %and act = and) %start
        eval(y,val&(\anyareg)+sy<<sizeshift)
        act = act+sy<<8 %if y > d7
      %finish %else eval(y,val&(\anyareg))
    %finish %else eval(y,val&(\anyareg))
  %else
    eval(y,val)
  %finish
  free = oldfree
fin1:
  plant(act,y,x)
  -> fin3 %if act > sub
fin2:
  plant(trapv,0,0) %if control&overbit # 0
fin3:
  pp = x;  c_reg_content(x) = p
  %if act <= opmax %then c_reg_ccx = p %and c_reg_ccy = 0 %c
  %else forget cc
  %return

do(muls): do(mulu):
  -> dataload %if rset&(\(anyareg!bregb)) = 0
  rset = rset&(\(anyareg!bregb))
  eval(x,rset&free)
  oldfree = free
  eval(y,anydreg) %if y > 0;  ![could do better for short]
  free = oldfree
  plant(act,y,x)
  -> fin2

do(lsl): do(lsr):
  -> dataload %if rset&(\(anyareg!bregb)) = 0
  rset = rset&(\(anyareg!bregb))
  eval(x,rset&free)
  %if y < 0 %and y >= litquick %start
    act = act!!(lsl!!lsr) %and y = y-1 %if y&1 # 0;  !negate if neg
  %else
    oldfree = free;  eval(y,anydreg);  free = oldfree
  %finish
  ->fin1
do(neg):
  %if y # 0 %start
   r = y;  y = x;  x = r
   act = sub
   -> do(sub)
  %finish
do(not):
  -> dataload %if rset&(\(anyareg!bregb)) = 0
  rset = rset&(\(anyareg!bregb))
  eval(x,rset&free)
  plant(act,0,x)
  -> fin3
do(iabs):
  -> dataload %if rset&(\(anyareg!bregb)) = 0
  rset = rset&(\(anyareg!bregb))
  x = y
  eval(x,rset&free)
  plant(move,x,x) %if c_reg_ccx # y %or c_reg_ccy # 0
  plantlit2(bge,0,2)
  plant(neg,0,x)
  ->fin2
do(fabs):
  -> dataload %if rset&(\(anyareg!bregb)) = 0
  rset = rset&(\(anyareg!bregb))
  x = y
  eval(x,rset&free)
  plantlit(and,16_7FFFFFFF,x)
  ->fin3

%routine DO SHIFT
%integer i=0
  i = i+1 %and j = j>>1 %until j&1 # 0
  %if i = 1 %then plant(add,x,x) %else %start
    i = litref(i)
    %if i < litquick %start
      oldfree = free;  eval(i,anydreg);  free = oldfree
    %finish
    plant(asl,i,x)
  %finish
%end

do(imul):
  -> dataload %if rset&(\(anyareg!bregb)) = 0
  rset = rset&(\(anyareg!bregb))
 !Test for power of 2 or pair of powers of 2
  %if y < 0 %start
    j = litval(y)
    i = j&(j-1)
    %if i = 0 %or i&(i-1) = 0 %start
      eval(x,rset&free)
      do shift %if j&1 = 0
      %if j # 1 %start
        plant(move,x,prea7)
        do shift
        plant(add,posta7,x)
      %finish
      ->fin2
    %finish
  %finish
do(fsub): do(fdiv):
do(ipow): do(fpow):
do(fadd): do(fmul):
  evalxy
  srcall(act)
  plant(trapv,0,0) %if act = imul %and control&overbit # 0
  forget(d1);  r = d0
  forget cc
  -> endloadr

do(idiv): do(drem):
  %if control&halfbit # 0 %start
    act = divs %if act = idiv
do(divs): do(divu):
    -> dataload %if rset&(\(anyareg!bregb)) = 0
    rset = rset&(\(anyareg!bregb))
    eval(x,rset&free)
    oldfree = free
    eval(y,anydreg)
    free = oldfree
    %if act = drem %then plant(divs,y,x) %and plant(swap,0,x) %c
    %else plant(act,y,x)
    plant(extl,0,x)
    -> fin3
  %finish
  evalxy
  srcall(idiv)
  putexp(act!!(idiv!!drem),xx,yy,inttype)
  %if act = idiv %start
    c_reg_content(d1) = item;  r = d0
  %else
    c_reg_content(d0) = item;  r = d1
  %finish
  forget cc
  ->endloadr

do(float):
do(fneg):
  commandeer(d0b)
  eval(x,d0b)
  srcall(act)
  forget cc
  r = d0
  ->endloadr

do(concat):      !not special case
![they have to be free]  commandeer(d0b+bregb+a0b+a1b+a2b)
  fault(plexerr) %if free&(a0b+a1b+a2b+d0b+bregb) # a0b+a1b+a2b+d0b+bregb
  stackop(-256)
endconc:
  %if rset&tostack = 0 %start
    %if c_sp # sp %start
      addimm(sp-c_sp,a7);  c_sp = sp
    %finish
  %finish %else rset = a0b
  r = a0
  ->endloadr

!!!!!!!!!!!!!!!!!!!!!   Conditions   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

%routine CONDSWOP
!Swop condition operands, adjusting operator accordingly
%integer temp
  temp = x;  x = y;  y = temp
  temp = xx;  xx = yy;  yy = temp
  temp = sx;  sx = sy;  sy = temp
  temp = wx;  wx = wy;  wy = temp
  case = case!!3 %if case&8 # 0;  !no change for '=','#'
%end

%routine UNSIGNED
  %if case&8 # 0 %start;  !no change for '=','#'
    case = case!!8
    case = case!!4 %if case&2 # 0
  %finish
%end

![Some confusion here of which operand (weightier) to evaluate first
![                   and which to bring to register
![EVAL improvements make possible greater finesse:
![               1. Decide which to evaluate first (weightier)
![               2. EVAL both 'val'
![               3. If either in register, OK
![               4. Load one
![*for IMP, conditions cannot be embedded in other expressions;
![*for Pascal, they can.  This needs improvement to cover that.
do(compare):
  flush %if pendcond # 0
  update sp
  sp = c_sp
  pp = pp+1;  dp == dp[1]
  case = dp_act
  %if x <= 0 %start;  ![1st literal: only for true,false]
    case = case!!1 %if x = 0;  !invert for false
    pendcond = case&1+bra
    -> endcomp
  %finish
  %if x >= explim %start;        !address
    dx == dict(x-ad);  sx = 4
  %else
    dx == dict(x)
    tx == dict(dx_type);  sx = size(dx_type)
  %finish
  dx_flags = dx_flags!rflag
  %if y >= explim %or y <= 0 %then sy = 4 %else sy = tsize(y)
  wx = 0 %and wy = 0 %and condswop %if c_reg_ccx = y %and c_reg_ccy = x
  %if c_reg_ccx # x %or c_reg_ccy # y %start;  ![???unsigned???]
    %if y # 0 %start;  !not comparison with zero
      wx = weight(x);  wy = weight(y)
      condswop %if wx < 999 %and wy > wx+1
      %if x >= explim %or y >= explim %start;  !one or other is address
        !swop if Y is not name (to use LEA)
        condswop %if 0 <= y-ad < dictlim %and dict(y-ad)_flags >= 0
        eval(x,anyareg)
        eval(y,sign+anyareg)
        plant(cmp,y,x)
        c_reg_ccx = xx;  c_reg_ccy = yy
      %else %if sx > 0;  !simple operand
        %if tx_flags&cat = realy %start
          eval(x,d0b);  eval(y,d1b)
          srcall(fsub)
          forget(x)
          c_reg_ccx = xx;  c_reg_ccy = yy
        %else %if y < 0;         !comparison with literal
          %if y >= litmite %start
            eval(x,val+sx<<sizeshift)
            %if (sx = 4 %and free&anydreg # 0) -
            %or (x > a7 %and dict(x)_mode&63 = pcmode) %start
              eval(y,anydreg)
              condswop %and sx = sy %unless x <= d7
            %finish
          %else
            sx = 0 %if sx = 1;   ![to ensure comparison fails?]
            eval(x,val+sx<<sizeshift)
            sx = 2 %if a0 <= x <= a7 %and is short(litval(y))
          %finish
          plant(cmp+sx<<8,y,x)
          unsigned %if sx = 1
          c_reg_ccx = xx;  c_reg_ccy = yy
        %else;  !Y not literal
          condswop %if sy < sx
          eval(x,anyreg)
          %if sy <= 2 %and sy = sx %and (sy=1 %or x < a0) %start
            eval(y,val+sy<<sizeshift)
            plant(cmp+sy<<8,y,x)
            unsigned %if sy = 1
            forget cc
          %else
            eval(y,val)
            plant(cmp,y,x)
            c_reg_ccx = xx;  c_reg_ccy = yy
          %finish
        %finish
      %else;            !structure
        stsiz = sx;  stsiz = -stsiz %if tx_flags&cat # stringy
        %if (case&8 = 0 %and control&strassbit = 0) -
        %or stringy # tx_flags&cat # sety %start
          !equals,notequals or rec,array
          ! [No routine call required to implement]
          %if wy >= 999 %start;  !both complex
            eval(x,tostack);  free = free!a0b
            eval(y,anyareg&free+asad)
            x = freeareg(undef)
            plant(move,a7,x)
          %else
            eval(x,anyareg&free+asad)
            forget(x)
            eval(y,anyareg&free+asad)
          %finish
          i = free dreg
          %if tx_flags&cat = stringy %start;  !string comparison
            plant(clr,0,i)
            plant(moveb,x+indir,i)
          %else
            plantlit(move,-sx-1,i)
          %finish
          plant(cmpmb,x+post,y+post)
          plantlit2(dbne,i,-4)
          forget(i);  forget(y)
        %else
         ! [Routine call required: must bring complex to stack]
          %if wx >= 999 %start
            eval(x,tostack);  free = free!a0b
            %if wy >= 999 %start
              stsiz = sy;  stsiz = -stsiz %if tx_flags&cat # stringy
              eval(y,tostack)
              y = a1;  plant(move,a7,y)
              sy = (|sy|+1)&(\1);  sy = 256 %if sy = 0
              x = a0;  plant(lea,tempd(a7,sy),x)
            %else
              eval(y,a1b+asad)
              x = a0;  plant(move,a7,x)
            %finish
          %else
            eval(x,a0b+asad);  eval(y,a1b+asad)
          %finish
!<<IMP
          srcall(scomp)
          unsigned
!<<BOTH
        %finish
        forget cc
      %finish
    %else;  !comparison with zero
      %if sx <= 0 %or (sx = 1 %and dx_mode >= dispmode) %start
        %if tx_flags&cat = stringy %or sx = 1 %start
          eval(x,ref)
          plant(tst+1<<8,0,x)
          forget cc;  !*for now*
          unsigned
        %else
          eval(x,anyareg&free+asad)
          i = free dreg
          plantlit(move,-sx-1,i)
          plant(tst+1<<8,0,x+post)
          plantlit2(dbne,i,-4)
          forget(i);  forget(x)
        %finish
      %else
        eval(x,anydreg)
        %if c_reg_ccx # xx %or c_reg_ccy # 0 %start
          plant(move,x,x);  c_reg_ccx = xx;  c_reg_ccy = 0
        %finish
      %finish
    %finish
  %finish
  pendcond = case
endcomp:
  pendin = dp_x;  pendout = dp_y
checksp:
  %if c_sp # sp %start
    addimm(sp-c_sp,a7);  c_sp = sp
  %finish
!<<IMP
  %return

do(resolves):
  flush %if pendcond # 0
  update sp
  sp = c_sp
!  push(mb)
!  eval(x,a0b+asad);  !string to be resolved
!  act = dict(y)_act;  x = dict(y)_x;  y = dict(y)_y
!  eval(x,a1b);  eval(act,a0b<<2);  eval(y,a0b<<3);  !match, fore, aft
!  srcall(resolves)
!  pop(mb)
!  forget regs
  dx == dict(act)
  call
  pp = pp+2;  dp == dict(pp)
  pendcond = dp_act
  -> endcomp

!<<BOTH
!!!!!!!!!!!!!!!!!!!!!!!!   Assignment   !!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
%predicate EASY(%integer y)
! Determine if structure assignment (string, set)
!  can be done by store-to-store op(s) and if so, do it.
%integer r1,f
%record(identinfo)%name dy
%owninteger s=0
  %false %if y < np0
  dy == dict(y)
  %false %if dy_act > concat %or dy_act = prel
  f = free
  %if dy_x = x %start;  !recursion ends, successfully
    s = tsize(x);  s = -s %if dy_act # concat;  !+ve unless string
    eval(x,a1b+asad)
  %else
    %false %if dy_y >= np0 %or dy_y = x %c
    %or %not easy(dy_x)
  %finish
  y = dy_y
  %if y >= np0 %and dict(y)_act = dtostring %start
    y = dict(y)_x;  eval(y,tobyte+val);  !character value
    r1 = clean reg
    plant(addb,one,x+indir);              !inc length(dest)
    plant(moveb,x+indir,r1)
    plant(moveb,y,tempx(x,r1));          !append char
    forget(r1)
  %else
    eval(y,a0b+asad)
    structcall(dy_act,s)
    forget(a0);  forget(a1)
    forget(d1);  forget(d2)
  %finish
  free = f&(\a1b)
  %true
%end

%routine BEWARE(%integer dest)
![not foolproof: ?too expensive to do properly
!                 too inefficient to fail safe]
%integer r,d
%predicate UNSAFE(%integer p)
![a bit cavalier]
  %cycle
    %false %if p <= undef;        !literal, basereg or undef
    %true %if p = dest %or p = d {%or d >= np0
    p = p-ad %if p >= explim
    %false %if p < np0
    %true %if dict(p)_act > opmax;  !funcall,mapcall
    %true %unless dest # dict(p)_y < np0
    p = dict(p)_x
  %repeat
%end
  forget(dest) %and %return %if dest <= a7
  d = dest;  d = d-ad %if d >= explim
  %for r = d0,1,maxareg %cycle
    forget(r) %if unsafe(c_reg_content(r))
  %repeat
  forget cc %if unsafe(c_reg_ccx) %or unsafe(c_reg_ccy)
%end

%predicate XFREE(%integer v,strong)
%record(identinfo)%name dp
  %cycle
    v = v-ad %if v >= explim
    %exit %if v < dictlim
    dp == dict(v)
    %false %if %not xfree(dp_y,1)
    strong = 1 %if dp_y >= dictlim
    v = dp_x
  %repeat
  %true %if v # x %or strong = 0
  %false
%end

!<<IMP
do(forass):  !FORASS:loopvar:start'
             ! --   :inc    :end
  eval(y,d0b)
  pp = pp+1;  dp == dp[1]
  i = dp_x;  eval(i,d1b);  i = dp_y;  eval(i,d2b)
  srcall(forok)
!<<BOTH
do(jamass):
do(assign):
do(okass):
  flush %if pendcond # 0
  %if xx >= explim %start;  !ad of ...
    wx = weight(xx-ad)
    dx == dict(xx-ad)
    sx = 4
  %else
    wx = weight(xx)
    dx == dict(xx)
    sx = size(dx_type)
  %finish
  tx == dict(dx_type)
  sp = c_sp-c_val
  %if sx <= 0 %start;  !structure assignment
    !Structure
    ![for rec/string assignment beware corruption of stacked
    ! structure in computing DEST]
    update sp
    %if tx_flags&cat = stringy %start
      sx = -256 %if sx = 0;   !string(*)
      op = -1;  op = dict(y)_act %if y >= np0
      %if y = 0 %start;  !""
        eval(x,ref)
        plant(clr+1<<8,0,x)
      %else %if op = dtostring
        y = dict(y)_x
        eval(y,tobyte+val);  !character value
        eval(x,anyareg&free+asad)
        plant(moveb,one,x+post)
        plant(moveb,y,x+indir)
        forget(x)
        forget cc
      %else %if act = jamass %or %not easy(y)
        %if op >= concat %and wx > 1 %start
        ! Danger of corruption of RHS
          stsiz = sx
          eval(y,tostack);  free = free!a0b
          eval(x,a1b+asad)
          plant(move,a7,a0);  y = a0
          structcall(strcopy,sx)
        %else %if act # assign %or sx = -256 %or control&capbit = 0
        ! No check needed
          %if wx > 1 %then eval(x,anyareg&free+asad) %and eval(y,anyareg&free+asad) %c
          %else eval(y,anyareg&free+asad) %and eval(x,anyareg&free+asad)
!not worth %if act # jamass %and sx >= -4 %start
!            %cycle
!              plant(moveb,y+post,x+post)
!              sx = sx+1
!            %repeat %until sx >= 0
!          %else
            i = free reg(anydreg!bregb)
            %if act = jamass %start
              plantlit(move,mite(-sx-1),i)
              plant(moveb,i,x+post)
              plant(cmpb,y+post,i)
              plantlit2(bcs,0,6);     ! 3 2-byte instructions **
              plant(sub,one,x)
              plant(moveb,y+pre,i)
            %else
              plant(moveb,y+indir,i);   !length (dirty OK)
            %finish
            plant(moveb,y+post,x+post)
            plant(subb,one,i)
            plantlit2(bcc,0,-6)
            forget(i)
!          %finish
        %else
          %if wx > 1 %then eval(x,a1b+asad) %and eval(y,a0b+asad) %c
          %else eval(y,a0b+asad) %and eval(x,a1b+asad)
          structcall(strcopy,sx)
        %finish
        forget(x);  forget(y)
        forget cc
      %finish
    %else %if %not easy(y)
      eval(x,anyareg&free+asad) %if y = 0 %or wx > 1
      %if y # 0 %start
        sx = tsize(y) %if sx = 0
        eval(y,anyareg&free+asad)
        forget(y)
        y = y+post
        eval(x,anyareg&free+asad) %if wx <= 1
      %finish
      forget(x)
      %if sx = 0 %then fault(sizerr) %else move block(y,x+post,-sx)
    %finish
    beware(xx)
    -> checksp
  %finish
!Simple operand
  %if c_val # 0 %start
    %if dx_val = sp %and dx_mode = c_mode %start
      %if sx = 4 %or x >= explim %then c_val = c_val-4 %c
      %else c_val = c_val-2
    %finish
    update sp
  %finish
  op = move
  case = val;  case = case+sx<<sizeshift %if sx # 4
  %if x <= a7 %start;  !explicit assignment to reg
    %if xfree(y,0) %start
      case = 1<<(x-d0);  free = free!case
    %else
      free = free&(\(1<<(x-d0)))
    %finish
  %finish
  %if sx # 4 %and act = assign %and control&capbit # 0 %start
    eval(y,d0b)
    srcall(dx_type);  !range check
  %finish
  i = y;  i = i-ad %if i >= explim
  %if i >= np0 %start;                        !SOURCE complex
    %if dx_flags&okflag # 0 %or control&bassbit>>1<<sx = 0 %start
      dy == dict(i)
      %if y >= explim %start
        %if dy_act = prel %and dy_x = x-ad %c
        %and (dy_y < 0 %or dy_type = bytetype) %start
          y = dy_y
          y = litref(litval(y)*|size(dy_type)|) %if dy_type # bytetype
          act = add
          -> tostore
        %finish
      %else
        %if dy_x = x %c
        %and (dy_act < neg %or (dy_act = neg %and dy_y = 0)) %start
          act = dy_act;  y = dy_y
          -> tostore
        %finish
      %finish
    %finish
    %if wx < 999 %then eval(y,case) %and eval(x,ref) %c
    %else eval(x,ref) %and eval(y,case)
  %else
    eval(x,ref)
    %if y <= 0 %start
      %if y = 0 %and dx_flags&readable # 0 %then op = clr %c
      %else %if y >= litmite %and sx = 4 %then eval(y,anydreg)
    %else
      eval(y,case) %unless y <= a7
    %finish
  %finish
  %if y # x %start
    %if 0 < y <= maxareg %and 0 < yy = c_reg_content(y) %start
      beware(xx)
      c_reg_content(y) = xx
    %finish %else beware(xx)
    plant(op+(sx&3)<<8,y,x)
    c_reg_ccx = xx;  c_reg_ccy = 0
  %finish %else beware(xx)
endass:
  dx_flags = dx_flags!okflag %if c_localdpos <= xx < dictlim %c
           %and c_forward = 0
  %return

do(incass):  !(for %for loop)
  flush %if pendcond # 0
  dx == dict(xx)
  sx = size(dx_type)
  wx = weight(x)
  act = add
tostore:
  %if y = 0 %start;  ![only for NOT,NEG]
    eval(x,ref)
  %else %if y < 0
    %if act = add %start;  ![+- literal]
      %if y >= litquick %start;  !-8:-1 or 1:8
        act = sub %and y = y-1 %if y&1 # 0;  !negate if neg
        eval(x,ref)
        -> past
      %finish
      act = sub %and y = y+1 %if y = -(128<<1);  !128=>-128
    %finish
    eval(x,ref)
    eval(y,anydreg) %if y >= litmite %and anydreg&free # 0
  %else %if x <= a7
    eval(y,val)
  %else
    %if 999 > wx < weight(y) %then eval(y,anydreg) %and eval(x,ref) %c
    %else eval(x,ref) %and eval(y,anydreg)
  %finish
past:
  plant(act+sx<<8,y,x)
  plant(trapv,0,0) %if control&overbit # 0 %and act <= sub
  beware(xx)
  c_reg_ccx = xx;  c_reg_ccy = 0
  ->endass


!!!!!!!!!!!!!!!!!!!!!!   Returns and jumps   !!!!!!!!!!!!!!!!!!!!!!!!
!
do(return):                 !terminate procedure
  update sp
  %if c_type # 0 %start;       !function,map
    r = typecell(c_dpid_type)_reg&15
    %if c_type > 0 %and size(c_type) > 0 %start;  !simple fn
      flush %if pendcond # 0 %and pendin # 0
      i = y
      %if c_reg_content(r+d0) # y %start
        flush %if pendcond # 0
        eval(y,d0b<<r)
      %finish
      c_status = c_status!wrongcc %unless c_reg_ccx = i %and c_reg_ccy = 0
    %else;   !struct fn or map
      c_status = c_status!wrongcc
      flush %if pendcond # 0
      y = y+ad %if c_type > 0;  !ie struct fn
      sp = c_sp
      eval(y,d0b<<r)
      %if c_sp # sp %start
        addimm(sp-c_sp,a7);  c_sp = sp
      %finish
    %finish
  %finish
  %if c_temps # 0 %start
    flush %if pendcond # 0
    addimm(c_temps,a7)
  %finish
  dict(dictlim)_val = c_return
  compile uncond branch(dictlim)
  c_return = -(pc-1)
  %return

do(jumpout):
  update sp
  flush %if pendcond > 0 %and pendin # 0
  save context(y) %if y # x;  !exit not continue
  compile uncond branch(y)
  %return

do(repeat):
  update sp
  compile uncond branch(x)
  define label(x+1) %if dict(x+1)_val < 0
  %if y < 0 %start;  !temp(s) declared
    c_val = y;  c_temps = c_temps+y;  !decrement temps
    update sp
  %finish
  %return

do(else):
  %if c_access # 0 %and c_access # -2 %start
    save context(y)
    compile uncond branch(y);  !outward branch for %else
  %finish
  define label(x) %if x # 0 %and dict(x)_val < 0;  !inward from false cond
  %return

do(goto):                        !user jump
  update sp
  c_forward = c_forward+1 %if dict(y)_val = 0
  addimm(c_temps,a7) %if c_temps # 0
  i = pendcond
  compile uncond branch(y)
  addimm(-c_temps,a7) %if i # 0 %and c_temps # 0
  %return

do(label):
  update sp
  define label(x)
  %return

do(stop):
  update sp
  flush %if pendcond # 0
  plant(clr,0,d0)
  srcall(signal)
  c_access = 0
  %return

do(signal):
  update sp
  flush %if pendcond # 0
  sp = c_sp
  pp = pp+1;  dp == dp[1]
  xx = dp_x;  yy = dp_y
  x = litval(x)
  %if yy # undef %start
    eval(yy,a0b+asad);  x = x+64
  %finish
  %if xx # undef %start
    eval(xx,d2b);  x = x+32
  %finish
  %if y # undef %start
    eval(y,d1b);  x = x+16
  %finish
  x = litref(x)
  eval(x,d0b)
  %if control&sysbit # 0 %then plant(jmp,0,signal) %else plant(jsr,0,signal)
  %if c_sp # sp %start;  ![earlier?]
    addimm(sp-c_sp,a7);  c_sp = sp
  %finish
  c_access = 0
  %return

do(settrap):
  update sp
  push(d0+6);                     ![historical]
  push(mb)
  plant(pea,0,temp(pcmode,10));  !address of mask [2+2+2+4]
  c_sp = c_sp-4
  push(gb+indir);                ![2 bytes]
  plant(move,a7,gb+indir);       ![2 bytes]
  c_eventsp = c_sp
  c_forward = c_forward+1
  lreg(c_lab1-dictlim) = c_reg
  plant(bra,0,c_lab1);           ![4 bytes]
  pflag(pc-1) = longjump;  !**not to be shortened
  forget regs
  plant(dc,0,temp(absmode,litval(y)));  !event mask
!  store(litval(y),0);  !event mask
  %return

do(swgoto):                     !switch jump
  flush %if pendcond # 0
  update sp
  dx == dict(x)
  dx_flags = dx_flags!rflag
  i = dx_val;  !start of table
  dy == typecell(dx_type)
  get bounds(dy_xtype,sx,sy)
  %if y <= 0 %start;  !literal subscript
    y = litval(y)
    i = i+y-sx
    addimm(c_temps,a7) %if c_temps # 0
    plant(bra,0,temp(labmode,prog(i)))
    prog(i) = dtemp_val;               !updated by PCREL
  %else
    eval(y,d0b)
    %if i > pc %start;                  !first jump (I >= SWPC)
      c_forward = c_forward+(sy-sx+1)
      %if dx_flags&arrflag = 0 %start;  !no check
        addimm(c_temps,a7) %if c_temps # 0
        plant(lea,temp(pcmode,10-sx-sx),a0); !LEA ?(PC),A0
        plant(add,d0,d0);                 !ADD D0,D0
      %else
        wx = 12
        %if c_temps # 0 %start
          wx = wx+2;  wx = wx+2 %if c_temps > 8
        %finish
        plant(lea,temp(pcmode,wx),a0)
        srcall(index)
        addimm(c_temps,a7) %if c_temps # 0
      %finish
      plant(add+2<<8,tempx(a0,d0),a0); !ADD.W 0(A0,D0),A0
      plant(jmp,0,a0+indir);         !JUMP (A0)
      %if dx_flags&arrflag # 0 %start
        store(sy>>16,0);  store(sy,0)
        store(sx>>16,0);  store(sx,0)
        store(0,0);  store(2,0)
      %finish
      dx_val = pc
      %cycle
        store(prog(i),0)
        swpc = swpc+1 %if i = swpc;  i = i+1
        sx = sx+1
      %repeat %until sx > sy
    %else;  !just branch to earlier sequence
            ![gives wrong line number for error]
            ![wrong if temps]
      i = i-7 %if dx_flags&arrflag # 0
      plant(bra,0,temp(labmode,i-6))
    %finish
  %finish
  c_access = 0
  %return

do(asize):
  %if y # 0 %start;  !first: prime D0
    update sp
    eval(y,d0b);  !basic itemsize
  %else
    srcall(asize)
  %finish
  pp = pp+1;  dp == dp[1]
  xx = dp_x;  yy = dp_y
  free = c_free-d0b;  !not d0
  eval(xx,d1b);  !lower
  eval(yy,d2b);  !upper
  push(d0);  !size
  push(d1);  push(d2)
  forget regs
  free = free!(d1b+d2b)
  dict(x)_val = c_sp
  %return
!
do(adok):  ![spare code]
!Push size of dynamic array (& 0-base value) for AGET
  update sp
  %if x # 0 %start
    %if x # d0 %then eval(x,d0b) %else srcall(asize)
  %finish
  push(y) %if y # 0
  push(d0)
  %return

do(aget):
  plant(move,x,d0)
  srcall(aget)
  plant(move,a7,x)
  %if y # 0 %start
    dx == dict(x)
    dx_val = dx_val+4
    plant(move,a7,d0)
    plant(add,d0,x)
    dx_val = dx_val-4
  %finish
  forget(d0);  forget(a0)
  %return

%routine COMPILE ENTRY(%integer linked,arg)
!Entry sequence generated at end
%integer i,r,vsp,lastvsp,holdsp
%record(identinfo)%name darg,tp
  holdsp = c_sp
  c_sp = 0;  lastvsp = 0
  c_stack = c_stack-4 %if linked > 0;  !allow for link
  %if linked = 0 %and c_status&onstack # 0 %start
    !justify addressing assumed for onstack parameters
    c_sp = 4;  holdsp = holdsp-4;  c_stack = c_stack-4
  %finish
  c_stack = c_stack-4;              !and return address
  c_totstack = c_stack %if c_stack < c_totstack
  %if control&stackbit # 0 %c
  %and (c_status&unknown # 0 %or c_totstack < -128) %start
    plantlit(move,c_stack,breg);  !*ok - gets cleared*
    srcall(stackok)
  %finish
  %if level > outerlevel %and linked > 0 %start;  !link required
    %if level > 1 %start
      plant(move,tempd(gb,level<<2),prea7);  !MOVE ?(GB),-(SP)
      plant(move,a7,tempd(gb,level<<2));  !MOVE SP,?(GB)
    %else
      plant(link,0,f1);       !LINK #0,Ax
    %finish
  %finish
  darg == dict(arg)
  %cycle
    arg = darg_link
    %exit %if arg = 0
    darg == dict(arg)
    %if darg_val <= 0 %start;  !passed in reg, not on stack
      vsp = darg_val
      r = darg_reg&15+d0
      %if darg_flags&mflag # 0 %or linked > 0 %start
        addimm(lastvsp-c_sp,a7);  c_sp = lastvsp
        i = nsize(darg)
        %if i > 0 %start
          ! name or simple operand by value
         !NB MOVE.B transfers to hi byte
          plant(move+i<<8,r,prea7)
        %else %if darg_flags&proc # 0;  !proc as param
          plant(move,r,prea7)
          plantlit(movew,16_4EF9,prea7)
        %else;                          !structure by value
          tp == typecell(darg_type)
          %if tp_flags&cat = stringy %start
            %if control&capbit # 0 %and tp_size > -256 %start
              plantlit(cmp+1<<8,-tp_size,r+indir)
              plantlit2(bcs,0,4)
              srcall(check)
            %finish
            i = c_sp-vsp
            addimm(-i,a7);            !SP = SP-bytes
            extend stack(i)
           !MOVE.B length,Dx
            plant(moveb,r+indir,breg)
           !MOVE.B 0(Ay,Dx),0(SP,Dx)
            plant(moveb,tempx(r,breg),tempx2(a7,breg))
            plant(subb,one,breg)
            plantlit2(bcc,0,-10)
          %else;  !fixed length structure
            free = bregb
            push block(r,c_sp-vsp)
          %finish
        %finish
        c_sp = vsp
      %finish
      lastvsp = vsp
    %finish
  %repeat
  %if c_sp # 0 %start;  !there are accesses to params
    addimm(lastvsp-c_sp,a7)
    c_sp = holdsp
  %finish %else c_sp = holdsp-lastvsp;  !reduce
%end

do(end):
  compile entry(c_status&globbed,c_dpid_type)
  %return

do(*): intern(8)
do(0):  !null action
%end;  !eval

%routine COMPILE(%integer startp)
%integer p
{?}  show exp(startp) %if control&explist # 0 %and control&list # 0
  np = np0 %and %return %if faultnum > 0
  pendcond = 0
  p = startp-1
  %cycle
    free = c_free
    p = p+1
    %if p >= np %start
      %if startp = np0 %start
        np = np0
        flush %if pendcond > 0
        %return
      %finish
      np = startp;  startp = np0;  p = startp
    %finish
    %if c_reg_line # line %and control&(tracebit!diagbit!linebit) # 0 %start
      flush %if pendcond > 0
      pendcond = -1
    %finish
    eval(p,inst)
  %repeat
%end;  !compile

%routine SET FIRST ENTRY
%integer j,k,p
%record(identinfo)%name dp
  firstpos = dictlim;  firstentry = finalbound
  p = 0
  %cycle
    p = p+1
    %exit %if p >= dlim
    dp == dict(p)
    %continue %if dp_mode # procmode
    %continue %if dp_val >= firstentry
    j = dp_val
    %if j <= 0 %start
      %continue %if j = 0
      k = -j
      %cycle
        j = k<<1
        k = code word(j)&16_FFFF
      %repeat %until k = 0
      %continue %if j >= firstentry
    %finish
    firstentry = j;  firstpos = p
  %repeat
%end

%routine DEFINE ENTRY(%integer chain,entry,pid)
%integer j
  %cycle
    chain = chain<<1
    report(reacherr,pid,0) %unless is short(entry-chain)
    j = code word(chain)&16_FFFF
!$IF VAX
{  final(chain) <- (entry-chain)>>8;  final(chain+1) <- entry-chain
!$IF APM
  shortinteger(final0+chain) <- entry-chain
!$FINISH
    chain = j
  %repeat %until chain = 0
%end

%routine CHECK REACH(%integer blocksize)
!Add stepping stones if necessary
%integer i
  %cycle
    i = blocksize+cad
    croak("Program too big") %if i >= ownbase
    %return %if i-firstentry < 31000;  !enough leeway
    %return %if blocksize >= 32000 %or cad-firstentry >= 32760;  !hopeless
    %if dict(firstpos)_val < 0 %start
      define entry(-dict(firstpos)_val,cad,firstpos)
      set code word(16_6000);  !BRA
      dict(firstpos)_val = -cad>>1
      set code word(0)
    %else
      dict(firstpos)_val = cad
      set code word(16_6000);  !BRA
      set code word(firstentry-cad)
    %finish
    steps = steps+2
    set first entry
  %repeat
%end

%routine PUT WORD(%integer v)
    printsymbol(v>>8&255);  printsymbol(v&255)
%end

%routine DO EXTERNALS(%integer chain,specs)
%integer k,a,b
%record(identinfo)%name dp,tp

  byteinteger(charlim) = 0;  ![see test for %alias]
  value = 2
  %cycle
    dp == dict(chain)
    a = dp_text+char0;  b = byteinteger(a)
    %if byteinteger(a+b+1)&128 # 0 %start;  !aliased
      a = a+b+1;  b = byteinteger(a)-128
    %finish
    value = value+(b+14)&(\1)
    %if specs >= 0  %start;  !for real
      put word(dp_flags&(ext+proc)!sign16)
      put word(dp_mode)
      k = 0
      %if dp_flags&proc # 0 %start
       !create type word
        tp == dict(dp_type)
        k = 4;  k = 6 %if tp_type # 0;  !100:R 11x:F,M
        %cycle
          k = k+1 %if tp_reg&8 # 0;    !0:dreg, 1:areg
          %exit %if tp_link <= 0
          tp == dict(tp_link);  k = k<<1
        %repeat
        !special code (11) for %routine ...(%string(255) parm)
        k = k+2 %if k = 9 %and tp_type = stringtype %and tp_flags >= 0
      %finish
      put word(k>>16);  put word(k)
      put word(dp_val>>16);  put word(dp_val)
      put word(b<<8+byteinteger(a+1))
      %cycle
        a = a+2;  b = b-2
        %exit %if b < 0
        k = byteinteger(a)<<8
        k = k+byteinteger(a+1) %if b > 0
        put word(k)
      %repeat
    %finish
    chain = dp_link
  %repeat %until chain = 0
  %if specs >= 0 %start
    put word(0)
    put word(0) %if value&3 # 0
  %finish
  value = (value+3)&(\3)
%end
!
%routine PUTACT(%integer act,x,y)
  dict(np)_act = act;  dict(np)_x = x;  dict(np)_y = y
  np = np+1
%end

%routine COMPILE END
%integer i,j,x,y,entry,lim
  %if c_reg_line # line %and control&(diagbit!linebit!tracebit) # 0 %c
  %and level > outerlevel %and c_access # 0 %start
    pendcond = -1
    flush
  %finish
  !Pop event block
  %if c_eventsp # 0 %start
    plant(move,temp(c_mode,c_eventsp),gb+indir)
    forget cc
  %finish
!Put pre-amble
  codeflag = '^';  x = pc;  !preserve
  putact(end,0,0)
  compile(np0)
  fill code(1) %if cad&1 # 0
  check reach((pc-c_localpc)<<1)
  entry = cad
  y = x
  %while y < pc %cycle
    %if pflag(y) = indglobal %then set code word(dict(prog(y))_val-cad) %c
    %else set code word(prog(y))
    y = y+1
  %repeat
  codeflag = ' ';  pc = x;  !restore
!Generate final sequence
  %if c_access # 0 %start
    %if level > outerlevel %and c_status&globbed # 0 %start
      %if level > 1 %start;  !display in store
        plant(move,tempd(gb,level<<2),a7);     !MOVE ?(GB),SP
        plant(move,posta7,tempd(gb,level<<2)); !MOVE (SP)+,?(GB)
        forget cc
      %else
        plant(unlk,0,f1)
      %finish
    %else %if c_sp < 0;  !some stack extension
      addimm(-c_sp,a7)
    %finish
    %if level > outerlevel %start
      c_dpid_flags = c_dpid_flags!okflag %if c_type > 0 %c
          %and c_status&wrongcc!c_reg_ccx!c_reg_ccy = 0
      plant(rts,0,0)
    %else
      plant(move,0,d0);  srcall(signal);  !%stop
    %finish
  %else;  !no return from procedure
    c_dpid_flags = c_dpid_flags!noret
  %finish
!Set start address
  x = c_dpid_val
  define entry(-x,entry,c_pid) %if x < 0;  !forward refs in FINAL
  c_dpid_val = entry
!
  lim = cad+(pc-c_localpc-c_shorts+zeroshorts)<<1
  x = c_localpc;  c_shorts = zeroshorts;  !reset
  %while x < pc %cycle
    y = prog(x);  j = pflag(x)
    %if j # 0 %start
      %if j < zeroshorts %start
        %if j <= longjump %start;  !shortjump/jump/longjump
          jumps = jumps+1
          y = (y-pflag(y)-x+c_shorts)<<1
          %if j = shortjump %start
            cad = cad-2
            y = prog(x-1)+y&255
            c_shorts = c_shorts+1
          %finish
        %else %if j = indglobal;  !procedure
          i = dict(y)_val
          %if i <= 0 %start;  !not yet encountered
            dict(y)_val = -(cad>>1);  y = -i
          %else
            i = i-cad
            report(reacherr,y,0) %unless is short(i)
            y = i
          %finish
        %else {global,negglobal,bigglobal}
          %if j # global+1 %start
            y = y&16_FFFF
            y = y+65536 %if j # global;  !bigglobal
          %finish
          y = y-cad
          %unless is short(y) %start
            %if prog(x-1)&16_F1FF # 16_41FA %start;  !LEA (PC),Ax
              report(creacherr,0,cad)
            %else
              i = cad;  cad = lim
              set code word(prog(x-1)!!(16_41FA!!16_207C)); !MOVEI #,Ax
              set code longword(y-2)
              set code word(prog(x-1)!!(16_41FA!!16_D1D7)); !ADD (SP),Ax
              set code word(16_4E75);                       !RTS
              lim = cad;  cad = i-2
              set code word(16_6100);  !BSR
              y = lim-10-cad
              steps = steps+5
            %finish
          %finish
        %finish
      %finish
    %finish
!$IF VAX
{    final(cad) <- y>>8;  final(cad+1) <- y
!$IF APM
    shortinteger(final0+cad) <- y
!$FINISH
    cad = cad+2
    x = x+1
  %repeat
  cad = lim
  forget all
%end;  !compile end

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!  end of Code Generation  !!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
!<<IMP
%routine TOPRED
  item = litref(value) %if item = 0
  putact(compare,item,0)
  condop = bne!!polarity
  item = np-1
%end
!<<BOTH
!
%routine RESET CONTEXT(%integer pid,free)
  starts = 0;  cycles = 0
  c = 0
  forget all
  c_localdpos = dlim;  c_parlim = dlim;  c_localtext = charlim
  c_localpc = pc;  c_localswpc = swpc;  c_lab1 = curlab
  c_shorts = zeroshorts;  c_free = free
  c_mode = framemode+level;  c_vintage = vintage
  c_pid = pid;  c_dpid == dict(c_pid)
%end

%routine OPEN BLOCK(%integer pid)
  forget regs;  !a bit extreme, but don't want to let LIT/EXP
                 ! get out of hand so RESET CONTEXT forgets triples
  croak("Too many levels") %if level = maxlevel
  c_oldcontrol = control
  hold(level) = c;  level = level+1;  vintage = vintage+1
  reset context(pid,c_free)
  c_access = 1;  c_localad = cad-accounted
%end;  !OPEN BLOCK

%predicate PARMATCH(%integer apos,bpos)
%record(identinfo)%name ap,bp,atp,btp
  %cycle
    ap == dict(apos);  bp == dict(bpos)
    %false %if ap_flags!!bp_flags < 0
    {%false %if ap_mode # bp_mode}
    %if ap_type # bp_type %start
      ![for now -- nominal]
      atp == typecell(ap_type);  btp == typecell(bp_type)
      %false %unless atp_flags&cat = arry = btp_flags&cat
    %finish
    apos = ap_link;  bpos = bp_link
    %if apos = 0 %start
      %false %if bpos # 0
      %true
    %else %if bpos = 0
      %false
    %finish
  %repeat
%end

%integer%fn CRUNCHED(%integer p)
%record(identinfo)%name dq,dp==dict(p)
%owninteger q=0,l=0
  dp_text = 0;  q = 0
  l = dp_link
  %if l # 0 %start
    l = crunched(l) %if dp_type < p
    %result = p %if p <= l
    dp_link = l
    q = l-1
  %finish
  dq == dict(q)
  %while q < p %cycle
    %if dq_type = dp_type %c
    %and dq_link = l %and dq_reg = dp_reg %and dq_val = dp_val %start
      dlim = p
      %result = q
    %finish
    q = q+1;  dq == dq[1]
  %repeat
  %result = p
%end

%routine POP CONTEXT
  pc = c_localpc;  swpc = c_localswpc;  curlab = c_lab1
  dlim = c_parlim
!  %for i = 0,1,255 %cycle
!    hashindex(i) = dict(hashindex(i))_hlink %while hashindex(i) >= c_localdpos
!  %repeat
  %if level > outerlevel %start
    charlim = c_localtext
    ranges = dict(ranges)_hlink %while ranges >= c_parlim
    c_dpid_type = crunched(c_dpid_type)
    level = level-1;  c = hold(level)
    control = control&editbit ! c_oldcontrol&(\editbit)
  %finish
  dictshown = dlim %if dictshown > dlim
  starts = 0;  cycles = 0
%end

%routine FIXUP SWITCH VECTOR(%integer pos,%record(identinfo)%name dp)
%integer x,y,j,default,temp,lo,hi
%record(identinfo)%name tp==typecell(dp_type)
  x = dp_val
  default = dp_link;  default = pc %if default = 0
  get bounds(tp_xtype,lo,hi)
  %if dp_flags&arrflag = 0 %then j = pflag(x-1)+lo %c
  %else j = pflag(x-7);  !allow for dope info
  j = x-j;  !base position
  %while lo <= hi %cycle;  !For each element
    y = prog(x)
    %if y <= 0 %start;  !not set
      %if dp_link = 0 %start;  !no default
        report(slabmissing+warn,pos,lo)
        c_access = 1
      %finish
      %if y < 0 %start;  !explicit jump(s) to this one
        y = -y
        %cycle;  !define jumps to default
          temp = y;  y = prog(temp);  prog(temp) = default
        %repeat %until y = 0
      %finish
      y = default
    %finish
    prog(x) = (y-pflag(y)-j)<<1
    x = x+1;  lo = lo+1
  %repeat
%end

%routine CLOSE BLOCK
%integer miss,under,pos,base
%record(identinfo)%name dp
 ! WRONGCC is clear if all %result statements leave correct CC
  %if c_type > 0 %and c_status&wrongcc = 0 %start
   ! set special values and see if they survive exit sequence
    c_reg_ccx = 0;  c_reg_ccy = 0
  %finish
  %if c_return # 0 %start
    %if c_return = -(pc-1) %and c_access = 0 %start
      c_return = -prog(pc-1);  pc = pc-2 
    %finish
    define jumps(c_return);  !must precede switch fixup
    c_access = -1
  %finish
  pflag(pc) = c_shorts;      !in case of terminal switch labels
  %if c_status&hadswitch # 0 %start
    pos = c_localdpos
    %while pos < dlim %cycle
      dp == dict(pos)
      fixup switch vector(pos,dp) %if dp_mode = labmode %and dp_type # 0
      pos = pos+1
    %repeat
  %finish
  compile end
  c_totstack = c_totstack-c_extra
  c_totstack = -c_totstack %if c_status&unknown = 0;  !positive if firm
  typecell(c_dpid_type)_val = c_totstack
{?}  %if control&maplist # 0 %start
{?}    put ident(c_pid,0)
{?}    mark at(20)
{?}    put string(" code:")
{?}    put num(cad-c_localad-accounted)
{?}    put string("  entry:")
{?}    put num(c_dpid_val-c_localad-accounted)
{?}    put string("  stack:");  put num(-c_stack)
{?}    putsym('/');  put num(|c_totstack|)
{?}    put sym('+') %if c_totstack < 0
{?}    accounted = cad-c_localad
{?}    print line
{?}  %finish
  !Check identifier usage
  miss = 0;  under = 0
  base = c_localdpos;  base = 0 %if level = outerlevel
  pos = dlim;  dp == dict(pos)
  %while pos > base %cycle
    pos = pos-1;  dp == dp[-1]
    %if dp_flags&ext = 0 %start
!<<IMP
!<<BOTH
      %if dp_text > 0 %start;               !user id
        set hashhead(string(dp_text+char0))
        %if head = pos %start;              !still active
          head = dp_hlink;                  !remove from hash list
check:    %if dp_flags&spec # 0 %start
            dp_hlink = miss;  miss = pos
          %else %if ((dp_flags&(readable+rflag) = readable %and dp_mode # litmode) %c
            %or (dp_flags&(writable+okflag+wflag+spec) = writable)) %c
            %and pos >= c_localdpos %and dp_mode # 0 %and dp_flags&typeid = 0 %c
            %and control&(list!maplist) # 0
            dp_hlink = under;  under = pos
          %finish
        %finish
      %finish
    %else %if level = outerlevel;  !external, external spec
      %if dp_flags&spec = 0 %start;  !external object
        dp_link = externs;  externs = pos
      %finish %else %if dp_flags&(rflag+wflag) # 0 %start
       !external spec (used)
        dp_link = extspecs;  extspecs = pos
      %finish
    %finish
  %repeat
  report(idmissing,miss,0) %if miss # 0
  %if under # 0 %and c_faults = 0 %start
    put ident(under,1)
    put string(" underused")
    print line
  %finish
  pop context
  set first entry %if firstpos >= dlim
%end;  !CLOSE BLOCK

%routine ERROR(%integer case)
  faultp = atomp
  report(case,0,0)
  %signal fail
%end

%constinteger DUD=63
%routine SYNTAX ERROR
  %if atom = dud %then error(atomerr+point) %else error(formerr+point)
%end

%routine EXPFAULT(%integer case)
  %if faultnum = 0 %or expp < faultp %start
    faultnum = case!point;  faultp = expp
  %finish
%end

%routine NONSTANDARD(%integer case)
%integer b
%owninteger hadit=0
  b = 1<<case
  %if b&hadit = 0 %and control&nonsbit = 0 %and faultnum = 0 %start
    hadit = hadit+b;  faultp = atomp
    %if control&strictbit # 0 %then report(nonstand+point,0,case) %c
    %else report(nonstand+point+warn,0,case)
  %finish
%end

%routine NAME ERROR
!check if the culprit has occurred before
!and, if not, add it to the pool of unknowns stored at the
!far end of the dictionary.
  %if item >= 0 %start;  !first time
    fault(namerr+point+now)
    %if charmin-newlen-80 >= charlim %start
      dmin = dmin-1;  dmin0 = dmin
      charmin = charmin-newlen-1
      string(charmin) = string(charlim)
      dict(dmin)_text = charmin-char0
      head == dict(head)_hlink %while head > 0;  !find last link
      dict(dmin)_hlink = head;  head = -dmin
    %finish
  %finish %else others = others+1
  %signal fail
%end

%routine FIND OP(%integer mnemonic,%integername op,types)
%integer i
  i = 0
  %cycle
    i = i+2
    error(namerr) %if i > defmax+defmax
  %repeat %until def(i) = mnemonic 
  types = def(i-1);  op = i>>1
%end

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!  Source input  !!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

%routine READ LINE(%integer flag)
! Read (or otherwise make available) the next source line
!     Output any pending error report;                 *NB*
!     Skip remnant of previous line if SYM # NL        *NB*
!     Set LINESTART to point to start of new line
!     Print new line on list output stream if listing requested
!       (Direct output routines CF diagnostics)
  report(faultnum,0,0) %if faultnum # 0
  %while sym > nl %cycle;               !Skip remnant
    sym = byteintegeR(fp);  fp = fp+1
  %repeat
  line = line+1
  %while fp = curlim %cycle
    %if curlim # cur_lim2 %start;  !in part1 of file
      fp = cur_start2
    %else %if curfile = main;      !on main
      %signal done
    %else
      cur_flag = -1
      disconnect edfile(cur)
      curfile = curfile-1
      cur == file(curfile)
      fp = cur_fp;  line = cur_line
      control = fcontrol(curfile)
      inclim = dlim %if level = outerlevel %and c_status < hadon
    %finish
    curstart = cur_start2;  curlim = cur_lim2
    %if fp < curstart %or fp > curlim %start
      curstart = cur_start1;  curlim = cur_lim1
    %finish
  %repeat
  linestart = fp
  %if flag = 0 %start
    flag = ' ';  flag = '&' %if curfile # main
  %finish
  listflag = flag
  %if control&list # 0 %start
    time1 = time1-cputime
    print line %if rep # ""
    show dict(dictshown) %if control&dictlist # 0
    dictshown = dlim
    write(line,4);  print symbol(listflag)
    print symbol(' ')
    %cycle
      sym = byteintegeR(fp);  fp = fp+1
      print symbol(sym)
    %repeat %until sym <= nl
    fp = linestart
    time1 = time1+cputime
  %finish
  sym = 0
%end;  !READ LINE

!<<IMP

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!  Lexical processing  !!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

%constinteger CASEBIT=32
%owninteger PERCENT=0, SUBATOM=0
!
!~!!!!!!!  Keyword codes -- used by KEYGEN to produce tables  !!
%constinteger KEYEND=1 {end},
  KEYREPEAT=2   {repeat},
  KEYFINISH=3   {finish},
  KEYELSE=4     {else},
  KEYBEGIN=5    {begin},
  EXIT=6        {exit_1,continue_0},
  KEYRETURN=7   {return},
  TF=8          {true_1,false_0},
  KEYRESULT=9   {result},
  KEYSTOP=10    {stop},
  KEYGOTO=11    {goto},
  KEYSIGNAL=12  {signal},
  KEYMONITOR=13 {monitor},
  KEYON=14      {on},
  IU=15         {if_0,unless_1},
  KEYWHILE=16   {while},
  KEYUNTIL=17   {until_1},
  KEYFOR=18     {for},
  KEYTHEN=19    {then},
  KEYSTART=20   {start},
  KEYCYCLE=21   {cycle},
  KEYLABEL=22   {label},
  KEYCONST=23   {const,constant},
  KEYOWN=24     {own},
  KEYEXT=25     {external_6,system_5,dynamic_7},
  KATTRIB=26    {readonly_0,writeonly_1,volatile_2},
  KTYPE=27      {short_3,half_6,byte_9,mite_12,boolean_15,char_18,text_25},
  KEYINTEGER=28 {integer},
  KEYLONG=29    {long},
  KEYREAL=30    {real},
  KEYSTRING=31  {string_0,cstring_1},
  KEYRECORD=32  {record},
  KEYNAME=33    {name},
  KEYFORMAT=34  {format},
  FNMAP=35      {fn_0,function_0,map_1},
  RPRED=36      {routine_0,predicate_1},
  KEYSPEC=37    {spec},
  KEYARRAY=38   {array},
  KEYSWITCH=39  {switch},
  KEYOF=40      {of},
  KEYFILE=41    {file},
  KEYPROGRAM=42 {program},
  KEYLIST=43    {list},
  KEYCONTROL=44 {control},
  KEYCOMMENT=45 {comment},
  KEYEVENT=46   {event},
  KEYINCLUDE=47 {include},
  KEYOPTION=48  {option},
  KEYALIAS=49   {alias},
  KEYNOT=50     {not},
  KEYAND=72     {and},
  KEYOR=73      {or}
!!  end of keyword codes
!
!Symbol lexical codes other than operators:
%constinteger TERMINATOR=51, CONST=52, IDENT=53, MODSIGN=54,
              COLON=59, COMMA=60, RIGHT=61, RIGHTB=62
{DUD=63}
%constinteger LEFT=55, LEFTB=56, ATSIGN=57, UNDERLINE=58

%constinteger ARROW=74, EQEQ=75, NOTEQEQ=76,
              EQUALS=77, NOTEQ=78, LESSEQ=79,
              LESS=80, GREATEQ=81, GREATER=82
%constinteger PLUS=83, MINUS=84, EXCLAM=85, EXCLAM2=86, DOT=87
%constinteger STAR=88, SLASH2=89, SLASH=90, AMPERSAND=91
%constinteger STAR2=92, BACKSLASH=93, UPARROW=94,
              BACKSLASH2=95, UPARROW2=96,
              TILDE=97,
              LSHIFT=98, RSHIFT=99
%constinteger ATOMMAX=99
%constinteger ALEFT=left, ARIGHT=right, RECSUB=underline,
              OVER=slash2, SCONC=dot

%constinteger SIMPLE=atommax+1, VSIMPLE=simple+1,
              MAJOR=plus, SCOND=arrow, COND=keyand, CONDQ=71
!
%integer%fn NEXT ATOM
!Encode next atom from source file
![Time-critical]
%switch s(0:255)
%constinteger TAB=9,
              MAX10=maxint//10, MAXDIG=maxint-max10*10
%integer i,j,p,radix,hash
%real rval
%constbytearray map(0:127) =
  0 ('0'),
  '0','1','2','3','4','5','6','7','8','9',
  0, 0, 0, 0, 0, 0, 0,
  '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',
  0, 0, 0, 0, 0, 0,
  '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',
  0, 0, 0, 0, 0

!~!!!!!!!!!!!!!!!  Ex KEYGEN  !!!!!!!!!!!!!!!!!!!!
%CONSTSHORTINTEGERARRAY SYMINIT(97:122) =  %C
2,15,31,72,79,102,133,137,141,1,1,156,169,183,190,205,
1,220,257,297,309,319,327,1,1,1

%CONSTBYTEINTEGERARRAY SYMBOL(1:340) =  %C
128,114,114,97,121,166,108,105,97,115,177,110,100,200,101,103,
105,110,133,121,116,101,155,111,111,108,101,97,110,155,111,110,
116,105,110,117,101,134,121,99,108,101,149,104,97,114,155,115,
116,114,105,110,103,159,109,109,101,110,116,173,115,116,97,110,
116,151,151,114,111,108,172,121,110,97,109,105,99,153,110,100,
129,108,115,101,132,120,105,116,134,118,101,110,116,174,116,101,
114,110,97,108,153,105,110,105,115,104,131,97,108,115,101,136,
111,114,109,97,116,162,110,163,117,110,99,116,105,111,110,163,
146,108,101,169,111,116,111,139,97,108,102,155,102,143,110,116,
101,103,101,114,156,99,108,117,100,101,175,97,98,101,108,150,
111,110,103,157,105,115,116,171,111,110,105,116,111,114,141,105,
116,101,155,97,112,163,97,109,101,161,111,116,178,110,142,119,
110,152,102,168,112,116,105,111,110,176,114,201,114,101,100,105,
99,97,116,101,164,111,103,114,97,109,170,101,112,101,97,116,
130,111,117,116,105,110,101,164,116,117,114,110,135,115,117,108,
116,137,97,100,111,110,108,121,154,99,111,114,100,160,108,158,
116,111,112,138,105,103,110,97,108,140,121,115,116,101,109,153,
104,111,114,116,155,112,101,99,165,119,105,116,99,104,167,97,
114,116,148,114,105,110,103,159,114,117,101,136,104,101,110,147,
101,120,116,155,110,108,101,115,115,143,116,105,108,145,111,108,
97,116,105,108,101,154,104,105,108,101,144,114,105,116,101,111,
110,108,121,154

%CONSTBYTEINTEGERARRAY ALTDISP(1:340) =  %C
0,5,0,0,0,0,5,0,0,0,0,0,0,0,5,0,
0,0,0,4,0,0,9,0,0,0,0,0,0,15,8,23,
28,34,0,0,0,0,5,0,0,0,0,4,0,0,18,0,
0,0,0,0,0,1,0,0,0,0,0,0,0,0,4,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,0,
0,4,0,0,0,4,8,0,1,0,0,0,0,0,0,0,
0,0,0,0,6,6,27,0,0,0,0,5,0,0,0,0,
6,0,14,0,0,0,2,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,6,2,0,0,6,
0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,
4,0,0,0,0,0,0,0,7,0,0,0,0,0,0,4,
0,0,12,0,0,1,4,0,0,0,0,0,0,2,0,3,
0,0,2,0,6,0,0,0,0,0,0,0,0,8,0,0,
0,0,0,0,1,0,0,0,0,0,0,6,12,0,0,0,
0,0,0,0,0,0,0,0,5,0,0,0,0,5,0,0,
0,0,7,11,0,0,0,0,0,0,0,0,0,0,0,0,
4,30,0,0,6,0,0,0,0,0,6,0,0,0,0,5,
5,0,0,0,3,4,0,0,0,0,0,0,0,0,0,4,
0,0,0,0,0,0,0,0,4,0,0,1,4,0,0,0,
0,0,0,25,0,5,0,0,0,1,0,0,0,1,0,0,
0,0,0,0,0,2,5,0,0,0,0,0,0,0,0,0,
0,0,0,1


!! end of generated tables

%routine GET SYM
  %cycle
    sym = byteintegeR(fp);  fp = fp+1
  %repeat %until sym # ' '
  i = sym-'0'
  %if i >= 10 %start
    i = sym!casebit-'a';  i = i+10 %if i >= 0
  %finish
%end

  matched = 0
again: s(tab):
  read line(0) %if sym = nl
again1:
  %cycle
    sym = byteintegeR(fp);  fp = fp+1
  %repeat %until sym # ' '
  atomp = fp;     !(actually one after)
  atoms = atoms+1
  -> s(sym)
linebreak: s(nl):
  %result = terminator %if atom # comma
continuation:
  read line('+')
  -> again1

s('{'):
  comments = comments+1
  %cycle
    sym = byteintegeR(fp);  fp = fp+1
    -> linebreak %if sym = nl
  %repeat %until sym = '}'
  -> again

s('+'): %result = plus
s('-'): fp = fp+1 %and %result = arrow %if byteintegeR(fp) = '>'
        -> continuation %if byteintegeR(fp) = nl
        %result = minus
s('*'): %result = star
s('/'): fp = fp+1 %and %result = slash2 %if byteintegeR(fp) = '/'
        %result = slash
s('\'): fp = fp+1 %and %result = backslash2 %if byteintegeR(fp) = '\'
        fp = fp+1 %and %result = noteq %if byteinteger(fp) = '='
        %result = backslash
s('^'): fp = fp+1 %and %result = uparrow2 %if byteintegeR(fp) = '^'
        %result = uparrow
s('~'): %result = tilde
s('!'): fp = fp+1 %and %result = exclam2 %if byteintegeR(fp) = '!'
        %result = exclam
s('&'): %result = ampersand
s('.'): rval = 0 %and -> fraction %if '0' <= byteinteger(fp) <= '9'
        %result = dot
s('='): fp = fp+1 %and %result = eqeq %if byteintegeR(fp) = '='
        %result = equals
s('#'): fp = fp+1 %and %result = noteqeq %if byteintegeR(fp) = '#'
        %result = noteq
s('<'): fp = fp+1 %and %result = lesseq %if byteintegeR(fp) = '='
        fp = fp+1 %and %result = noteq %if byteintegeR(fp) = '>'
        fp = fp+1 %and %result = lshift %if byteintegeR(fp) = '<'
        %result = less
s('>'): fp = fp+1 %and %result = greateq %if byteintegeR(fp) = '='
        fp = fp+1 %and %result = rshift %if byteintegeR(fp) = '>'
        %result = greater
s('_'): %result = underline
s(':'): %result = colon
s(','): %result = comma
s(';'): %result = terminator
s('('): %result = left
s('['): %result = leftb
s(')'): %result = right
s(']'): %result = rightb
s('|'): %result = modsign
s('@'): %result = atsign

s('M'): s('m'):
  fp = fp+1 %and -> charconst %if byteintegeR(fp) = ''''
s('A'):s('B'):s('C'):s('D'):s('E'):s('F'):s('G'):s('H'):
s('I'):s('J'):s('K'):s('L'):s('N'):s('O'):s('P'):
s('Q'):s('R'):s('S'):s('T'):s('U'):s('V'):s('W'):s('X'):
s('Y'):s('Z'):s('a'):s('b'):s('c'):s('d'):s('e'):s('f'):
s('g'):s('h'):s('i'):s('j'):s('k'):s('l'):s('n'):
s('o'):s('p'):s('q'):s('r'):s('s'):s('t'):s('u'):s('v'):
s('w'):s('x'):s('y'):s('z'):
  -> keyword %if percent # 0
  newlen = charlim+1;  hash = sym!casebit;  !lower-case (if letter)
  byteinteger(newlen) = hash
  %cycle
    sym = byteintegeR(fp);  fp = fp+1
  %repeat %until sym # ' '
  %if sym = '''' %start;  !damned IBM-style literals
    radix = 16 %and ->ibm %if hash = 'x'
    radix = 8 %and ->ibm %if hash = 'k'
    radix = 2 %and ->ibm %if hash = 'b'
  %finish
  sym = map(sym)
  %if sym # 0 %start
    %cycle
      newlen = newlen+1;  byteinteger(newlen) = sym
      hash = hash<<1!!sym
      %cycle
        sym = byteintegeR(fp);  fp = fp+1
      %repeat %until sym # ' '
      sym = map(sym)
    %repeat %until sym = 0
  %finish
  fp = fp-1
  newlen = newlen-charlim;  byteinteger(charlim) = newlen
  %if subbed # 0 %then head == dformat_link %c
  %else head == hashindex(hash&255)
  item = head
  %if item # 0 %start
    %cycle
      ditem == dict(|item|)
      %exit %if string(ditem_text+char0) = string(charlim) %c
            %and (item > a7 %or item < 0 %or control&lowbit # 0)
      item = ditem_hlink
    %repeat %until item = 0
  %finish
  identatoms = identatoms+1
  %result = ident

s('%'):
  sym = byteintegeR(fp)
  -> again %unless 'a' <= sym!casebit <= 'z'
  fp = fp+1
keyword:
  percent = 0
  p = syminit(sym!casebit)
  %cycle
!     %cycle
!       sym = byteintegeR(fp)!casebit
!       %exit %if symbol(p) # sym
    %while symbol(p) = byteintegeR(fp)!casebit %cycle
      p = p+1;  fp = fp+1
    %repeat
    %exit %if symbol(p) > 127
    atom = altdisp(p)
    %if atom = 0 %start
      %result = dud %unless sym!casebit = 'c' %and byteintegeR(fp) = nl
      ->continuation
    %finish
    p = p+atom
  %repeat
  percent = 1 %if 'a' <= byteintegeR(fp)!casebit <= 'z'
  subatom = altdisp(p)
  atom = symbol(p)-128
  %result = dud %if atom = 0
  %result = atom

ibm:
  nonstandard(20)
  item = -1;  value = 0
  -> ibm1
s('0'):s('1'):s('2'):s('3'):s('4'):s('5'):s('6'):s('7'):s('8'):s('9'):
  item = 0;  type = inttype
  radix = 10;  value = sym-'0'
ibm1:
  %cycle
    %cycle
      %cycle
        sym = byteintegeR(fp);  fp = fp+1
      %repeat %until sym # ' '
      i = sym-'0'
      %if radix = 10 %start
        %exit %if i < 0 %or i >= 10
        fault(rangerr+point+warn) %if value > max10 %or (value=max10 %and i > maxdig)
        value = (value<<2+value)<<1+i
      %else
        i = sym!casebit-'a'+10 %if i >= 10
        %exit %if i < 0 %or i >= radix
        j = radix
        %cycle
          i = i+value %if j&1 # 0
          value = value<<1;  j = j>>1
        %repeat %until j = 0
        value = i
      %finish
    %repeat
    %exit %unless sym = '_'
    radix = value
    %result = dud %if radix = 0
    value = 0
  %repeat
  %if item < 0 %start;  !IBM-style
    %result = dud %if sym # ''''
    item = 0
  %else
    j = 0
    %if sym = '.' %start
      rval = value %if type = inttype
fraction:
      j = 0
      type = realtype
      %cycle
        get sym
        %exit %unless 0 <= i < radix
        rval = rval*radix+i;  j = j-1
      %repeat
      %result = dud %if j = 0
    %finish
    %if sym = '@' %start
      type = realtype %and rval = value %if type = inttype
      get sym
      value = 0
      %if sym = '+' %then get sym %c
      %else %if sym = '-' %then value = 1 %and get sym
      %result = dud %unless 0 <= i < radix
      p = 0
      %cycle
        p = p*radix+i
        get sym
      %repeat %until %not 0 <= i < radix
      p = -p %if value # 0
      j = j+p
    %finish
    %if type = realtype %start
      rval = rval*radix^j %if j # 0
      value = integer(addr(rval)) %if type = realtype
    %finish
    fp = fp-1;  sym = 0
  %finish
  litatoms = litatoms+1
  %result = const

s(''''):
charconst:
  item = 0;  type = inttype
  value = 0
  %cycle
    sym = byteintegeR(fp);  fp = fp+1
    %result = dud %if sym = nl;  !?allow
    %if sym = '''' %start
      %exit %unless byteintegeR(fp) = ''''
      fp = fp+1
    %finish
    value = value<<8+sym
  %repeat
  %result = const %if value # 0
  %result = dud

s('"'):
  item = 0
  value = cad;  type = stringtype
  i = line;  j = linestart;  p = 0
  %cycle
    sym = byteintegeR(fp);  fp = fp+1
    %if sym = '"' %start
      %exit %if byteintegeR(fp) # '"'
      fp = fp+1
    %finish
    p = p+1
    %if p > 255 %start
      sym = 0
      fp = atomp;  linestart = j
      %result = dud
    %finish
    final(value+p) = sym
    read line('"') %if sym = nl
  %repeat
  %if p # 0 %start;  !not empty string
    final(value) = p
    cad = cad+(p+1)
  %finish %else value = 0
  litatoms = litatoms+1
  %result = const

s(*):
  %result = dud
%end;  !NEXT ATOM

!<<BOTH

%predicate A (%integer k)
!Basic atom-testing predicate
  atom = next atom %if matched # 0
  %false %if k # atom
  matched = 1
  %true
%end

%routine GET(%integer k)
  atom = next atom %if matched # 0
  matched = 1
  %return %if atom = k
  syntax error { %if atom = dud
!  faultp = atomp
!  report(formerr+point,-k,0)
!  %signal fail
%end

!<<IMP

%routine ALLOW(%integer k)
  %if a(k) %start
  %finish
%end

%routine GET LITSTRING
%integer holditem
!Must be quoted string (for %alias and %include)
  holditem = item;  !preserve
  get(const)
  error(typerr+point) %unless type = stringtype
  cad = value;  !reset
  item = holditem;  !restore
%end

!<<BOTH

%integer%fn IDTEXT(%integer f)
%integer k
  %result = ditem_text %if item > 0 %and f&ext = 0;  !already exists
  charlim = charlim+newlen+1
  croak("Identifier space exhausted") %if charlim+80 >= charmin
  k = charlim-newlen-1-char0
  %if f&ext # 0 %and a(keyalias) %start
    get LITSTRING
    string(charlim) = string(final0+value)
    byteinteger(charlim) = byteinteger(charlim)+128
    charlim = charlim+byteinteger(charlim)-127
  %finish
  %result = k
%end

%record(objinfo)%map DETAILS(%integer f,t,m,v)
%ownrecord(objinfo) D=0
  d_flags = f;  d_type = t
  d_mode = m;  d_val = v
  %result == d
%end

%routine DECLARE(%record(objinfo)%name d)
%integer i
%record(identinfo)%name dp
  dp == dict(dlim)
  %if speccing = 0 %start;  !not within spec params
    %if item >= c_localdpos %start;  !there already
      %if d_flags&spec = 0 %and ditem_flags&spec # 0 %start
        !body after spec (proc,label,typeid)
        %if d_flags&(ext+proc+typeid) = ditem_flags&(ext+proc+typeid) %start
          i = item
          %if d_flags&ext # 0 %start
            ![can't allow %ext%spec, then use, then %ext object]
            ->ok %if ditem_flags&rflag # 0;  ![so create new entry]
            ditem_mode = d_mode;  ditem_val = d_val
            %if a(keyalias) %start
              get LITSTRING;  !ignore [should be identical]
              item = i
            %finish
          %finish
          %if d_flags&proc = 0 %start
            ditem_flags = ditem_flags&(\(spec+indirect))
          %finish
          %return
        %finish
        %if ditem_flags&(ext+proc) = proc1 %and d_flags&ext # 0 %c
            %and d_flags&proc # 0 %start;  !(internal) %spec then %ext
          ditem_flags = ditem_flags-proc1+(d_flags&(ext+proc))
          ditem_text = idtext(ext);  !in case alias
          %return
        %finish
      %finish
!<<IMP
      %if item < inclim %and ditem_flags&(rflag+wflag) = 0 %c
      %then fault(duperr+warn+point) %else fault(duperr+point)
!<<BOTH
    %finish
ok: dp_hlink = head;  head = dlim;  !insert in list
    dp_text = idtext(d_flags)
  %finish %else dp_hlink = 0 %and dp_text = 0
  item = dlim;  ditem == dp
  ditem_details = d
  dlim = dlim+1
  %if dlim >= dmin %start
{?}    show dict(0) %if control&logbit # 0
    croak("Too many identifiers")
  %finish
%end;  !DECLARE

%routine DECLARE ANON(%record(objinfo)%name d)
  speccing = speccing+1
  item = 0
  declare(d)
  speccing = speccing-1
%end
!
%routine DECLARE TEMP(%integer t)
  c_val = c_val+4;  c_temps = c_temps+4
  declare anon(details(okflag+writable+readable,t,c_mode,c_sp-c_val))
%end
!
%routine DECLARE RANGE(%integer type,lower,upper)
!Type ident just declared
%integer s
%predicate OK(%integer l,u)
  %true %if (l <= lower %and upper <= u) {signed} %c
        %or (0 <= lower %and upper <= u-l) {unsigned}
  %false
%end
  s = 4
  %if ok(-32768,32767) %start
    s = 2;  s = 1 %if ok(-128,127)
  %finish
  ditem_details = details(typeid,type,absmode,sign)
  ditem_size = s
  declare anon(details(okflag,type,litmode,lower))
  declare anon(details(okflag,type,litmode,upper))
  ditem_hlink = ranges;  ranges = item
  item = item-2
%end

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!  Expressions  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

%owninteger LITERAL=0, JAMMY=0

%routine%spec GET EXPRESSION(%integer rank,etype)
!
%predicate VALOK(%integer wanted,t)
%integer lo,hi,l,h,wc,tc
%record(identinfo)%name wp,tp
  %true %if wanted = t # recstar
  wp == typecell(wanted);  tp == typecell(t)
  wc = wp_flags&(packed+cat);  tc = tp_flags&(packed+cat)
  %if wc = tc %start;  !same class
    %if wc&nonord = 0 %start;  !ordinal wanted
      %if wp_type = tp_type %start;  !same base-type
        %true %if wp_type = wanted;  !base-type (rather than subrange)
        %if wp[1]_mode # litmode %then get bounds(wp[1]_type,lo,hi) %c
        %else lo = wp[1]_val
        %if wp[2]_mode # litmode %then get bounds(wp[2]_type,hi,hi) %c
        %else hi = wp[2]_val
        %if item = 0 %start;  !literal
          %true %if lo <= value <= hi
          jammy = jammy!!1
        %else
          jammy = jammy!!1 %and %true %if tp_type = t
          %if tp[1]_mode # litmode %then get bounds(tp[1]_type,l,h) %c
          %else l = tp[1]_val
          %if tp[2]_mode # litmode %then get bounds(tp[2]_type,h,h) %c
          %else h = tp[2]_val
          %if l >= lo %start
            %true %if h <= hi
            jammy = jammy!!1
            %true %if l <= hi
          %else
            jammy = jammy!!1
            %true %if h >= lo
          %finish
        %finish
        expfault(rangerr) %if jammy # 0
        %true
      %finish
    %else %if wc = realy
      %true
    %else %if wc = stringy;  !string wanted
      %true %if wanted = stringstar
      %if item = 0 %start
        %true %if value = 0;  !empty string
        l = final(value)+1
      %else
        l = |tp_size|
        l = 256 %if l = 0
      %finish
      %if l > |wp_size| # 0 %start
        jammy = jammy!!1
        expfault(rangerr) %if item = 0 %and jammy # 0
      %finish
      %true
!<<IMP
    %else %if wc&cat = arry
      %true %if wp_type = tp_type %and valok(wp_xtype,tp_xtype)
!<<BOTH
    %else;                          !record etc
      %if wanted = recstar %start
        %true %if t # recstar
      %else
        %true %if t = recstar %or item!value = 0
      %finish
    %finish
  %else;                            !category difference
    %if tc = inty %start
      %true %if wc = recy %and item!value = 0;  !RECORD = 0
      toreal %and %true %if wc = realy;         !REAL   = INT
    %else %if wc = stringy %and t = chartype;   !STRING = CHAR
      %if item = 0 %start;           !null string
        final(cad) = 1;  final(cad+1) = value
        value = cad;  cad = cad+2
        type = stringtype
      %finish %else putexp(dtostring,normitem,0,string1)
      %true
!<<IMP
! sets again
!<<BOTH
    %finish
  %finish
  %false
%end
!
%routine GET VALUE(%integer valtype)
  get EXPRESSION(major,valtype)
%end;  !GET VALUE
!
%routine GET LITERAL(%integer t)
  literal = literal+1
  get EXPRESSION(major,t)
  literal = literal-1
%end
!
!!!!!!!!!!!!!!!!!!!!!!  Machine-code  !!!!!!!!!!!!!!!!!!!!!!!!!!
!
%routine GET MIDENT(%integer min,max)
  get(ident)
  %if item <= 0 %start
    name error %if string(charlim) # "sp"
    item = a7
    ditem == dict(item)
  %finish
  %if ditem_mode = litmode %start
    value = ditem_val;  item = 0
  %finish
  syntax error %unless min <= item <= max
%end

%routine GET REGSET
%integer hold,set=0
  %cycle
    get mident(d0,a7)
    hold = item
    get mident(hold,a7) %if a(minus)
    %cycle
      set = set!1<<(hold-d0)
      hold = hold+1
    %repeat %until hold > item
  %repeat %until %not a(slash)
  item = 0;  value = set
%end

%routine get MCODE
%integer op,x,y,types

%integer%fn OPSIZE(%integer okbyte)
  %result = 0 %if %not a(dot)
  sym = byteinteger(fp)&(\casebit);  fp = fp+1
  %result = 4 %if sym = 'L'
  %result = 2 %if sym = 'W'
  %result = 1 %if sym = okbyte
  syntax error
%end

%routine get MOP(%integer t,dummy,%record(identinfo)%name dp)
!Get Mcode operand
%constinteger HASHSIGN=noteq
%integer sign,hold,holdval,m
  %if a(hashsign) %start
    get LITERAL(inttype)
    %return
  %finish
  sign = 0;  hold = -1;  holdval = 0
  sign = 1 %if a(minus)
  %if a(ident) %start
    matched = 0
    get mident(0,dlim)
    hold = item
    %if hold # 0 %start
      syntax error %if sign # 0
      %if item > a7 %start
        dp_flags = ditem_flags
        dp_mode = ditem_mode;  dp_val = ditem_val
        %while a(recsub) %cycle
          dformat == typecell(ditem_type)
          syntax error %unless dformat_flags&cat = recy %c
                       %and ditem_flags&(name+indirect) = 0
          subbed = 1;  get(ident);  subbed = 0
          error(namerr+point) %if item <= 0
          dp_flags = ditem_flags;  dp_type = ditem_type
          dp_val = dp_val+ditem_val
          item = dummy;  ditem == dp
        %repeat
        %return
      %finish
      %if op&255 = movem %and item > 0 %start
        matched = 0
        get regset
      %finish
      %return
    %finish
    holdval = value
  %else %if a(const)
    hold = 0;  holdval = value
  %finish
  holdval = -holdval %if sign # 0
  %if a(left) %start
    get mident(a0,a7)
    %if hold < 0 %start
      get(right)
      %if sign # 0 %then item = item+pre %c
      %else %if %not a(plus) %then item = item+indir %c
      %else item = item+post
      %return
    %finish
    m = item+(dispmode-a0)
    %if a(comma) %start
      get mident(d0,a7)
      fault(rangerr) %unless is mite(holdval)
      m = m+(indexmode-dispmode)
      holdval = (item-d0)<<12+holdval&255
      holdval = holdval+16_0800 %if opsize(0) # 2
    %finish
    get(right)
  %else
    syntax error %if hold < 0
    m = absmode
  %finish
  dp_mode = m;  dp_val = holdval
  item = dummy
%end

%constinteger temp=((('t'&31)<<5+('e'&31))<<5+('m'&31))<<5+('p'&31)
  update sp
!Pack mnemonic
  atomp = fp+1
  x = 0
  %cycle
    sym = byteinteger(fp);  fp = fp+1
    %exit %unless 'A' <= sym&(\casebit) <= 'Z'
    sym = sym&31
    x = x<<5+sym
  %repeat
  fp = fp-1;  sym = 0
  syntax error %if x = 0
  %if x = temp %start;       !*TEMP ...
    value = 0
    matched = 0 %and get regset %if a(ident)
    c_free = value
    %return
  %finish
  x = x<<5 %until x&(31<<25) # 0
  x = x!16_C0000000
  find op(x,op,types)
  op = op+opsize('B')<<8 %if types&(sized!asized) # 0
  x = 0;  y = 0
  %if types>>6&63 # 0 %start
    get MOP(types>>6&63,lablim,dtemp)
    x = normitem
    get(comma) %if types&63 # 0
  %finish
  %if types&63 # 0 %start
    get MOP(types&63,lablim+1,dtemp2)
    y = normitem
  %finish
  plant(op,x,y)
  forget regs;  c_access = -1
%end;  !get MCODE

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

%predicate REFOK(%integer wanted,t)
%record(identinfo)%name wp,tp
  %true %if t = wanted %or wanted = 0 %or t = 0 %or item!value = 0
  wp == typecell(wanted);  tp == typecell(t)
  %if (wp_flags!!tp_flags)&(name+packed+cat) = 0 %start
    %if wp_flags&cat = arry %start
      !**check index compatible
      %true %if refok(wp_type,tp_type)
    %else %if wp_flags&cat = stringy
      %true %if tp_size = 0 %or wp_size = 0
!<<IMP
!<<BOTH
    %else
      %true %if t = recstar %or wanted = recstar
    %finish
  %finish
  %false
%end

%routine TOREF
  atomp=expp %and error(nonref+point) %if item <= 0 %or ditem_mode < dispmode
  %if item >= dictlim %start
!    %if ditem_act = prel %and (ditem_y < 0 %or ditem_type = bytetype) %start
!      value = ditem_y
!      value = litref(litval(value)*|size(ditem_type)|) %if ditem_type # bytetype
!      putexp(add,ditem_x+ad,value,ditem_type)
!      %return
!    %finish
  %else
    %if ditem_mode = absmode %and ditem_flags >= 0 %start
      item = 0;  value = ditem_val
      %return
    %finish
  %finish
  item = item+ad
%end
!
%routine COPY DOWN(%integer np1)
  %while np > np1 %cycle
    np = np-1;  explo = explo-1
    dict(explo) = dict(np)
  %repeat
%end

%routine GET REFERENCE(%integer reftype)
  get EXPRESSION(simple,reftype!sign16)
%end
!
%routine GET PARLIST(%integer special)
%integer procnp,pact,hold,count,headitem,arg,p,q,restype
%record(identinfo)%name hp,tp
%record(identinfo)%name darg

%routine PUT ACTUAL
  item = litref(value) %if item = 0
  %if count&1 = 0 %then hold = item %c
  %else putact(pact,hold,item) %and pact = 0
  count = count+1
%end

%predicate NO ALT
  %if hp_flags&alt = 0 %start;  !no alternative
    expfault(typerr)
    %true
  %finish
  item = hp_hlink
  %cycle
    report(internerr,0,6) %and %signal fail %if item <= 0
    ditem == dict(item)
    %exit %if string(ditem_text+char0) = string(hp_text+char0)
    item = ditem_hlink
  %repeat
  headitem = item;  pact = headitem;  hp == ditem
  arg = hp_type;  darg == dict(arg);  restype = darg_type
  %false
%end

%routine PUT BOUNDS(%integer ft,at)
! FT is TYPE of formal, AT of actual array
%integer maxarg=arg
%record(identinfo)%name ftp,atp,fxp,axp
%cycle
  ftp == typecell(ft);  atp == typecell(at)
!  %if ftp_flags&indirect # 0 %start;           !complete dope vector
!    ![now only for %string(*)%array%name]
!    intern(11) %unless ftp_type = stringstar
!    item = at
!    put actual
!    maxarg = ft %if ft > maxarg
!    %exit
!  %finish
  %if ftp_flags&cat = stringy %start
    %exit %if ftp_size # 0
    %if atp_size # 0 %then item = litref(|atp_size|) -
    %else item = at-1
    put actual
    maxarg = ft-1 %if ft-1 > maxarg
    %exit
  %finish
  %if ftp_xtype >= arg %start;    !index type
    fxp == typecell(ftp_xtype);  axp == typecell(atp_xtype)
    %if fxp[1]_mode # litmode %start;  !non-literal lower
      item = atp_xtype+1
      item = 0 %and value = axp[1]_val %if axp[1]_mode = litmode
      put actual
      maxarg = ftp_xtype+1 %if ftp_xtype >= maxarg
    %finish
    %if fxp[2]_mode # litmode %start;  !non-literal upper
      item = atp_xtype+2
      item = 0 %and value = axp[2]_val %if axp[2]_mode = litmode
      put actual
      maxarg = ftp_xtype+2 %if ftp_xtype+1 >= maxarg
    %finish
  %finish
  ft = ftp_type;  at = atp_type;        !element types
%repeat %until ft <= arg
arg = maxarg;  darg == dict(arg)
%end

  count = 0;  hold = 0
  procnp = np
  headitem = item;  pact = headitem;  hp == ditem
  arg = hp_type;  darg == dict(arg);  restype = darg_type
  %if a(left) %start
    %cycle
      arg = darg_link
      %if arg = 0 %start
        error(toomany+point) %if special = 0
        get REFERENCE(0)
        value = item-ad;  !save extra item
        %cycle
          %if type = realtype %start
            %exit %if restype = realtype;  !no coercion
          %else
            %exit %if valok(type,restype)
          %finish
        %repeat %until no alt
        special = 0
      %else
        darg == dict(arg)
        %if darg_flags&proc # 0 %start
          get(ident)
          name error %if item <= 0
          fault(typerr+point) %if ditem_flags&proc = 0 %c
                              %or %not parmatch(darg_type,ditem_type)
          fault(classerr+point) %if item > headitem -
                                %and ditem_mode = procmode {OK if param?}
          item = item+ad
          put actual
        %else %if darg_flags >= 0
          jammy = 0
          get EXPRESSION(major,0)
          %cycle
            %exit %if valok(darg_type,type)
          %repeat %until no alt
          putexp(check,darg_type,item,darg_type) %if jammy # 0 %c
                                        %and control&capbit # 0 %c
                                        %and category(darg_type) < realy
          put actual
        %else;  !name
          get REFERENCE(0)
          %cycle
            %exit %if refok(darg_type,type)
          %repeat %until no alt
          put actual
          tp == typecell(darg_type)
          %if tp_flags&cat = arry %c
          %and dict(arg+1)_type # darg_type %c
          %and tp_mode >= framemode %start
            !array name (last in group) with non-literal dope vector
            put bounds(darg_type,type)
          %finish
        %finish
      %finish
    %repeat %until %not a(comma)
    error(toofew+point) %if darg_link # 0 %or special # 0
    get(right)
  %else;                              !no LEFT
    error(toofew+point) %if darg_link # 0
  %finish
  put act(pact,hold,0) %if count&1 # 0 %or count = 0
  type = restype
  %if type # 0 %start;  !not routine
    %if hp_flags&volatile = 0 %start
      p = explo
      %while p < explim %cycle
        %if dict(p)_act = headitem %start;  ![enough?]
          item = p;  q = procnp
          %cycle
            %exit %if dict(p)_x # dict(q)_x %or dict(p)_y # dict(q)_y
            p = p+1;  q = q+1
            ->okf %if q >= np
          %repeat
        %finish
        p = p+1
      %repeat
    %finish
    copy down(procnp)
    item = explo
okf:ditem == dict(item)
    ditem_flags = hp_flags&heritable
    ditem_mode = 0
    %if hp_flags&writable # 0 %start;  !map
      ditem_mode = dispmode
    %finish
    ditem_type = type
    np = procnp
  %finish
%end;  !get PARLIST

!<<IMP

%routine get RESOLUTION(%integer t,item1)
%integer fore,ftype,s
!  type check needed
  s = size(t)
  s = -256 %if s = 0
  fore = 0
  %if %not a(left) %start
    get REFERENCE(stringstar)
    fore = item;  ftype = type
    get(dot);  get(left)
  %finish
  get VALUE(stringtype);  get(right)
  %if item = 0 %start
    item = litref(value);  s = s+final(value)
  %finish
  fault(rangerr+warn) %if fore # 0 %and s < size(ftype) # 0
  putact(resolves,item1+ad,item+ad)
  item = 0
  %if a(dot) %start
    get REFERENCE(stringstar)
    fault(rangerr+warn) %if s < size(type) # 0
  %finish
  putact(0,fore,item)
  putact(0,0,0);       !preserve 'parity'
%end

%integer%fn ANON(%record(objinfo)%name d)
  dict(lablim+3)_details = d
  %result = lablim+3
%end

%predicate A ASSOP(%integer t)
  %if t <= 0 %start
    %false %if %not a(eqeq)
  %else
    atom = next atom %if matched # 0
    %if atom # equals %start
      %false %unless atom = less %and byteintegeR(fp) = '-'
      jammy = 1;  fp = fp+1
    %finish %else jammy = 0
    matched = 1
  %finish
  %true
%end

!<<BOTH

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
%routine GET EXPRESSION(%integer rank,etype)
!Main expression recognition routine
!To bring together the treatment of all binary operators
! and ensure fast recognition of simple expressions,
! expressions of different levels are handled by
! precedence techniques rather than syntactically
%integer atomp0,item1,type1,cat1,val1,double,op
%record(identinfo)%name ditem1,tp
%constinteger nop=0;  !to distinguish from numeric zero in OPVAL

%routine GET RECORD
![literal only at this stage]
%integer fid,ad,arg,hold,count,max,s
%record(identinfo)%name darg,fidp
  literal = literal+1
  fill code(1) %if cad&1 # 0
  ad = cad
  fid = item;  fidp == ditem
  arg = fidp_link
  count = 0;  max = -1
  get(left)
  %cycle
    ![*beware premature lexical coding: may alter CAD*]
    %cycle
      error(toomany+point) %if arg <= 0
      darg == dict(arg)
      %exit %if ad+darg_val-cad >= 0
      arg = darg_hlink
    %repeat
    fill code(ad+darg_val-cad)
   ! [*now OK to code atom*]
    %if a(recsub) %start
      subbed = 1;  dformat == fidp
      get(ident)
      subbed = 0
      name error %if item < arg
      fill code(ditem_val-darg_val)
      arg = item;  darg == ditem
      syntax error %if %not a assop(darg_flags&name+darg_type)
    %finish
    s = nsize(darg)
    %if %not a(comma) %start
      get VALUE(darg_flags&name+darg_type)
      %if s > 0 %start
        %if s = 4 %start
!$IF VAX
{          value = ieee(value) %if darg_type = realtype %and darg_flags >= 0
!$FINISH
          set code longword(value)
        %else %if s = 2
         set code word(value)
        %else
          final(cad) <- value;  cad = cad+1
        %finish
      %finish
      %exit %if a(right)
      get(comma)
    %else %if s > 0
      fill code(s)
    %finish
    arg = darg_hlink
  %repeat
  fill code(ad+|fidp_val|-cad)
  item = 0;  value = ad
  literal = literal-1
%end

%routine SWOP
%integer temp
  temp = item1;  item1 = item;  item = temp
  temp = val1;  val1 = value;  value = temp
  temp = type1;  type1 = type;  type = temp
%end

%constinteger INTOK=1<<inty, CHAROK=1<<chary,
              BOOLOK=1<<booly, ENUMOK=1<<enumy,
              REALOK=1<<realy, STRINGOK=1<<stringy,
              ARROK=1<<arry, SETOK=1<<sety,
              RECOK=1<<recy, POINTOK=1<<pointy,
              NUMOK=intok!realok,
              ORDOK=intok!charok!boolok!enumok,
              RELOK=ordok!realok!stringok
%routine CHECK1(%integer ok)
  cat1 = category(type)
  %if ok>>(cat1&cat)&1 = 0 %start
    %if cat1 = inty %and ok&realok # 0 %start
      toreal;  cat1 = realy
    %else %if ok&stringok # 0 %and valok(stringtype,type)
      cat1 = stringy
    %else
      fault(typerr+point)
    %finish
  %finish
  type1 = type;  item1 = item;  val1 = value
%end

%integer%fn FROZEN LIT(%integer t,v)
! Used when the type of a literal will not be recoverable from context
%integer hold,res
  hold = item
  putexp(move,0,litref(v),t);  !NO-OP (distinctive Y)
  ditem_flags = okflag+wflag
  ditem_mode = constmode;  ditem_val = v
  res = item;  item = hold
  %result = res
%end

%routine COERCE(%integer c)
  %if c = inty %and cat1 = realy %start
    toreal
  %else %if cat1 = inty %and c = realy
    ![rather sloppy]
    %if item1 # 0 %start
      val1 = item;  item = item1
      toreal
      item1 = item;  item = val1
    %finish %else real(addr(val1)) = val1
    type1 = realtype;  cat1 = realy
  %else
    expfault(typerr)
  %finish
%end

%routine GET ARITH(%integer rank)
  get EXPRESSION(rank,0)
  rank = category(type)
  coerce(rank) %if rank # cat1
%end

%integer%fn RCOND(%integer op)
%constinteger EQUAL=2_1001000010,
              LESS =2_1010000001,
            GREATER=2_0101000001
%integer which,c
!<<IMP
  check1(relok)
  get EXPRESSION(major,0)
  c = category(type)
  coerce(c) %if c # cat1
  %if equals <= atom <= greater %start;  ![ATOM always primed]
    syntax error %if double >= 0
    double = item
  %else %if double < 0
    double = -2
  %finish
!<<BOTH
  %if item1 = 0 %start
    %if item = 0 %start
      %if size(type1) > 0 %or item1!val1 = 0 %or item!value = 0 %start
        !non-structure (compile-time)
        ![integer tests ok for real?]
        %if val1 < value %then which = less %c
        %else %if val1 = value %then which = equal %c
        %else which = greater
        %result = which>>(op-bne)&1
      %finish
      item1 = frozen lit(type1,val1)
    %else
      swop
      op = op!!3 %if op&8 # 0;  !no change for '=','#'
    %finish
  %finish
  %result = op
%end;  !RCOND
!<<IMP

%integer%fn OPVAL
! Returns result value for literal (ITEM=ITEM1=0)
!         0 for no-op (result is ITEM1,TYPE1)
!         operator otherwise (result type is TYPE)
! NB literal INTY type is always INTTYPE (not subrange)
%switch op(keyand:rshift)
  -> op(atom)
op(plus):
  check1(numok+setok)
  get ARITH(star)
  %if cat1 = inty %start
    %if item1 = 0 %start
      %result = val1+value %if item = 0
      swop
    %finish
    %result = nop %if item!value = 0
    type = inttype
    %result = add
  %else
    %if item1 = 0 %start
      %if item = 0 %start
        real(addr(val1)) = real(addr(val1))+real(addr(value))
        %result = val1
      %finish
      swop
    %finish
    %result = nop %if item!value = 0
    %result = fadd
  %finish
op(minus):
  check1(numok+setok)
  get ARITH(star)
  %if cat1 = inty %start
    %if item1 = 0 %start
      %result = val1-value %if item = 0
      swop %and %result = neg %if val1 = 0
    %finish
    type = inttype
    %if item = 0 %start
      %result = nop %if value = 0
      value = -value %if value # minint
      %result = add
    %finish
    %result = sub
  %else
    %if item = 0 %start
      %if item1 = 0 %start
        real(addr(val1)) = real(addr(val1))-real(addr(value))
        %result = val1
      %finish
      %result = nop %if value = 0
    %finish
    %result = fsub
  %finish
op(exclam):
  check1(intok);  get EXPRESSION(star,inttype)
  %if item1 = 0 %start
    %result = val1!value %if item = 0
    swop
  %finish
  %result = nop %if item!value = 0
  type = inttype
  %result = or
op(exclam2):
  check1(intok);  get EXPRESSION(star,inttype)
  %if item1 = 0 %start
    %result = val1!!value %if item = 0
    swop
  %finish
  %result = nop %if item!value = 0
  type = inttype
  %result = eor
op(ampersand):
  check1(intok);  get EXPRESSION(star2,inttype)
  %if item1 = 0 %start
    %result = val1&value %if item = 0
    swop
  %finish
  item1 = 0 %and %result = 0 %if item!value = 0
  type = inttype
  %result = and
op(star):
  check1(numok+setok)
  get ARITH(star2)
  item1 = 0 %and %result = 0 %if item!value = 0
  %if cat1 = inty %start
    %if item1 = 0 %start
      %result = val1*value %if item = 0
      swop
    %finish
    type = inttype
    %result = imul %if control&halfbit = 0
    %result = muls
  %else
    %if item1 = 0 %start
      %if item = 0 %start
        real(addr(val1)) = real(addr(val1))*real(addr(value))
        %result = val1
      %finish
      swop
    %finish
    %result = fmul
  %finish
op(over):
  check1(intok);  get EXPRESSION(star2,inttype)
  %if item = 0 %start
    fault(rangerr) %and %result = nop %if value = 0
    %result = val1//value %if item1 = 0
  %finish
  type = inttype
  %result = idiv
op(slash):
  check1(realok)
  get EXPRESSION(star2,realtype)
  %if item = 0 %start
    fault(rangerr) %and %result = nop %if value = 0
    %if item1 = 0 %start
      real(addr(val1)) = real(addr(val1))/real(addr(value))
      %result = val1
    %finish
  %finish
  %result = fdiv
op(backslash2): op(uparrow2):
  check1(intok);  get EXPRESSION(simple,inttype)
  %if item = 0 %start
    %result = val1\\value %if item1 = 0
    item1 = 0 %and %result = 1 %if value = 0
    %result = nop %if value = 1
    item = item1 %and %result = imul %if value = 2
  %finish
  type = inttype
  %result = ipow
op(backslash): op(uparrow): op(star2):
  check1(realok)
  get EXPRESSION(simple,inttype)
  type = realtype
  %if item!item1 = 0 %start
    real(addr(val1)) = real(addr(val1))\value
    %result = val1
  %finish
  %result = fpow
op(lshift):
  check1(intok);  get EXPRESSION(simple,inttype)
  %if item = 0 %start
    %result = val1<<value %if item1 = 0
    %result = nop %if value = 0
  %finish
  type = inttype
  %result = lsl
op(rshift):
  check1(intok);  get EXPRESSION(simple,inttype)
  %if item = 0 %start
    %result = val1>>value %if item1 = 0
    %result = nop %if value = 0
  %finish
  type = inttype
  %result = lsr
op(tilde):
  check1(intok)
  get EXPRESSION(simple,inttype)
  %result = \value %if item = 0
  swop
  type = inttype
  %result = not
op(sconc):
  check1(stringok);  get EXPRESSION(dot+1,stringtype)
  %if item = 0 %start
    %if item1 = 0 %start
      %result = val1 %if value = 0
      %result = value %if val1 = 0
      %if final(val1)+final(value) <= 255 %start
        string(final0+val1) = string(final0+val1) %c
                                 . string(final0+value)
        cad = cad-1
      %finish %else fault(rangerr)
      %result = val1
    %finish
    %result = nop %if value = 0
  %else %if item1!val1 = 0
    item1 = item;  val1 = value;  type1 = type
    %result = nop
  %finish
  type = stringtype
  %result = concat
op(equals):
  %result = RCOND(beq)
op(noteq):
  %result = RCOND(bne)
op(lesseq):
  %result = RCOND(ble)
op(less):
  %result = RCOND(blt)
op(greateq):
  %result = RCOND(bge)
op(greater):
  %result = RCOND(bgt)
%integer%fn RACOND(%integer op)
  toref
  item1 = normitem;  type1 = type
  get REFERENCE(type1)
  val1 = 0 %and swop %if item1 = 0
  syntax error %if arrow <= atom <= greater;  ![ATOM always primed]
  double = -2
  %result = op
%end
op(eqeq):
  %result = RACOND(beq)
op(noteqeq):
  %result = RACOND(bne)
op(arrow):
  check1(stringok)
  item1 = litref(val1) %if item1 = 0
  get RESOLUTION(type,item1)
  item1 = np-3
  condop = bne!!polarity
  type1 = booltype
  %result = nop
op(keyand):
  topred %if condop = 0
  item1 = np;  type1 = booltype
  putact(condop!!polarity!!1+polarity<<7,item,0)
  condop = 0
  get EXPRESSION(scond,booltype)
  dict(item1)_y = item
  syntax error %if a(keyor)
  %result = nop
op(keyor):
  topred %if condop = 0
  item1 = np;  type1 = booltype
  putact(condop!!polarity+(polarity!!1)<<7,item,0)
  condop = 0
  get EXPRESSION(scond,booltype)
  dict(item1)_y = item
  syntax error %if a(keyand)
  %result = nop
%end

!Get leading operand
  atom = next atom %if matched # 0
  atomp0 = atomp;  jammy = jammy<<1;  !preserve
  %if atom = ident %start
    matched = 1
    name error %if item <= 0 %or (ditem_mode = labmode %and item < c_localdpos)
    fault(namerr+point) %if item >= dlim0
    type = ditem_type
    %if ditem_flags&typeid # 0 %start
      %if ditem_flags&cat = recy %and item > dnil %start
        get RECORD
        %return
      %else
        item1 = item;  ditem1 == ditem
        %if a(less) %start;  !type coercion
          get VALUE(0);  get(greater)
          type = item1
        %else
          get(left);          !store mapping
          get VALUE(inttype)
          get(right)
          putexp2(storemap,item1,item1)
          ditem_flags = writable!readable
          ditem_mode = dispmode
        %finish
      %finish
    %else %if ditem_mode = litmode
      item = 0;  value = ditem_val
    %else;                                    !non-literal ident
      %cycle
        %if ditem_flags&proc # 0 %start
          %if item = daddr %or item = dsizeof %or item = dnew %start
            get(left)
            %if item = daddr %start
              get REFERENCE(0)
              type = inttype
            %else
              item1 = item
              get REFERENCE(0)
              value = |size(type)|
              expfault(sizerr) %if value = 0
              %if item1 = dsizeof %start
                item = 0;  type = inttype
              %else
                putexp(dnew,0,litref(value),0)
                ditem_mode = dispmode
              %finish
            %finish
            get(right)
!          %else %if item = dsnl
!            putexp(dtostring,nl,0,string1)
          %else
            get PARLIST(0)
            atomp=atomp0 %and error(classerr+point) %if type = 0;  !routine
          %finish
        %else;                                   !not procedure
          atom = next atom %if matched # 0
          %exit %unless aleft <= atom <= recsub %and rank <= simple
          %if atom = aleft %start;  !array subscript
            %cycle
              item1 = item;  ditem1 == ditem
              tp == typecell(type)
              %if tp_flags&cat = stringy %start
                matched = 1
                nonstandard(2)
                get VALUE(bytetype)
                putexp2(sindex,item1,chartype)
              %else
                -> out %unless tp_flags&cat = arry
                matched = 1
                get VALUE(tp_xtype);  !get index
                putexp2(index,item1,tp_type)
              %finish
              ditem_flags = ditem1_flags&heritable
              ditem_mode = ditem1_mode
            %repeat %until %not a(comma)
            ditem_flags = ditem_flags+(tp_flags&name)
            get(right)
          %else %if atom = recsub;  !record subfield
            item1 = item;  ditem1 == ditem
            dformat == typecell(ditem_type)
            syntax error %unless dformat_flags&cat = recy
            matched = 1
            subbed = 1;  get(ident);  subbed = 0
            error(namerr+point) %if item <= 0
            val1 = ditem1_flags&heritable!ditem_flags
            putexp2(recref,item1,ditem_type)
            ditem_flags = val1
            ditem_mode = ditem1_mode
          %else %if atom = atsign
            nonstandard(4)
            syntax error %if ditem_flags&typeid = 0
            matched = 1
            ditem1 == ditem;  item1 = item
            get EXPRESSION(vsimple,inttype)
            putexp2(storemap,item1,item1)
            ditem_flags = writable!readable
            ditem_mode = dispmode
          %else;  !pointer relative
            error(nonref+point) %if ditem_mode < dispmode
            fault(sizerr) %if size(ditem_type) = 0
            matched = 1
            ditem1 == ditem;  item1 = item
            get VALUE(inttype);  get(rightb)
            putexp2(prel,item1,ditem1_type)
            ditem_flags = writable!readable
            ditem_mode = ditem1_mode
          %finish
        %finish
      %repeat
    %finish
  %else
    %if atom = const %start
      matched = 1
    %else %if atom = minus;  !leave unmatched
      item = 0;  value = 0;  type = inttype
    %else %if atom = left
      matched = 1
      %if rank < major %start;  !condition
        get EXPRESSION(condq,0)
      %else
        get EXPRESSION(major,0)
      %finish
      get(right)
    %else %if a(keynot)
      syntax error %if rank >= major
      polarity = polarity!!1
      get EXPRESSION(scond,booltype)
      %if item = 0 %then value = value!!1
      polarity = polarity!!1
    %else %if atom = backslash
      item = 0;  value = 0;  type = inttype
      atom = tilde
    %else %if a(modsign)
      get EXPRESSION(major,0)
      %if valok(inttype,type) %start
        %if item = 0 %start
          %if value < 0 %start
            %if value # minint %then value = -value %else expfault(rangerr)
          %finish
        %else
          putexp2(iabs,0,inttype)
        %finish
      %else %if valok(realtype,type)
        putexp2(fabs,0,realtype)
      %else
        error(typerr+point)
      %finish
      get(modsign)
    %else
      syntax error
    %finish
  %finish
out:
  atom = next atom %if matched # 0;  ![always primed on return]

  %if etype < 0 %start;  !reference required
    expp = atomp0;  jammy = jammy>>1;  !restore
%unless item!value = 0 %start;  !*temp*
    toref
    expfault(typerr) %if %not refok(etype-sign16,type)
%finish %else atomp = atomp0 %and nonstandard(21)
  %else
    %while atom >= rank %cycle
      matched = 1
      double = -1
      op = opval
      %if item1!item = 0 %start;  !both literal
        %if double # -1 %start
          %if double >= 0 %start
            literal = literal+1;  !enforce all literal
            op = op&opval
            literal = literal-1
          %finish
          type = booltype
        %finish
        value = op
      %else %if double = -1;         !not relop
        %if op # 0 %start
          item1 = litref(val1) %if item1 = 0
          putexp(op,item1,normitem,type)
        %else;         !nop
          item = item1;  type = type1
        %finish
      %else;                      !conditional operation
        condop = op!!polarity
        putact(compare,item1,normitem)
        item = np-1
        %if double >= 0 %start
          putact(condop!!polarity!!1+polarity<<7,np-1,np+1);  !implicit %and
          item = double;  ![TYPE,VALUE unchanged]
          matched = 1
          op = opval
          error(nonliteral) %if item1!item = 0;  !mixed non-lit, lit
          condop = op!!polarity
          putact(compare,item1,normitem)
          item = np-2
        %finish
        type = booltype
      %finish
    %repeat
    expp = atomp0;  jammy = jammy>>1
    %if etype # 0 %start
      %if type = booltype %start
        topred %if (rank = cond %or rank = scond) %and condop = 0
      %finish
      expfault(typerr) %if %not valok(etype,type)
    %finish
  %finish
  atomp=expp %and error(nonliteral+point) %if literal # 0 %and item # 0
%end;  !get EXPRESSION
  
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!  Conditions and loops  !!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
%routine GET CONDITION
%integer maxlab,condnp

%routine ASSIGN LABELS(%integer p,lab,pol)
%integer base=maxlab
%record(identinfo)%name dp
  %while (p-condnp)&1 # 0 %cycle;  !compound
    dp == dict(p);  p = dp_y
    %if dp_act&1<<7 = pol %then assign labels(dp_x,lab,pol) %c
    %else maxlab = base+1 %and assign labels(dp_x,maxlab,pol!!1<<7)
  %repeat
  dp == dict(p+1);  dp == dp[2] %if dp_act = 0;  !resolution
  %if maxlab > base %then dp_x = maxlab %and maxlab = base %c
  %else dp_x = 0
  dp_y = lab
  dp_act = dp_act&127
%end

  condnp = np
  polarity = subatom;  condop = 0
  get EXPRESSION(cond,booltype)
  putact(condop!!1,item,0)
  %return %if faultnum > 0
  maxlab = curlab+1
  assign labels(item,maxlab,0)
%end;  !get CONDITION

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

%routine DO DYNAMIC ARRAYS
  update sp
  c_mode = c_mode!2_01000000;   !bar to SP rel addressing
  c_status = c_status!globbed;  !needs link
  %while c_dynarray # 0 %cycle
    %if c_dynarray < 0 %then putact(aget,-c_dynarray,one) %c
    %else putact(aget,c_dynarray,0)
    c_dynarray = dict(|c_dynarray|)_link
  %repeat
  compile(np0)
%end

%routine GET STATEMENTS(%integer stopper)
! STOPPER = 0          -- initial call
!           1 (END)    -- for procedure or block body
!           2 (REPEAT) -- for loop body
!           3 (FINISH) -- for condition body (ELSE not valid)
!           4 (ELSE)   --         "          (ELSE valid)
%switch initial(0:atommax)
%integer forinf,endval,loopstart

%routine THIS IS INST
  %if c_status < hadinst %start;  !first in block
    c_status = c_status+hadinst
    fault(ordererr) %if stopper = 0
  %finish
  fault(accesserr+warn) %if c_access = 0 %and np = np0
  do dynamic arrays %if c_dynarray # 0
%end

%routine PUTACT2(%integer act,item1)
  putact(act,item1,normitem)
%end

%routine GET RESULT
  get VALUE(c_type)
!  fault(rangerr+warn) %if c_type > 0 %and item # 0 %c
!                      %and |size(type)| > |size(c_type)|
%end

%routine GET INSTRUCTION
%integer item1
%record(identinfo)%name tp
  this is inst
  %cycle
    %if a(ident) %start
      name error %if item <= 0
      %if ditem_flags&(writable!typeid) # 0 %start
        matched = 0
        get EXPRESSION(simple,0)
        item1 = item
        %if a(equals) %start
          jammy = 0
          get VALUE(type)
          putact2(okass+jammy,item1);  !okass,assign
        %else %if a(eqeq)
          syntax error %if ditem_flags >= 0
          get REFERENCE(type)
          putact2(assign,item1+ad)
        %else %if atom = less %and byteintegeR(fp) = '-'
          fp = fp+1;  matched = 1
          jammy = 1
          get VALUE(type)
          putact2(jamass+jammy,item1);  !jamass,okass
        %else
          syntax error %if %not a(arrow)
          get RESOLUTION(type,item1)
          putact(bne,0,curlab)
          putact(signal,litref(7),undef)
          putact(0,undef,undef)
        %finish
      %else
        error(classerr+point) %if ditem_flags&proc = 0
        tp == typecell(ditem_type)
        %if tp_type # 0 %start;  !function as routine
          get PARLIST(tp_type)
          putact2(assign,value)
        %else
          get PARLIST(0)
        %finish
      %finish
    %else
      c_access = 0 %if np = np0;  !unconditional
      %if a(keymonitor) %start
        c_access = 1
!        fault(monitor<<8)
     %else %if a(exit);  !%exit, %continue
        %if c_looplab = 0 %then fault(notinloop+point) %c
        %else putact(jumpout,c_looplab,c_looplab+subatom)
        %exit
     %else %if a(keyreturn)
        item = 0;  value = 0
        get RESULT %if c_type # 0
        putact2(return,0)
        %exit
     %else %if a(keyresult)
        error(notinfun+point) %if c_type = 0
        syntax error %if %not a assop(c_type)
        get RESULT
        putact2(return,0)
        %exit
     %else %if a(tf);  !%true, %false
        %if c_type # booltype %then fault(notinpred+point) %c
        %else putact(return,0,litref(subatom))
        %exit
     %else %if a(arrow) %or a(keygoto)
        nonstandard(5) %if atom = keygoto
        get(ident)
        %if byteinteger(fp) # '(' %start
          declare(forwardlabel) %if item < c_localdpos {new} %c
                                %or ditem_type # 0 {error}
          putact2(goto,0)
        %else
          name error %if item < c_localdpos
          error(classerr+point) %unless ditem_mode = labmode %c
                                %and ditem_type # 0
          item1 = item
          get(left)
          get VALUE(typecell(ditem_type)_xtype);  !index
          get(right)
          putact2(swgoto,item1)
        %finish
        %exit
     %else %if a(keystop)
        putact(stop,0,0)
        %exit
     %else %if a(keysignal)
        c_access = 1
        allow(keyevent)
        get LITERAL(inttype)
        expfault(rangerr) %unless 0 <= value <= 15
        item1 = litref(value);  item = undef
        %if a(comma) %start
l1:       %if a(comma) %then matched = 0 %else get VALUE(bytetype)
        %finish
        putact2(signal,item1)
        item = undef
        %if a(comma) %start
l2:       %if a(comma) %then matched = 0 %else get VALUE(inttype)
        %finish
        item1 = normitem;  item = undef
        get VALUE(stringtype) %if a(comma)
        putact2(0,item1)
        %exit
      %else
        syntax error
      %finish
    %finish
  %repeat %until %not a(keyand)
%end;  !GET INSTRUCTION

%routine GET FOR CLAUSE
!Global: FORINF,ENDVAL
%integer loopvar,lvtype,k,s,start,sval,i,inc,ival,e,n
%integer end
%record(identinfo)%name tp
  forinf = 0
  get(ident)
  name error %if item <= 0
  lvtype = ditem_type;  tp == typecell(lvtype)
  fault(typerr+point) %if tp_flags&nonord # 0
  loopvar = item
  get(equals)
  get VALUE(lvtype)
  start = item;  sval = value
  get(comma)
  get VALUE(lvtype)
  inc = item;  ival = value
  expfault(rangerr) %and ival = 1 %if inc = 0 = ival
!Deal with INC and replace START by START-INC
  k = undef
  k = dict(start)_y %if start >= np0 %and dict(start)_act = add
  %if inc = 0 %start;  !literal increment
    i = litref(ival)
    %if start = 0 %start;  !START and INC both literal
      sval = sval-ival;  item = litref(sval)
    %else %if k <= 0;  !START is x+lit
      k = litval(k)-ival
      item = dict(start)_x
      putexp(add,item,litref(k),inttype) %if k # 0
    %else
      putexp(add,start,litref(-ival),inttype)
    %finish
  %else;  !variable
    i = inc
    %if control&volbit # 0 %start
      declare temp(inttype);  i = item
      putact(assign,i,inc);  forinf = forinf-4
    %finish
    %if start = inc %start;  !identical
      item = 0;  sval = 0
    %else %if k = inc;  !START is x+INC
      item = dict(start)_x
    %else
      item = start;  item = litref(sval) %if item = 0
      putexp(sub,item,i,inttype)
    %finish
  %finish
  s = item
!Get end-value
  get(comma)
  get VALUE(lvtype)
  end = item
  %if end = 0 %start;  !literal end-value
    e = litref(value);  endval = value
  %else
    e = item
    %if control&volbit # 0 %start
      declare temp(inttype);  e = item
      putact(assign,e,end);  forinf = forinf-4
    %finish
  %finish
  %if start!inc!end # 0 %and control&loopbit # 0 %start
    putact(forass,loopvar,s)
    putact(forass,i,e)
  %else
    putact(assign,loopvar,s)
  %finish
  putact(label,curlab,0)
  %if start!inc!end = 0 %start;  !all literal
    k = endval-sval;  n = k//ival
    %if n = 0 %start
      fault(dubious+warn)
      putact(else,0,curlab+1);  !ie unconditional branch
      %return
    %finish
    fault(boundserr) %if n < 0
    fault(unending) %if n*ival # k
    forinf = loopvar
  %else
    putact(compare,loopvar,e)
    putact(beq,0,curlab+1)
  %finish
  putact(incass,loopvar,i)
%end;  !get FORCLAUSE

%routine GET LOOP BODY
%integer hold=c_looplab
  c_looplab = curlab;  curlab = curlab+2
  get STATEMENTS(keyrepeat)
  curlab = curlab-2;  c_looplab = hold
%end

%routine GET SWITCH INDEX
%integer i,lo,hi
%record(identinfo)%name dp,tp
%routine SET LABEL(%shortname p)
  value = p
  expfault(duperr) %if value > 0
  set user label(value)
  p = value
%end
  dp == ditem;  tp == typecell(ditem_type)
  get(left)
  %if a(star) %start
    set label(dp_link)
  %else
    get VALUE(tp_xtype)
   !beware faulty declaration or index
    %if tp_xtype > inttype %and faultnum = 0 %start
      get bounds(tp_xtype,lo,hi)
      i = value-lo+dp_val
      c_forward = c_forward-1 %if i < pc;  !(had goto)
      set label(prog(i))
    %finish
  %finish
  get(right)
%end

![unsure of efficiency implications of trapping overflow lower down]
%on %event oflow,fail,done %start
  %if event_event = 0 %start;  !failure in %option,%include or ^Y
    %stop %if event_sub # 0
    %signal abandon
  %finish
  %if event_event = done %start
    croak("Premature end of input") %if stopper # 0
    close block
    c_dpid_val = 0;  !zero entry-point
    %return
  %finish
  fault(rangerr+now) %if event_event = oflow
  -> ignore
%finish
!!!!!!!!!!!!!!!!!!!  Start of new statement  !!!!!!!!!!!!!!!!!!!
next:
  statements = statements+1
  compile(startnp) %if np > np0
  define label(curlab) %if dict(curlab)_val < 0
  define label(curlab+1) %if dict(curlab+1)_val < 0
next1:
  report(faultnum,0,0) %if faultnum # 0
  dlim0 = dlim
  speccing = 0;  subbed = 0
  literal = 0;  jammy = 0;  condop = 0
  dict(curlab)_val = 0;  dict(curlab+1)_val = 0
  np = np0;  startnp = np0
  maxcalldreg = maxdreg;  maxcallareg = maxareg
  zaps = zaps+1 %and forget all %if explo < np0+50
  zaps = zaps+1000 %and forget all %if litpos > litmax-40
  value = 0
!
initial(terminator):
  atom = next atom;  matched = 1
  -> initial(atom)

initial(keycomment): initial(exclam): initial(exclam2):
  comments = comments+1
  read line(0)
  -> next1
term:
  get(terminator)
  -> next

ignore:
  c_access = -1
  %if atom # terminator %start
    %cycle
      subatom = atom;  atom = next atom
    %repeat %until atom = terminator
    starts = starts+1 %if subatom = keystart
    cycles = cycles+1 %if subatom = keycycle
  %finish
  -> next1

initial(dud):
  syntax error;  !ie atom error

initial(*):
  error(nonstarter+point)

initial(ident):
  %if byteintegeR(fp) = ':' %start;  !simple label
    fp = fp+1
    declare(definedlabel)
    set user label(ditem_val)
    ->next
  %finish
  name error %if item <= 0
  %if ditem_mode = labmode %and ditem_type # 0 %start
    literal = 1
    get SWITCH INDEX
    get(colon)
    ->next
  %finish
initial(keyreturn): initial(keyresult): initial(tf):
initial(keystop): initial(keysignal): initial(keymonitor):
initial(exit): initial(keygoto): initial(arrow):
  matched = 0
  get INSTRUCTION
  -> next %if a(terminator)
  c_access = 1
  %if a(iu) %start
    startnp = np
    get CONDITION
  %else %if a(keywhile)
    putact(repeat,curlab,0);  !append repeat
    startnp = np
    define label(curlab)
    get CONDITION
 %else %if a(keyfor)
    putact(0,0,0)
    putact(0,0,0)
    putact(repeat,curlab,0);  !append repeat
    startnp = np
    get FOR CLAUSE
    value = np;  np = startnp-3
    %if forinf > 0 %start
      putact(compare,forinf,litref(endval))
      putact(beq,0,curlab)
    %finish %else np = np+2
    putact(repeat,curlab,forinf)
    np = value
  %else
    syntax error %if %not a(keyuntil)
    get CONDITION
    putact(repeat,curlab,0)
    define label(curlab)
  %finish
  -> term

initial(iu):  !%if, %unless
  this is inst
  %cycle
    get CONDITION
    %if a(keythen) %and %not a(keystart) %start
      get INSTRUCTION
    %else
      matched = 0;   ![unsee %start]
      get(keystart)
      %cycle
        get(terminator)
        curlab = curlab+2
        get STATEMENTS(keyelse)
        curlab = curlab-2
        %exit %if atom # keyelse;  !%finish ->
        putact(else,curlab+1,curlab)
        -> exit2 %if %not a(iu)
        get CONDITION
      %repeat
      -> initial(keyend) %if atom = keyend
    %finish
    -> term %if %not a(keyelse)
    putact(else,curlab+1,curlab)
  %repeat %until %not a(iu)
  %if %not a(keystart) %start
    get INSTRUCTION
  %else
exit2:
    get(terminator)
    curlab = curlab+2
    get STATEMENTS(keyfinish)
    curlab = curlab-2
    -> initial(keyend) %if atom = keyend
  %finish
  -> term

initial(keycycle):
  this is inst
  %if a(terminator) %start
    define label(curlab)
    get LOOP BODY
    -> initial(keyend) %if atom = keyend
    get CONDITION %if a(keyuntil)
    putact(repeat,curlab,0)
    -> term
  %finish
  nonstandard(22)
  get FOR CLAUSE
  -> for1
initial(keywhile):
  this is inst
  define label(curlab)
  get CONDITION
  get(keycycle)
  get(terminator)
  compile(np0)
  get LOOP BODY
  -> initial(keyend) %if atom = keyend
  nonstandard(6) %and get CONDITION %if a(keyuntil)
  putact(repeat,curlab,0)
  ->term
initial(keyfor):
  this is inst
  get FOR CLAUSE
  get(keycycle)
for1:
  get(terminator)
  compile(np0)
  %if forinf > 0 %start;           !Literal for loop
   !%continue must come to end for increment
    loopstart = dict(curlab)_val;  !save start position
    dict(curlab)_val = 0
  %finish
  get LOOP BODY
  -> initial(keyend) %if atom = keyend
  %if forinf > 0 %start;  !literal FOR loop
    define label(curlab)
    dict(curlab)_val = loopstart;  !restore
    putact(compare,forinf,litref(endval))
    putact(beq,0,curlab)
  %finish
  putact(repeat,curlab,forinf)
  -> term

initial(keyon):
  fault(ordererr+point) %if c_status >= hadon %or stopper = 0
  do dynamic arrays %if c_dynarray # 0
  c_status = c_status!hadon
  matched = 1
  allow(keyevent)
  dump = 0
  %cycle
    get LITERAL(inttype)
    expfault(rangerr) %unless 0 <= value <= 15
    dump = dump!1<<value
  %repeat %until %not a(comma)
  get(keystart)
  putact(settrap,0,litref(dump))
  curlab = curlab+2
  get STATEMENTS(keyfinish)
  curlab = curlab-2
  -> initial(keyend) %if atom = keyend
  -> term
!
initial(keyelse):
  -> ignore %if starts # 0
  %return %if stopper = keyelse
  error(noif) %if stopper = keyfinish
initial(keyfinish):
  starts = starts-1 %and -> ignore %if starts # 0
  %return %if stopper = keyfinish %or stopper = keyelse
  error(nostart)
initial(keyrepeat):
  cycles = cycles-1 %and -> ignore %if cycles # 0
  %return %if stopper = keyrepeat
  error(nocycle)

initial(star):
  fault(lowlevel+warn+point) %and control = control!lowbit %if control&lowbit = 0
  matched = 1
  %if byteinteger(fp) = '=' %start
    fp = fp+1
    get LITERAL(inttype)
    plant(dc,0,temp(absmode,value))
  %else
    get MCODE
  %finish
  ->term

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!  Declarations  !!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
%routine DECLARE LIT RANGE(%integer basetype,lo,hi)
%own%record(objinfo) D=0
  fault(boundserr) %and hi = lo %if lo > hi
  item = ranges
  %cycle
    ditem == dict(item)
    item = item-2 %and %return %if ditem_val = hi %and ditem_type = basetype %c
          %and ditem[-1]_val = lo
    item = ditem_hlink
  %repeat %until item = 0
  declare anon(d);               !blank (for updating)
  declare range(basetype,lo,hi)
%end

%routine DECLARE STRING TYPE(%integer size)
  item = stringtype %and %return %if size = -256
  item = string1 %and %return %if size = -2
  item = ranges
  %cycle
    ditem == dict(item)
    %return %if ditem_size = size %and ditem_type = chartype
    item = ditem_hlink
  %repeat %until item = 0
  declare anon(details(typeid+stringy,chartype,0,0))
  ditem_size = size
  ditem_hlink = ranges;  ranges = item
%end

%routine GET LIT RANGE(%integer basetype)
%integer holdval
  get LITERAL(basetype);  holdval = value
  get(colon)
  get LITERAL(basetype)
  declare lit range(basetype,holdval,value)
%end

%routine GET IDENTLIST(%record(objinfo)%name d)
  dlim0 = dlim
  get(ident) %and declare(d) %until %not a(comma)
%end

%routine RECALIGN(%integername val)
  align(val,2)
  val = -val %if val > 4
%end

%routine GET DECLARATION(%integer FLAGS,MODE,%integer%name DISP,%integer DEPTH)
%record(objinfo) DECL
%record(identinfo)%name DFHOLD
%owninteger ITEMTYPE=0,ITEMSIZE=0,ADIM=0
%integer BASE,HOLD,MAX,STMAX,DREG,AREG

%routine%spec GET VAR BOUND

%routine GET DATA TYPE
%switch s(ktype:keyname)
  atom = next atom %if matched # 0
  syntax error %unless kattrib <= atom <= keyname
  matched = 1
  -> s(atom)
s(ktype):
  itemtype = inttype+subatom
  itemsize = size(itemtype)
  nonstandard(7) %if itemtype >= mitetype
  allow(keyinteger)
  %return
s(keyinteger):                    !%integer
  itemtype = inttype;  itemsize = 4
  %if a(left) %start
    nonstandard(8)
    get LIT RANGE(inttype)
    get(right)
    itemtype = item
    itemsize = typecell(itemtype)_size
  %finish
  %return
s(keylong):                   !%long
  itemtype = inttype;  itemsize = 4;  !**for now**
  %if a(keyinteger) %then fault(notin+point+warn) %c
  %else itemtype = realtype %and get(keyreal)
  %return
s(keyreal):                   !%real
  itemtype = realtype;  itemsize = 4
  %return
s(keystring):                 !%string
  itemsize = 0
  %if a(left) %start
    atom = next atom
!    %if depth # 0 %and ktype <= atom <= keyinteger %start
!      get VAR BOUND
!      itemtype = stringstar
!    %else %if a(star)
     %if a(star) %start
      itemtype = stringstar
    %else
      get LITERAL(bytetype)
      itemsize = -(value+1)
      declare string type(itemsize)
      itemtype = item
    %finish
    get(right)
  %else
    syntax error %if mode # constmode
    itemtype = stringtype
  %finish
  %return
s(keyrecord):                    !%record
  get(left)
  %if %not a(star) %start
    %if %not a(ident) %start
      declare anon(typeident)
      hold = item;  dfhold == dformat
      dformat == ditem
      get DECLARATION(writable+readable,0,dformat_val,0)
      recalign(dformat_val)
      ditem == dformat
      dformat == dfhold;  item = hold
    %finish
    name error %if item <= 0
    error(classerr+point) %if ditem_flags&(\spec) # typeid+recy
    itemtype = item;  itemsize = ditem_val
  %else
    itemtype = recstar;  itemsize = 0
  %finish
  get(right)
  %return
s(keyname):    !untyped %name - leave unmatched
  itemtype = 0;  matched = 0
%end

%routine ASSIGN ADDRESS(%integer size)

%routine ASSIGN STACK ADDRESS
  align(stmax,2);  ditem_val = stmax
  stmax = stmax+|size|
  c_status = c_status!onstack %if depth = 1 %and speccing = 0
%end

  size = -4 %if ditem_flags&(name+indirect) # 0
  %if depth # 0 %start
    dlink_link = item;  dlink == ditem
    %if size > 0 %start
     !simple value
      %if dreg > maxcalldreg %start
        assign stack address
        %return
      %finish
      c_reg_content(dreg) = item %if speccing = 0
      ditem_reg = dreg-d0;  dreg = dreg+1
    %else
      %if areg > maxcallareg %start
        assign stack address
        ditem_reg = 8     {would have been in AREG}
        %return
      %finish
      c_reg_content(areg) = item+ad %if speccing = 0 %and ditem_flags < 0
      ditem_reg = areg-d0;  areg = areg+1
    %finish
  %finish
  size = |size|
  align(disp,size)
  ditem_val = disp
  %if constmode # ditem_mode # ownmode %start
    disp = disp+size
    %if ditem_mode >= framemode %start
      align(disp,2)
      ditem_val = c_sp-disp;  !neg stack disp.
    %finish
  %finish
%end
!
%routine GET QIDENT
  get(ident)
  %if mode = 0 %start;  !within record format
    head == dformat_link;  item = head
    %if item > 0 %start
      %cycle
        ditem == dict(item)
        fault(duperr+point) %if string(ditem_text+char0) = string(charlim)
        head == ditem_hlink;  item = head
      %repeat %until item <= 0
    %finish
  %finish
  declare(decl)
%end

!<<BOTH
%routine DUMP CONST(%integer v,n)
! Plant N replications of value V (of type ITEMTYPE and size ITEMSIZE)
! For simple operand V is value, otherwise V is address in FINAL
! Alignment requirement has been enforced (since it depends on context)
%integer i,j,k,kk,vv
  k = itemsize
  %if k <= 0 %start;  !structure
    k = -k
    k = final(v)+1 %if k = 0;  ![string]
    cad = v %if v # 0;  !reset cad
  %finish
  kk = k
  %return %if n < 1
  kk = kk*n %if n > 1
  %if mode = constmode %start
    i = cad;  cad = cad+kk
    croak("Program too big") %if cad >= ownbase
  %else
    %if ownbase+ownad+kk-finalbound > 0 %start
      make room(ownbase+ownad+kk-finalbound)
    %finish
    i = ownbase+ownad;  ownad = ownad+kk
  %finish
  %if itemsize <= 0 %start
    %while n > 0 %cycle
      n = n-1;  j = i+k
      %if v # 0 %start
        vv = v
        %cycle
          final(i) = final(vv)
          i = i+1;  vv = vv+1
        %repeat %until i =j
      %else
        final(i) = 0 %and i = i+1 %while i < j
      %finish
    %repeat
  %else
!$IF VAX
{    v = ieee(v) %if itemtype = realtype;  !vax->ieee
!$FINISH
    %while n > 0 %cycle
      n = n-1
      %if itemsize >= 2 %start
        %if itemsize > 2 %start;  !longword
          final(i) <- v>>24
          final(i+1) <- v>>16
          i = i+2
        %finish
        final(i) <- v>>8
        i = i+1
      %finish
      final(i) <- v
      i = i+1
    %repeat
  %finish
%end;  !dump const
!<<IMP

%routine GET VAR BOUND
%integer f
  f = decl_flags
  get DATA TYPE
  decl_flags = okflag+mflag;  decl_type = itemtype
  get(ident);  declare(decl)
  decl_flags = f
  assign address(itemsize)
%end

%routine DECLARE BOUND(%integer mode,val)
  declare anon(details(okflag,inttype,mode,val))
  %if depth # 0 %and mode >= framemode %start
    ditem_flags = ditem_flags!mflag
    assign address(4)
  %finish
%end

%routine GET ARRAY DECLARATION(%integer dim)
%integer pos,dlim1,holdval,holdz,jam,elements,tot,totsize,lo1,size1
%record(identinfo)%name dp
%ownrecord(objinfo) ATYPE=0

%integer%fn XTYPE
  declare anon(details(typeid,inttype,0,0))
  %result = item
%end

%routine STRING STAR ARRAY
  fault(notin+point) %if depth = 0
 ! VAR for size
  declare anon(details(okflag+mflag+inty,inttype,mode,0))
  tot = item
  assign address(4)
 ! TYPEID for string(*)
  declare anon(details(typeid+stringy,inttype,0,0))
  atype_type = item
  elements = maxint
%end

%routine GET REST
%integer e,r,lo,loval,hi,hival
  r = 0
  atom = next atom %if matched # 0
  %if decl_flags < 0 %start;  !%array%name
    %if depth > 0 %and ktype <= atom <= keyinteger %start;  !variable
      r = xtype;  get VAR BOUND
    %else
      get LITERAL(inttype)
    %finish
  %else;                   !%array
    get VALUE(inttype)
  %finish
  loval = value;  lo = item
  loval = minint %if lo # 0
  get(colon)
  atom = next atom %if matched # 0
  %if decl_flags < 0 %start
    %if depth > 0 %and ktype <= atom <= keyinteger %start;  !variable
      %if r = 0 %start
        r = xtype;  declare bound(litmode,loval)
      %finish
      get VAR BOUND
    %else
      %if dim!r = 0 %and a(star) %start
        item = 0;  value = maxint
      %else
        get LITERAL(inttype)
        declare bound(litmode,value) %if r # 0
      %finish
    %finish
  %else
    get VALUE(inttype)
  %finish
  hival = value;  hi = item
  hival = maxint %if hi # 0
  e = maxint
  %if r = 0 %start;  !no range yet declared
    %if lo!hi = 0 %start
      e = hival-loval %if hival!!loval >= 0 %or minint+hival-loval < 0
      e = e+1 %if e # maxint
      e = 0 %if hival = maxint
      declare lit range(inttype,loval,hival)
    %else
      declare anon(typeident);               !blank (for updating)
      declare range(inttype,loval,hival)
    %finish
    r = item
  %finish
  elements = e
  %if a(comma) %start
    dim = dim+1
    get REST
    %if elements # maxint %and e # maxint %start
      elements = elements*e
    %else
      elements = maxint
    %finish
  %finish
  atype_xtype = r
  size1 = totsize;  lo1 = loval;       !for outer dimension
  string star array %if atype_type = stringstar
  %if elements = maxint %start;             !non-literal bounds
    atype_mode = mode
    declare anon(atype)
    atype_type = item;          !save type id
    %if decl_flags >= 0 %or (depth = 1 %and speccing = 0) %start
      lo = litref(loval) %if lo = 0
      hi = litref(hival) %if hi = 0
      tot = litref(totsize) %if tot = 0
      putact(asize,item,tot)
      putact(0,lo,hi)
      %if decl_flags >= 0  %start
        compile(np0)
        dict(r+1)_mode = c_mode %and dict(r+1)_val = c_sp+4 %if lo > 0
        dict(r+2)_mode = c_mode %and dict(r+2)_val = c_sp %if hi > 0
      %finish
    %finish
    tot = 0;  totsize = 0
  %else;  !literal bounds
    item = 0
    %cycle
      ditem == dict(item)
      %exit %if ditem_type = atype_type %and ditem_xtype = atype_xtype %c
            %and ditem_flags = atype_flags
      item = item+1
      %if item = dlim %start
        declare anon(atype)
        %exit
      %finish
    %repeat
    atype_type = item
    totsize = totsize*e
  %finish
%end;  !get REST

%routine PUT BOUNDS
%integer i
  i = xtype;                         !index type
  declare bound(mode,0);             !lower
  declare bound(mode,0);             !upper
  dim = dim-1
  put bounds %if dim > 0
  string star array %if atype_type = stringstar
  atype_xtype = i
  declare anon(atype);                  !array type
  %if speccing = 0 %start
    tot = litref(totsize) %if tot = 0
    putact(asize,item,tot)
    putact(0,i+1,i+2)
  %finish
  tot = 0;  totsize = 0;  lo1 = minint
  atype_type = item
%end

  pos = dlim0;  dlim1 = dlim;  dp == ditem
  atype_flags = typeid+arry+okflag;  atype_type = itemtype
  %if atype_type < 0 %start;  !element %name
    atype_flags = atype_flags+name;  atype_type = atype_type-name
  %finish
  atype_mode = constmode;   !by default (literal bounds)
  tot = 0;  totsize = |itemsize|
  %if dim > 0 %start;  !%array(n)%name
    atype_mode = mode
    put bounds
    elements = maxint
  %else;  !left parenthesis recognised
    get REST
    get(right)
  %finish
  dp_type = atype_type
  %if mode # constmode %and mode # ownmode %start
    holdval = d0
    %while pos # dlim1 %cycle
      dp == dict(pos)
      dp_type = atype_type
      %if mode >= framemode %start
        dp_flags = dp_flags!arrflag %if lo1 = minint %or size1 = 0
        %if decl_flags >= 0 %start;  !%array not %array%name
          %if totsize # 0 {all literal bounds} %c
          %and totsize<<1-c_sp+disp <= 32000 %start
            !if array will occupy less than half remaining reach
            !then allocate directly on stack
            disp = disp+totsize
            align(disp,2)
          %else
            fault(ordererr) %if c_mode&2_01000000 # 0; !hard order error
            %if totsize # 0 %start;  !known bounds but too big
              c_extra = c_extra+totsize
              holdval = litref(totsize)
            %finish
            ![ADOK updates C_SP]
            holdz = 0;  holdz = litref(-lo1*size1) %if dp_flags&arrflag = 0
            putact(adok,holdval,holdz);  !compute & store space needed
            compile(np0)
            dp_flags = dp_flags+indirect
            dp_link = c_dynarray
            c_dynarray = pos;  c_dynarray = -c_dynarray %if holdz # 0
            c_status = c_status!unknown
            holdval = 0
          %finish
          dp_val = c_sp-disp
        %finish
      %else { %if decl_flags >= 0};  !record field or absolute
                                  !** to be corrected **
                                  !name already allocated
{        dp_val = disp;  disp = disp+totsize}
        dp_val = disp
        %if decl_flags < 0 %then disp = disp+4 %else disp = disp+totsize
      %finish
      pos = pos+1
    %repeat
  %else;                           !const,own
    %if decl_flags&(name+indirect) # 0 %start
      %if mode = constmode %then fill code(4) %else fill own(4)
    %else
      %if a assop(itemtype) %start
        jam = jammy
        dp_flags = dp_flags!okflag;  ![hum]
        allow(terminator)
        %cycle
          jammy = jam
          get VALUE(itemtype)
          faultnum = rangerr+point+warn %if faultnum = rangerr+point
          holdval = value
          value = 1
          %if a(left) %start
            value = elements
            get LITERAL(halftype) %if %not a(star)
            get(right)
          %finish
          elements = elements-value
          value = value+elements %if elements < 0
          dump const(holdval,value)
        %repeat %until %not a(comma)
        %if faultnum = 0 %and elements # 0 %start
          %if elements < 0 %then report(counterr,pos,elements) %c
          %else report(counterr+warn,pos,elements)
        %finish
      %finish
      dump const(0,elements) %if elements > 0
    %finish
  %finish
%end;  !get ARRAY DECLARATION
!
%routine GET PROCEDURE DECLARATION
%integer pos,dlim1,argmode,argad,restype,stack
%record(identinfo)%name headditem,dhold

%predicate DUPOK
!Check that the proc being declared can reasonably alias existing id
%record(identinfo)%name tp
  %false %if ditem_flags&proc = 0
  tp == typecell(ditem_type)
  %if restype = 0 %start;  !routine
    %false %if tp_type # 0 %or tp_link = 0; !not routine, or no pars
  %else
    %false %if restype = tp_type;  !function of same type
  %finish
  %true
%end

  restype = itemtype
  stack = 0;  !unknown
  decl_flags = decl_flags&(\okflag)
  decl_type = procstar;             !by default
  %if depth # 0 %start;             !procedure as param
    decl_flags = decl_flags!proc2;  ![must push MB in case external]
  %else %if mode >= framemode
    decl_mode = procmode;  decl_val = 0
    decl_flags = decl_flags!proc1
    decl_flags = decl_flags!spec %if a(keyspec)
  %else %if mode = ownmode;               !external (not @)
    decl_mode = procmode;  decl_val = 0
    %if a(keyspec) %start
      decl_mode = ownmode;  decl_flags = decl_flags!spec
    %finish
  %else;   !@...
    decl_flags = decl_flags!proc1
    decl_val = disp
    stack = 4
  %finish
  %if decl_flags&ext # 0 %and a(keyalias) %start
    nonstandard(9)
    get(ident)
    %if item <= 0 %start
      fault(namerr+point)
    %else
      item = 0 %and decl_flags = decl_flags!alt %if dupok
    %finish
  %else
    get(ident)
  %finish
  declare(decl)
  headditem == ditem
  assign address(-6) %if depth # 0
  argmode = c_mode&(\2_01000000)+1
  %if decl_flags&spec # 0 %or decl_mode # procmode %start
    speccing = speccing+1
  %else
    c_forward = c_forward-1 %if ditem_flags&rflag # 0
    open block(item)
    c_type = restype
    c_type = c_type!sign16 %if decl_flags&writable # 0 {%map}
  %finish
  dlim1 = dlim
  declare anon(details(0,restype,0,stack))
 ! Result in A0 for %map or structure %fn
  ditem_reg = 8 %if decl_flags&writable # 0 {%map} -
                %or size(restype) <= 0 {structure %fn}
!Declare parameters
  argad = c_sp;     !ok for both spec and body
  %if a(left) %start
    dhold == dlink;  dlink == ditem
    get DECLARATION(okflag+writable+readable,argmode,argad,1)
    dlink == dhold
    get(right)
  %finish
  %if speccing # 0 %start
    speccing = speccing-1
    pos = crunched(dlim1)
    %if pos < dlim1 %or speccing = 0 %start
      headditem_type = pos
    %else;                    !proc as param
      fault(classerr);  dlim = dlim1
    %finish
  %else;                        !procedure body
    %if c_dpid_flags&spec # 0 %start
      c_dpid_flags = c_dpid_flags-spec
      %if %not parmatch(c_dpid_type,dlim1) %start
        %if c_pid = dlim1-2 %then fault(matcherr+warn) %c
        %else fault(matcherr)
      %finish
    %finish
    headditem_type = dlim1
    c_parlim = dlim
    c_sp = -argad
    compile(np0)
    get(terminator)
    get STATEMENTS(keyend)
  %finish
%end;  !get procedure declaration

%routine GET INITIAL VALUE(%record(identinfo)%name dp)
%integer present=0
  jammy = 0
  %if a assop(itemtype) %start
    get VALUE(itemtype)
    dp_flags = dp_flags!okflag
    present = 1
  %finish
  %if mode >= framemode %start;  !dynamic
    %if present # 0 %start
      atomp = expp %and nonstandard(1) %if item # 0
      %if itemtype < 0 %start
        putact(okass,dlim0+ad,normitem)
      %else
        putact(okass+jammy,dlim0,normitem)
      %finish
      compile(np0)
    %finish
  %else %if mode = constmode
    syntax error %if present = 0
    %if itemtype < 0 %start;  !name
      dp_flags = writable+readable
      dp_mode = absmode;  dp_val = value
    %else
      faultnum = rangerr+point+warn %if faultnum = rangerr+point
      %if itemsize <= 0 %then dump const(value,1) %c
      %else dp_mode = litmode %and dp_val = value
    %finish
  %else;  !own
    %if present # 0 %start
      faultnum = rangerr+point+warn %if faultnum = rangerr+point
      dump const(value,1)
    %else
      %if itemtype < 0 %then fill own(4) %else fill own(|itemsize|)
    %finish
  %finish
%end;  !get initial value

dreg = d0;  areg = a0;  stmax = 8;  !allow for RETAD & LINK
max = 0;  base = disp
%cycle
  disp = base
  %cycle
    decl = 0
    decl_flags = flags;  decl_mode = mode
    adim = -1
    %while a(kattrib) %cycle
      decl_flags = decl_flags!!(1<<subatom)
    %repeat
    %if depth = 0 %and a(left) %start;  !start of sub-group
      align(disp,2)
!      ad_cat = ad_cat+1 %if mode = 0
      get DECLARATION(flags,mode,disp,0);  get(right)
!      ad_cat = ad_cat-1 %if mode = 0
    %else %if a(rpred);  !%routine,(%predicate)
      %if subatom # 0 %start;  !pred
        decl_flags = decl_flags&(\(writable))
        decl_flags = decl_flags!volatile %if control&volbit # 0
        itemtype = booltype
      %else
        decl_flags = decl_flags&(\(writable+readable))
        itemtype = 0
      %finish
      get PROCEDURE DECLARATION
      %return %if depth = 0
    %else
      get DATA TYPE
      !Appendages
      %if a(fnmap) %start;  !%fn, %map
        decl_flags = decl_flags!volatile %if control&volbit # 0
        %if subatom = 0 %start
          decl_flags = decl_flags&(\writable)
          fault(illstarred) %if itemsize = 0
        %finish
        get PROCEDURE DECLARATION
        %return %if depth = 0
      %else
        decl_flags = decl_flags&(\proc)
        decl_type = itemtype
        %if a(keyname) %start
          decl_flags = decl_flags+name;  itemtype = itemtype+name
          itemsize = 4
        %finish
        %if a(keyarray) %start
          fault(illstarred) %if itemtype = recstar;  !%record(*)%array
          adim = 0
         ! ITEMTYPE now reflects element type (+name)
         ! DECL is for the array itself
          decl_flags = decl_flags&(\name)
          decl_type = arrstar
          decl_flags = decl_flags!arrflag %if control&arrbit # 0
          %if a(left) %start
            fault(notin+point) %if depth = 0
            get LITERAL(inttype)
            %if value&(\7) # 0 %then expfault(rangerr) %else adim = value
            get(right)
            get(keyname);  matched = 0
          %finish
         ! %array%name versus %array
          decl_flags = decl_flags+name %if a(keyname)
        %finish
       ! %record(*) or %string(*) needs %name (or @)
       ! %string alone allowed only for %const%string
        fault(illstarred) %if itemsize = 0 %c
                          %and decl_flags >= 0 %and disp ## jokerad %c
                          %and decl_type # stringtype {const}
        %if disp == c_val %start;  !main declaration
          fault(notinblock) %if stopper = 0
          %if c_status >= hadon %start
            %if c_forward!c_return # 0 %or curlab # c_lab1 %start
              fault(ordererr)
            %else %if c_status&hadordererr = 0
              fault(ordererr+warn);  c_status = c_status+hadordererr
            %finish
          %finish
        %else %if decl_flags&ext # 0 %and a(keyspec)
          decl_flags = decl_flags!(spec+indirect)
        %finish
       !Read identifier list
        %cycle
          dlim0 = dlim
          %unless decl_type = arrstar %start;  !not array
            get QIDENT
            assign address(itemsize)
            %if mode >= ownmode %and depth = 0 %start
              %if decl_flags&spec = 0 %then get INITIAL VALUE(ditem) %c
              %else set own word(0) %and set own word(0)
            %finish
          %else
            %cycle
              get QIDENT
              assign address(0);  !(4 if name)
              %exit %if %not a(comma)
              atom = next atom
              %if atom # ident %start;  !ie new type
                %if adim = 0 %start;    !treat %array%name as %array(1)%name
                  syntax error %if decl_flags >= 0
                  adim = 1
                %finish
                get ARRAY DECLARATION(adim)
                -> exit22
              %finish
            %repeat
            %if adim # 0 %or %not a(left) %start
               %if adim = 0 %start
                 syntax error %if decl_flags >= 0
                 adim = 1
               %finish
               get ARRAY DECLARATION(adim)
               -> exit2
            %finish
            get ARRAY DECLARATION(adim)
          %finish
          -> exit2 %if %not a(comma)
          atom = next atom
        %repeat %until atom # ident
exit22:
        %continue
      %finish
    %finish
    %exit %if %not a(comma);  ![NB %continue above]
  %repeat
exit2:
  max = disp %if disp > max
%repeat %until %not a(keyor)
disp = max
%end;  !get declaration

initial(keyconst):
  literal = 1
  get DECLARATION(okflag+readable,constmode,cad,0)
  -> term

initial(atsign):
  dump = 0
atted:
  fault(lowlevel+warn+point) %and control = control!lowbit %if control&lowbit = 0
  get LITERAL(inttype)
  jokerad = value
  %if a(left) %start
    get MIDENT(a0,a7)
    get(right)
    value = item+(dispmode-a0)
  %finish %else value = absmode
  literal = 1
  get DECLARATION(dump!(okflag+writable+readable),value,jokerad,0)
  -> term

initial(keyown):
  literal = 1
  get DECLARATION(writable+readable,ownmode,ownad,0)
  -> term

initial(keyext):
  fault(ordererr) %if level # outerlevel
  literal = 1
  dump = subatom<<12
  -> atted %if a(atsign)
  %if a(left) %start
    get LITERAL(inttype);  get(right)
    maxcalldreg = (d0-1)+value&15
    maxcallareg = (a0-1)+value>>4&15
    dump = dump!!(value&(\255))
  %finish
  get DECLARATION(dump!(writable+readable),ownmode,ownad,0)
  -> term

initial(keyrecord):
  %if %not a(left) %start
    get(keyformat)
    %if a(keyspec) %start
      typeident_flags = typeid+spec+recy
      get(ident);  declare(typeident)
    %else
      typeident_flags = typeid+recy
      get(ident);  declare(typeident)
      get(left)
      dformat == ditem
      get DECLARATION(writable+readable,0,dformat_val,0)
      recalign(dformat_val)
      get(right)
    %finish
    -> term
  %finish
  fp = fp-1;  atom = keyrecord;  !back-up
initial(ktype): initial(keylong):
initial(keyinteger): initial(keyreal):
initial(kattrib): initial(keystring):
initial(rpred):
  matched = 0
  get DECLARATION(writable+readable,c_mode,c_val,0)
  -> term

initial(keylabel):
  get IDENTLIST(forwardlabel)
  -> term

%routine GET SWITCH DECLARATION
%integer i,lo,hi,dlim1
%ownrecord(objinfo) d=0
  matched = 1
  %cycle
    d_type = arrstar;  !(in case of error)
    d_flags = d_flags+arrflag %if control&arrbit # 0
    d_mode = labmode
    get IDENTLIST(d)
    dlim1 = dlim
    declare anon(details(typeid+arry,0,0,0))
    get(left);  get LIT RANGE(inttype);  get(right)
    dict(dlim1)_xtype = item
    get bounds(item,lo,hi)
    %cycle;  !For each ident in group
      %for i = lo,1,hi %cycle
        swpc = swpc-1;  prog(swpc) = 0
        croak("Code space exhausted") %if swpc <= pc
      %repeat
      dict(dlim0)_val = swpc
      dict(dlim0)_type = dlim1
      dlim0 = dlim0+1
    %repeat %until dlim0 = dlim1
  %repeat %until %not a(comma)
%end
initial(keyswitch):
  literal = 1
  get SWITCH DECLARATION
  c_status = c_status!hadswitch
  ->term

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!  Control statements  !!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
%routine OPT
%integer c=control
  set options(string(final0+value))
  select output(listout);  !**for now - PAM may alter**
  control = control&(\list) %if initcon&list = 0
  control = control!list %if control&(\c)&(ttlist+codelist+explist+dictlist) # 0
%end

initial(keyoption):
  get LITSTRING
  get(terminator)
  opt %if faultnum = 0
  -> next

initial(keyinclude):
  get LITSTRING
  get(terminator)
  %if faultnum = 0 %start
    croak("Too many nested includes") %if curfile = 3
    line = line+1 %if sym = nl
    cur_fp = fp;  cur_line = line
    fcontrol(curfile) = control
    control = control&(\list) %if control&(codelist+explist+dictlist) = 0
    curfile = curfile+1
    lastfile = -1 %if curfile = lastfile
    cur == file(curfile);  cur = 0
    time1 = time1-cputime
    define param("INC",cur_name,nodefault)
    opt
    connect edfile(cur)
    time1 = time1+cputime
    %signal abandon %if cur_flag # 0
    line = 0;  sym = nl
    curstart = cur_start2;  curlim = cur_lim2
    fp = cur_start2
  %finish
  ->next

initial(keycontrol):
  get LITERAL(inttype)
  control = 0 %if value = 0
  control = control!!value
  show dict(0) %if control&dictlist # 0
  ->term

initial(keylist):
  control = control!list
  ->term

initial(keybegin):
  get(terminator)
  %if stopper = 0 %start;  !first %begin
    c_localdpos = dlim;  c_parlim = dlim
    c_access = 1
    get STATEMENTS(keyend)
    %return
  %finish
  declare anon(beginblock)
  open block(dlim0)
  get STATEMENTS(keyend)
  update sp
  this is inst
  srcall(dlim-1)
  -> term

initial(keyend):
  %if stopper > keyend %start
    %if stopper = keyrepeat %then fault(norepeat+now) -
    %else fault(nofinish+now)
  %else
    %if a(keyof) %start
      %if a(keylist) %start
        control = control&(\list)
        ->term
      %finish
      %if a(keyfile) %start
       fp = curlim;  sym = nl
        ->next
      %finish
      get(keyprogram)
      fault(noend+now) %if level # outerlevel
    %finish
    fault(nobegin+now) %if stopper = 0
    %if c_access > 0 %start
      fault(noresult+now) %if c_type # 0;  !fn/map/pred
    %finish
    close block
  %finish
%end;  !GET STATEMENTS

!<<BOTH

%routine ANNOUNCE(%integer value,%string(255) message)
  write(value,1);  space;  printstring(message)
  printsymbol('s') %if value # 1
%end

%routine OUTPUT OBJECT FILE
%constinteger OBJOUT=1
%constinteger INITSIZE=18
!%constinteger INITSIZE=30
%integer i,reset,totsize,ownsize
! INIT SEQUENCE
!   code to copy own values from end of code area to data area
!
!    Program area                 Data area
!   ________________         __________________
!   |              |         |                |
!   |              |         |  STACK SPACE   |
!   |    CODE      |         |                |
!   |              |     SP->|~~~~~~~~~~~~~~~~|
!   |______________|         |                |
!   |    init      |         |                |
!   |~~~~~~~~~~~~~~|         |GLOBAL DYNAMICS |
!   |              |         |                |
!   |  OWN VALUES  |     MB->|~~~~~~~~~~~~~~~~|
!   |              |         |                |
!   |              |         |    OWNS        |
!   |______________|         |                |
!                        orig|                |
!                        SP->|~~~~~~~~~~~~~~~~|
!
 
  reset = 0;  totsize = cad
  ownsize =  ownad
  %if ownsize # 0 %start
    fill own(4-ownad&3) %if ownad&3 # 0
    ownsize = ownad
    reset = cad;    !entry-point for RESET
    totsize = totsize+(initsize+ownad);  !total code size
  %finish
  set extension(objfile,".mob")
  time1 = time1-cputime
  open output(objout,objfile)
  select output(objout)
  put word(16_FE02);  !object module flag, version
  put word(control>>20<<4);  !checking options
  value = 0
  do externals(externs,-1) %if externs # 0;  !find size
  put word(value);        !length of exports
  value = 0
  do externals(extspecs,-1) %if extspecs # 0;  !find size
  put word(value);        !length of imports
  put word(totsize>>16);  !length of code + init pattern
  put word(totsize)
  put word(reset>>1);     !reset entry-point
  put word(c_dpid_val>>1);  !main entry-point
  put word(ownsize>>16);       !static data requirement
  put word(ownsize)
  put word(c_totstack>>16);  !stack requirement
  put word(c_totstack)
  put word(0);            !spare for diag
  put word(0)
  put word(0)
  put word(0)
  do externals(externs,0) %if externs # 0
  do externals(extspecs,1) %if extspecs # 0
  final(0) = 16_4E;  final(1) =16_75;  !RTS (as null reset,main?)
  i = 0
  %cycle
    print symbol(final(i));  i = i+1
  %repeat %until i = cad
  %if ownsize # 0 %start
    put word(16_2248+mb-a0);       !   move.l mb,a1
    put word(16_41FA);             !   lea initpatt,a0
    put word(16_000E)
    put word(16_303C);             !   move.w #????,d0
    put word(ownad>>1-1);          ![individual owns in shortwords - 1]
    put word(16_32D8);             !l1 move.w (a0)+,(a1)+
    put word(16_51C8);             !   dbra d0,l1
    put word(-4)
    put word(16_4E75);             !   rts
    i = 0
    %cycle
      print symbol(final(i+ownbase));  i = i+1
    %repeat %until i = ownad
  %finish
  time1 = time1+cputime
%end

%routine CLOSE EDIT
!_FLAG is negative if edit abandoned
!_CHANGE is untouched (inf) if no changes
  %if file(main)_flag >= 0 %and 0 < file(main)_change # 16_7FFFFFFF %start
    file(main)_name = mainfile;  ![in case modified by OPEN IN]
    time1 = time1-cputime
    disconnect edfile(file(main))
    printstring(file(main)_name."  updated");  newline
    time1 = time1+cputime
  %finish
%end

%begin
%on %event redo,abandon %start
  close edit %and %stop %if event_event = abandon
%finish
  time2 = cputime-time1
  statements = 1;  comments = 0;  atoms = 0
  identatoms = 0;  litatoms = 0
  faults = 0;  others = 0;  faultnum = 0
  zaps = 0;  steps = 0;  jumps = 0;  shorts = 0
  rep = ""
  forget triples;  !reset LITPOS,EXPLO,OLDEXPLO
  char0 = addr(char(0));  final0 = addr(final(0))
  preset
  dint == dict(inttype)
  dtemp == dict(lablim);  dtemp2 == dtemp[1]
  dtsprel == dtemp2[1]
  dmin = dictlim;  dmin0 = dmin
  inclim = 0
  accounted = 0
  firstentry = finalbound;  firstpos = dictlim
  pc = 1;  swpc = progbound+1
  cad = 2
  final(0) = 0;  !for empty string (compile-time only)
  ownbase = finalbound-4095;  ownad = 0
  level = outerlevel;  vintage = 1
  pendout = 0;  pendin = 0;  polarity = 0
  curlab = dictlim+1
  reset context(procstar,defaultfree)
  c_sp = -4;   !allow for BSR

  control = initcon
  lastfile = main
  curfile = main;  cur == file(main)
  curstart = file(main)_start1;  curlim = file(main)_lim1
  fp = file(main)_start1
  line = 0;  sym = nl
  np = np0
!<<IMP
  get STATEMENTS(0)
!<<BOTH
%end

  time2 = cputime-time2-time1
  close edit
  output object file %if faults = 0 %or control&forcebit # 0
  %cycle
    select output(listout)
    printstring(file(main)_name)
    %if faults = 0 %or control&forcebit # 0 %start
      printstring(" compiled:")
      announce(statements,"statement")
      print string(" (+")
      announce(comments,"comment")
      printstring(") to")
      announce(cad,"byte")
      printstring(" (+");  write(ownad,1)
      printsymbol(')')
      newline
    %finish
    %if faults # 0 %start
      printsymbol(':')
      announce(faults,"fault")
      printstring(" reported")
      %if others # 0 %start
        printstring(" (+");  announce(others,"other")
        printsymbol(')')
      %finish
      newline
    %finish
    %if control&logbit # 0 %start
      printstring(%c
"  CODE  OWNS  JUMPS SHORT STEPS  ZAPS | ATOMS LITS IDS  TIME")
      newline
      write(cad,5)
      write(ownad,5)
      write(jumps,6);  write(shorts,5)
      write(steps,5);  write(zaps,5)
      print(atoms/statements,5,1)
      print(litatoms/statements,2,1)
      print(identatoms/statements,1,1)
      print(time2/statements,2,3)
      printsymbol('+')
      print(time1/statements,0,3)
      newline
    %finish
    %exit %if listout = 0
    listout = 0
  %repeat
!<<IMP
%endofprogram
