perm filename RECSER.OLD[S,AIL] blob
sn#163717 filedate 1975-06-19 generic text, type T, neo UTF8
00100 COMMENT ⊗ VALID 00017 PAGES
00200 C REC PAGE DESCRIPTION
00300 C00001 00001
00400 C00003 00002 FANCY SMALL SPACE SERVICE
00500 C00011 00003 SPECIAL FIXED SIZE BLOCK HANDLERS: $FXGET, $FXDEL
00600 C00020 00004 SAIREC -- SYSTEM RECORD HANDLER ROUTINES
00700 C00022 00005 GETSTR, STRINIT, RELSTR, RSGC
00800 C00024 00006 RECORD STRING SUBFIELD GARBAGE COLLECTION
00900 C00027 00007 SAIREC -- $REC$ AND $RECFN
01000 C00033 00008 SAIREC -- $RCINI
01100 C00038 00009 SAIREC -- FLDKIL ROUTINE
01200 C00043 00010 SAIREC (RECGC) -- $ENQR,ENQRB,ENQRBB,PAMRK
01300 C00046 00011 SAIREC (RECGC) -- %PSMRR
01400 C00048 00012 SAIREC (RECGC) -- RCIMRK
01500 C00050 00013 SAIREC (RECGC) -- $MRK.1, $MFLDS
01600 C00053 00014 SAIREC (RECGC) -- $RGCMK
01700 C00054 00015 SAIREC (RECGC) -- $RGCSW
01800 C00057 00016 SAIREC (RECGC) -- MAIN ROUTINE
01900 C00058 00017 SAIREC (RECGC) -- $M1FLD
02000 C00060 ENDMK
02100 C⊗;
00100 ;; FANCY SMALL SPACE SERVICE
00200 COMPIL(SPC,,,,,,DUMMYFORGDSCISS)
00300
00400 DEFINE SPCINS <$FUNLK,$FXBLD,$FXGET,$FXG,$FXDEL,$FXD>
00500
00600
00700
00800 COMPXX(SPC,<$GETB,$GET1B,$DELB,$DEL1B,$FSADD,$FSINS,$FSINI,SPCINS>
00900 ,<GOGTAB,X22,X33,CORGET,CORREL>
01000 ,<SMALL SPACE SERVICE ROUTINES>,,HIIFPOSIB)
01100
01200 BEGIN SPCSER -- SMALL FREE BLOCK SERVICE
01300
01400 DSCR $GETB,$DELB,$GET1B,$DEL1B,$FSADD,$FSINS,$FUNLK
01500
01600 These routines are generally useful for handling allocation of small
01700 blocks of storage. Essentially, there is a linked list (homed at
01800 $FSLIS(<gogtab>) ) of blocks, each of which specifies a "space".
01900
02000 <prev on chain>,,<next on chain>
02100 <addr of "allocate" routine>
02200 <addr of "deallocate" routine>
02300 < ... miscellaneous info ... >
02400 :
02500 < ... miscellaneous info ... >
02600
02700 Each allocate routine is assumed to take as parameters:
02800
02900 A -- pointer to the space descriptor block
03000 C -- size of request
03100
03200 results:
03300 skip return -- B points to a fresh block of the correct size
03400 no skip return -- failure
03500
03600 Each deallocate routine is assumed to take as parameters:
03700
03800 A -- pointer to the space descriptor block
03900 B -- pointer to block to be released
04000
04100 results:
04200 skip return -- the block release was successful
04300 no skip return -- block release was unsuccessful
04400
04500 Except as stated above, the routines are assumed to have no side effects.
04600 (except possibly to load USER with GOGTAB).
04700
04800 $GET1B acts just like an allocate routine, except that it takes (in A)
04900 a pointer to the first block in a whole list of routines
05000 and returns as its value (in A) a pointer to the descriptor
05100 block of the last allocate routine called.
05200
05300 $DEL1B acts like a deallocate routine except that it takes (in A)
05400 a pointer to the first block in a whole list of routines
05500 and returns as its value (in A) a pointer to the descriptor
05600 block of the last deallocate routine called.
05700
05800 SAIL calling sequence routines that cdr down $FRELIS:
05900
06000 <block>←$GETB(size) ;returns 0 if lose
06100 <result>←$DELB(blockid) ;returns 0 if lose, space id if win
06200
06300 $FSLIS service routines (munch USER,TEMP,LPSA):
06400
06500 $FSADD(<dcsr block>) ; adds named block to $FSLIS
06600 $FSINS(@<list owner>,<block addr>) ;adds named block to named list (at head)
06700 $FUNLK(<dscr block>) ; removes named block from any list
06800
06900 ⊗
07000
07100 %GPROC ←← 1 ;GETTING PROC
07200 %DPROC ←← 2 ;DELETING PROC
07300 %FFRXX ←← 3 ;INDEX OF FIRST FREE LOCATION
07400
07500 HERE($GETB)
07600 MOVE C,-1(P) ;GET SIZE
07700 MOVE USER,GOGTAB ;
07800 SKIPE A,$FSLIS(USER)
07900 PUSHJ P,$GET1B ;CDR DOWN LIST
08000 TDZA A,A ;NO JOY
08100 MOVE A,B ;THE RESULT
08200 RET22: SUB P,X22
08300 JRST @2(P) ;RETURN
08400
08500 HERE($DELB)
08600 MOVE B,-1(P) ;THE BLOCK
08700 MOVE USER,GOGTAB
08800 SKIPE A,$FSLIS(USER)
08900 PUSHJ P,$DEL1B
09000 MOVEI A,0
09100 JRST RET22
09200
09300 GET1B1: HRRZ A,(A) ;PART OF THE $GET1B LOOP
09400 HERE($GET1B)
09500 JUMPE A,CPOPJ ;CHECK NULLITUDE
09600 PUSHJ P,@%GPROC(A) ;CALL THE ROUTINE
09700 JRST GET1B1 ;LOOP ON TO NEXT, THIS ONE LOST
09800 CPOPJ1: AOS (P) ;SKIP RETURN IF WIN
09900 CPOPJ: POPJ P, ;RETURN
10000
10100 DEL1B1: HRRZ A,(A) ;SAME KLUGE
10200 HERE($DEL1B)
10300 JUMPE A,CPOPJ ;
10400 PUSHJ P,@%DPROC(A) ;ALLOCATE ROUTINE
10500 JRST DEL1B1 ;LOST, TRY NEXT
10600 JRST CPOPJ1 ;WIN
10700
10800 HERE($FSADD) ;LINKS IN ONE BLOCK
10900 MOVE USER,GOGTAB
11000 MOVEI LPSA,$FSLIS(USER)
11100 PUSH P,LPSA ;THIS IS THE OWNER
11200 PUSH P,-2(P) ;THE RECORD TO ADD
11300 PUSHJ P,$FSINS ;CALL INSERT ROUTINE
11400 JRST RET22 ;GO RETURN
11500
11600 HERE($FUNLK)
11700 MOVE LPSA,-1(P) ;THE BLOCK WE ARE TO UNLINK
11800 MOVE TEMP,(LPSA) ;THE LEFT,,RIGHT
11900 TRNE TEMP,-1 ;IF HAVE A RIGHT HAND
12000 HLLM TEMP,(TEMP) ;LET HIM HOLD MY LEFT
12100 MOVSS TEMP ;SWAP HALVES
12200 HLRM TEMP,(TEMP) ;LET HIM HOLD MY RIGHT
12300 JRST RET22 ;DONE
12400
12500 HERE($FSINS) ;
12600 HRRZ TEMP,-1(P) ;THE THING TO INSERT
12700 HRRZ LPSA,-2(P) ;ADDRESS OF OWNER CELL
12800 HRLM LPSA,(TEMP) ;REMEMBER AS BACK POINTER
12900 EXCH LPSA,(LPSA) ;LPSA IS NOW FWD PTR
13000 TRNE LPSA,-1 ;WAS THE CHAIN NULL?
13100 HRLM TEMP,(LPSA) ;NO HE GETS A BACK PTR TOO
13200 HRRM LPSA,(TEMP) ;OLD HEAD IS NEW RIGHT BROTHER
13300 RET33: SUB P,X33 ;RETURN
13400 JRST @3(P) ;
13500
13600 NOLOW <
13700 NOUP <
13800 REN <
13900 USE
14000 >;REN
14100 FSI: 0
14200 $FSINI
14300 0
14400 LINK %INLNK,FSI
14500 REN <
14600 USE HIGHS
14700 >;REN
14800 >;NOUP
14900 >;NOLOW
15000
15100 HERE($FSINI)
15200 SKIPN USER,GOGTAB
15300 ERR <$FSINI CALLED W/O GOGTAB INITIALIZED>
15400 SKIPE $FSLIS(USER)
15500 ERR <$FSINI CALLED WITH THINGS ON $FSLIS>,1
15600 MOVEI C,3 ;JUST A LITTLE BLOCK
15700 PUSHJ P,CORGET
15800 ERR <CORGET DIDN'T GIVE ME ANY>,1
15900 HRRZM B,$FSLIS(USER)
16000 HRLZI C,$FSLIS(USER)
16100 MOVEM C,(B)
16200 MOVEI C,CORGET
16300 MOVEM C,%GPROC(B)
16400 MOVEI C,[PUSHJ P,CORREL
16500 AOS(P)
16600 POPJ P,
16700 ]
16800 MOVEM C,%DPROC(B)
16900 POPJ P,
00100 ;; SPECIAL FIXED SIZE BLOCK HANDLERS: $FXGET, $FXDEL
00200
00300 DSCR $FXG,$FXD,$FXGET,$FXDEL,$FXSPC,$FXBLD
00400
00500 DES These routines operate on space descriptor blocks of the form:
00600
00700 word 0: left,,right
00800 $FXG
00900 $FXD
01000 blksiz: block size
01100 minsiz: minimum size request to honor
01200 blkcnt: number of blocks per space
01300 usecnt: number of blocks allocated from this space
01400 maxadr: address of last record in this space
01500 frelis: free list of blocks
01600 sublis: a list header word for other blocks with this format
01700 firblk: ... first "data word" in the space ...
01800 :
01900 < blkcnt*blksiz +firblk words of corget space >
02000 :
02100
02200 Note: the "top" such block (Ie the one on the $FSLIS) will usually
02300 contain the routines $FXGET & $FXREL & will have actually no
02400 blocks (ie frelis=0). They will mapcar down their subordinates
02500 looking for customers. The subordinates ($FXG & $FXD) will
02600 work by having brothers. If a $FXG block gets bloated, it
02700 will just fail. If one goes empty, it will just go away.
02800 If all of a $FXGET block's subordinates lose, it just adds a
02900 new one as the left subchild.
03000
03100 A space descriptor block ($FXGET style) may be built by the runtime routine
03200
03300 <block> ← $FXSPC(<block size>,<min size>,<block count>)
03400
03500 Thus a new space for allocating blocks of size 9 to 16 could be
03600 defined & added to $FSLIS by the statement
03700
03800 $FSADD($FXSPC(16,9,32)); ! 32 blocks per buffer;
03900
04000 The routine $FXBLD(@<chain header>,<template block>) makes a fresh
04100 block patterned after the template & puts it on the named chain.
04200
04300 ⊗
04400 %FXIX ←← %FFRXX ;FIRST LEGAL FIELD
04500 DEFINE $FXFLD(ID) <
04600 ID ←← %FXIX
04700 %FXIX ←← %FXIX+1
04800 >
04900 $FXFLD %BLKSIZ ;BLOCK SIZE
05000 $FXFLD %MINSIZ ;MIN ACCEPTABLE SIZE
05100 $FXFLD %BLKCNT ;NUMBER OF BLOCKS PER SPACE
05200 $FXFLD %USECNT ;NUMBER OF BLOCKS ALLOCATED FROM THIS SPACE
05300 $FXFLD %MAXADR ;MAX ADDRESS OF A BLOCK IN THIS SPACE
05400 $FXFLD %FRELIS ;FREE LIST
05500 $FXFLD %SUBLIS ;SUBLIST OF SIMILAR BLOCKS
05600 $FXFLD %FIRBLK ;FIRST DATA WORD
05700
05800 HERE($FXGET)
05900
06000 CAMG C,%BLKSIZ(A) ;WOULD IT FIT
06100 CAMGE C,%MINSIZ(A) ;
06200 POPJ P, ;NO
06300 PUSH P,A ;YEP GO DOWN KINDERN
06400 FGTRY: SKIPE A,%SUBLIS(A) ;IF ANY
06500 PUSHJ P,$GET1B ;
06600 JRST ADDAB ;ADD A BLOCK
06700 FGWIN: POP P,A ;I AM SUCH A WINNER
06800 JRST CPOPJ1 ;& GO WIN
06900 ;# # RHT ! I HAD LEFT OUT THE RESTORE OF A
07000 ADDAB: MOVE A,(P) ;SINCE A IS ZERO AT THIS POINT
07100 MOVEI B,%SUBLIS(A) ;OWNER OF NEW LIST
07200
07300 PUSH P,B ;BUILD CALL TO $FXBLD
07400 PUSH P,-1(P) ;PUSH A COPY OF A
07500 PUSHJ P,$FXBLD ;MAKES A NEW SPACE FOR $FXG
07600
07700 MOVE A,(P) ;WHERE WE HAD SAVED IT
07800 JRST FGTRY ;GO TRY AGAIN -- EXPECT TO WIN
07900
08000 HERE($FXG)
08100 CAMG C,%BLKSIZ(A) ;WOULD IT FIT?
08200 CAMGE C,%MINSIZ(A) ;
08300 POPJ P, ;NO WAY
08400 SKIPN B,%FRELIS(A) ;ONE ON FREE LIST
08500 POPJ P, ;NO SUCH LUCK
08600 AOS %USECNT(A) ;ONE LESS FREE NOW
08700 PUSH P,(B) ;KLUGY WAY TO COPY FREE LIST
08800 POP P,%FRELIS(A) ;PUTS BACK THE NEXT ONE
08900 JRST CPOPJ1 ;GO SKIP RETURN -- WE WIN
09000
09100 HERE($FXDEL)
09200 PUSH P,A ;IN THIS CASE, JUST GO DOWN CHILDREN
09300 SKIPE A,%SUBLIS(A) ;
09400 PUSHJ P,$DEL1B ;LIKE SO
09500 SOS -1(P) ;WILL NA SKIP RETURN
09600 POP P,A ;GET OWN NAME BACK
09700 JRST CPOPJ1 ;I AM A WINNER
09800
09900 HERE($FXD)
10000 CAMG B,%MAXADR(A) ;IN RANGE?
10100 CAIG B,(A) ;A IS MY OWN POINTER,REMEMBER
10200 POPJ P, ;NOPE
10300 SOSG %USECNT(A) ;IF THIS WAS THE LAST
10400 JRST BIGKIL ;THEN THE WHOLE BLOCK GOES AWAY
10500 PUSH P,B ;MUST PRESERVE
10600 HRRZS B ;JUST BE SURE RHS ONLY IS ON
10700 EXCH B,%FRELIS(A) ;SAVE AWAY NEW LIST
10800 MOVEM B,@%FRELIS(A) ;& LINK IT TO OLD
10900 POP P,B ;GET BACK
11000 JRST CPOPJ1 ;WHAT WINNAGE!
11100 BIGKIL: PUSH P,LPSA ;SAVE A COUPLE
11200 PUSH P,TEMP ;
11300 PUSH P,B
11400 PUSH P,A ;GO UNLINK THIS BLOCK
11500 PUSHJ P,$FUNLK ;LIKE SO
11600 MOVE B,A ;GO CLOBBER THE WHOLE BLOCK
11700 PUSHJ P,CORREL ;LIKE SO
11800 POP P,B ;A PITY CANNOT JUST ZERO OUT B
11900 POP P,TEMP ;GET ACS BACK
12000 POP P,LPSA ;
12100 JRST CPOPJ1 ;RETURN
12200
12300 HERE($FXSPC)
12400 MOVEI C,%FIRBLK ;HOW BIG IT NEEDS TO BE
12500 PUSHJ P,CORGET ;USE CORGET SPACE FOR THIS (DONT REALLY HAVE TO
12600 ERR <NO CORE TO BE HAD>,1 ; BUT MAY WANT TO DO THIS AT FUNNY TIMES)
12700 MOVE A,B ;WHERE WE WILL RETURN VALUE
12800 HRL B,B ;CLEANSE IT
12900 HRRI B,1(B)
13000 SETZM (B)
13100 BLT B,%FIRBLK-1(A)
13200 MOVEI B,$FXGET ;
13300 MOVEM B,%GPROC(A)
13400 MOVEI B,$FXDEL
13500 MOVEM B,%DPROC(A)
13600 POP P,B
13700 POP P,%BLKCNT(A)
13800 POP P,%MINSIZ(A)
13900 POP P,%BLKSIZ(A)
14000 JRST (B)
14100
14200
14300 HERE($FXBLD)
14400
14500 MOVE A,-1(P) ;MUST ADD A BLOCK
14600 PUSH P,C ;SAVE THIS SIZE REQUEST
14700 PUSH P,TEMP ;SAVE A COUPLE ACS
14800 PUSH P,LPSA ;WHICH WE PROMISSED NOT TO MUNGE
14900 PUSH P,B
15000 SKIPN C,%BLKCNT(A) ;
15100 ERR <IT DOESN'T HELP YOU MUCH TO ALLOCATE ZERO MORE BLOCKS>,1,L1DON
15200 IMUL C,%BLKSIZ(A) ;B ← NOMINAL BLOCK SIZE * COUNT + OVERHEAD
15300 ADDI C,%FIRBLK ;
15400 PUSHJ P,CORGET ;A BLOCK OF THIS GREAT SIZE
15500 ERR <COULDN'T GET ANY MORE SPACE FROM CORGET>,1
15600 MOVEI TEMP,%FIRBLK(A) ;NOW CHAIN ALL SUB-BLOCKS TOGETHER
15700 MOVEI LPSA,0 ;
15800 MOVE C,%BLKCNT(A) ;SO WE WILL COUNT DOWN
15900 MOVEM C,%BLKCNT(B) ;ALSO, THE BLOCK COUNT FOR THIS
16000 L1B: MOVEM LPSA,(TEMP) ;POINT TO NEXT
16100 MOVE LPSA,TEMP ;REMEMBER THE BACK POINTER
16200 ADD TEMP,%BLKSIZ(A) ;NEXT BLOCK
16300 SOJG C,L1B ;COUNT DOWN TO ZERO
16400 L1DON: MOVEM LPSA,%FRELIS(B) ;THIS IS THE FIRST FREE
16500 MOVEM LPSA,%MAXADR(B) ;ALSO THE MAX ADDRESS BLOCK IN THIS SPACE
16600 SETZM %USECNT(B) ;USE COUNT IS ZERO
16700 SETZM %SUBLIS(B) ;THE SUBLIST IS ZERO
16800 MOVE LPSA,%MINSIZ(A) ;COPY THESE, TOO (HRROI POP IS FASTER
16900 MOVEM LPSA,%MINSIZ(B) ;BUT THIS ALLOWS EASIER REARRANGEMENT)
17000 MOVE LPSA,%BLKSIZ(A) ;
17100 MOVEM LPSA,%BLKSIZ(B) ;
17200 MOVEI LPSA,$FXG ;THE HANDLERS FOR THESE
17300 MOVEM LPSA,%GPROC(B) ;REMEMBER THE HANDLER
17400 MOVEI LPSA,$FXD
17500 MOVEM LPSA,%DPROC(B) ;
17600 PUSH P,-6(P) ;GO LINK ONTO THIS ADDRESS
17700 PUSH P,B ;THE BLOCKID
17800 PUSHJ P,$FSINS ;USING THE STANDARD INSERTER
17900 POP P,B
18000 POP P,LPSA ;GET ACS BACK
18100 POP P,TEMP ;
18200 POP P,C ;
18300 SUB P,X33
18400 JRST @3(P) ;RETURN
18500
18600 BEND SPCSER
18700
18800 ENDCOM (SPC)
00100 ;; SAIREC -- SYSTEM RECORD HANDLER ROUTINES
00200 COMPIL(REC,<$REC$,FLDKIL,$RERR,$RECGC,$M1FLD,$ENQR,$RECFN,$RCINI,$RMARK>
00300 ,<RECQQ,ALLFOR,ARYEL,CORGET,CORREL,X11,X22,X33,CLSLNK,STRCHN,SGINS,RSGCLK,GOGTAB,$DEL1B,$GET1B>
00400 ,<SAIL RECORD HANDLER>,<$RDREF,$RALLO>);
00500
00600 BEGIN RECORD
00700 IFE ALWAYS, <
00800 EXTERNAL $CLASS,RECCHN,RGCLST,RBLIST,RUNNER,SPRPDA,PLISTE,ACF
00900 >;IFE ALWAYS
01000
01100 PDA ← 7 ;DEF USED BY THE GARBAGE COLLECTOR
01200
01300
01400 ; FORMAT OF ALL RECORDS
01500 CLSRNG←-2 ;RING OF COMPILED-IN CLASSES
01600 RING←-1 ;RING OF RECORDS OF SAME CLASS
01700 RMARK←←0 ;GARBAGE COLLECTOR MARK CHAIN IN LEFT HALF
01800 CLSPTR←←0 ; RIGHT HALF OF THIS WORD POINTS TO CLASS TEMPLATE RECORD
01900
02000
02100 ; FORMAT OF RECORD CLASS TEMPLATES, IE CLASS="CLASS"
02200 ;WORDS -1 AND 0 ARE STANDARD, IE. RING AND MARK
02300 RECRNG←←1 ;RING OF RECORDS OF THIS CLASS - FOR RECORDS OF CLASS = "CLASS"
02400 HNDLER←←2 ;HANDLER PROCEDURE FOR THIS CLASS
02500 RECSIZ←←3 ;COUNT OF # FIELDS IN RECORDS OF THIS CLASS
02600 TYPARR←←4 ;INTEGER ARRAY OF TYPE INFO FOR FIELDS
02700 ; - 0TH WORD IN ARRAY IS TYPE BITS FOR THE CLASS
02800 TXTARR←←5 ;STRING ARRAY OF FIELD NAMES
02900 ; - 0TH ELEMENT IS NAME OF RECORD CLASS
03000
03100 ;;** VARIOUS "TYPE BITS" ARE NOW DEFINED UP IN HEAD
00100 ;; GETSTR, STRINIT, RELSTR, RSGC
00200
00300 ; ROUTINE TO SET UP A BLOCK OF FREE STRING DESCRS.
00400 FSTRSIZ←←20
00500
00600 STRINIT:
00700 MOVEI C,2*FSTRSIZ+1 ;ENOUGH ROOM FOR 20 STRINGS
00800 PUSHJ P,CORGET
00900 ERR <NO CORE FOR RECORD STRINGS>,1,ZPOPJ
01000 ;;*** CHECK THAT CORGET SETS UP USER ***
01100 MOVE A,STBLST(USER) ;LINKED LIST OF FREE STRING DESCR ARRAYS
01200 MOVEM A,(B) ;LINK NEW ONE IN
01300 MOVEM B,STBLST(USER) ;
01400 MOVEI A,FSTRSIZ
01500 ADDI B,2
01600 MOVEM B,STRCHN ;HEAD OF NEW CHAIN
01700 L: SETZM -1(B)
01800 ADDI B,2
01900 HRRZM B,-2(B) ;CONSTRUCT FREE CHAIN
02000 SOJG A,L
02100 SETZM -2(B) ;ZERO LAST ENTRY
02200 MOVE A,STRCHN
02300 POPJ P,
02400
02500 ; ROUTINE TO GET A FREE STRING DESCRIPTOR (CLOBBERS A & B AND SOMETIMES THE REST)
02600 GETSTR: SKIPN A,STRCHN ;ANY FREE STRINGS?
02700 PUSHJ P,STRINIT ;SET UP ANOTHER BLOCK OF STRINGS
02800 MOVE B,(A)
02900 MOVEM B,STRCHN ;CDR DOWN FREE CHAIN
03000 SETZM -1(A) ;CLEAR BOTH WORDS
03100 SETZM (A)
03200 POPJ P,
03300
03400
03500 ; RETURN A STRING TO FREE STRING LIST;
03600 RELSTR: SKIPN A,(A) ; POINTER TO STRING ARRAY ENTRY
03700 JRST CPOPJ ; NOTHING TO DO
03800 MOVE B,STRCHN ; CHAIN OF FREE STRINGS
03900 HRRZM B,(A) ; CHAIN TOGETHER
04000 SETZM -1(A) ; ZERO CHARACTER COUNT
04100 MOVEM A,STRCHN
04200 POPJ P,
04300
04400
00100 ; RECORD STRING SUBFIELD GARBAGE COLLECTION
00200
00300 BEGIN RSGC
00400 F←←E+1
00500 ; STRING AND STRING ARRAY SUBFIELDS ARE MARKED BY SWEEPING
00600 ; THROUGH ALL RECORD CLASSES LOOKING FOR ONES THAT ARE RELEVENT,
00700 ; AND MARKING STRING AND STRING ARRAY SUBFIELDS OF ALL RECORDS
00800 ; UNDER THE APPROPRIATE CLASSES
00900
01000 ↑RSGCMK:
01100 HRRZ D,RECRNG+$CLASS ;RING OF ALL CLASSES
01200
01300 RSGSWC: MOVE TEMP,@TYPARR(D) ;TYPE BITS FOR THIS CLASS
01400 TRNN TEMP,HASSTR ;DOES IT HAVE STRING OR STRING ARRAY SUBFIELDS?
01500 JRST NXTCLS ;NO STRING ARRAYS IN THIS CLASS
01600 HRRZ E,RECRNG(D) ;RING OF RECORDS FOR THIS CLASS;
01700 JRST NXTREC
01800
01900 RSGSWP: MOVN F,RECSIZ(D)
02000 MOVSS F
02100 HRR F,TYPARR(D) ;MAKE AOBJN WORD FOR TYPE ARRAY
02200 PUSH P,E
02300
02400 DOFLD: ADDI E,1
02500 LDB B,[POINT 6,1(F),=12] ;GET TYPE BITS
02600 CAIN B,STTYPE
02700 JRST DOSTR ;IT'S A STRING
02800 CAIN B,ARRTYP+STTYPE
02900 JRST DOSTRA ;IT'S A STRING ARRAY
03000 NXFLD: AOBJN F,DOFLD
03100 POP P,E
03200 HRRZ E,RING(E) ;POINT AT NEXT IN CLASS
03300 NXTREC: CAIE E,RECRNG-RING(D) ;IS IT HEAD OF CLASS?
03400 JRST RSGSWP ;NOPE, CONTINUE
03500
03600 NXTCLS: HRRZ D,RING(D) ;NEXT CLASS ON RING OF CLASSES
03700 CAIE D,$CLASS+RECRNG-RING ;HEAD OF RING OF CLASSES?
03800 JRST RSGSWC ;NOPE, CONTINUE
03900 POPJ P, ;DONE AT LAST
04000
04100 DOSTR: MOVE A,(E) ;GET SUBFIELD -- POINTER TO STRING DESCR
04200 SUBI A,1 ;CRETINS - POINT TO FIRST WORD OF DESCR
04300 PUSHJ P,@-2(P) ;CALL STRING MARK ROUTINE
04400 JRST NXFLD
04500
04600 DOSTRA: PUSH P,D
04700 MOVE D,(E) ;GET SUBFIELD -- POINTER TO STRING ARRAY
04800 MOVN A,-2(D) ;STRING ARRAY LENGTH
04900 HRL D,A ;MAKE AOBJN WORD
05000 STALP: MOVEI A,-1(D) ;POINTER TO FIRST WORD OF STRING DESCR
05100 PUSHJ P,@-3(P)
05200 AOBJN D,.+1
05300 AOBJN D,STALP
05400 POP P,D
05500 JRST NXFLD
05600
05700 BEND RSGC
00100 ;; SAIREC -- $REC$ AND $RECFN
00200 ;;$REC$ CALLED VIA PUSH P,[OP]
00300 ; PUSH P,ARG1
00400 ; PUSHJ P,$REC$
00500 ; IS ASSUMED TO WIPE OUT THE ACS
00600 ;;$RECFN IS CALLED JUST LIKE $REC$
00700
00800 $RDISP: JRST $RDREF ;DEREFERENCE ARG1
00900 JRST $RALLO ;ALLOCATE RECORD WITH CLASS ARG1
01000 JRST CPOPJ ;2 NON-STANDARD PRINT ROUTINE?
01100 JRST CPOPJ ;3 NON-STANDARD READ ROUTINE?
01200 JRST $MFLDS ;4 -- MARK ALL FIELDS OF A RECORD
01300 JRST $DIE ;5 DELETE SPACE FOR RECORD
01400 $RMAX ←← (.-$RDISP)-1
01500
01600 HEREFK($RECFN,$RECF.)
01700 SKIPN A,-1(P) ;PICK UP ARG1
01800 JRST NLARG1 ;
01900 MOVE B,-2(P) ;PICK UP OP
02000 CAIE B,1 ;RALLO IS FUNNY
02100 HRRZ A,CLSPTR(A) ;
02200 HACK <
02300 HRLZI C,777740 ;OLD-STYLE COUNT FIELD
02400 TDNE C,(A) ;CHECK TO BE SURE NOT OLD-STYLE CLASS
02500 ERR <OLD STYLE RECORD DESCRIPTOR. RECOMPILE>
02600 >;HACK
02700 JRST @HNDLER(A) ;DISPATCH TO HANDLER ROUTINE
02800 NLARG1: ERR <NULL ARGUMENT TO $RECFN>,1
02900 SUB P,X33 ;
03000 JRST @3(P) ;RETURN
03100
03200 HERE($REC$)
03300 POP P,C ;RET ADR
03400 POP P,A
03500 EXCH C,(P) ; NOW C=OP, A=ARG1
03600 CAILE C,$RMAX
03700 POPJ P,
03800 JUMPN C,@$RDISP(C) ; OBEY COMMAND
03900
04000 ↑↑$RDREF:
04100 ERR <CALL ON $RDREF IN RECORD GC VERSION>,1
04200 POPJ P,
04300
04400 $DIE: JUMPE A,CPOPJ ;
04500 PUSH P,A ; SO CAN LATER CALL CORREL
04600 HLRZ B,RING(A)
04700 HRRZ C,RING(A)
04800 HRRM C,RING(B)
04900 HRLM B,RING(C) ; UNLINK FROM RING OF CLASS
05000
05100 HRRZ C,CLSPTR(A) ; CLASS ADDRESS
05200 PUSH P,RECSIZ(C) ; RECORD SIZE
05300 HRRZ C,TYPARR(C) ; CLASS TYPE ARRAY
05400 SUBI C,(A) ; CORRECTION FACTOR
05500 ADDI A,1 ; FIRST DATA ELEMENT
05600 HRLI C,(<POINT =13,(A),=12>); DESCRIPTOR TO GET BITS
05700 PUSH P,C
05800
05900 GETFLD: SOSGE -1(P) ; IS THIS THE LAST FIELD
06000 JRST NOMORE
06100 LDB C,(P) ; GET FIELD
06200 DPB C,[POINT =13,A,=12] ; PUT DESCRIPTOR BITS IN PLACE
06300 PUSHJ P,FLDKIL ; GO KILL THIS FIELD
06400 AOJA A,GETFLD ; GO ON TO NEXT
06500
06600 NOMORE: SUB P,X22 ; JUST POP TWO OFF
06700 POP P,B ; THE CORREL POINTER
06800 SUBI B,1 ; NOW IT IS (THE REF CNT WORD, REMEMBER)
06900 MOVE USER,GOGTAB ; FREE THE SPACE UP
07000 MOVE A,$FSLIS(USER) ; BY CALLING THE FREER-UPPER
07100 PUSHJ P,$DEL1B ;
07200 ERR <CONFUSION IN FREEING A BLOCK>,1
07300 POPJ P,
07400
07500 ↑↑$RALLO:
07600 HACK <
07700 HRLZI C,777740 ;OLD-STYLE COUNT FIELD
07800 TDNE C,(A) ;CHECK TO BE SURE NOT OLD-STYLE CLASS
07900 ERR <OLD STYLE RECORD DESCRIPTOR. RECOMPILE>
08000 >;HACK
08100 MOVE C,RECSIZ(A) ; A = RECORD CLASS ID. GET THE WORD COUNT
08200 ADDI C,2 ; RECORD SIZE +1 FOR RING WORD
08300 ; AND +1 FOR DESCRIPTOR WORD
08400 PUSH P,A ; EVENTUALLY, BECOMES THE RECID POINTER
08500 MOVE USER,GOGTAB ; GET THE SYSTEM FREE LIST
08600 MOVE A,$FSLIS(USER) ;
08700 PUSHJ P,$GET1B ; MAY WANT MORE EFFICIENCY LATER
08800 ERR <NO CORE FOR RECORD ALLOCATION>,1,ZPOPJ
08900 MOVEI A,1(B) ;THE POINTER WE WILL ACTUALLY RETURN
09000
09100 ;;#SF# ! USED TO BE (B)
09200 ADDI C,-1(B) ;STOPPING PLACE
09300 SETZM (B); ;ZERO OUT (ALSO REF CNT ← 0)
09400 HRL B,B ;BUILD BLT PTR
09500 HRRI B,1(B)
09600 BLT B,(C) ;BLT THEM AWAY
09700 PUSH P,A
09800 PUSH P,A
09900 MOVE A,-2(P) ;GET CLASS POINTER
10000 MOVE B,@TYPARR(A) ;GET TYPE BITS FOR CLASS
10100 TRNN B,HASSTR
10200 JRST NOSTRS ;NO STRINGS TO ALLOCATE
10300 MOVN C,RECSIZ(A) ;WE GOT STRINGS
10400 MOVSS C
10500 HRR C,TYPARR(A) ;BUILD IOWD FOR TYPARR
10600
10700 STALLO: MOVS B,1(C)
10800 AOS (P)
10900 CAIE B,140 ;### CHANGE THIS TO TYPE BIT SYMBOL
11000 JRST NXTFLD
11100 PUSH P,C
11200 PUSHJ P,GETSTR ;GET A FREE STRING DESCR
11300 POP P,C
11400 MOVEM A,@(P) ;STORE POINTER TO STRING DESCR IN FIELD
11500 NXTFLD: AOBJN C,STALLO
11600 NOSTRS: SUB P,X11
11700 POP P,A
11800
11900 RNGIT2: POP P,B ; CLASSID
12000 RNGIT: HRRZM B,CLSPTR(A) ; PUT ZERO IN MARK FIELD
12100 ADDI B,RECRNG-RING ; OFFSET FOR HEAD OF CLASS
12200 HRRZ C,RING(B) ; RING OF RECORDS FOR THE CLASS
12300 HRRZM C,RING(A) ; NEW RECORD POINTS TO RING
12400 HRRM A,RING(B) ; CLASS POINTS TO NEW RECORD
12500 HRLM B,RING(A) ; NEW RECORD POINTS TO CLASS
12600 HRLM A,RING(C) ; RING POINTS BACK TO NEW RECORD
12700 POPJ P, ;RETURN
12800
12900 ZPOPJ: MOVEI A,0
13000 POPJ P,
13100
13200
13300
13400
13500
13600
13700
13800
13900 HERE($RERR)
14000 ERR <ACCESS TO A SUBFIELD OF A NULL RECORD>,1
14100 POPJ P,
14200
00100 ;; SAIREC -- $RCINI
00200
00300 ;; SETS UP $CLASS, THEN RUNS DOWN THE CLASS LINKS
00400 ;; HOMED ON CLSLNK & SETS UP THE QUAM-STYLE RING LINKAGES.
00500 ;; ALSO ZEROS ALL OWN (AND OUTER BLOCK) RECORD POINTERS.
00600
00700 NOLOW <
00800 NOUP <
00900 REN <
01000 USE
01100 >;REN
01200 RCLK: 0
01300 $RCINI
01400 0
01500 LINK %INLNK,RCLK
01600 REN <
01700 USE HIGHS
01800 >;REN
01900 >;NOUP
02000 >;NOLOW
02100
02200 HEREFK($RCINI,$RCIN.)
02300 PUSH P,[RSGCMK] ;POINTER TO RECORD STRING GC
02400 MOVEI A,RSGCLK+1(USER)
02500 PUSH P,A
02600 PUSHJ P,SGINS ;ENQUE RECORD STRING GARBAGE COLLECTOR
02700
02800
02900 MOVE A,[XWD $CLASS,$CLASS] ;
03000 HRRZM A,$CLASS ;INITIALIZE $CLASS
03100 MOVEM A,$CLASS+RECRNG ;
03200 ADD A,[XWD RECRNG-RING,RECRNG-RING];
03300 MOVEM A,$CLASS+RING ;
03400 MOVEI A,$REC$ ;HANDLER
03500 MOVEM A,$CLASS+HNDLER ;
03600 MOVEI A,$CLSTY ;TYPE ARRAY
03700 MOVEM A,$CLASS+TYPARR ;
03800 MOVEI A,$CLSTX+1 ;TEXT ARRAY
03900 MOVEM A,$CLASS+TXTARR ;
04000 MOVEI A,5 ;TEST MUNGAGE
04100 ;*** CAME A,$CLASS+RECSIZ ;OF THE COUNT
04200 ;*** ERR <WARNING. $CLASS WAS MUNGED>,1
04300 MOVEM A,$CLASS+RECSIZ
04400
04500 SKIPN D,CLSLNK ;PICK UP THE CLASS LIST
04600 POPJ P, ;IF NO CLASSES, THEN DONE
04700 LNKCLS: MOVEI B,$CLASS ;CLASS OF CLASSES
04800 MOVEI A,-CLSRNG(D) ;POINT AT CLASS DESCRIPTOR
04900 PUSHJ P,RNGIT ;LINK THIS CLASS ONTO CLASS RING
05000 MOVEI D,RECRNG-RING(A) ;SET UP RECORD RING
05100 HRL D,D ;RECRNG SHOULD POINT AT ITSELF
05200 MOVEM D,RECRNG(A) ;MAKE IT DO SO
05300 HRRZ D,CLSRNG(A) ;POINT AT NEXT CLASS
05400 JUMPN D,LNKCLS ;GO ON IF HAVE ANY LEFT
05500 MOVE USER,GOGTAB
05600 SETZM STRCHN ;ZERO CHAIN OF FREE STRING DESCRS
05700 SETZM STBLST(USER) ;AND CHAIN OF FREE STRING DESCR ARRAYS
05800
05900 ; ZERO ALL THE OWN AND OUTER BLOCK RECORD POINTERS
06000 HRRZ D,RBLIST ;CHAIN OF ALL OWN AND OUTER BLOCK RECORD POINTERS
06100 JRST ZERO3
06200 ZERO1: HRRZ D,(D) ;NEXT BLOCK IN RBLIST CHAIN
06300 ZERO3: JUMPE D,CPOPJ ;DONE
06400 HRRZI B,1(D)
06500 ZERO2: SKIPN C,(B) ;GET AOBJN WORD
06600 JRST ZERO1 ;DONE WITH THIS BLOCK
06700 SETZM (C) ;ZERO THE RECORD POINTER (ARRAY)
06800 AOBJN C,.-1
06900 AOJA B,ZERO2
07000
07100 $CLSTY ;TYPE BITS ARRAY HEADER
07200 0 ;LB
07300 TXTARR ;UB
07400 1
07500 XWD 1,TXTARR+1 ;NDIMS,,TOTAL SIZE
07600 $CLSTY: CMPLDC+NODELC+HASSTR ;TYPE BITS
07700 INTYPE*1B12 ;RECRNG
07800 INTYPE*1B12 ;HNDLER
07900 INTYPE*1B12 ;RECSIZ --ONLY "REAL" INTEGER
08000 (ARRTYP+INTYPE)*1B12 ;TYPE ARRAY
08100 (ARRTYP+STTYPE)*1B12 ;TEXT ARRAY
08200
08300 CLSTXT: ASCIZ /$CLASSRECRNGHNDLERRECSIZTYPARRTXTARR/
08400
08500 DEFINE SUBSTR(STR,N,CNT) <
08600 CNT
08700 POINT 7,STR-1+(N+4)/5,6+7*(N+4-5*((N+4)/5))
08800 >
08900
09000 DEFINE IDTXT(CNT) <
09100 SUBSTR(CLSTXT,II,CNT)
09200 II ←← II+CNT
09300 >
09400
09500 II ←← 0
09600
09700 $CLSTX+1 ;TEXT ARRAY HEADER
09800 0 ;LB
09900 TXTARR ;UB
10000 1 ;MUL(1)
10100 XWD -1,2*(TXTARR+1) ;TOTAL SIZE
10200 $CLSTX: IDTXT(6) ;$CLASS
10300 IDTXT(6) ;RECRNG
10400 IDTXT(6) ;HNDLER
10500 IDTXT(6) ;RECSIZ
10600 IDTXT(6) ;TYPARR
10700 IDTXT(6) ;TXTARR
10800
00100 ;; SAIREC -- FLDKIL ROUTINE
00200
00300 HERE(FLDKIL)
00400 ;CALLED WITH REFITEM TYPE DESCRIPTOR IN A
00500 ;WILL TAKE ALL APPROPTIATE ACTION
00600 ;IF TMPB IS ON IN A, THEN ASSUMES THAT CALLED FROM LEAP
00700 ; -- THUS, IF TMPB AND NOT REFB, WILL DO THE RIGHT THING
00800 ; ABOUT ONE & TWO WORD FREES
00900 ;PRESERVES A BUT ALL OTHERS MAY BE MUNGED
01000
01100 TLNN A,REFB ; IF REFB ON, THEN NO DELETION REQUIRED
01200 SKIPN @A ; NOTHING TO DO IF A NULL
01300 POPJ P,
01400 TLNE A,ARY2B ;ITEMVAR ARRAY ??
01500 JRST ARYKIL ;YEP
01600 TLNN A,ITEMB ;NOTHING TO DO IF ITEM
01700 TLNE A,PROCB ;OR PROCEDURE
01800 POPJ P,
01900 LDB TEMP,[POINT 6,A,=12] ; SIX BIT TYPE
02000 CAIL TEMP,INVTYP ;VERIFY VALID
02100 ERR <DRYROT -- INVALID REFERENCE TYPE IN FLDKIL>,5,RPOPJ
02200 CAIG TEMP,MXSTYP ;IS THIS A LEGAL ARRAY TYPE ??
02300 JRST @FKDISP(TEMP) ;NOPE DO WHATEVER YOU MUST
02400 MOVEI TEMP,@FKDISP-ARRTYP(TEMP) ;FIND OUT WHAT SORT OF ARRAY YOU HAVE
02500 CAIE TEMP,WZAPR ;A DONOTHING ??
02600 CAIN TEMP,WSTRKL ;A STRING ARRAY?
02700 JRST ARYKIL ;YEP
02800 PUSH P,A ;HERE MUST CALL SELF RECURSIVELY TO
02900 MOVEI A,@A ;PROCESS EACH ARRAY ELEMENT
03000 PUSH P,TEMP ;ROUTINE TO CALL
03100 HRRZ TEMP,-1(A) ;COUNT
03200 JUMPE TEMP,NOELS ;NONE
03300 PUSH P,TEMP ;SAVE COUNT
03400 DEL1EL: SKIPE (A) ;HAVE ONE
03500 PUSHJ P,@-1(P) ;CALL THE ROUTINE
03600 SOSG (P) ;DECREMENT THE COUNT
03700 AOJA A,DEL1EL ;DELETE ONE ELEMENT
03800 POP P,TEMP ;GET THIS OFF
03900 NOELS: POP P,TEMP ;GET THIS OFF, TOO.
04000 JRST ARYKL2 ;MAY AS WELL LEAVE A ON THE STACK
04100
04200 ARYKIL: PUSH P,A ;SINCE ARYEL CLOBBERS IT
04300 ARYKL2: PUSH P,@A ;CALL TO ARYEL
04400 SETZM @A ;ZAP IT
04500 PUSHJ P,ARYEL ;KILL THE ARRAY
04600 POP P,A ;OH WELL, GET A BACK
04700 POPJ P, ;RETURN FROM KILLING THE ARRAY
04800
04900 FKDISP: WZAPR ;ACTUALLY A NOTHING
05000 WZAPR ;1 UNTYPED
05100 WZAPR ;2 BTRIP
05200 WSTRKL ;3 STRING
05300 WZAPR ;4 REAL
05400 WZAPR ;5 INTEGER
05500 WSLKL ;6 SET
05600 WSLKL ;7 LIST
05700 WZAPR ;8 PROCEDURE ITEM
05800 WZAPR ;9 PROCESS ITEM
05900 WZAPR ;10 EVENT TYPE
06000 WCTXTK ;11 CONTEXT
06100 WZAPR ;12 REFITEM
06200 WZAPR ;13 RECORD DEREFERENCING
06300
06400 WSTRKL: PUSH P,A
06500 PUSHJ P,RELSTR
06600 POP P,A
06700 JRST WZAPR
06800
06900 WSLKL: SKIPN B,@A ;DO WE HAVE ONE
07000 JRST WZAPR ;NOPE JUST WORRY ABOUT FREES
07100 PUSH P,A ;WHO KNOWS WHAT EVIL LURKS IN THE HEART OF LEAP
07200 SETZM @A ;CLEAR IT OUT
07300 MOVE A,B ;
07400 MOVEI 5,0 ;ALL SET UP
07500 PUSHJ P,RECQQ ;RELEASE THE SET OR LIST
07600 POP P,A ;GET A BACK
07700 JRST WZAPR
07800
07900 WCTXTK: SKIPN B,@A ;HAVE ONE
08000 POPJ P, ;YEP
08100 SETZM @A ;
08200 PUSH P,A ;KILLING A CONTEXT
08300 PUSH P,B
08400 PUSHJ P,ALLFOR ;FORGET IT
08500 POP P,A ;GET BACK A
08600 JRST WZAPR
08700
08800 WRDRF: PUSH P,A ;SAVE
08900 MOVE A,@A ; DO DEREFERENCE
09000 PUSHJ P,$RDREF ;CALL DEREFERENCER
09100 POP P,A ;GET A BACK
09200 ;FALL INTO WZAPR
09300 WZAPR: TLNN A,TMPB ;CALLING FROM LEAP ???
09400 RPOPJ: POPJ P, ;
09500 ;MUST WORRY ABOUT LEAPISHNESS
09600 ERR <FLDKIL NOT YET READY FOR CALL FOR REFITEMS>,1,RPOPJ
09700
09800
00100 ;; SAIREC (RECGC) -- $ENQR,ENQRB,ENQRBB,PAMRK
00200
00300
00400 HERE($ENQR)
00500 JUMPE A,CPOPJ ;NULL NEVER
00600 HLRZ TEMP,RMARK(A) ;BE SURE NOT THERE YET
00700 JUMPN TEMP,CPOPJ
00800 HRR TEMP,RECCHN ;LINK ONTO CHAIN
00900 HRLM TEMP,RMARK(A)
01000 HRRM A,RECCHN
01100 POPJ P,
01200
01300 ENQRB: TLNN C,-1 ;C =-COUNT,,ADR
01400 POPJ P, ;NULL CALL
01500 HRRZ A,(C)
01600 PUSHJ P,$ENQR ;PUT ONE ON QUEUE
01700 AOBJN C,.-2 ;ITERATE
01800 POPJ P,
01900
02000 ENQRBB: MOVE C,(B) ;B →→ A BLOCK OF -CNT,,ADR WORDS
02100 JUMPE C,CPOPJ ;TERMINATED BY A ZERO
02200 PUSHJ P,ENQRB
02300 AOJA B,ENQRBB ;ITERATE
02400
02500 ENQRBL: HRRZ D,RBLIST ;ROUTINE THAT HANDLES RBLIST
02600 EQRB.L: JUMPE D,CPOPJ
02700 HRRZI B,1(D) ;POINT AT THIS BLOCK
02800 PUSHJ P,ENQRBB ;MARK EM ALL
02900 HRRZ D,(D) ;ITERATE
03000 JRST EQRB.L
03100
03200 PAMRK: HLRZ PDA,1(RF) ;HANDLES ONE EACH PROCEDURE ACTIVATION
03300 CAIN PDA,SPRPDA ;CAN QUIT ON THIS
03400 POPJ P,
03500 MOVEI D,-1(RF) ;LAST PARAMETER LOCATION
03600 HRLI D,C
03700 HRRZ C,PD.NPW(PDA) ;NUMBER OF ARITH PARAMS
03800 MOVNI C,(C) ;
03900 HRRZ B,PD.DLW(PDA) ;POINT AT PARAMS
04000 MKPRM: AOJGE C,PRMSDN ;COUNT UP, QUIT WHEN RUN OUT
04100 LDB TEMP,[POINT =12,(B),=12] ;INTERESTED IN VALUE RECORDS
04200 CAIE TEMP,RECTYP ;TEST CODE
04300 AOJA B,MKPRM ;NO, GO MARK NEXT
04400 HRRZ A,@D ;PICK UP PARAMETER
04500 PUSHJ P,$ENQR ;HANDLE IT
04600 AOJA B,MKPRM
04700 PRMSDN: HRRZ B,PD.LLW(PDA) ;POINT AT LVI
04800 LVI.DO: SKIPN D,(B) ;A ZERO MEANS DONE
04900 POPJ P,
05000 LDB TEMP,[POINT 4,D,3]
05100 CAIN TEMP,RPACOD
05200 JRST MRKRPA
05300 CAIE TEMP,RPCOD
05400 AOJA B,LVI.DO
05500 HRRZ A,@D ;GET DESCRIPTOR
05600 PUSHJ P,$ENQR
05700 AOJA B,LVI.DO
05800 MRKRPA: SKIPN C,@D
05900 AOJA B,LVI.DO
06000 MOVN TEMP,-1(C) ;WORD COUNT
06100 HRL C,TEMP
06200 PUSHJ P,ENQRB ;DO THEM ALL
06300 AOJA B,LVI.DO
06400
00100 ;; SAIREC (RECGC) -- %PSMRR
00200
00300 %PSMRR:
00400 SKIPE TEMP,RUNNER ;FANCY CASE
00500 JRST PSMK.2 ;HERE IF PROCESSES IN USE
00600 PUSH P,RF ;SAVE RF
00700 PUSHJ P,PSMK.1 ;
00800 POP P,RF
00900 POPJ P,
01000
01100 PSMK.1: PUSHJ P,PAMRK ;MARK
01200 HRRZ RF,(RF) ;DYNAMIC LINK
01300 CAIE RF,-1 ;DONE??
01400 JUMPN RF,PSMK.1 ;NO (ALSO TEST DONE ANOTHER WAY)
01500 POPJ P, ;DONE ALL
01600
01700 PSMK.2: MOVEM RF,ACF(TEMP) ;SAVE RF IN TABLE
01800 HRLZI B,-NPRIS
01900 HRR B,GOGTAB
02000 PSCHL: SKIPN TEMP,PRILIS(B)
02100 JRST NXLS
02200 PUSH P,B ;SAVE B
02300 PSCHL2:
02400 PUSH P,TEMP
02500 MOVE RF,ACF(TEMP)
02600 PUSHJ P,PSMK.1 ;MARK THAT STACK
02700 POP P,TEMP
02800 HRRZ TEMP,PLISTE(TEMP)
02900 JUMPN TEMP,PSCHL2
03000 POP P,B
03100 NXLS: AOBJN B,PSCHL
03200 MOVE TEMP,RUNNER
03300 MOVE RF,ACF(TEMP)
03400 POPJ P,
00100 ;; SAIREC (RECGC) -- RCIMRK
00200
00300 RCIMRK: MOVE USER,GOGTAB
00400 SKIPE HASMSK(USER) ;ACTUALLY HAVE LEAP
00500 SKIPG C,MAXITM(USER) ;ALL THE ITEMS TO MARK
00600 POPJ P, ;NOPE
00700 RI1MK: LDB TEMP,INFOTAB(USER) ;GET TYPE
00800 MOVE A,@DATAB(USER) ;AND DATUM READY
00900 CAIN TEMP,RFITYP ;REFERENCE
01000 JRST RFFOL
01100 CAIN TEMP,ARRTYP+RECTYP ;RECORD ARRAY??
01200 JRST RAIMK ;YES
01300 CAIN TEMP,RECTYP ;REGULAR RECORD
01400 PUSHJ P,$ENQR ;YES
01500 RIMITR: SOJG C,RI1MK ;ITERATE
01600 POPJ P,
01700
01800 RFFOL: PUSH P,C ;SINCE NO PROMISSES WERE MADE
01900 PUSHJ P,$M1FLD ;MARK A FIELD
02000 POP P,C
02100 JRST RIMITR
02200
02300 RAIMK:
02400 SKIPN TEMP,@A ;POINT AT RECORD ARRAY
02500 JRST RIMITR ;EMPTY
02600 PUSH P,C ;SAVE ITEM NUMBER
02700 MOVN C,-1(TEMP)
02800 HRL C,TEMP
02900 MOVS C,C ;-CNT,,ADR
03000 PUSHJ P,ENQRB ;HANDLE EM ALL
03100 JRST RIMITR ;ITERATE
00100 ;; SAIREC (RECGC) -- $MRK.1, $MFLDS
00200
00300 $MRK1R: PUSHJ P,$ENQR ;ENQUEUE ONE RECORD
00400 HEREFK($RMARK,$RMAR.)
00500 $MRK.1: HRRZ A,RECCHN ;GET A RECORD OFF THE CHAIN
00600 CAIN A,-1 ;END OF THE ROAD??
00700 POPJ P, ;YES
00800 HLRZ D,RMARK(A) ;CDR THE QUEUE
00900 HRRM D,RECCHN ;NEW NEXT ELT ON QUEUE
01000 HLRZ D,RECCHN ;
01100 HRLM D,RMARK(A) ;MAKE CHAIN OF ALL MARKED RECORDS
01200 HRLM A,RECCHN
01300 HRRZ D,CLSPTR(A) ;POINTER TO CLASS
01400 HRRZ D,HNDLER(D) ;GET HANDLER ADDRESS
01500 CAIN D,$REC$ ;STANDARD HANDLER??
01600 JRST MFLDS1 ;YES
01700 PUSH P,[4] ;THE "MARK" OP
01800 PUSH P,A ;REC ID
01900 PUSHJ P,(D) ;CALL ROUTINE
02000 JRST $MRK.1
02100
02200 MFLDS1: PUSH P,[$MRK.1]
02300 $MFLDS: JUMPE A,CPOPJ ;MARK ALL FIELDS OF RCD IN A
02400 HRRZ C,CLSPTR(A) ;CLASS ID
02500 PUSH P,RECSIZ(C) ;RECORD SIZE
02600 HRRZ C,TYPARR(C) ;POINTER TO TYPE ARRAY
02700 ;;%##% RHT + PDQ DO NOT PROCEED FURTHER IF NO RECORD SUBFIELDS
02800 HRL C,(C) ;GET TYPE BITS
02900 TLNN C,HASRPS ;HAVE RECORD OR RECORD ARRAY SUBFIELDS
03000 JRST CPOP1J ;NO
03100 ;;%##%
03200 SUBI C,(A) ;CORRECTION FACTOR
03300 ADDI A,1 ;FIRST DATA FIELD
03400 HRLI C,(<POINT =13,(A),=12>) ;TO GET TYPE BITS
03500 PUSH P,C ;SAVE IT
03600 G1FLD: SOSGE -1(P) ;ARE WE DONE?
03700 JRST CPOP2J ; YEP
03800 LDB C,(P) ;GET TYPE
03900 DPB C,[POINT =13,A,=12] ;DESCRIPTOR FOR ONE FIELD
04000 PUSHJ P,$M1FLD ;MARK ONE FIELD
04100 AOJA A,G1FLD ;ITERATE UNTIL DONE
04200
04300 CPOP2J: SUB P,X22
04400 POPJ P,
04500
04600 CPOP1J: SUB P,X11
04700 CPOPJ: POPJ P,
04800
00100 ;; SAIREC (RECGC) -- $RGCMK
00200
00300 $RGCMK: PUSHJ P,ENQRBL ;DO SOME STANDARD MARK ROUTINES -- OWNS
00400 PUSHJ P,RCIMRK ;ITEMS
00500 PUSHJ P,%PSMRR ;ACTIVE PROCEDURES
00600 PUSH P,RGCLST ;NOW DO ANY SPECIAL ENLISTED ROUTINES
00700 RGCMK1: POP P,A ;GET NEXT ENQUEUEING ROUTINE TO CALL
00800 JUMPE A,$MRK.1 ;NO MORE -- GO PROCESS ALL WE HAVE SEEN
00900 PUSH P,(A) ;SAVE LINK
01000 PUSHJ P,@1(A) ;CALL THIS FELLOW
01100 JRST RGCMK1 ;GO GET SOME MORE
01200
00100 ;; SAIREC (RECGC) -- $RGCSW
00200
00300 $RGCSW: ;;**** THESE LINES CHANGED FROM PDQ METHOD ****
00400 ;;HRRZ D,CLSREC ;HEAD OF ALL CLASSES
00500 ;;MOVEI TEMP,RECRNG-RING(D) ;HEAD OF RING OF ALL CLASSES
00600 ;;MOVEM TEMP,CLSRHD#
00700 ;;HRRZ D,RECRNG(D) ;RING OF ALL CLASSES
00800 ;;****
00900 HRRZ D,RECRNG+$CLASS ;RING OF ALL CLASSES
01000
01100 RGSWC: MOVE TEMP,@TYPARR(D) ;TYPE BITS FOR THIS CLASS
01200 HRRZ A,RECRNG(D) ;RING OF RECORDS FOR THIS CLASS;
01300 TRNN TEMP,NODELC
01400 JRST NXTREC ;DELETE UNMARKED RECORDS OF THIS CLASS;
01500 ;RESET MARKS FOR ALL RECORDS OF THIS CLASS -- NEVER DELETE
01600 RGNODL: HRRZS RMARK(A) ;CLEAR MARK
01700 HRRZ A,RING(A)
01800 CAIE A,RECRNG-RING(D) ;HEAD OF CLASS?
01900 JRST RGNODL ;NO, AGAIN
02000 JRST NXTCLS ;DONE WITH THIS RECORD CLASS -- ON TO NEXT
02100
02200
02300 RGSWPP: HLL TEMP,RMARK(A) ;GET MARK
02400 TLNN TEMP,-1 ;
02500 JRST RGSWP1 ;UNMARKED MEANS IT DIES
02600 HRRZS RMARK(A) ;CLEAR MARK
02700 HRRZ A,RING(A) ;POINT AT NEXT IN CLASS
02800 NXTREC: CAIE A,RECRNG-RING(D) ;IS IT HEAD OF CLASS?
02900 JRST RGSWPP ;NOPE, CONTINUE
03000 NXTCLS: HRRZ D,RING(D) ;NEXT CLASS ON RING OF CLASSES
03100 ;;**** CAME D,CLSRHD ;HEAD OF RING OF CLASSES?
03200 CAIE D,$CLASS+RECRNG-RING ;HEAD OF RING OF CLASSES?
03300 JRST RGSWC ;NOPE, CONTINUE
03400 POPJ P, ;DONE AT LAST
03500
03600 RGSWP1: HRRZ TEMP,RING(A)
03700 PUSH P,TEMP ;SAVE POINTER TO NEXT ON RING
03800 PUSH P,D
03900 HRRZ TEMP,CLSPTR(A) ;CLASS
04000 HRRZ TEMP,HNDLER(TEMP) ;HANDLER FOR CLASS
04100 CAIE TEMP,$REC$ ;IS IT STANDARD
04200 JRST RGSWP3 ;NO DO A REGULAR CALL
04300 PUSHJ P,$DIE ;KILL RECORD
04400 RGSWP2: POP P,D
04500 POP P,A
04600 JRST NXTREC
04700
04800 RGSWP3: PUSH P,[5] ;KILL YOURSELF
04900 PUSH P,A
05000 PUSHJ P,(TEMP)
05100 JRST RGSWP2
00100 ;; SAIREC (RECGC) -- MAIN ROUTINE
00200
00300 HERE($RECGC)
00400
00500 SETOM RECCHN ;INITIALIZE MARK AS NULL
00600 PUSHJ P,$RGCMK ;MARK THEM ALL
00700 JRST $RGCSW ;SWEEP THEM ALL
00800 ;ALL DONE NOW
00900
00100 ;; SAIREC (RECGC) -- $M1FLD
00200
00300 HERE($M1FLD)
00400 ;CALLED WITH REFITEM TYPE DESCRIPTOR IN A
00500 ;WILL TAKE ALL APPROPTIATE ACTION
00600 ;PRESERVES A BUT ALL OTHERS MAY BE MUNGED
00700
00800 JUMPE A,CPOPJ ;NOTHING TO DO IF NULL
00900 TLNN A,ITEMB ;NOTHING TO DO IF ITEMISH
01000 TLNE A,PROCB ;OR PROCEDURE
01100 POPJ P,
01200 LDB TEMP,[POINT 6,A,=12] ; SIX BIT TYPE
01300 CAIN TEMP,RECTYP ;A RECORD??
01400 JRST M1REC ;YES, ENQUEUE IT
01500 CAIN TEMP,RFITYP ;A REFERENCE ITSELF
01600 JRST M1REF ;YES
01700 CAIE TEMP,RECTYP+ARRTYP; A RECORD ARRAY??
01800 POPJ P, ;NOPE
01900 PUSH P,A ;SINCE AGREED TO LEAVE ALONE
02000 PUSH P,B
02100 SKIPN B,(A) ;PICK UP ARRAY DESCRIPTOR
02200 POPJ P, ;EMPTY
02300 MOVN TEMP,-1(B) ;WORD COUNT
02400 JUMPE TEMP,M1AXIT ;NO WORDS
02500 HRL B,TEMP
02600 M1ALP: MOVE A,(B) ;PICK UP A WORD
02700 PUSHJ P,$ENQR ;ENQUEUE IT
02800 AOBJN B,M1ALP
02900 M1AXIT: POP P,B ;
03000 POP P,A
03100 POPJ P,
03200
03300 M1REC: PUSH P,A ;WE PROMISSED TO LEAVE ALONE
03400 MOVE A,@A ;FETCH VARIABLE
03500 PUSHJ P,$ENQR ;ENQUEUE IT
03600 POP P,A ;RESTORE
03700 POPJ P,
03800
03900 M1REF: PUSH P,A
04000 MOVE A,@A
04100 PUSHJ P,$M1FLD ;MARK THE THING REFERENCED
04200 POP P,A
04300 POPJ P,
04400
04500 BEND RECORD
04600
04700 ENDCOM(REC)