.title RNODYN .ident 'BL3.0' .if ndf $VMS .if ndf RT11 .MCALL EXTK$S .ENDC .ENDC ; ; The symbol $DEBUG is enabled for complte dynamic subroutine checking ; It is off for normal operation since it slows down the routines. ;$DEBUG=1 ; ; The following routines are designed to handle buffers in dynamic ; pool memory. The data should be accessed via these routines. The offset ; BF.FUL is the index to your data bytes. The BF.ADD always points to the ; current byte (one accessed last by GBYT or PBYT). All data in buffers should ; be accessed via these routines. BEGBF sets pointers to beginning of buffer. ; FNDBF sets to specified byte so you may use GBYT or GWRD to get the data. You ; may access the current byte via the offset BF.ADD,when BF.FUL is non zero, ; but no other bytes ; may be accessed directly. The routine RSTBF, and ENDBF set the index and then ; set up the buffers for input via PBYT,PWRD. After BEGBF,FNDBF reading past ; past the end of the data is inhibited. If CARRY is set the routine failed. ; CLRBF resets all pointers, deallocates all dynamic memory and sets the ; buffer chain ready for output. GBYT always returns an error if at end of ; buffer chain. PBYT causes a fatal error if you attempt to write ; past the end of the chain while in input mode. ; In essence this is similar to reading and writing a sequential file with ; a record size of 1 byte. The functions are: ; GBYT,GWRD Read a record during input mode ; PBYT,PWRD Write input or output mode ; CBYT,CWRD Write zero ; BEGBF Rewind set input mode ; ENDBF Find end of file and set output mode (append) ; FNDBF Find arbitrary record set input mode ; RSTBF Find arbitrary record, truncate file, set output mode ; ; Registers: ; R3 = buffer header ; R1 = data ; R0 destroyed ; ; GBYT1,GBYT2 R1,R2 = buffer header ; ; The buffer chain is a doubly linked list of buffers ; With a foreward link, and backward link. ; The last buffer has link=0 ; .if ndf $VMS BFSIZ = 200 ; 128. BYTES OF DATA (MUST BE POWER OF 2) .endc .if df $VMS BFSIZ = ^o100000 ; Should be power of 4 (for alignment purposes) .endc ; ; R3=BUFFER HEADER ; R1=DATA BYTE TO PUT/GET/FIND ; R0=DESTROYED BY THESE ROUTINES ; ; ROUTINE TO CLEAR BUFFER FOR MORE DATA ; EXTRA BUFFERS ARE RETURNED TO POOL ; .code CLRBF:: .if DF $DEBUG CALL TEST ; *** DEBUG .ENDC MOV #BFSIZ,(R3) ; SET UP COUNT CMPNE R3,BUFADD,10$ ; Not primary input buffer? MOV #IBFSZ,(r3) ; Set to input buffer size 10$: CLR BF.FUL(R3) ; RESET INDEX CLR BF.MAX(R3) ; RESET DATA RESIDENT CLR BF.SPC(R3) ; clear spacing char count CLR BF.VSP(R3) ; Clear vertical spacing CLR BF.HED(R3) ; Clear header MOV BF.BEG(R3),R0 ; GET HEAD OF CURRENT BUFFER CHAIN MOV R0,BF.CAD(R3) ; INTO CURRENT BUFFER ADDRESS MOV R0,BF.ADD(R3) ; INTO DATA ADDRESS ADD #BFLNK,BF.ADD(R3) ; POINTS TO FIRST BYTE-1 RETBF: MOV BF.CAD(R3),R0 ; Current buffer TSTEQ (R0),10$ ; No more in chain ? 5$: TSTEQ (R0),6$ ; At end of chain MOV (R0),R0 ; Next entry BR 5$ 6$: MOV LNKHD,(R0) ; ADD BUFFER POOL TO END OF CHAIN MOV @BF.CAD(R3),LNKHD ; PUT COMPLETE CHAIN INTO POOL CLR @BF.CAD(R3) ; AND NO FOREWARD LINK 10$: .if DF $DEBUG CALL TEST ; *** DEBUG .ENDC CLR R1 RETURN ; ; RSTBF ; ROUTINE TO SET REQUESTED LOCATION AS END OF BUFFER READY FOR INPUT ; ; ENDBF ; SET TO END OF BUFFER + MADE READY FOR PUTTING TO BUFFER ; Both of these routines return excess buffers to the pool ; ENDBF:: MOV BF.MAX(R3),R1 ; LOCATION TO GO TO BNE RSTBF ; Not zero ? MOV BF.FUL(r3),R1 ; Current location RSTBF:: CALL FNDBF ; GO TO IT BCC 10$ ; OK ? JMP HLTER ; NO !!!!! 10$: CLR BF.MAX(R3) ; CLEAR DATA MAX MOV #BFSIZ,(R3) ; BUFFER SIZE CMPNE R3,BUFADD,20$ ; Not input buffer ? MOV #IBFSZ,(R3) ; Input buffer size 20$: SUB R1,(R3) ; ADJUST COUNT TO BUFFER SIZE .if DF $DEBUG CALL TEST ; *** DEBUG .ENDC BR RETBF ; ; GETS NEXT BYTE FROM BUFFER ; R1=data ; C = set if no data available ; Z = set if R1 is zero ; N = set if Byte R1 is negative ; V = undefined ; GBYT2:: MOV R2,R1 ; Address of header BR GBYT1 .IF DF $VMS ; If native mode VMS .ALIGN LONG ; Align this entry for speed, since one of .ENDC ; The most common entry points in program GBYT:: MOV R3,R1 ; FOR GBYT1 ; ; SPECIAL PURPOSE ROUTINE ; R1=HEADER (INPUT) ; R1=DATA BYTE (OUTPUT) ; GBYT1:: .if DF $DEBUG MOV R3,-(SP) ; *** DEBUG MOV R1,R3 ; *** DEBUG CALL TEST ; *** DEBUG MOV (SP)+,R3 ; *** DEBUG .ENDC TSTEQ BF.MAX(R1),40$ ; Bad get ?? DEC (R1)+ ; DECREMENT COUNT BLT 20$ ; Nothing in buffer ? INC (R1)+ ; INCREMENT INDEX INC (R1) ; NEXT BYTE MOVB @(R1),R1 ; GET BYTE CLC RETURN 20$: INC -(R1) ; Restore count to zero BLT 50$ ; Bad CNT CMPEQ BF.FUL(R1),BF.MAX(R1),40$; End of buffers ? BHI 50$ ; ERROR ????? MOV BF.CAD(R1),R0 ; GET CURRENT BUFFER MOV (R0),R0 ; GET NEXT BUFFER IN CHAIN BEQ 50$ ; NONE ?? MOV BF.MAX(R1),(R1) ; NUMBER OF BYTES TOTAL SUB BF.FUL(R1),(R1) ; LESS INDEX=REMAINING CMP (R1),#BFSIZ ; IS IT OK BLOS 30$ ; YES MOV #BFSIZ,(R1) ; NO, MAKE IT FULL BUFFER SIZE 30$: MOV R0,BF.CAD(R1) ; NEW CURRENT BUFFER ADD #BFLNK,R0 ; POINTS TO BYTE IN FRONT OF FIRST MOV R0,BF.ADD(R1) ; SAVE ADDRESS BR GBYT1 ; AND GET THE BYTE FINALLY 40$: .if DF $DEBUG MOV R3,-(SP) ; *** DEBUG MOV R1,R3 ; *** DEBUG CALL TEST ; *** DEBUG MOV (SP)+,R3 ; *** DEBUG .ENDC CLR R1 SEC RETURN 50$: CALL HLTER ; bad count ; ; PBYT - Puts next byte into buffer ; CBYT - Clears next byte in buffer ; CBYT:: CLR R1 .IF DF $VMS ; If native mode VMS, align entry for speed .ALIGN LONG,1 ; ,1 is NOP code for fill. PBYT is one of most .ENDC ; often called entry points PBYT:: MOV R3,R0 ; BUFFER HEADER .if DF $DEBUG CALL TEST ; *** DEBUG .ENDC DEC (R0)+ ; DECREMENT REMAINDER COUNT BLT 10$ ; YES, TRY TO ALLOCATE ANOTHER INC (R0)+ ; INCREMENT INDEX INC (R0) ; INCREMENT ADDRESS MOVB R1,@(R0) ; SAVE BYTE CLC RETURN 10$: TSTEQ BF.FUL(R3),11$ ; Zero ?? BITEQ #BFSIZ-1,BF.FUL(R3),15$ ; legal end of buffer? 11$: CALL HLTER ; NO NO NO 15$: CMPEQ R3,BUFADD,11$ ; Input buffer ?? MOV BF.CAD(R3),R0 ; CURRENT ADDRESS MOV (R0),R0 ; ANOTHER IN CHAIN? BNE 20$ ; YES, USE IT MOV LNKHD,R0 ; GET BUFFER FROM POOL? BEQ 30$ ; NONE! MOV (R0),LNKHD ; REMOVE IT FROM POOL CLR (R0) ; NO FOREWARD LINK MOV BF.CAD(R3),$WORDL(R0) ; BACKWARD LINK MOV R0,@BF.CAD(R3) ; FOREWARD LINK 20$: MOV R0,BF.CAD(R3) ; NEW CURRENT BUFFER ADD #BFLNK,R0 ; POINTS TO BYTE IN FRONT OF FIRST MOV R0,BF.ADD(R3) ; SAVE ADDRESS MOV #BFSIZ,(R3) ; NEW COUNT MOV BF.MAX(r3),R0 ; Get max count BEQ PBYT ; Output buffer ? SUB BF.FUL(R3),R0 ; Subtract current CMP R0,#BFSIZ ; Check if smaller BLT 25$ ; Smaller ? JMP PBYT 25$: MOV R0,(R3) ; New count BR PBYT ; AND GET THE BYTE FINALLY 30$: .if ndf RT11 .if ndf $VMS CALL EXTEND ; try to extend memory BCC 10$ ; success .ENDC .ENDC MOV #12.,R0 ; No more memory avilable message JMP ILINP ; KILL KILL KILL ; ; ROUTINE GETS 1 WORD FROM BUFFERS ; R1=data ; C = set if no data ; N,Z correspond to value in R1 ; GWRD:: CLR -(SP) ; Set up stack CALL GBYT ; GET LOWER BYTE MOVB R1,(SP) ; SAVE IT CALL GBYT ; NEXT UPPER MOVB R1,1(SP) .if df $long CALL GBYT ; NEXT UPPER MOVB R1,2(SP) CALL GBYT ; NEXT UPPER MOVB R1,3(SP) .endc MOV (SP)+,R1 ; GET RESULT RETURN ; ; PWRD - Save 1 word in buffer ; CWRD - Clear 1 word in buffer ; CWRD:: CLR R1 PWRD:: MOV R1,-(SP) ; Save word CALL PBYT ; SAVE LOWER BYTE MOVB 1(SP),R1 ; Get upper byte CALL PBYT ; SAVE UPPER MOV (SP)+,R1 ; Get word again RETURN ; ; extend the available pool ; .if ndf $VMS .if ndf RT11 EXTEND: EXTK$S #5 BCC 10$ RETURN 10$: ADD #500,XTOP ; readjust top for extend .endc .endc ; ; subroutine to set up linked list of dynamic buffers ; LNKSET:: .if ndf $VMS MOV XBOT,R0 ; save value ADD #BFSIZ+6,XBOT ; raise bottom BCS 40$ ; done CMP XBOT,XTOP ; too big BHIS 40$ ; yes MOV LNKHD,(R0) ; Save current linked buffer chain CLR $WORDL(R0) ; No backward link MOV R0,LNKHD ; put current buffer at head BR LNKSET ; try another 40$: SUB #BFSIZ+6,XBOT ; restore .endc CLC RETURN ; ; ROUTINE SETS POINTER TO START OF BUFFER FOR GETTING DATA ; IF BUFFER HAS NO DATA MAX SET, MAX=CURRENT INDEX ; BEGBF:: CLR R1 ; ; SETS POINTERS TO BUFFER LOCATION SPECIFIED IN R1 ; C SET if bad location specified ; C CLEAR if good location ; IF MAX IS NOT SET MAX=CURRENT INDEX ; To get the data GBYT or GWRD must be called ; BF.ADD does not necessarily point to correct data ; FNDBF:: .if DF $DEBUG CALL TEST ; *** DEBUG .ENDC TSTNE BF.MAX(R3),1$ ; Currently input ? MOV BF.FUL(R3),BF.MAX(R3) ; Reset max so now input 1$: CMP R1,BF.MAX(R3) ; GREATER THAN CURRENT BLOS 5$ ; NO .if DF $DEBUG CALL TEST ; *** DEBUG .ENDC CLR R1 SEC RETURN ; RETURN NO ACTION 5$: CMPNE R3,BUFADD,10$ ; Not primary input buffer? ; ; Section for input buffer only ; MOV BF.MAX(R3),(R3) ; MAX SIZE SUB R1,(R3) ; NOW REMAINING SIZE MOV BF.CAD(R3),R0 ; START OF BUFFER ADD #BFLNK,R0 ; POINTS TO DATA-1 ADD R1,R0 ; CURRENT ADDRESS MOV R0,BF.ADD(R3) ; Saved MOV R1,BF.FUL(R3) ; NEW LOCATION BR 90$ ; ; Section for all other buffers ; 10$: MOV R2,-(SP) ; Save CMP R1,#BFSIZ ; Compare with buffer size BGT 20$ ; Not first buffer ? MOV BF.BEG(R3),R0 ; Start at first CLR R2 ; zero = base BR 60$ 20$: MOV BF.ADD(R3),R0 ; current address SUB BF.CAD(R3),R0 ; minus cuurrent buffer address SUB #BFLNK,R0 ; minus header offset=bytes this buff. MOV BF.FUL(R3),R2 SUB R0,R2 ; now set index to start of buffer MOV BF.CAD(R3),R0 ; CURRENT BUFFER CMP R1,R2 ; go foreward? BHI 40$ ; yes 30$: MOV $WORDL(R0),R0 ; GO BACK 1 BUFFER BNE 35$ ; OK ? CALL HLTER 35$: SUB #BFSIZ,R2 CMP R1,R2 ; add on buffer size BLOS 30$ ; NOT THERE YET BR 60$ ; FOUND CORRECT ONE 40$: ADD #BFSIZ,R2 CMP R1,R2 ; add on buffer size BLOS 50$ ; yes MOV (R0),R0 ; GO FOREWARD BNE 40$ ; OK ? CALL HLTER ; ERROR *** 50$: SUB #BFSIZ,R2; ADJUST TO POSITIVE 60$: MOV R1,BF.FUL(R3) ; Final position MOV R0,BF.CAD(R3) ; SAVE CURRENT BUFFER SUB R2,R1 ; Current cnt ADD R1,R0 ; ALMOST CURRENT DAT ADD #BFLNK,R0 ; DATA -1 MOV R0,BF.ADD(R3) ; SAVED MOV BF.MAX(R3),R2 ; Max bytest SUB BF.FUL(r3),R2 ; Count MOV R2,(R3) ; Possible count MOV #BFSIZ,R0 ; BUFFER SIZE SUB R1,R0 ; - OFFSET = COUNT CMP R0,R2 ; Compare BGE 80$ ; Too big ? MOV R0,(R3) ; SMALLER ONE 80$: MOV (SP)+,R2 90$: .if DF $DEBUG CALL TEST ; *** DEBUG .ENDC CLC ; Success !! RETURN ; ; GET TEMPORARY BUFFER ; ; R2= current buffer ; R3= temporary buffer address ; GETTBF::MOV #TMPBF,R3 ; Temporary buffer address SAVTBF::MOV R3,-(SP) ; Save R3 MOV R2,R0 ; Will be input MOV #/$WORDL+1,R1 ; Number of words 10$: MOV (R0)+,(R3)+ ; transfer SOB R1,10$ ; Till done MOV (SP)+,R3 ; Restore buffer address CLC RETURN ; ; CALL TMPIN ; Set up input from temporary buffer ; INPUT: R2 = String address ; OUTPUT: = Last byte address in string+1 ; R0,R1 are destroyed ; CALL TMPINB ; INPUT: R2 = Buffer header ; ; CALL PSHINS - Set up for next input stack entry ; OUTPUT: R3 = input buffer header formed on return ; CALL POPINS - Go back 1 level in input stack ; PSHINS::MOVB SUBSTK,R0 ; Get stack pointer CMPEQB R0,SUBSTK+1,20$ ; Is it too big ? MOV R2,-(SP) ; Save R2 MOV #SUBF0,R2 ; Lowest header TSTEQ R0,2$ MOV R0,R2 ADD #BUFADD,R2 MOV (R2),R2 ; Previous header 2$: ADD #$WORDL,R0 ; Next level in stack MOVB R0,SUBSTK ; New stack MOV R0,R3 ADD #BUFADD,R3 MOV (R3),R3 ; Get current buffer header MOV R3,BUFAD ; Save it CALL SAVTBF ; Make current same MOV (SP)+,R2 ; Restore 10$: RETURN 20$: CALL HLTER POPINS::MOVB SUBSTK,R0 ; Get stack pointer BEQ 20$ ; Already at end ? SUB #$WORDL,R0 ; Backup 1 level MOVB R0,SUBSTK ; New stack ADD #BUFADD,R0 MOV (R0),BUFAD ; Get current buffer header 10$: RETURN 20$: CALL HLTER TMPINB::MOV #-1,R1 ; Indicate buffer header BR TMPIN1 TMPIN:: CLR R1 ; Indicates R2=string TMPIN1: MOV R3,-(SP) ; Save R3 MOV R1,-(SP) ; Save R1 CALL SETINS ; Start temp input TSTEQ (SP)+,10$ ; String input ?? 5$: CALL GBYT2 ; Get byte BLOS 20$ ; Done ? CALL PBYT ; Save it BR 5$ ; Continue till done 10$: MOVB (R2)+,R1 ; Get 1 byte BEQ 20$ ; At end of buffer ? CALL PBYT ; Save it BR 10$ 20$: MOVB #LF,R1 ; Put line feed CALL PBYT ; Into buffer MOV BF.SPC(R3),R1 ; Back to start of line CALL FNDBF ; Set for reading buffer MOV (SP)+,R3 ; Restore CLC RETURN ; ; Setup a temporary input buffer to simulate input. ; This is used to bring in headers, numbers etc. ; OUTPUT: R3=temporary input buffer ; note: input must be terminated by #LF or null ; SETINS::CALL PSHINS CALL ENDBF ; go to end of buffer CALL CWRD ; Chock buffer MOV BF.FUL(R3),BF.SPC(R3) ; For traceback RETURN ; ; This checks the integrity of the buffer chain ; The stack contains the offset of the bad param ; .if DF $DEBUG TEST: MOV R0,-(SP) ; Save R0 MOV R1,-(SP) MOV R2,-(SP) MOV #BF.CAD,-(SP) MOV #BFSIZ,R1 CMPNE R3,BUFADD,1$ ; Not Input buffer ? MOV #IBFSZ,R1 ; Buffer size TSTEQ @BF.CAD(R3),1$ ; Only one in chain ? JMP 10$ 1$: MOV BF.ADD(r3),R2 SUB BF.CAD(r3),R2 SUB #BFLNK,R2 ; Now have count again MOV R1,R0 ; Save it SUB R2,R0 ; Same as BF.CNT TSTEQ BF.MAX(R3),5$ ; Output ? MOV #BF.FUL,(SP) CMP BF.FUL(R3),BF.MAX(R3) BHI 10$ ; Not correct ? MOV BF.MAX(R3),R1 ; Last SUB BF.FUL(R3),R1 CMP R1,R0 ; Which is bigger ? BGE 5$ MOV R1,R0 5$: MOV #BF.CNT,(SP) CMPEQ (R3),R0,7$; correct ? TSTNE BF.MAX(R3),10$ ; Not output ? TSTNE (r3),10$ ; Also not input ? ; Check whole string 7$: CLR R1 ; Backward link MOV BF.BEG(R3),R0 ; CHeck entire chain MOV #BF.BEG,(SP) 8$: CMPNE $WORDL(R0),R1,10$ ; Backward wrong ? MOV R0,R1 CMPNE R0,BF.CAD(R3),18$ ; Not current buffer ? MOV #BF.FUL,(SP) CMPNE R2,BF.FUL(R3),10$ ; BAD ? MOV #-1,(SP) ; Mark it bad 18$: ADD #BFSIZ,R2 ; add on next size MOV (R0),R0 ; Next in chain BNE 8$ ; End of chain ?? ; CHeck if BF.CAD is in chain 9$: TST (SP) BGE 10$ ; BF.CAD no in chain TST (SP)+ MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 ; restore return 10$: CALL HLTER .ENDC ; ; The input file is the exception to the buffer access rules. ; Since it is never extended it may be accessed directly. ; BFLNK==2*$WORDL-1 ; Offset from buffer to data-1 ; ; Macro to create buffer header with data area (sub-buffer) ; .const ; ; Input buffer stack table ; BUFADD::.WORDA IBUF1 ; POINTS TO INPUT HEADER .WORDA SUBF1 .WORDA SUBF2 .WORDA SUBF3 .WORDA SUBF4 .WORDA SUBF5 .WORDA SUBF6 ; subst. buffers ; ; Variables used by this routine ; .vars .MACRO BUFF,SIZE .WORDA SIZE ; BF.CNT .WORDA 0 ; BF.FUL .WORDA 10$+BFLNK ; BF.ADD .WORDA 10$ ; BF.CAD .WORDA 10$ ; BF.BEG .WORDA 0 ; .BLKA 4 ; BF.MAX,SPC,HED,VSP 10$: .BLKA 2 ; buffer foreward/backward links .BLKB SIZE ; data area .ENDM ; ; extra header macro (no data area) ; .MACRO BUFFHD,ADD .WORDA 0 ; BF.CNT .WORDA 0 ; BF.FUL .WORDA ADD+BFLNK ; BF.ADD .WORDA ADD ; BF.CAD .WORDA ADD ; BF.BEG .WORDA 0 ; .BLKA 4 ; BF.MAX,SPC,HED,VSP .ENDM ; ; BUFFER DEFINITIONS ; Each buffer consists of a header and a string of ; sub-buffers each of uniform size. While a buffer is being filled ; sub-buffers are automatically added as needed from the pool. ; If FNDBF or BEGBF are called then BF.MAX is generated and this ; serves as a limit on adding more data, or reading past BF.MAX. ; CLRBF and ENDBF reset BF.MAX so more data may be added. ; Each sub-buffer consists of a Foreward link, backward link, ; and data area. ; BF.CNT==0 ; Count of char remaining in sub-buffer BF.FUL==1*$WORDL ; Index to current location in buffer chain BF.ADD==2*$WORDL ; Current char address BF.CAD==3*$WORDL ; Current sub-BUFFER address BF.BEG==4*$WORDL ; First sub-BUFFER address BF.MAX==5*$WORDL ; MAX # characters (all sub-buffers) ; = 0 if currently at end + output allowed BF.SPC==6*$WORDL ; Spacing chars (current line, or traceback) BF.HED==7*$WORDL ; Header (begins current line, or traceback) BF.VSP==8.*$WORDL ; Vertical spacing (all lines, or traceback) ; ; Traceback info is for input buffers only ; ; THE ACTUAL DATA BUFFER HAS THE FOLLOWING FORMAT ; WORD 1= FOREWARD LINK ; WORD 2= BACKWARD LINK ; 3 - N = N-4 BYTES OF DATA ; ; ; TEXT BUFFER HEADER (PRECEEDS TEXT) TEXT TERMINATED BY A NULL ; APPLIES TO FOOTNOTE + SECONDARY BUFFERS ; ; BYTE 0 LINE SKIP COUNT ; 1 FLAGS 1=CHANGE BAR ; 2 LEFT MARGIN SPACING ; 3 SPACES/EXPANDABLE SPACE ; 4 EXPANDABLE SPACES TO LEFT ; 5 LEFT/RIGHT INDICATOR ; ; ; IMPURE DATA STORAGE FOR INPUT BUFFERS ; SUBLEV==3 ; Maximum number of substitutions BUFAD:: .WORDA IBUF1 ; Current buffer pointer SUBSTK:: .BYTE 0,SUBLEV*$WORDL ; current substitute pointer,max .BLKB 2 ; Padding for $WORDL=4 .EVEN ; (actually .ALIGN LONG, NECESSARY! for speed) ; ; Input buffer (contains 1 line only) ; IBUF1:: BUFF IBFSZ+4 ; ; substitution buffer headers ; SUBF0:: BUFFHD SUBBUF SUBF1: BUFFHD SUBBUF SUBF2: BUFFHD SUBBUF SUBF3: BUFFHD SUBBUF SUBF4: BUFFHD SUBBUF SUBF5: BUFFHD SUBBUF SUBF6: BUFFHD SUBBUF SUBBUF: .BLKB BFSIZ+4 ; Data for substitutions buffers ; ; dynamic memory control locations ; XBOT:: .BLKA 1 ; BEGINNING OF ALLOCATED INDEX AREA XTOP:: .BLKA 1 ; HIGHEST VIRTUAL ADDRESS IN PROGRAM LNKHD:: .BLKA 2 ; POOL BUFFERS HEADER ; ; Footnote buffer ; FOTBF:: BUFF BFSIZ ; ; Deferred text buffer ; TXDBF:: BUFF BFSIZ ; ; IF command buffer ; IFBF:: BUFF BFSIZ ; ; Index entry buffer ; INXBF:: BUFF BFSIZ ; ; Command line input buffer/ message buffer/ general format buffer ; This buffer may be used freely as scratch storage ; TTLIN==BFSIZ TTBF:: BUFF 0 ; Input buffer header TTBUF:: .BLKB BFSIZ+$WORDL ; COMMAND LINE INPUT BUFFER (82 bytes or more) ; ; Final output buffer ; .if ndf RT11 .WORDA 0 HFOUT:: .WORDA OBFSZ .worda 0 .worda 0 OUBUF:: .BLKB OBFSZ .endc ; ; Escape sequence table ; ESCBF:: BUFF BFSIZ ; ; Secondary text buffer ; TX2BF:: BUFF BFSIZ ; ; Temporary buffers just a header/ no buffer ; TMPBF: BUFFHD 0 ; ; Title buffers ; TTLBF:: BUFF BFSIZ ; ; Subtitle buffer ; STLBF:: BUFF BFSIZ ; ; Tabulation buffer ; TABBF:: BUFF BFSIZ ; ; Backspace buffer ; This buffer contains a line with spaces and underline chars. ; for underlining if not doing it by backspace. ; ULNMAX:: .WORDA 0 ; MAX NUMBER OF CHARS IN BUFFER UBUFF:: .BLKB ULNSZ+$WORDL ; ; Traceback buffer ; Format: ; Address of current line number, followed by string ; 1 word line number ; String-file-name ; 1 zero byte ; Line number + string occupies bytes ; .if DF RT11 TRCBUF::.BLKA 1 ; CURRENT BUFFER ADDRESS .BLKA 1 ; LINE NUMBER .ASCIZ "Main File" ; FILE NAME .blkb TRCLN-12. ; COMPLETE FIRST BUFFER .BLKB 6*TRCLN ; UP TO 6 NESTED .REQ FILES .endc .if ndf RT11 TRCBUF::.BLKB <6*TRCLN>+$WORDL .ENDC .END