!Graham Toal - new development version of SKIMPD 13/02/80 13.27

const string (1) snl = "
"

external integer array spec a(1 : 500)

external byte integer array spec named(1 : 1024)

external integer array spec namedlink(0 : 255)

external integer array spec taglink(0 : 255)

external integer array spec tag(1 : 512)

external integer array spec link(1 : 512)

external integer array spec nextrad(0 : 15)

external integer array spec rt(0 : 15)

external integer array spec parms(0 : 15)

external string (5) array spec display(0 : 15)

external integer faults = 0
external integer spec tagasl, level, tagsopt, nextcad, namedp, c
 traceopt, aopt, pstr
!-----------------------------------------------------------------------
external integer fn spec intstr(string (6) val)
external routine spec expr(integer exprp)
routine spec popitem(integer name f, l)
! Local
external integer fn spec outstream
!-----------------------------------------------------------------------
own integer array used(0 : 15) = 0(*)

own integer array worklist(0 : 15) = 0(16)

own integer array namelist(0 : 15) = 0(16)

own integer array branchlist(0 : 15) = 0(16)

own integer array startlist(0 : 15) = 0(16)

own integer array cot(0 : 127)

own integer cotp, params
!-----------------------------------------------------------------------
external string (255) fn strint(integer n, p)
   string (255) r
   string (1) s
   if n < 0 then s = "-" and n = -n else s = ""
   r = ""
   r = tostring(n - n // 10 * 10 + '0') . r and n = n // 10 until n = 0
   r = s . r
   r = " " . r while length(r) < p
   result = r
end
!-----------------------------------------------------------------------
external string (7) fn s(integer i)
   result = strint(i, 0)
end
!-----------------------------------------------------------------------
external string (8) fn strhex(integer n)
   const string (1) array h(0 : 15) = c
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"

   integer i
   string (8) sh
   sh = ""
   for i = 1, 1, 8 cycle
      sh = h(n & 16_F) . sh
      n = n >> 4
   repeat
   result = sh
end
!-----------------------------------------------------------------------
external routine fault(string (63) mess)
   integer st
   printstring("?  " . mess . "

")
   st = outstream
   selectoutput(0)
   printstring("*" . mess . snl)
   selectoutput(st)
   faults = faults + 1
end
!-----------------------------------------------------------------------
external routine dump(string (7) lab, op, reg, addr)
   own string (7) label = ""
   routine spec codeout(string (7) l, o, r, a)
   if label # "" start
      if lab = "" then lab = label else start
         codeout(label, "EQU", "", "*")
         label = ""
      finish
   finish
   if (op = "ADD" or op = "SUB" or op = "EOR" or op = "OR") and addr = "#0" then return
   if (op = "AND" or op = "LD") and reg # "D" and addr = "#0" then op = "CLR" and addr = ""
   if op = "ADD" and addr = "#1" and reg # "D" then start
      op = "INC"
      addr = ""
   finish
   if op = "SUB" and addr = "#1" and reg # "D" then start
      op = "DEC"
      addr = ""
   finish
   if op = "CMP" and addr = "#0" and reg # "D" then op = "TST" and addr = ""
   if op = "EQU" and addr = "*" then label = lab c
   else label = "" and codeout(lab, op, reg, addr)

   routine codeout(string (7) lab, op, reg, addr)
      string (6) nums
      integer i
      routine dump2(string (7) lab, op, reg, addr)
         own string (7) lastop = "silly"
         own integer inhibit = 0
         if reg = "B" and op = "LD" and addr -> ("#") . nums c
           and (not nums -> ("-") . nums) and intstr(nums) > 255 then reg = "D"
         if lab # "" then start
            if op = "EQU" and addr = "*" then inhibit = 0
            if op # "EQU" then inhibit = 0
         finish
         if inhibit = 0 or op = "EQU" then start
            lastop = op
            return if op = "TST" and reg = "B" and lab = ""
            !   ****FRIG****
            if op = "CMP" and addr = "#1" then addr = "" and op = "DEC"
            printstring(lab)
            spaces(10 - length(lab))
            op = op . reg
            printstring(op)
            spaces(10 - length(op))
            printstring(addr)
            newline
            nextcad = nextcad + 1
         finish
         if op = "LBRA" or op = "SWI2" or (op = "SWI" and reg = "2") c
           then inhibit = 1
         return unless op = "LBSR"
         if addr = "SHL" then used(12) = 1
         if addr = "SHR" then used(13) = 1
         if addr = "EXP" then used(14) = 1
         if addr = "DIV" then used(15) = 1
      end
      own string (7) array l(1 : 2) = ""(2)

      own string (7) array o(1 : 2) = ""(2)

      own string (7) array r(1 : 2) = ""(2)

      own string (7) array a(1 : 2) = ""(2)

      own integer buffptr = 0
      switch load(0:2)
      switch store(0:2)
      routine flushbuffer
         integer i
         for i = 1, 1, buffptr cycle
            dump2(l(i), o(i), r(i), a(i))
         repeat
         buffptr = 0
      end
      routine checklabel(integer buff)
         if buff = 3 then start
            if lab # "" then dump2(lab, "EQU", "", "*")
            return
         finish
         if l(buff) # "" then dump2(l(buff), "EQU", "", "*")
      end
      routine savethisinstr
         buffptr = buffptr + 1
         if buffptr > 2 then start
            printstring("*?????Buffer full..." . snl)
            flushbuffer
         finish
         l(buffptr) = lab
         o(buffptr) = op
         r(buffptr) = reg
         a(buffptr) = addr
      end
      if op = "SEX" and buffptr # 0 and o(buffptr) = "LD" c
      and a(buffptr) -> ("#") . nums and (not nums -> ("-") . nums) c
      and intstr(nums) > 255 then return
      if reg # "B" then start
         flushbuffer
         dump2(lab, op, reg, addr)
         return
      finish
      if op = "LD" then start
         -> load(buffptr)
load(0): 
         savethisinstr
         return
load(1): 
         if o(1) = "LD" then checklabel(1) and buffptr = 0 else start
            if o(1) = "ST" and a(1) = addr then start
               if lab # "" then start
                  flushbuffer
                  savethisinstr
                  return
               finish else return
            finish
         finish
         savethisinstr
         return
load(2): 
         dump2(l(1), o(1), r(1), a(1))
         l(1) = l(2)
         r(1) = r(2)
         o(1) = o(2)
         a(1) = a(2)
         buffptr = 1
         printstring("?***** Unexpected third el = load" . snl)
         -> load(1)
      finish
      if op = "ST" then start
         -> store(buffptr)
store(0): 
         savethisinstr
         return
store(1): 
         if o(1) = "LD" or o(1) = "ST" then start
            if a(1) = addr then start
               if lab # "" then start
                  flushbuffer
                  savethisinstr
                  return
               finish else return
            finish else start
               flushbuffer
               savethisinstr
               return
            finish
         finish
         if o(1) = "CLR" then start
            checklabel(1)
            buffptr = 0
            dump2(lab, "CLR", "", addr)
            return
         finish
         flushbuffer
         savethisinstr
         return
store(2): 
         if o(1) = "LD" and a(1) = addr and (o(2) = "INC" or o(2) = "DEC" c
           or o(2) = "NEG" or o(2) = "COM") then start
            checklabel(2)
            checklabel(3)
            dump2(l(1), o(2), "", addr)
            buffptr = 0
            return
         finish
         dump2(l(1), o(1), r(1), a(1))
         l(1) = l(2)
         o(1) = o(2)
         r(1) = r(2)
         a(1) = a(2)
         buffptr = 1
         -> store(1)
      finish
      if op = "TST" then start
         if buffptr # 0 then start
            if o(buffptr) = "LD" then start
               dump2(l(buffptr), op, "", a(buffptr))
               checklabel(3)
               buffptr = buffptr - 1
               return
            finish
         finish
         flushbuffer
         dump2(lab, op, reg, addr)
         return
      finish
      if op = "INC" or op = "DEC" or op = "CLR" or op = "NEG" c
        or op = "COM" then start
         if buffptr = 2 then start
            dump2(l(1), o(1), r(1), a(1))
            l(1) = l(2)
            o(1) = o(2)
            r(1) = r(2)
            a(1) = a(2)
            l(2) = lab
            o(2) = op
            r(2) = reg
            a(2) = addr
            buffptr = 2
            return
         finish
         savethisinstr
         return
      finish
      flushbuffer
      dump2(lab, op, reg, addr)
   end
end
!-----------------------------------------------------------------------
external string (255) fn name(integer ident)
   unless 0 <= ident <= 255 and namedlink(ident) # 0 then result = ""
   result = string(addr(named(namedlink(ident))))
end
!-----------------------------------------------------------------------
external integer fn newtag
   integer i
   if tagasl = 0 then fault("TAG SPACE FULL") and stop
   i = tagasl
   tagasl = link(tagasl)
   result = i
end
!-----------------------------------------------------------------------
external integer fn returntag(integer tagi)
   integer l
   l = link(tagi)
   link(tagi) = tagasl
   tagasl = tagi
   result = l
end
!-----------------------------------------------------------------------
external integer fn getwork
   !%integername cell
   !  cell==worklist(level)
   !  %while cell#0 %cycle
   !    %if tag(cell)<0 %then tag(cell)=-tag(cell) %and %result=tag(cell)
   !    cell==link(cell)
   !  %repeat
   !  cell=newtag
   !  tag(cell)=nextrad(level)
   !  nextrad(level)=nextrad(level)+1
   !  link(cell)=0
   !  %result=tag(cell)
   result = 0
end
!-----------------------------------------------------------------------
external routine returnwork(integer work)
   !%integer cell
   !  cell=worklist(level)
   !  %while cell#0 %cycle
   !    %if tag(cell)=work %then tag(cell)=-work %and %return
   !    cell=link(cell)
   !  %repeat
end
!-----------------------------------------------------------------------
external routine clearwork
   integer cell
   cell = worklist(level)
   cell = returntag(cell) while cell # 0
   worklist(level) = 0
end
!-----------------------------------------------------------------------
external integer fn getcoti(integer const)
   integer coti
   if cotp > 0 then start
      for coti = 0, 1, cotp - 1 cycle
         if cot(coti) = const then result = coti
      repeat
   finish
   if cotp = 128 then fault("CONSTANT TABLE FULL") and stop
   cot(cotp) = const
   cotp = cotp + 1
   result = cotp - 1
end
!-----------------------------------------------------------------------
external routine pushtag(integer ident, form, type, dim, level, rad)
   integer tagi
   if taglink(ident) # 0 and tag(taglink(ident)) >> 16 & 16_F = level c
   then fault("NAME " . name(ident) . " DECLARED TWICE")
   tagi = newtag
   tag(tagi) = form << 28 ! type << 24 ! dim << 20 ! level << 16 ! rad
   link(tagi) = taglink(ident)
   taglink(ident) = tagi
   tagi = newtag
   tag(tagi) = ident
   link(tagi) = namelist(level)
   namelist(level) = tagi
end
!-----------------------------------------------------------------------
external routine poptags
   integer cell, ident, nametag, params
   string (63) s
   if tagsopt = 1 then newline
   cell = namelist(level)
   while cell # 0 cycle
      ident = tag(cell)
      cell = returntag(cell)
      nametag = tag(taglink(ident))
      taglink(ident) = returntag(taglink(ident))
      if tagsopt = 1 then start
         s = name(ident)
         printstring(strint(ident, 3) . "   " . s)
         spaces(10 - length(s))
         printstring(strhex(nametag))
      finish
      if nametag >> 28 = 4 then start
         ! procedure type
         params = nametag >> 20 & 16_F
         while params # 0 cycle
            if tagsopt = 1 then printstring("
                    " . strhex(tag(taglink(ident))))
            taglink(ident) = returntag(taglink(ident))
            params = params - 1
            ! pop up parameter tags
         repeat
      finish
      if tagsopt = 1 then newline
      if taglink(ident) = 0 then namedp = namedlink(ident) and namedlink(ident) = 0
      ! backtrack name dictionary
   repeat
   if tagsopt = 1 then newline
   namelist(level) = 0
end
!-----------------------------------------------------------------------
external integer fn getlabel(integer constp)
   integer label
   label = a(constp + 1)
   if label > 9999 then fault("LABEL " . strint(label, 1) . " TOO LARGE") c
     and result = -1 else result = label
end
!-----------------------------------------------------------------------
external routine filllabel(integer label)
   !%integer cell
   return if label < 0
   ! for conditional statements
   !  cell=branchlist(level)
   !  %while cell#0 %cycle
   !    %if tag(cell)>>16=label %then %start
   !      %if tag(cell)&16_8000=0 %then fault("DUPLICATE LABEL ". !        strint(label,1)) %else %start
   dump("L" . s(label), "EQU", "", "*")
   !        tag(cell)=label<<16!nextcad
   !      %finish
   !      %return
   !    %finish
   !    cell=link(cell)
   !  %repeat
   !  cell=newtag
   !  link(cell)=branchlist(level)
   !  branchlist(level)=cell
   !  tag(cell)=label<<16!nextcad
end
!-----------------------------------------------------------------------
external integer fn fillbranch(integer label)
   integer cell, cad
   result = 0 if label < 0
   cell = branchlist(level)
   while cell # 0 cycle
      if tag(cell) >> 16 = label then start
         cad = tag(cell) & 16_7FFF
         if tag(cell) & 16_8000 # 0 then tag(cell) = label << 16 ! 16_8000 ! nextcad
         result = cad
      finish
      cell = link(cell)
   repeat
   cell = newtag
   link(cell) = branchlist(level)
   branchlist(level) = cell
   tag(cell) = label << 16 ! 16_8000 ! nextcad
   result = 0
end
!-----------------------------------------------------------------------
external routine poplabels
   integer cell
   cell = branchlist(level)
   while cell # 0 cycle
      if tag(cell) & 16_8000 # 0 then fault("LABEL " . strint(tag(cell) >> 16, 1) . c
        " NOT SET (BRANCH LIST " . strint(tag(cell) & 16_7FFF, 1) . ")")
      cell = returntag(cell)
   repeat
   branchlist(level) = 0
end
!-----------------------------------------------------------------------
external integer fn nextplabel
   own integer plabel = 9999
   plabel = plabel + 1
   result = plabel
end
!-----------------------------------------------------------------------
external routine pushstart(integer flag, plab)
   integer cell
   cell = newtag
   tag(cell) = flag << 16 ! plab & 16_FFFF
   ! plab may be -1
   link(cell) = startlist(level)
   startlist(level) = cell
end
external predicate find(integer type, integer name t, lab)
   integer cell
   cell = startlist(level)
   while cell # 0 cycle
      t = tag(cell) >> 16
      if t & 2 = type then start
         lab = tag(cell) & 16_FFFF
         true
      finish
      cell = link(cell)
   repeat
   t = 0
   lab = 0
   false
end
external routine findcontinue(integer name type, lab)
   if find(2, type, lab) then lab = lab + 1 c
   else type = 0 and lab = 0 and fault("%CYCLE MISSING")
end
external routine findexit(integer name type, lab)
   if find(2, type, lab) then lab = lab + 2 c
   else type = 0 and lab = 0 and fault("%CYCLE MISSING")
end
predicate findcycle
   integer t, l
   if find(2, t, l) then true
   false
end
predicate findstart
   integer t, l
   if find(0, t, l) then true
   false
end
external routine popcycle(integer name type, lab)
   popitem(type, lab)
   if type & 2 = 0 then start
      if findcycle then start
         fault("%FINISH MISSING {Or spurious %REPEAT??}")
      finish else start
         fault("SPURIOUS %REPEAT")
         pushstart(type, lab) if lab # 0
      finish
      lab = 0
      type = 3
   finish
end
external routine popstart(integer name type, lab)
   popitem(type, lab)
   if type & 2 = 2 or lab = 0 then start
      if findstart then start
         fault("%REPEAT MISSING {Or spurious %FINISH??}")
      finish else start
         fault("SPURIOUS %FINISH")
         pushstart(type, lab) if lab # 0
      finish
      lab = 0
      type = 0
   finish
end
!-----------------------------------------------------------------------
routine popitem(integer name flag, plab)
   integer cell
   cell = startlist(level)
   if cell = 0 then start
      flag = 0
      plab = 0
   finish else start
      flag = tag(cell) >> 16
      plab = tag(cell) & 16_FFFF
      if plab = 16_FFFF then plab = -1
      startlist(level) = returntag(cell)
   finish
end
!-----------------------------------------------------------------------
external routine clearstart
   integer cell
   const string (7) array what(0 : 1) = "%FINISH", "%REPEAT"

   cell = startlist(level)
   while cell # 0 cycle
      fault(what(tag(cell) >> 17) . " MISSING")
      cell = returntag(cell)
   repeat
   startlist(level) = 0
end
!-----------------------------------------------------------------------
external integer fn enter
   own string (4) array regs(1 : 2) = "A", "A,B"

   string (4) base
   integer alloc, dim
   if level = 1 then start
      if nextcad # 1 then fault("%BEGIN NOT FIRST STATEMENT")
      dump("", "ORG", "", "$F800")
      dump("START", "EQU", "", "*")
      dump("", "SWI", "3", "") if traceopt = 1
      dump("", "LD", "U", "#STACK")
      dump("", "LEA", "X", "-USTK,U")
      base = ",X"
      alloc = 34
      ! Already set up by calling program
      ! Rest for I/O buffers and perm locations.
   finish else start
      ! STORE STP (=Y) IF NECCESARY
      if level > 2 start
         dump("", "ST", "Y", display(level - 1))
      finish
      dump("", "PSH", "S", "Y")
      dump("", "TFR", "", "S,Y")
      alloc = 0
      base = ",Y"
   finish
   !  cad=nextcad
   if level # 1 then start
      ! REMOVED TO 'SKIMPB'
   finish else start
      dump("", "LEA", "S", "-A" . s(rt(level)) . ",X")
   finish
   nextrad(level) = alloc
   result = alloc
end
!-----------------------------------------------------------------------
external routine dumpreturn
   dump("", "TFR", "", "Y,S")
   dump("", "PUL", "S", "Y,PC")
end
!-----------------------------------------------------------------------
external routine array(integer arrayp)
   integer namep, actualp, exprp, exprsp, ident, nametag, basep, disp
   string (4) base
   namep = a(arrayp + 1)
   actualp = a(arrayp + 2)
   ident = a(namep + 1)
   if a(actualp) = 1 then start
      dump("  ", "CLR", "A", "")
      dump("", "ANDCC", "", "0")
      exprp = a(actualp + 1)
      exprsp = a(actualp + 2)
      expr(exprp)
      nametag = tag(taglink(ident))
      basep = nametag >> 16 & 16_F
      base = display(basep)
      base = ",Y" if basep = level
      base = ",X" if basep = 1
      disp = nametag & 16_FFFF
      dump("", "BCC", "", "*+3")
      dump("", "INC", "A", "")
      if basep = 1 or basep = level start
         dump("", "ADD", "D", "-" . s(disp) . base)
      finish else start
         dump("", "PSH", "U", "A,B")
         dump("", "LD", "D", display(basep))
         dump("", "SUB", "D", "#" . s(disp))
         dump("", "ST", "D", "0,X")
         dump("", "LD", "D", "[0,X]")
         dump("", "ADD", "D", ",U++")
      finish
      dump("", "ST", "D", "0,X") if aopt = 0
      aopt = 0
      !    dump("ADD","ACC",display(nametag>>16&16_f),nametag&16_ffff)
      if a(exprsp) = 1 then fault("ARRAY " . name(ident) . " HAS EXTRA INDEX")
   finish else fault("ARRAY " . name(ident) . " HAS NO INDEX")
end
!-----------------------------------------------------------------------
external routine proc(integer procp)
   string (4) opn, base, reg
   integer namep, ident, nametag, ptagl, l, actualp, exprp, unaryp, operandp, c
     npars, ptag, pnamep, pident, pnametag, pactualp, disp, exprrestp, exprsp, c
     oldparams, basep, size
   !  %if params>2 %then dump("LDA","STP","STP",params)
   !***! hack !***!
   if params >= 2 then dump("", "LEA", "S", "-" . s(params + 1) . ",S")
   !***! hack !***!
   oldparams = params
   params = 4
   namep = a(procp + 1)
   actualp = a(procp + 2)
   ident = a(namep + 1)
   l = taglink(ident)
   nametag = tag(l)
   ptagl = link(l)
   npars = nametag >> 20 & 16_F
   if npars = 0 then start
      if a(actualp) = 1 then fault(name(ident) . " HAS PARAMETERS") and return
   finish else start
      if a(actualp) = 2 then fault(name(ident) . " MISSING PARAMETERS") and return
      exprp = a(actualp + 1)
      exprsp = a(actualp + 2)
      cycle 
         ! for each parameter
         ptag = tag(ptagl)
         if ptag >> 28 = 0 then expr(exprp) and reg = "B" else start
            reg = "D"
            unaryp = a(exprp + 1)
            operandp = a(exprp + 2)
            exprrestp = a(exprp + 3)
            unless a(unaryp) = 4 and a(operandp) = 1 and a(exprrestp) = 2 c
         then fault("NOT A %NAME PARAMETER") else start
               pnamep = a(operandp + 1)
               pactualp = a(operandp + 2)
               pident = a(pnamep + 1)
               !?          %if taglink(pident)=0 %then fault(name(pident). !?            " NOT DECLARED") %else %start
               if taglink(pident) = 0 then start
                  dump("", "LD", "B", name(pident))
               finish else start
                  pnametag = tag(taglink(pident))
                  if pnametag >> 28 = 4 then fault(name(pident) . " NOT A %NAME") else start
                     basep = pnametag >> 16 & 16_F
                     base = display(basep)
                     disp = pnametag & 16_FFFF
                     base = "Y" if basep = level
                     base = "X" if basep = 1
                     if ptag >> 28 = 1 then start
                        ! %name
                        if pnametag >> 28 >= 2 then aopt = 1 and array(operandp) else start
                           if pnametag >> 28 = 1 then start
                              if 1 < basep < level start
                                 dump("", "LD", reg, base)
                                 dump("", "SUB", reg, "#" . s(disp))
                                 dump("", "ST", reg, "0,X")
                                 dump("", "LD", reg, "[0,X]")
                              finish else start
                                 dump("", "LD", reg, "-" . s(disp) . "," . base)
                              finish
                           finish else start
                              if 1 < basep < level start
                                 dump("", "LD", reg, base)
                                 dump("", "SUB", reg, "#" . s(disp))
                              finish else start
                                 if basep = 1 = level then start
                                    dump("", "LEA", "Y", "-" . s(disp) . ",X")
                                    reg = "Y"
                                 finish else start
                                    dump("", "TFR", "", base . ",D")
                                    dump("", "SUB", reg, "#" . s(disp))
                                 finish
                                 ! GET ADDRESS OF A %NAME INTO B
                              finish
                           finish
                           !   CHECK FOR SILLY BASE REGISTER
                           !                  dump(opn,"ACC",base,disp)
                           if a(pactualp) = 1 then fault(name(pident) . " DECLARED AS SCALAR")
                        finish
                     finish else start
                        !                dump("LOAD","ACC",base,disp)    ;! %array
                        if base = "Y" or base = "X" start
                           dump("", "LD", reg, "-" . s(disp) . "," . base)
                        finish else start
                           dump("", "LD", reg, base)
                           dump("", "SUB", reg, "#" . s(disp))
                           dump("", "ST", reg, "0,X")
                           dump("", "LD", reg, "[0,X]")
                        finish
                        !   CHECK SILLY BASE REGISTER
                        if a(pactualp) = 1 then fault("%ARRAYNAME " . name(pident) . " HAS INDEX")
                     finish
                  finish
               finish
            finish
         finish
         !      dump("STR","ACC","STP",params)
         if reg = "D" or reg = "Y" then size = 2 else size = 1
         params = params + size
         dump("", "ST", reg, "-" . s(params) . ",S")
         npars = npars - 1
         if npars = 0 then start
            if a(exprsp) = 1 then fault(name(ident) . " HAS EXTRA PARAMETERS")
            exit
         finish
         ptagl = link(ptagl)
         if a(exprsp) = 2 then fault(name(ident) . " IS MISSING PARAMETERS") and exit
         exprp = a(exprsp + 1)
         exprsp = a(exprsp + 2)
      repeat
   finish
   ! external i/o routines at level 0
   if nametag >> 16 & 16_F = 0 then base = "EXT" else base = "E"
   if nametag >> 16 & 16_F = 0 then start
      used(nametag & 16_F) = 1
   finish
   dump("", "LBSR", "", base . s(nametag & 16_FFFF))
   params = oldparams
   !                      EH??????
   !***! frig !***!
   if params >= 2 then dump("", "LEA", "S", s(params + 1) . ",S")
   !  %if params>2 %then dump("SUB","STP","COT",getcoti(params))
end
!-----------------------------------------------------------------------
external routine endofprog
   integer i
   dump("", "SWI", "2", "")
   dump("STACK", "EQU", "", "$0800-1")
   dump("USTK", "EQU", "", "$20")
   !  DUMP("EXT1","EQU","","") %IF USED(1)=1
   !  DUMP("EXT2","EQU","","") %IF USED(2)=1
   !  DUMP("EXT3","EQU","","") %IF USED(3)=1
   !  DUMP("EXT4","EQU","","") %IF USED(4)=1
   !  DUMP("EXT5","EQU","","") %IF USED(5)=1
   !  DUMP("EXT6","EQU","","") %IF USED(6)=1
   !  DUMP("EXT7","EQU","","") %IF USED(7)=1
   !  DUMP("EXT8","EQU","","") %IF USED(8)=1
   !  DUMP("EXT9","EQU","","") %IF USED(9)=1
   !  DUMP("EXT10","EQU","","") %IF USED(10)=1
   !! READSYMBOL POSING AS READ
   !  DUMP("EXT11","EQU","","") %AND USED(15)=1 %IF USED(11)=1
   if used(12) = 1 then start
      dump("DOSHL", "LSL", "B", "")
      dump("", "SUB", "A", "#1")
      dump("SHL", "CMP", "A", "#0")
      dump("", "BGT", "", "DOSHL")
      dump("", "RTS", "", "")
   finish
   if used(13) = 1 then start
      dump("DOSHR", "LSR", "B", "")
      dump("", "SUB", "A", "#1")
      dump("SHR", "CMP", "A", "#0")
      dump("", "BGT", "", "DOSHR")
      dump("", "RTS", "", "")
   finish
   if used(14) = 1 then start
      dump("EXP", "PSH", "S", "B")
      dump("EXP2", "CMP", "A", "#1")
      dump("", "BGT", "", "DOEXP")
      dump("", "LEA", "S", "1,S")
      dump("", "RTS", "", "")
      dump("DOEXP", "PSH", "U", "A")
      dump("", "LDA", "", "0,S")
      dump("", "MUL", "", "")
      dump("", "PUL", "U", "A")
      dump("", "SUB", "A", "#1")
      dump("", "BRA", "", "EXP2")
   finish
   if used(15) = 1 then start
      ! 'B'//'A'
      dump("DIV", "EQU", "", "*")
      dump("", "CLR", "", "-1,S")
      dump("", "CLR", "", "-2,S")
      dump("", "INC", "", "-2,S")
      dump("", "TST", "B", "")
      dump("", "BGE", "", "TRYA")
      dump("", "NEG", "B", "")
      dump("", "CLR", "", "-2,S")
      dump("TRYA", "TST", "A", "")
      dump("", "BGE", "", "OK")
      dump("", "NEG", "A", "")
      dump("", "TST", "", "-2,S")
      dump("", "BNE", "", "OK")
      dump("", "INC", "", "-2,S")
      dump("OK", "TST", "B", "")
      dump("", "BLT", "", "DONE")
      dump("", "INC", "", "-1,S")
      dump("", "PSH", "U", "A")
      dump("", "SUB", "B", ",U+")
      dump("", "BRA", "", "OK")
      dump("DONE", "DEC", "", "-1,S")
      dump("", "TST", "", "-2,S")
      dump("", "BNE", "", "RET")
      dump("", "NEG", "", "-1,S")
      dump("RET", "LD", "B", "-1,S")
      dump("", "RTS", "", "")
   finish else dump("DIV", "EQU", "", "0")
   !  newline
   if pstr # 0 then start
      dump("OUTCH", "LD", "A", "ACIAS")
      dump("", "AND", "A", "#2")
      dump("", "BEQ", "", "OUTCH")
      dump("", "ST", "B", "ACIAD")
      dump("WAITX", "LD", "B", "#$FF")
      dump("", "DEC", "B", "")
      dump("", "BNE", "", "WAITX")
      dump("PSTR", "LD", "B", "[0,S]")
      dump("", "INC", "", "1,S")
      dump("", "BNE", "", "NOCAR")
      dump("", "INC", "", "0,S")
      dump("NOCAR", "CMP", "B", "#$80")
      dump("", "BNE", "", "OUTCH")
      dump("", "RTS", "", "")
   finish
   if faults > 0 start
      begin
         integer st
         st = outstream
         selectoutput(0)
         printstring("Program contains " . s(faults) . " fault")
         printsymbol('s') if faults > 1
         newline
         selectoutput(st)
      end
   finish
   newline
   if faults > 0 then printstring("?" . strint(faults, 4)) else printstring("*NO")
   printstring(" FAULT")
   printsymbol('S') if faults # 1
   printstring(" IN THIS PROGRAM
")
   signal event 13
   ! Not again!!!
end
end of file