Contents of SUBGROUPSRB1

Using my disassembler the contents of SUBGROUPSRB1 were found to be the segments:
#PROGRAM       /%BCR(DBM,15AM)
#PROGRAM       /%BDEBUG(DBM,15AM,22AM)
#PROGRAM       /%BEDI(DBM,15AM)
#PROGRAM       /%BEDO(DBM,15AM)
#PROGRAM       /%BEDSFILES(DBM,15AM)
#PROGRAM       /%BFIXEDSAVE(DBM,15AM)
#PROGRAM       /%BFLOAT(DBM,15AM)
#PROGRAM       /%BLIB0(DBM)
#PROGRAM       /%BOVERLAY(DBM,15AM)
#PROGRAM       /%BPOINTERS(DBM,15AM,22AM)
#PROGRAM       /%BSSO(DBM,15AM)
#PROGRAM       /%BSTART(DBM)
#PROGRAM       /%BSWITCHES(DBM,15AM)
#PROGRAM       /%BSYSTEM(DBM,15AM)
#PROGRAM       /%BTRACE(DBM,15AM,22AM)
#PROGRAM       /%BTRACESAVE(DBM,15AM)
#PROGRAM       /%BTR(DBM,15AM)
#PROGRAM       /%BTYROUTINE(DBM,15AM)
#PROGRAM       /LIB2(DBM,15AM,22AM)
#PROGRAM       /LIB4(DBM,15AM,22AM)
#PROGRAM       /%ROL(DBM,15AM)
#PROGRAM       /SEG1001(DBM,15AM,22AM)
#PROGRAM       /SEG1002(DBM,15AM,22AM)
#PROGRAM       /SEG1003(DBM,15AM,22AM)
#PROGRAM       /SEG1004(DBM,15AM,22AM)
#PROGRAM       /SEG1005(DBM,15AM,22AM)
#PROGRAM       /SEG1006(DBM,15AM,22AM)
#PROGRAM       /SEG1007(DBM,15AM,22AM)
#PROGRAM       XXXX99/%BBASICIO(DBM,15AM)
#PROGRAM       XXXX99/%BBASICPERI(DBM,15AM)
#PROGRAM       XXXX99/%BEXECUTE(DBM,15AM)
#PROGRAM       XXXX99/%BSAVE(DBM,15AM)
#PROGRAM       XXXX99/%BTPLPCP(DBM,15AM)
#PROGRAM       XXXX99/READCH(DBM,15AM)
#PROGRAM       XXXX99/WRITECH(DBM,15AM)
Some of those are found in the PLAN source file PLANSEGMENTS, others are found in the BCPL source file BCPLLIB, but the source for the following segments seems to be missing:
%BFIXEDSAVE
%BOVERLAY
LIB2
SEG1001
SEG1002
SEG1003
SEG1004
SEG1005
SEG1006
SEG1007
The code generator, CCMX, uses the segment LIB2 and the standard program description uses the segment SEG1001.

On examination of the code of SEG1001 it seems to be a version of %BLIB0 compiled with an earlier version of the compiler. For example SEG1001 includes use of #LOWER locations where the current version of the code generator uses literals. Similarly:

SEG1001 => %BLIB0
SEG1002 => %BDEBUG
SEG1003 => %BSTART
SEG1004 => LIB4
SEG1005 => LIB2
SEG1006 => %BTRACE
SEG1007 => %BPOINTERS
This implies the only real lost source is for %BOVERLAY, %BFIXEDSAVE and LIB2.

%BOVERLAY contains a version of the subroutine entry and exit functions %BSAVE and %BRETURN that presumably implement overlay loading and unloading, they use the common block %AAOVDIR and the routine %ROL.

%BFIXEDSAVE contains a trivial versions of the %BSAVE and %BRETURN functions that contain no tracing or stack expansion functions.

LIB2 contains the BCPL functions:

GLOBAL $(
    NEWVEC1: 80
    NEWWORD1: 81
    RETURNVEC1: 82
    RETURNWORD1: 83
    NEWFREESTORE1: 84
    RESTOREFREESTORE1: 85
    SETUPVECASFREESTORE1: 86
    REPORTFREESTORESTATE1: 88
    FSERR1: 89
$)
it seems to correspond to the GET file NHEAD2 which claims to be the "MODIFIED OXFORD FREE STORE SYSTEM". A version of LIB2 in PLAN has been extracted from the existing SUBGROUPSRB1 in preperation for recompiling the library.

Searching the web for some of these function names lead to the paper THE TEXT OF OSPub by Christopher Strachey and Joseph Stoy which describes a small operating system written in BCPL. Here is the code: freestore.bcpl.

using the OSPub routines as a template it has proved possible to recreate reasonable BCPL versions of some of the routines in LIB2, for example NEWVEC seems to correspond to:

LET NewVec[n] = VALOF
$(NV
        IF n < 0 DO
        $(
                FSErr["Negative arg in NewVec"]
                FINISH
        $)

        IF (n = 0) LOGAND (FS!FWC NE END) DO
        $(
                LET w = FS!FWC          // First word in FreeWordChain
                FS!FWC := RV w
                RESULTIS w
        $)

        $(
                LET BP = LV FS!FBC      // Block Pointer
                LET B = RV BP           // Block

                $(R
                        IF B = END DO
                        $(
                                FSErr("Free Store exhausted"]
                                FINISH
                        $)
                        IF B!SIZE >= n BREAK
                        BP := LV B!NXTB
                        B := RV BP
                $)R REPEAT

                IF B!SIZE > n DO RETURNVEC (B + n + 1, B!SIZE - n - 1)

                RESULTIS B
        $)
$)NV
A lightly modified version of the OSPub FREESTORE routine.

However attempts to re-create RETURNVEC have met with rather less success. The OSPub version of RETURNVEC starts:

AND ReturnVec[V, n] BE
$(RV
        UNLESS FS!LB <= V <= V+n <= FS!UB DO
        $(PEND
		... the vector being freed is not in the current free store
		... area, just add it to the list of blocks to be freed
		... when the free store area is changed

		RETURN
	$)PEND

	... the vector being freed is in the current free store areag,
	... add the block to the free chain, merging it with adjacent
	... free words or blocks.
The code for the LIB2 RETURNVEC function starts:
LET RETURNVEC[V, N] BE
$(RV

	TEST FS!LB <= V <= V+N <= FS!UB THEN
	$(
		TEST N = 0 THEN $(
			V!0 := FS!FWC
			FS!FWC := V
		$)
		OR $(
			LET PB = @ FS!FBC
			LET B = !PB

			UNTIL B = 0 LOGOR B!NXTB > V DO
			$(

				PB := @ B!NXTB
				B := !PB
			$)

			V!SIZE := N
			V!NXTB := B

			!PB := V
		$)
	$)

Which looks like an attempt was made to replace the original code by something like
	TEST block not in arena
	THEN $(
		add to pending free chain
	$)
	ELSE $(
		free block
	$)
but the sense of the tests was accidentally inversed and the code was "fixed" by changing the THEN leg of the TEST to add the block to the free chain rather than the pending free chain. Unfortunately this means the code to merge a freed block into adjacent blocks is lost.

This problem has been fixed by replacing the copy of RETURNVEC in SUBGROUPSRB1 with the RETURNVEC from OSPub.

SUBGROUPSRB1 can now be recreated from source.