Apply 4 patches sent to MR on 2023-12-28 23:13 and add /intcode/session.txt master
authorNick Downing <nick@ndcode.org>
Mon, 8 Jan 2024 15:10:08 +0000 (02:10 +1100)
committerNick Downing <nick@ndcode.org>
Mon, 8 Jan 2024 15:10:28 +0000 (02:10 +1100)
cintcode/com/bcplsyn.b
cintcode/com/cg-intcode.b
cintcode/g/bcplfecg.h
intcode/dlib.b
intcode/interp.b
intcode/session.txt [new file with mode: 0644]

index 3b707bf..2618eb1 100644 (file)
@@ -697,6 +697,7 @@ IF noselst DO writef("NOSELST option was given*n")
   selectoutput(sysprint)
 
   // Now syntax analyse, translate and code-generate each section
+  param := 4000 // Nick, for cg-intcode.b
   { LET b = VEC 64/bytesperword+1
     chbuf := b
     FOR i = 0 TO 63 DO chbuf%i := 0
index f4313aa..fe3a159 100755 (executable)
@@ -39,7 +39,7 @@ datap
 datat
 proglength
 linep
-param
+//param Nick, now defined in bcplfecg.h
 
 maxgn
 maxlab
@@ -1102,7 +1102,7 @@ LET codegenerate(workspace, workspacesize) BE
      }
      ssp, state := 2, nil
      ad_a, ad_k := 0, m_n
-     datap, linep,  param := 0, 0, 1000
+     datap, linep/*,  param*/ := 0, 0/*, 1000*/
 
      gencode()
 //writef("before repeatuntil op=%n %s*n", op, opstr(op))
index 8d41d60..b1fd10c 100755 (executable)
@@ -237,6 +237,7 @@ flt1  // Floating point 1.0 constructed by sys(Sys_flt, fl_mk, 1, 0)
 flt10 // Floating point 10.0 constructed by sys(Sys_flt, fl_mk, 10, 0)
 
 nocomments // Added 03/09/2022
+param // Nick, for cg-intcode.b
 
 lastintglobal // Used to check for global overlap with syng
 }
index 3ef12d6..2eb9a16 100755 (executable)
@@ -30,7 +30,7 @@ LET findstream(name, id, path) = VALOF // MR 8/5/03
 //THEN sawritef("DLIB: findstream(%s, %n, %s)*n", name, id, path)
 //ELSE sawritef("DLIB: findstream(%s, %n, 0)*n", name, id)
 //sawritef("DLIB: currentdir=%n*n", currentdir)
-
+//sawritef("findstream: name=%s*n", name)
   IF console DO
   { IF id=id_inscb & rootnode!rtn_keyboard RESULTIS rootnode!rtn_keyboard
     IF id=id_outscb & rootnode!rtn_screen  RESULTIS rootnode!rtn_screen
@@ -39,11 +39,14 @@ LET findstream(name, id, path) = VALOF // MR 8/5/03
   scb := getvec(scb_upb)
   UNLESS scb RESULTIS 0
 
+//sawritef("findstream: task %i2 allocating scb =%i6 for %s*n",
+//          taskid, scb, name)
+  // Clear all scb fields
   FOR i = 0 TO scb_upb DO scb!i := 0
 
   scb!scb_id := id  // id_inscb, id_outscb, id_inoutscb or id_appendscb
 
-  // Copy (truncated) stream name into the scb
+  // Copy (possibly truncated) stream name into the scb
   { LET len = name%0
     LET scbname = @scb!scb_name
     LET maxlen = scb_maxnamelen
@@ -59,6 +62,7 @@ LET findstream(name, id, path) = VALOF // MR 8/5/03
     scb!scb_type    := scbt_console
     scb!scb_buf     := buf
     scb!scb_bufend  := 4096
+    scb!scb_endfn := cnslendfn
 
     IF id=id_inscb DO
     { scb!scb_rdfn   := cnslrdfn // fn to replenish current buffer
@@ -66,31 +70,56 @@ LET findstream(name, id, path) = VALOF // MR 8/5/03
       RESULTIS scb
     }
     IF id=id_outscb DO
-    { scb!scb_wrfn   := cnslwrfn // fn to output current buffer
+    { scb!scb_wrfn   := cnslwrfn // fn to deplete current buffer
       rootnode!rtn_screen := scb
       RESULTIS scb
     }
     // Bad stream id
     freevec(scb)
+    freevec(buf)
     RESULTIS 0
   }
 
   splitname(prefix, ':', name, 1)
+
   IF compstring(prefix, "NIL")=0 DO
   { // On reading always gives endstreamch
     // On writing always throws away the data
-    scb!scb_wrfn    := nilrdfn
-    scb!scb_endfn   := nilwrfn
+    scb!scb_wrfn := nilwrfn
 //sawritef("DLIB: Opening stream to/from NIL:*n")
     RESULTIS scb 
   }
 
+  IF compstring(prefix, "RAM")=0 DO
+  { // Open a RAM stream.
+    // It is always a read/write stream.
+    // Its buffer is automatically extended as needed.
+    // All stream buffers are allocated using getvec and
+    // must be freed using freevec when the stream is closed.
+    // Note that rewindstream, note, point and record access
+    // all work with RAM streams.
+    LET buf = getvec(1024/bytesperword) // Initial allocation
+    UNLESS buf DO { freevec(scb); RESULTIS 0 }
+    scb!scb_type    := scbt_ram
+    scb!scb_id      := id_inoutscb
+    scb!scb_buf     := buf
+    scb!scb_pos     := 0     // Initial position
+    scb!scb_end     := 0     // End of valid data
+    scb!scb_bufend  := 1024  // Current size of buf
+
+    scb!scb_wrfn    := ramwrfn // This automatically expands the buffer
+                               // if needed.
+//sawritef("DLIB: Opening stream to/from RAM:*n")
+    RESULTIS scb 
+  }
+
   IF compstring(prefix, "TCP")=0 | compstring(prefix, "NET")=0 DO
-  { sawritef("TCP connections not yet available*n")
+  { sawritef("TCP connections not yet available in cintsys*n")
     freevec(scb)
     RESULTIS 0
   }
 
+
   // Open a file stream
 //sawritef("DLIB: %s must be a file*n", name)
 
@@ -103,13 +132,26 @@ LET findstream(name, id, path) = VALOF // MR 8/5/03
   RESULTIS 0
 }
 
-AND nilrdfn(scb) = FALSE
-
 AND nilwrfn(scb) = VALOF
 { scb!scb_pos := 0 // Throw away the buffer contents (if any)
   RESULTIS TRUE
 }
 
+AND ramwrfn(scb) = VALOF
+{ // Replace the buffer by one of twice the size
+  LET oldbufend = scb!scb_bufend
+  LET oldbufupb = oldbufend/bytesperword
+  LET oldbuf    = scb!scb_buf
+  LET newbufend = oldbufend*2    // Double the buffer size
+  LET newbufupb = newbufend/bytesperword
+  LET newbuf    = getvec(newbufupb)
+  UNLESS newbuf RESULTIS FALSE
+  FOR i = 0 TO oldbufupb DO newbuf!i := oldbuf!i
+  scb!scb_buf, scb!scb_bufend := newbuf, newbufend
+  freevec(oldbuf)
+  RESULTIS TRUE
+}
+
 AND cnslrdfn(scb) = VALOF
 { LET buf, p = scb!scb_buf, 0
 
@@ -157,6 +199,11 @@ AND cnslwrfn(scb) = VALOF
   RESULTIS TRUE
 }
 
+AND cnslendfn(scb) = VALOF
+{ //freevec(scb!scb_buf)
+  RESULTIS TRUE
+}
+
 AND flush() = VALOF
 { IF cos=0 | cos!scb_id~=id_outscb DO abort(187)
   RESULTIS fh0wrfn(cos)
@@ -211,7 +258,8 @@ AND fh0findinput(scb, name, path) = VALOF
 // Returns TRUE   if successful
 // Returns FALSE, result2=100  Can't open file
 //                result2=101  Can't allocate buffer
-{ LET fp, buf = 0, 0
+{ LET fp, fp1 = 0, 0
+  LET buf = 0
   LET filesize = 0
   LET filename = VEC 50
   trfilename(name, filename)
@@ -219,8 +267,7 @@ AND fh0findinput(scb, name, path) = VALOF
 //sawritef("DLIB: fh0findinput calling sys_openread %s %s*n",
 //          filename, path->path,"null")
   // Open the file for input
-  fp := sys(Sys_openread, filename, path)  // MR 8/5/03
-  UNLESS fp DO
+  UNLESS sys(Sys_openread, filename, path, @fp) DO  // MR 8/5/03
   {
 //sawritef("DLIB: fh0findinput sys_openread %s failed*n", filename)
     result2 := 100
@@ -228,13 +275,13 @@ AND fh0findinput(scb, name, path) = VALOF
   }
 
 //sawritef("DLIB: %s opened*n", filename)
-  filesize :=sys(Sys_filesize, fp)
+  filesize :=sys(Sys_filesize, @fp)
 //sawritef("DLIB: filesize=%n*n", filesize)
 
   // allocate a buffer
   buf := getvec(buflen/bytesperword)
   UNLESS buf DO
-  { sys(Sys_close, fp) // First close the file
+  { sys(Sys_close, @fp) // First close the file
     result2 := 101
     RESULTIS 0
   }
@@ -246,7 +293,8 @@ AND fh0findinput(scb, name, path) = VALOF
   scb!scb_rdfn    := fh0rdfn
   scb!scb_wrfn    := 0       // An input stream cannot be depleted
   scb!scb_endfn   := fh0endfn
-  scb!scb_fd      := fp
+  scb!scb_fd      := fp      // Allow for 64 bit file pointer
+  scb!scb_fd1     := fp1
   scb!scb_bufend  := buflen
   scb!scb_write   := FALSE   // No data waiting to be written
   scb!scb_blength := buflen  // MR 15/3/02
@@ -264,14 +312,14 @@ AND fh0findoutput(scb, name) = VALOF
 // Returns TRUE   if successful
 // Returns FALSE, result2=100  Can't open file
 //                result2=101  Can't allocate buffer
-{ LET fp, buf = 0, 0
+{ LET fp, fp1 = 0, 0
+  LET buf = 0
   LET sysop = scb!scb_id=id_appendscb -> Sys_openappend, Sys_openwrite
   LET filename = VEC 50
   trfilename(name, filename)
 
   // Open the file for output
-  fp := sys(sysop, filename)
-  UNLESS fp DO
+  UNLESS sys(sysop, filename, @fp) DO
   { result2 := 100
     RESULTIS FALSE
   }
@@ -279,12 +327,12 @@ AND fh0findoutput(scb, name) = VALOF
   // allocate a buffer
   buf := getvec(buflen/bytesperword)
   UNLESS buf DO
-  { sys(Sys_close, fp) // First close the file
+  { sys(Sys_close, @fp) // First close the file
     result2 := 101
     RESULTIS FALSE
   }
 
-//sawritef("DLIB: fh0findoutput scb %n  %n  buf %n*n", scb, fp, buf)
+//sawritef("DLIB: fh0findoutput scb %n  buf %n*n", scb, buf)
 
   scb!scb_type    := scbt_file
   scb!scb_task    := 0
@@ -293,6 +341,7 @@ AND fh0findoutput(scb, name) = VALOF
   scb!scb_wrfn    := fh0wrfn
   scb!scb_endfn   := fh0endfn
   scb!scb_fd      := fp
+  scb!scb_fd1     := fp1
   scb!scb_bufend  := buflen
   scb!scb_write   := FALSE   // No data waiting to be written
   scb!scb_blength := buflen
@@ -312,31 +361,30 @@ AND fh0findinoutput(scb, name) = VALOF
 // Returns TRUE   if successful
 // Returns FALSE, result2=100  Can't open file
 //                result2=101  Can't allocate buffer
-{ LET fp, buf, res1, res2 = 0, 0, 1, 0
+{ LET fp, fp1 = 0, 0
+  LET buf, res1, res2 = 0, 1, 0
   LET filesize = 0
   LET filename = VEC 50
   trfilename(name, filename)
 
   // open the file for input and output
-  fp := sys(Sys_openreadwrite, filename)
-//sawritef("DLIB: open %s in inout mode => %n*n", filename, fp)
-  UNLESS fp DO
+  UNLESS sys(Sys_openreadwrite, filename, @fp) DO
   { result2 := 100
     RESULTIS FALSE
   }
 
-  filesize :=sys(Sys_filesize, fp)
+  filesize :=sys(Sys_filesize, @fp)
 //sawritef("BLIB: filesize=%n*n", filesize)
 
   // allocate a buffer
   buf := getvec(buflen/bytesperword)
   UNLESS buf DO
-  { sys(Sys_close, fp) // First close the file
+  { sys(Sys_close, @fp) // First close the file
     result2 := 101
     RESULTIS FALSE
   }
 //sawritef("DLIB: buflen = %n*n", buflen)
-//sawritef("DLIB: fh0findinoutput scb %n  %n  buf %n*n", scb, fp, buf)
+//sawritef("DLIB: fh0findinoutput scb %n  fp=(%n %n) buf %n*n", scb, fp, fp1, buf)
 
   scb!scb_type    := scbt_file
   scb!scb_buf     := buf
@@ -344,12 +392,13 @@ AND fh0findinoutput(scb, name) = VALOF
   scb!scb_wrfn    := fh0wrfn
   scb!scb_endfn   := fh0endfn
   scb!scb_fd      := fp
+  scb!scb_fd1     := fp1
   scb!scb_bufend  := buflen
   scb!scb_write   := FALSE   // No data waiting to be written
   scb!scb_blength := buflen  // MR 15/3/02
   scb!scb_block   := 0 //1 MR 29/7/02
   scb!scb_lblock  := filesize/buflen //+ 1  // MR 16/4/02 MR 29/7/02
-  scb!scb_ldata   := filesize REM buflen  // MR 16/4/02
+  scb!scb_ldata   := filesize MOD buflen  // MR 16/4/02
 //sawritef("fh0findinoutput: lblock=%n*n", scb!scb_lblock)
 
   // Initialise the buffer by reading the first block
@@ -455,8 +504,9 @@ AND fh0endfn(scb) = VALOF
 //sawritef("DLIB: fh0endfn pos=%n end=%n*n", scb!scb_pos, scb!scb_end)
   IF scb!scb_write UNLESS fh0putbuf(scb) RESULTIS FALSE
 //sawritef("DLIB: fh0endfn freeing buf=%n*n", scb!scb_buf)
-  freevec(scb!scb_buf)
-  RESULTIS sys(Sys_close, scb!scb_fd)
+  ///freevec(scb!scb_buf)
+  ///scb!scb_buf := 0
+  RESULTIS sys(Sys_close, @scb!scb_fd)
 }
 
 // Result TRUE: posv contains the stream block and pos
@@ -490,10 +540,13 @@ AND point(scb, posv) = VALOF
 //sawritef("DLIB: point block=%n lblock=%n blkno=%n pos=%n end=%n*n",
 //               block, lblock,  blkno, pos, end)
 
-   // The stream must be a readable disc or RAM file
-  UNLESS (type=scbt_file | type=scbt_ram) &
-         (id=id_inscb | id=id_inoutscb) RESULTIS FALSE
-
+  // The stream must be a disc or RAM file
+  UNLESS (type=scbt_file | type=scbt_ram)
+  { sawritef("DLIB: point can only used with file and ram streams*n")
+    abort(999)
+    RESULTIS FALSE
+  }
+  
   IF pos=0 & blkno=lblock+1 DO blkno, pos := lblock, buflen
  
 //sawritef("DLIB: point block=%n lblock=%n blkno=%n pos=%n end=%n*n",
@@ -528,13 +581,21 @@ AND point(scb, posv) = VALOF
     UNLESS fh0putbuf(scb) DO abort(5003)
   }
 
+  // Reading a block from file or ram is only allowed if
+  // reading is permitted.
+
+  UNLESS id=id_inscb | id=id_inoutscb DO
+  { sawritef("DLIB: The stream did not permit reading*n")
+    abort(999)
+    RESULTIS FALSE
+  }
   scb!scb_block := blkno  // Set the new position
  
 //sawritef("DLIB: point read block %n*n", blkno)
 
   UNLESS fh0getbuf(scb) DO
   { sawritef("DLIB: point fh0getbuf failed block %n => %n*n", blkno, end)
-    abort(5004)
+    abort(999)
     RESULTIS FALSE
   }
 
@@ -546,7 +607,7 @@ AND point(scb, posv) = VALOF
     sawritef("DLIB point: end %n buflen %n*n", scb!scb_end, buflen)
     sawritef("DLIB point: block %n lblock %n*n", blkno, lblock)
     sawritef("DLIB point: end %n ldata %n*n", end, scb!scb_ldata)
-    abort(5005)
+    abort(999)
   }
 
   scb!scb_pos   := pos  // Set the desired offset
@@ -565,7 +626,7 @@ AND fh0putbuf(scb) = VALOF
 // Returns FALSE, otherwise.
 { LET end    = scb!scb_end    // Number of bytes of valid data in buf
   LET block  = scb!scb_block
-  LET fd     = scb!scb_fd
+  LET fdptr  = @scb!scb_fd
   LET offset = buflen*block   // File offset of buffer's first byte MR 29/7/02
 
   IF end<=0 DO
@@ -580,10 +641,10 @@ AND fh0putbuf(scb) = VALOF
   IF block = scb!scb_lblock DO scb!scb_ldata := end
 
 //sawritef("DLIB: putbuf seeking offset %n (block %n)*n", offset, block)
-  UNLESS sys(Sys_seek, fd, offset) RESULTIS FALSE
+  UNLESS sys(Sys_seek, fdptr, offset) RESULTIS FALSE
 
 //sawritef("DLIB: putbuf write %n bytes at offset %n*n", end, offset)
-  IF sys(Sys_write, fd, scb!scb_buf, end) < 0
+  IF sys(Sys_write, fdptr, scb!scb_buf, end) < 0
     RESULTIS FALSE
   scb!scb_write := FALSE // The buffer has been written successfully
   RESULTIS TRUE
@@ -595,18 +656,18 @@ AND fh0putbuf(scb) = VALOF
 // Returns FALSE, otherwise.
 
 AND fh0getbuf(scb) = VALOF
-{ LET fd      = scb!scb_fd
+{ LET fdptr   = @scb!scb_fd
   LET block   = scb!scb_block   // Block number (>=0)
   LET offset  = buflen*block    // MR 29/7/02
   LET end     = ? 
 
 //sawritef("DLIB: fh0getbuf seeking start of block %n (offset %n)*n",
 //            block, offset)
-  UNLESS sys(Sys_seek, fd, offset) RESULTIS FALSE
-//sawritef("DLIB: fh0getbuf file position now %n*n", sys(Sys_tell, fd))
+  UNLESS sys(Sys_seek, fdptr, offset) RESULTIS FALSE
+//sawritef("DLIB: fh0getbuf file position now %n*n", sys(Sys_tell, fdptr))
 
 //sawritef("DLIB: fh0getbuf reading block %n offset=%n*n", block, offset)
-  end := sys(Sys_read, fd, scb!scb_buf, buflen)
+  end := sys(Sys_read, fdptr, scb!scb_buf, buflen)
 //sawritef("DLIB: fh0getbuf read => %n*n", end)
 //sawritef("DLIB: fh0getbuf block=%n lblock=%n ldata=%n*n",
 //               block, scb!scb_lblock, scb!scb_ldata)
@@ -615,28 +676,18 @@ AND fh0getbuf(scb) = VALOF
   RESULTIS TRUE
 }
 
-AND delay(ms) = sys(Sys_delay, ms)
-
-/*
-AND delay(ms) = VALOF
-{ LET days, msecs = ?, ?
-  MANIFEST { msperday = 24*60*60*1000 }
-  datstamp(@days)
-//sawritef("delay: time now       days=%i5 msecs=%n*n", days, msecs)
-  msecs := msecs+ms
-  IF ms>msperday DO days, msecs := days+1, msecs-msperday
-//sawritef("delay: delaying until days=%i5 msecs=%n*n", days, msecs)
-  RESULTIS delayuntil(days, msecs)
-}
-*/
+AND delay(msecs) = sys(Sys_delay, msecs)
 
 AND delayuntil(days, msecs) BE
-{ LET ds, ms = 0, 0
+{ LET ds, ms, dummy = 0, 0, 0
   datstamp(@ds)
   IF ds<days RETURN
   IF ds=days & ms<=msecs RETURN
   sys(Sys_delay, 1) // Sleep for 1 msec
 } REPEAT
 
+// Dummy definition of testflags
+AND testflags(flags) = FALSE
+
 
 
index 6f83eb0..2d18000 100755 (executable)
@@ -3,23 +3,31 @@ This program was an ASCII INTCODE assembler and interpreter
 for a 16 bit EBCDIC machine. The original version was tested
 in 1982 on the IBM 370(a 32 bit EBCDIC machine).
 
-This version is a modification of the program to run under 32-bit
-Cintcode BCPL. It is still under development.
+This version has been modified and extended to modern BCPL on the
+current 32-bit BCPL Cintcode system. It is still under development.
 
 Implemented by Martin Richards (c) September 2012
 
 To compile and run a BCPL program, type eg
 
-bcplint com/hello.b to hello.int
-type hello.int
-bcplint sysb/blib.b to blib.int
-bcplint sysb/dlib.b to dlib.int
-interp blib.int dlib.int hello.int
+bcplint com/cmpltest.b to cmpltest.int noselst
+type cmpltest.int
+interp cmpltest.int
 
-The above sequence is nowhere near working yet, given time who knows.
+Alternatively, use bcint
 
-30/09/12
-Initial modification of the original interp.b. At least it compiles.
+c bcint cmpltest
+interp cmpltest.int
+
+This is nearly working.
+
+History
+
+14/03/2021
+Made substantial changes to interp.b.
+
+30/09/2012
+Initial modification of the original interp.b.
 
 */
  
@@ -33,33 +41,59 @@ tracing
 source
 tofile
 tostream
-progsize
 
 etoa       // EBCDIC -> ASCII  table
 atoe       // ASCII  -> EBCDIC table
+
 progvec
+progupb
 
 g
 p
 ch
 cyclecount
 labv
-cp
+cp          // Number of characters assembled in word
+            // at location p. If cp>=4 the current word
+           // full and the next character require a new
+           // word to be allocated.
 a
 b
-c
-d
-w
+c           // Program counter
+
+w           // Current instruction
+d           // Effective address of current instruction
 }
  
 MANIFEST {
-fshift=13
-ibit=#10000; pbit=#4000; gbit=#2000; dbit=#1000
-abits=dbit-1
-wordsize=16; bytesize=8
-lig1=0<<fshift | ibit | gbit | 1 //#012001
-k3  =6<<fshift |  3              //#140003
-x22 =7<<fshift | 22              //#160026
+// Intcode instruction format - Original version for 16-bit machines
+//         fff ipgd aaaaaaaaa    
+//fshift=13
+//ibit=#10000; pbit=#4000; gbit=#2000; dbit=#1000
+//abits=dbit-1             // Address bits
+//wordsize=16; bytesize=8
+
+// Intcode instruction format - Extended version for 32-bit machines
+//         0fff ipgd aaaa aaaa aaaa aaaa aaaa aaaa
+//          fff                                     Op code
+//              i                                   Indirection bit
+//               p                                  Add P pointer bit
+//                g                                 Add G pointer bit
+//                 d                                Double length bit
+//                   aaaa aaaa aaaa aaaa aaaa aaaa  Address field
+fshift=28
+ibit=#x08000000; pbit=#x04000000; gbit=#x02000000; dbit=#x01000000
+abits=dbit-1             // Address bits
+wordsize=32; bytesize=8
+
+// Preloaded instruction words
+lig1= 0<<fshift | ibit | gbit | 1 //#x0_A_000001       LIG1
+k3  = 6<<fshift |  3              //#x3_0_000003       K3
+x22 = 7<<fshift | 22              //#x7_0_060016       FINISH
+x27 = 7<<fshift | 27              //#x7_0_06001B       SYS
+x4  = 7<<fshift |  4              //#x7_0_060004       RTN
+
+labvupb = 4000                    // Originally 2000
 }
  
  
@@ -67,8 +101,8 @@ LET assemble(filename) BE
 { LET f = 0
   LET oldin = input()
   LET filestream = findinput(filename)
-  LET v = VEC 2000
-  writef("assemble %s*n", filename)
+  LET v = VEC labvupb
+  IF tracing DO writef("assemble %s*n", filename)
   labv := v
 
   UNLESS filestream DO
@@ -79,7 +113,7 @@ LET assemble(filename) BE
   selectinput(filestream)
  
 clear:   // Start reading the next section, if any.
-  FOR i = 0 TO 2000 DO labv!i := 0
+  FOR i = 0 TO labvupb DO labv!i := 0 // First clear the label vector.
   cp := 4
  
 next:
@@ -106,18 +140,19 @@ sw:
     CASE '*n':
             GOTO next
  
-    CASE 'L': f := 0; ENDCASE
-    CASE 'S': f := 1; ENDCASE
-    CASE 'A': f := 2; ENDCASE
-    CASE 'J': f := 3; ENDCASE
-    CASE 'T': f := 4; ENDCASE
-    CASE 'F': f := 5; ENDCASE
-    CASE 'K': f := 6; ENDCASE
-    CASE 'X': f := 7; ENDCASE
+    CASE 'L': f := 0; ENDCASE // B := A; A := EA
+    CASE 'S': f := 1; ENDCASE // Store A in memory address EA
+    CASE 'A': f := 2; ENDCASE // A := A + EA
+    CASE 'J': f := 3; ENDCASE // PC := EA
+    CASE 'T': f := 4; ENDCASE // PC := EA if A is non zero
+    CASE 'F': f := 5; ENDCASE // PC := EA if A is zero
+    CASE 'K': f := 6; ENDCASE // Call function at entry point A
+                              // incrementing P by EA and saving the link
+    CASE 'X': f := 7; ENDCASE // Execute special operation EA
  
     CASE 'C': rch(); stc(rdn()); GOTO sw   // Cn     assemble a character
 
-    CASE 'D': rch()
+    CASE 'D': rch()                        // Assemble a word ofmemory
               TEST ch='L'
               THEN { rch()                 // DLn
                      stw(0)
@@ -130,7 +165,7 @@ sw:
             { LET gn, ln = ?,?
               rch()                  // GgLn   set global g to Ln
               gn := rdn()
-              a := gn + g
+              a := g + gn
               TEST ch='L'
               THEN rch()
               ELSE writef("*nbad code at p = %n*n", p)
@@ -142,7 +177,7 @@ sw:
             }
  
     CASE 'Z': // End of section
-              FOR i = 0 TO 500 IF labv!i>0 DO writef("L%n unset*n", i)
+              FOR i = 0 TO labvupb IF labv!i>0 DO writef("L%n unset*n", i)
               GOTO clear
   }
  
@@ -161,22 +196,20 @@ sw:
        }
   ELSE { LET a = rdn()
          TEST (a&abits)=a
-         THEN stw(w+a)
-         ELSE { stw(w+dbit); stw(a)  }
+         THEN stw(w+a)                 // a fits in the address field
+         ELSE { stw(w+dbit); stw(a)  } // a is too large for the address field
        }
  
   GOTO sw
 }
  
-AND stw(w) BE {
-                 writef("stw %8x %8x*n", p, w)
-                 !p := w
-                 p, cp := p+1, 4
+AND stw(w) BE { IF tracing DO writef("stw %8x %8x*n", p, w)
+                !p := w                // Store a word of code
+                p, cp := p+1, 4
               }
  
-AND stc(c) BE {
-                writef("stc %8x %8x %8x*n", p, cp, c)
-                IF cp>=4 DO { stw(0)
+AND stc(c) BE { IF tracing DO writef("stc %8x %8x %8x*n", p, cp, c)
+                IF cp>=4 DO { stw(0)   // Store a byte of code
                               cp := 0
                            }
                 (p-1)%cp := c
@@ -185,7 +218,7 @@ AND stc(c) BE {
  
 AND rch() BE { ch := rdch()
                UNLESS ch='/' RETURN          // Comment character
-               UNTIL ch='*n' DO {ch := rdch(); wrch(ch)}
+               UNTIL ch='*n' DO {ch := rdch(); IF tracing DO wrch(ch)}
              } REPEAT
 
 AND rdn() = VALOF
@@ -198,11 +231,11 @@ AND rdn() = VALOF
  
 AND setlab(n) BE
 { LET k = labv!n
-  writef("setlab: n=%x8 p=%x8*n", n, p)
+  IF tracing DO writef("setlab: n=%x8 p=%x8*n", n, p)
   IF k<0 DO writef("L%n already set TO %n at p = %n*n",n,-k,p)
   WHILE k>0 DO { LET n = !k
                  !k := p
-                 writef("fixup: %x8 %x8*n", k, p)
+                 IF tracing DO writef("fixup: %x8 %x8*n", k, p)
                  k := n
                }
   labv!n := -p
@@ -210,8 +243,9 @@ AND setlab(n) BE
 
 AND labref(n, a) BE
 { LET k = labv!n
-  writef("labref: n=%x8 a=%x8*n", n, a)
-  TEST k<0 THEN {k := -k; writef("fixup: %x8 %x8*n", a, !a + k)} ELSE labv!n := a
+  IF tracing DO writef("labref: n=%x8 a=%x8*n", n, a)
+  TEST k<0 THEN {k := -k; IF tracing DO writef("fixup: %x8 %x8*n", a, !a + k)}
+           ELSE labv!n := a
   !a := !a + k
 }
 
@@ -231,7 +265,7 @@ AND interpret() = VALOF
 { // Start of main loop
 
   IF tracing DO
-  { LET w = !c
+  { LET w = !c                   // c is the address of the next instruction
     LET op = w>>fshift
     LET opstr = fstr(op)
     writef("a=%x8 b=%x8 p=%x8 c=%x8 w=%x8(%s",a, b, p, c, w, opstr)
@@ -240,13 +274,15 @@ AND interpret() = VALOF
     IF (w & gbit) ~= 0 DO wrch('G')
     IF (w & dbit) ~= 0 DO wrch('D')
     writef("%n)", w&abits)
+    IF (w & dbit) ~= 0 DO writef(",%x8", c!1)
+    //abort(3456)
   }
 
   cyclecount := cyclecount + 1
   w := !c
   c := c + 1
  
-  TEST (w&dbit)=0 THEN d := w&abits
+  TEST (w&dbit)=0 THEN { d := w&abits }
                   ELSE { d := !c; c := c+1  }
  
   IF (w & pbit) ~= 0 DO d := d + p
@@ -279,7 +315,7 @@ AND interpret() = VALOF
     CASE 5: UNLESS a DO c := d; LOOP // F
  
     CASE 6: d := p + d               // K
-            d!0, d!1, d!2 := p, c, a
+            d!0, d!1, d!2 := p, c, a // old P, old C, entry point
             p, c := d, a
             LOOP
  
@@ -287,51 +323,53 @@ AND interpret() = VALOF
  
     { DEFAULT: GOTO error
  
-      CASE 1:  a := !a;      LOOP
-      CASE 2:  a := -a;      LOOP
-      CASE 3:  a := NOT a;   LOOP
-      CASE 4:  c := p!1     // FNRN
+      CASE 1:  a := !a;      LOOP     // RV
+      CASE 2:  a := -a;      LOOP     // NEG
+      CASE 3:  a := NOT a;   LOOP     // NOT
+      CASE 4:  c := p!1               // FNRN   
                p := p!0
                LOOP
-      CASE 5:  a := b * a;   LOOP
-      CASE 6:  a := b / a;   LOOP
-      CASE 7:  a := b MOD a; LOOP
-      CASE 8:  a := b + a;   LOOP
-      CASE 9:  a := b - a;   LOOP
-      CASE 10: a := b = a;   LOOP
-      CASE 11: a := b ~= a;  LOOP
-      CASE 12: a := b < a;   LOOP
-      CASE 13: a := b >= a;  LOOP
-      CASE 14: a := b > a;   LOOP
-      CASE 15: a := b <= a;  LOOP
-      CASE 16: a := b << a;  LOOP
-      CASE 17: a := b >> a;  LOOP
-      CASE 18: a := b & a;   LOOP
-      CASE 19: a := b | a;   LOOP
-      CASE 20: a := b XOR a; LOOP
-      CASE 21: a := b EQV a; LOOP
- 
-      CASE 22: RESULTIS a         // FINISH  ie leave the interpreter
- 
-      CASE 23: b, d := c!0, c!1   // SWITCHON n dlab
+      CASE 5:  a := b * a;   LOOP     // MUL
+      CASE 6:  a := b / a;   LOOP     // DIV
+      CASE 7:  a := b MOD a; LOOP     // MOD
+      CASE 8:  a := b + a;   LOOP     // ADD
+      CASE 9:  a := b - a;   LOOP     // SUB
+      CASE 10: a := b = a;   LOOP     // EQ
+      CASE 11: a := b ~= a;  LOOP     // NE
+      CASE 12: a := b < a;   LOOP     // LT
+      CASE 13: a := b >= a;  LOOP     // GE
+      CASE 14: a := b > a;   LOOP     // GT
+      CASE 15: a := b <= a;  LOOP     // LE
+      CASE 16: a := b << a;  LOOP     // LSHIFT
+      CASE 17: a := b >> a;  LOOP     // RSHIFT
+      CASE 18: a := b & a;   LOOP     // AND
+      CASE 19: a := b | a;   LOOP     // OR
+      CASE 20: a := b XOR a; LOOP     // XOR
+      CASE 21: a := b EQV a; LOOP     // EQV
+ 
+      CASE 22: RESULTIS a             // FINISH  ie leave the interpreter
+ 
+      CASE 23: b, d := c!0, c!1       // SWITCHON n dlab
                UNTIL b=0 DO
-               { b, c := b-1, c+2 // case k and label
+               { b, c := b-1, c+2     // case k and label
                  IF a=c!0 DO
                  { d := c!1
                    BREAK
                  }
                }
-               c := d             // Jump to default
+               c := d                 // Jump to default
                LOOP
-      CASE 24: a := b % a; LOOP
-      CASE 25: b % a := p!(c!0)
+      CASE 24: a := b % a; LOOP       // GBYT
+      CASE 25: b % a := p!(c!0)       // PBYT
                c := c+1
                LOOP
-      CASE 26: a := ABS a; LOOP
+      CASE 26: a := ABS a; LOOP       // ABS
  
-      CASE 27: // The sys function
-               //writef("SYS %n %n %n*n", p!3, p!4, p!5)
+      CASE 27: // The sys function    // SYS
+               IF tracing DO writef(" SYS %x8 %x8 %x8 %x8 %x8*n", p!3, p!4, p!5, p!6, p!7)
+              //IF p!4=11 & p!5=118 DO abort(3478)
                a := sys(p!3, p!4, p!5, p!6, p!7)
+              g!g_result2 := result2
                LOOP
 
 // cases 40 upwards are only called from the following
@@ -391,6 +429,8 @@ AND interpret() = VALOF
              }
       CASE 38: a := ABS a  // abs
                LOOP
+
+abort(1234)
     }
   }
 } REPEAT
@@ -423,7 +463,7 @@ LET start() = VALOF
  
   writes("intcode system entered*n")
 
-  UNLESS rdargs(",,,,,,,,,,TO/K,SIZE/K/N,TRACE/S", argv, 100) DO
+  UNLESS rdargs(",,,,,,,,,,TO/K,SIZE/K/N,-t=TRACE/S", argv, 100) DO
   { writef("Bad arguments for interp*n")
     RESULTIS 0
   }
@@ -431,43 +471,49 @@ LET start() = VALOF
   tofile := 0
   IF argv!10 DO tofile := argv!10            // TO/K
 
-  progsize := 1_000_000
-  IF argv!11 DO progsize := !(argv!11)       // SIZE/K/N
+  progupb := 1_000_000                       // In words
+  IF argv!11 DO progupb := !(argv!11)        // SIZE/K/N
 
   tracing := argv!12                         // TRACE/S
 
-  g, progvec := getvec(1000), getvec(progsize)
+  g, progvec := getvec(1000), getvec(progupb)
   FOR i = 0 TO 1000 DO g!i := 0
-  FOR i = 0 TO progsize DO progvec!i := 0
+  FOR i = 0 TO progupb DO progvec!i := 0
 
   // Initialise some globals
   g!0 := 1000
   introotnode := progvec+100
   g!g_rootnode := introotnode
 
-  // Initialise some rootnode elements
+  // Copy some rootnode elements
   FOR n = 0 TO 49 DO introotnode!n := rootnode!n
   // ... but force console to be reopened
   introotnode!rtn_keyboard := 0
   introotnode!rtn_screen := 0
 
   // Leave space for the rootnode
-  p := progvec+200
+  p := progvec+200                  // Position of the first instructions
 
   stdin  := input()
   stdout := output()
  
-  c := p       // Initial program counter
+  c := p       // Initial program counter -- Execution starts here
   p!0 := lig1  // Initial orders
   p!1 := k3
   p!2 := x22
-  p := p+3
 
-  // Load the Intcode programs
+  g!g_sys := p+3 // Initialise the sys global
+  
+  p!3 := x27   // SYS    Code for the sys function
+  p!4 := x4    // RTN
+  
+  p := p+5     // Position of the first assembled intcode section
+
+  // Load up to 10 Intcode program files.
   FOR i = 0 TO 9 IF argv!i DO assemble(argv!i)
  
   IF FALSE 
-  IF tracing DO
+  //IF tracing DO
   { writef("Loaded program*n*n")
     FOR i = 200 TO 220 DO
     { LET w = progvec!i
@@ -484,12 +530,12 @@ LET start() = VALOF
       newline()
     }
 
-    //writef("*nGlobals*n*n")
-    //FOR i = 0 TO 10 DO writef("G%i3: %x8 %n*n", i, g!i, g!i)
+    writef("*nGlobals*n*n")
+    FOR i = 0 TO 10 DO writef("G%i3: %x8 %n*n", i, g!i, g!i)
 
-    //writef("*nRootnode*n*n")
-    //FOR i = 0 TO 49 DO writef("Rootnode!%i2: %x8 %n*n",
-    //                           i, introotnode!i, introotnode!i)
+    writef("*nRootnode*n*n")
+    FOR i = 0 TO 49 DO writef("Rootnode!%i2: %x8 %n*n",
+                               i, introotnode!i, introotnode!i)
   }
   writef("*nProgram size = %n*n", p-progvec-200)
  
@@ -551,14 +597,15 @@ LET start() = VALOF
   //c := TABLE lig1, k3, x22
  
   cyclecount := 0
-
+//abort(2345)
   a := interpret()
  
   freevec(g)
   freevec(progvec)
 
   selectoutput(stdout)
-  writef("*n*nExecution complete cycles = %n", cyclecount)
+  writef("*n*nExecution complete after executing %n intcode instruction%-%ps",
+          cyclecount)
   IF a DO writef(" return code = %n", a)
   newline()
 }
diff --git a/intcode/session.txt b/intcode/session.txt
new file mode 100644 (file)
index 0000000..da37283
--- /dev/null
@@ -0,0 +1,59 @@
+nick@jane:~/unix/bcpl/BCPL/cintcode$ cintsys -c c bc32 bcplint
+
+BCPL 32-bit Cintcode System (13 Dec 2023)
+Estimated 448780 Cintcode instructions per milli-second
+0.000> bcpl com/bcplint.b to cin/bcplint t32 
+
+32 bit BCPL (18 Jul 2022) with pattern matching, 32 bit target
+Code size = 21844 bytes of 32-bit little ender Cintcode
+Code size = 20600 bytes of 32-bit little ender Cintcode
+Code size =  5680 bytes of 32-bit little ender Cintcode
+0.106> 
+nick@jane:~/unix/bcpl/BCPL/cintcode$ cd ../intcode
+nick@jane:~/unix/bcpl/BCPL/intcode$ cintsys -c c b interp
+
+BCPL 32-bit Cintcode System (13 Dec 2023)
+Estimated 408888 Cintcode instructions per milli-second
+0.000> bcpl interp.b to interp 
+
+32 bit BCPL (18 Jul 2022) with pattern matching, 32 bit target
+Code size =  5300 bytes of 32-bit little ender Cintcode
+0.015> 
+nick@jane:~/unix/bcpl/BCPL/intcode$ cintsys -c c bint bcplint
+
+BCPL 32-bit Cintcode System (13 Dec 2023)
+Estimated 408888 Cintcode instructions per milli-second
+0.000> bcplint bcplint.b to bcplint.int hdrs BCPLHDRS 
+
+32 bit BCPL (18 Jul 2022) with pattern matching, 32 bit target
+cg-intcode 28 Sept 2012
+Program size = 15892 words
+cg-intcode 28 Sept 2012
+Program size = 16161 words
+cg-intcode 28 Sept 2012
+Program size = 3957 words
+0.528> 
+nick@jane:~/unix/bcpl/BCPL/intcode$ cintsys -- c xint bcplint
+
+BCPL 32-bit Cintcode System (13 Dec 2023)
+Estimated 418181 Cintcode instructions per milli-second
+0.000> interp syslib.int blib.int dlib.int bcplint.int 
+intcode system entered
+
+Program size = 41393
+bcplint.b to bcplint_new.int hdrs BCPLHDRS
+
+32 bit BCPL (18 Jul 2022) with pattern matching, 32 bit target
+cg-intcode 28 Sept 2012
+Program size = 15892 words
+cg-intcode 28 Sept 2012
+Program size = 16161 words
+cg-intcode 28 Sept 2012
+Program size = 3957 words
+
+
+Execution complete after executing 88723310 intcode instructions
+7.658> logout
+
+nick@jane:~/unix/bcpl/BCPL/intcode$ diff bcplint.int bcplint_new.int
+nick@jane:~/unix/bcpl/BCPL/intcode$