.TITLE QUEUE .IDENT /S1.4/ ;Derived from DECUS version M02 ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ;* * ;* General permission to copy (but not for profit) is hereby * ;* granted, provided that reference is made to the fact that * ;* reproduction privileges were granted by DECUS. * ;* * ;* The information in this document is subject to change with- * ;* out notice and should not be construed as a commitment by * ;* the contributor(s), DECUS or Digital Equipment Corporation. * ;* * ;* These parties make no warranty as to the suitability of this * ;* material for use by the recipient, nor as to the accuracy or * ;* functioning of the software or related material, and no * ;* responsibility is assumed in connection therewith. * ;* * ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; RUNOFF commands and subroutines related to delayed text blocks ; and the REQUIRE command ; (Portions formerly contained in RNCMD.MAC) ; ; AUTHOR: C. H. Spalding ; ; MODIFIED BY ; ; C. H. Spalding, Adept Technology, Aug. '83 ; ; MODIFICATIONS ; ; chs33 Misc. fixes to footnote processing ; chs37 Fix FIGURE to work as claimed; added queue ; chs54a Footnote processing reworked ; chs54b Add FOOTNOTE LINE ; chs60 Make syntax for command arguments common ; chs78 Add text queue & BLOCK ; revamp footnote processing ; chs80 Add text argument to FIGURE ; chs88 Add ENABLE and DISABLE ; chs96 Prevent cummulative output of blank lines ; chs99 Add REQUIRE and CHAIN ; ; ALL COMMAND ROUTINES ARE ENTERED WITH: ; ; R4 = Address of number conversion routine ; R5 = Address of flag word F.1 ; ; MACRO LIBRARY CALLS ;chs99+ .IF NZ REQCMD .MCALL CLOSE$,CSI$1,CSI$2,OPEN$R,OFID$R .ENDC ; NZ REQCMD ;chs99- ; FOOTNOTE command FOOTN:: CALL (R4) ;HOW MANY LINES TO RESERVE? 5$: JMP ILCM ;MUST HAVE SPEC .IF NZ AUTOFN ;chs54b TSTEQB FTNCHR,7$ ;SKIP IF AUTO FOOTNOTE LINE DISABLED ;chs54b .IF NZ TXTQUE ;chs78 TSTNEB FTNCNT,7$ ;...OR IF FOOTNOTE ALREADY QUEUED ;chs78 .IFF ;chs78 CMPNE FOOTP1,FOOTP2,7$ ;...OR IF FOOTNOTE ALREADY QUEUED ;chs54b .ENDC ; -NZ TXTQUE ;chs78 ADD #2,R3 ;ADJUST LINE COUNT FOR SPACE & LINE ;chs54b 7$: ;chs54b .ENDC ; NZ AUTOFN ;chs54b .IF NZ TXLTST ;chs78e+ CMPB R3,TXTLEN ;COULD FOOTNOTE FIT ON A PAGE? .IFF ;chs78e- CMP R3,PNLPG ;VALUE WITHIN REASON? .ENDC ; -NZ TXLTST ;chs78e BHI 5$ ;IF HI NO .IF NZ NEWFTN ;chs54a SUB R3,NLPG ;ADJUST CURRENT PAGE LENGTH ;chs54a .IFF ;chs54a MOV NSPNG,R0 ;RESERVE N TIMES SPACING MOV R3,R1 CALL $MUL ;MULTIPLY ADD R1,FOOTC ;ADD TO RESERVED FOOTNOTE LINES .ENDC ; -NZ NEWFTN ;chs54a .IF NZ TXTQUE ;chs78+ INCB FTNCNT ;COUNT THIS FOOTNOTE MOV #-1,R1 ;SET QUEUE RECORD TYPE QUETXT::CALL QUENEW ;SETUP DATA FOR QUEUE RECORD .ENDC ; NZ TXTQUE ;chs78- 8$: CALL $FRCND ;FORCE TO LOGICAL END OF LINE ;chs33+ .IF NZ FNFIX CMPEQ #SEMI,R1,8$ ;KEEP LOOKING FOR REAL STUFF CMPEQ #PD,R1,20$ ;SAVE REST OF COMMAND LINE .IFF ;chs33- CLRB GCSCH ;CLEAR TERMINAL CHARACTER CMPNE #CR,R1,40$ ;NOT END OF LINE? .ENDC ; -NZ FNFIX ;chs33 10$: CALL SKPLF ;IGNORE REST OF CURRENT LINE ;chs60+ ;; CALL CCIN ;SKIP REST OF COMMAND LINE ;; CMPNE R1,#LF,10$ ;NOT LINE FEED? ;chs60- BR 40$ ; 20$: CALL CCIN ;READ A CHARACTER 30$: CALL WCIFTN ;WRITE CHARACTER IN BUFFER CMPNE R1,#LF,20$ ;LOOP IF NOT END OF LINE? 40$: CALL CCIN ;CHECK CHARACTER AFTER LINE FEED CMPEQ R1,#EOF,50$ ;SKIP IF END OF FILE? CMPNE #'!,R1,30$ ;LOOP IF NOT END OF FOOTNOTE? TSTNEB FIGCMD,46$ ;SKIP IF FIGURE COMMAND 45$: CALL CCIN ;READ NEXT CHARACTER CMPNEB #CR,R1,45$ ;IGNORE EVERYTHING UNTIL CR MOVB R1,GCSCH ;SAVE CR FOR REREAD 46$: CLRB FIGCMD ;MAKE SURE FLAG IS OFF MOV #EOF,R1 ;SET END OF FOOTNOTE 50$: .IF Z TXTQUE ;chs78 JMP WCIFTN ;STORE THIS CHARACTER .IFF ;chs78+ CALL WCIFTN ;STORE LAST CHARACTER MOV QEND,R1 ;POINT TO START OF LAST RECORD MOV FOOTP2,R3 ;...AND LAST CHARACTER OF RECORD MOV R3,4(R1) ;STORE END POINTER INC R3 ;ADVANCE TO NEXT WORD CLRB (R3)+ BIC #1,R3 MOV R3,(R1) ;SET FORWARD POINTER MOV R3,QEND ;STORE POINTER FOR NEXT RECORD CLR (R3) ;MARK AS END OF QUEUE RETURN .ENDC ; -Z TXTQUE ;chs78- ; FOOTNOTE LINE command ;chs54b+ .IF NZ AUTOFN FOOTL:: CALL (R4) ;GET LINE LENGTH JMP 10$ ;DEFAULT TO CURRENT LENGTH MOVB R3,FTNLEN ;STORE NEW LENGTH 10$: CALL NXTCHR ;GET FOLLOWING CHARACTER BCS 20$ ;SKIP IF END OF COMMAND HIT MOVB R1,FTNCHR ;SAVE AS NEW LINE CHARACTER BR 30$ 20$: CLRB FTNCHR ;DISABLE AUTO FOOTNOTE LINE 30$: RETURN .ENDC ; NZ AUTOFN ;chs54b- ; FIGURE command .IF NZ BLKCMD ;chs78b+ FIGUR:: BITEQ #BLKF!FOTF,(R5),20$ ;MUST PROCESS VIA QUEUE ; Command coming from queue MOV R4,-(SP) ;SAVE ADDRESS OF CONVERSION ROUTINE CALL (R4) ;GET ARGUMENT MOV #1,R3 ;IF NONE, ASSUME ONE LINE MOV R3,R2 ;SAVE FIGURE LENGTH MOV (SP)+,R4 ;RESTORE ADDRESS OF CONV. ROUTINE CALL (R4) ;IGNORE LENGTH OF SETOFF ; (IT'S DONE BY THE QUEUE PROCESSOR) NOP ;SPACE FILLERS FOR WHEN NO SETOFF NOP CALL SKIPN ;SKIP THE FIGURE LINES ; Process figure caption ;chs80+ .IF NZ FIGCAP CALL SKPSEP ;SKIP TO TEXT ARGUMENT BCS 10$ ;ALL DONE IF NONE CALL GETTXT ;STORE TEXT MOV RMARG,-(SP) ;PUSH RIGHT MARGIN ONTO STACK JMP CENT2 ;OUTPUT TEXT CENTERED .ENDC ; NZ FIGCAP ;chs80- 10$: RETURN ; Put command into queue 20$: MOV SDINP,-(SP) ;SAVE CURRENT BUFFER POINTER MOV SDINP+2,SDINP ;POINT TO START OF COMMAND ARGUMENTS MOV R4,-(SP) ;SAVE ADDRESS OF CONVERSION ROUTINE MOV #<50$>,R3 ;POINT TO LOCAL SUBROUTINE CLRB GCSCH ;CLEAR REREAD CHARACTER 30$: CALL CCIN ;GET CHARACTER FROM INPUT CALL (R3) ;WRITE CHARACTER TO SECONDARY BUFFER CMPNEB #LF,R1,30$ ;UNTIL END OF LINE MOV #FIGSTR,R2 ;POINT TO TERMINAL STRING 40$: MOVB (R2)+,R1 ;GET A CHARACTER BEQ 46$ ;DONE IF NULL CALL (R3) ;PUT CHARACTER IN SECONDARY BUFFER BR 40$ ;GET ANOTHER CHARACTER 46$: CLRB GCSCH ;CLEAR REPEAT CHARACTER ; Now have command name and arguments in secondary buffer INCB $SDISW ;SIGNAL INPUT FROM BUFFER CALL @(SP) ;GET FIGURE LENGTH MOV #1,R3 ;IF NONE, ASSUME ONE LINE MOV R3,R2 ;SAVE LENGTH FOR BELOW INC R2 ;ADD LINE FOR ASSUMED CAPTION .IF NZ TXLTST ;chs78e+ CMPB R2,TXTLEN ;CHECK FOR RATIONAL ARGUMENT .IFF ;chs78e- CMP R2,PNLPG ;CHECK FOR RATIONAL ARGUMENT .ENDC ; -NZ TXLTST ;chs78e+ BLE 48$ ;OKAY IF FIGURE LENGTH LE TEXT LENGTH CLRB $SDISW ;STOP INPUT FROM BUFFER CMP (SP)+,(SP)+ ;CLEAN STACK JMP ILCM ;ERROR 48$: CALL @(SP)+ ;GET SETOFF LENGTH .IF NZ BLKSTK ;chs78f+ MOV FIGDFT,R3 ;IF NONE, USE DEFAULT MOV R3,FIGDFT ;SAVE AS NEW DEFAULT .IFF ;chs78f- MOV #FIGDFT,R3 ;IF NONE, USE DEFAULT .ENDC ; -NZ BLKSTK ;chs78f MOV R3,R1 ;COMPOSE QUEUE RECORD PARM. WORD SWAB R1 ; WITH SETOFF IN HIGH BYTE ADD R2,R1 ; AND LENGTH IN LOW BYTE MOV (SP)+,SDINP ;RESTORE POINTER TO START OF BUFFER MOVB #LF,GCSCH ;SET REPEAT CHARACTER INCB FIGCMD ;SET FLAG BR BLOCK2 ;GO PROCESS VIA QUEUE ; Local subroutine to write character in R1 to secondary buffer 50$: MOV #SDINP,R4 ;POINT TO SECONDARY BUFFER JMP WCI ;WRITE CHARACTER TO SECONDARY BUFFER FIGSTR: .BYTE EXCL,CR,LF,0 ;CHARACTERS TO APPEND TO COMMAND .EVEN ; **** Remainder of this page implements processing of figures with ; special queue .IFF ;OLD FIGURE PROCESSING... ;chs78b- .ENABL LSB ;chs37 FIGUR:: CALL (R4) ;GET ARGUMENT MOV #1,R3 ;IF NONE, ASSUME ONE LINE .IF NZ FIGFIX ;chs37+ MOV R3,R2 ;CHECK FOR RATIONAL ARGUMENT ADD $HDRSW,R2 ; CONSIDERING HEADER LINES CMP R2,PNLPG ;WILL FIGURE FIT ON A PAGE? .IFF ;chs37- CMP R3,PNLPG ;CHECK FOR RATIONAL ARGUMENT .IFTF ;chs37 BLOS 10$ ;IF LOS OKAY ;chs37 5$: JMP ILCM ;ERROR 10$: .IFT ;chs37+ TSTNEB FIGTAB,40$ ;JUST ADD TO QUEUE IF ALREADY OCCUPIED FIGOUT::CLRB FIGTAB ;MAKE SURE QUEUE ENTRY AVAILABLE MOV R3,R0 ;COPY TO WORKING REGISTER ADD LINEC,R0 ;ADD ON CURRENT LINE COUNT CMP R0,NLPG ;ROOM ON PAGE? BHI 40$ ; NO, MUST WAIT MOV R3,R2 ; YES, SKIP THE LINES CALL SKIPN CMP LINEC,NLPG ;PAGE FULL? BLT 15$ ; NO, KEEP GOING MOV SP,$PGPSW ; YES, SIGNAL NEW PAGE 15$: MOV #FIGTAB,R0 ;CHECK FOR OTHER POSSIBLE REQUESTS TSTNEB (R0),30$ ;IF FIRST ENTRY EMPTY... MOV #FIGFIX-1,R1 ;...BUMP DOWN THE QUEUE 20$: MOVB 1(R0),(R0)+ SOB R1,20$ CLRB (R0) ;CLEAR LAST ENTRY 30$: MOVB (R0),R3 ;ANOTHER REQUEST PENDING? BEQ 70$ ; NO, ALL DONE TSTEQ $PGPSW,FIGOUT ; YES, NEED TO START NEW PAGE? CALL PAGEC ; YES, DO IT BR FIGOUT ;GO BACK FOR NEXT FIGURE ; REQUEST CAN'T BE PROCESSED NOW, PUT IT INTO THE QUEUE 40$: MOV #FIGTAB,R0 ;POINT TO QUEUE MOV #FIGFIX,R1 ;NUMBER OF ENTRIES 50$: TSTEQB (R0)+,60$ ;QUEUE LOCATION EMPTY? SOB R1,50$ ;CHECK ALL LOCATIONS JMP ILCM2 ;ILLEGAL COMMAND IN THIS CONTEXT 60$: MOVB R3,-(R0) ;PUT REQUEST IN QUEUE 70$: RETURN .DSABL LSB ; PROCESS ALL QUEUED REQUESTS FIGDMP::MOV R4,-(SP) ;SAVE REGISTER 10$: MOVB FIGTAB,R3 ;ANY OUTSTANDING FIGURE REQUESTS? BEQ 20$ ;QUIT IF NONE CALL FIGOUT ;PROCESS REQUEST(S) TSTEQB FIGTAB,20$ ;QUIT IF ALL FIGURES DONE CALL BPAGE ;START ANOTHER PAGE BR 10$ ;AND PROCESS MORE FIGURES 20$: MOV (SP)+,R4 ;RESTORE REGISTER RETURN .IFF ;chs37- MOV R3,-(SP) ;SAVE DESIRED SPACE CALL TESTP ;TEST IF PAGE SHOULD BE BROKEN MOV (SP)+,R2 ;GET BACK DESIRED SIZE JMP SKIPN ;SPACE THAT OUT .ENDC ; -NZ FIGFIX ;chs37 .ENDC ; -NZ BLKCMD ;chs78b ; BLOCK command ;chs78a+ .IF NZ BLKCMD .ENABL LSB BLOCK:: CALL (R4) ;GET NUMBER OF LINES 10$: JMP ILCM ;MUST BE ONE .IF NZ TXLTST ;chs78e+ CMPB R3,TXTLEN ;WILL THEY FIT ON A PAGE? .IFF ;chs78e- CMP R3,PNLPG ;VALUE REASONABLE? .ENDC ; -NZ TXLTST ;chs78e+ BHI 10$ ; NO, ERROR MOV R3,-(SP) ;SAVE FOR BELOW CALL (R4) ;GET LENGTH OF WHITE SPACE .IF NZ BLKSTK ;chs78f+ MOV BLKDFT,R3 ;USE DEFAULT MOV R3,BLKDFT ;SAVE AS NEW DEFAULT .IFF ;chs78f- MOV #BLKDFT,R3 ;USE DEFAULT .ENDC ; -NZ BLKSTK ;chs78f MOV R3,R1 ;COPY TO WORKING REGISTER SWAB R1 ;MOVE TO HIGH BYTE ADD (SP)+,R1 ;PUT BLOCK LENGTH IN LOW BYTE .IF NZ BLKALT ;chs78g+ MOV R1,-(SP) ;SAVE PARAMETERS CALL (R4) ;GET LENGTH OF ALTERNATE WHITE SPACE MOV #0,R3 ;USE DEFAULT MOVB R3,BLKALW ;SAVE FOR POSSIBLE USE MOV (SP)+,R1 ;RESTORE PARAMETERS .ENDC ; NZ BLKALT ;chs78g- BLOCK2: INCB BLKCNT ;COUNT THIS BLOCK CALL QUETXT ;PUT INPUT IN QUEUE (R1 HAS RECORD WORD) CMPB BLKCNT,#1 ;WAS THERE ALREADY A BLOCK IN THE QUEUE? .IF NZ BLKALT ;chs78g+ BGT 50$ ; YES, CAN'T OUTPUT THIS ONE .IFF ;chs78g- BGT QUEBRP ; YES, CAN'T OUTPUT THIS ONE .ENDC ; -NZ BLKALT ;chs78g INCB BLKNEW ; NO, SIGNAL PROCESSING NEW BLOCK BR 20$ ;TRY TO OUTPUT IT ; Routine to enable output of blocks ;chs88+ ; Invoked by ENABLE BLOCK .IF NZ ENADIS EN$BLK::MOVB #1,$BLKSW ;ENABLE BLOCK OUTPUT INCB BLKNEW ;ENABLE OUTPUT OF WHITE SPACE BR 15$ ;SEE IF ANY BLOCKS WILL FIT .ENDC ; NZ ENADIS ;chs88- ; BLKOUT subroutine ; Purpose: Output queued text block if possible ; On entry: BLKCNT = Number of blocks in queue ; BLKALL = Flag signaling dump all blocks ; BLKNEW = Flag to signal white space needed BLKOUT:: .IIF NZ ENADIS, TSTEQB $BLKSW,BLKSK3 ;SKIP IF OUTPUT DISABLED ;chs88 CLRB BLKNEW ;DISABLE WHITE SPACE .IF NZ BLKALT ;chs78g+ 15$: TSTEQB BLKCNT,50$ ;CONTINUE IF BLOCKS IN THE QUEUE .IFF ;chs78g- 15$: TSTNEB BLKCNT,20$ ;CONTINUE IF BLOCKS IN THE QUEUE CLRB BLKALL ;MAKE SURE "DUMP" FLAG CLEAR BR QUEBRP ;GO BURP QUEUE & RETURN TO CALLER .ENDC ; -NZ BLKALT ;chs78g 20$: MOV #1,R1 ;SET QUEUE RECORD TYPE CALL QUENXT ;GET DETAILS FOR NEXT RECORD MOV R1,@QTEMP ;PUT PARAMETERS BACK RIGHT AWAY ; (THEY'RE GOTTEN AGAIN BY "SAVSTA") MOV R1,R2 ;MAKE WORKING COPY MOVB R2,R3 ;EXTRACT LINE COUNT SWAB R2 MOVB R2,BLKWHT ; AND WHITE SPACE CMP $HDRSW,LINEC ;AT TOP OF PAGE? BGE 40$ ; YES, GO AHEAD & OUTPUT BLOCK ; NO, CHECK WHETHER IT FITS ADD LINEC,R3 ;HOW MANY LINES WOULD BLOCK MAKE TSTEQB BLKNEW,25$ ;IF NOT REAL-TIME BLOCK, ADD BLKWHT,R3 ; DON'T INCLUDE WHITE SPACE 25$: CMP R3,NLPG ;WILL IT FIT ON THIS PAGE BLE 30$ ; YES, PUT IT OUT ; NO, MAYBE START NEW PAGE .IF NZ BLKALT ;chs78g+ TSTEQB BLKALL,50$ ;BURP QUEUE & RETURN IF NOT DUMPING .IFF ;chs78g- TSTEQB BLKALL,QUEBRP ;BURP QUEUE & RETURN IF NOT DUMPING .ENDC ; -NZ BLKALT ;chs78g JMP BPAGE ; ELSE, START NEW PAGE ; Ready to output this block 30$: TSTEQB BLKNEW,40$ ;SKIP IF NOT REAL-TIME BLOCK CLRB BLKNEW ;RESET FLAG CALL BLKSKP ;OUTPUT WHITE SPACE 40$: MOV #BLKF,R2 ;SET TEMPORARY FLAG MOV NLPG,-(SP) ;SAVE CURRENT PAGE LENGTH ADD #100.,NLPG ;SET PAGE LENGTH LARGE .IIF NZ BLKALT, CLRB BLKALW ;ERASE ALTERNATE WHITE SPACE ;chs78g JMP SAVSTA ;SAVE STATE & PROCESS BLOCK ; THEN COME BACK TO "BLKEND" .IF NZ BLKALT ;chs78g+ 50$: CLRB BLKALL ;MAKE SURE "DUMP" FLAG CLEAR MOVB BLKALW,R2 ;GET ALTERNATE WHITE SPACE BEQ 60$ ;SKIP IF NONE CLRB BLKALW ;ERASE IT .IF NZ BLFIX ;chs96+ CALL SKIPNT ;OUTPUT BLANK LINES (MAYBE) .IFF ;chs96- CALL SKIPN ;OUTPUT BLANK LINES .ENDC ; -NZ BLFIX ;chs96 60$: BR QUEBRP ;BURP QUEUE & RETURN TO CALLER .ENDC ; NZ BLKALT ;chs78g- .DSABL LSB ; BLKEND subroutine ; Purpose: Finish up after queued text block has been output ; On entry: BLKCNT = Number of blocks in queue (incl. one just output) ; On exit: State restored to that before last block BLKEND::DECB BLKCNT ;REDUCE BLOCK COUNT INCB BLKACT ;SET FLAG JMP GETSTA ;RESTORE STATE BEFORE BLOCK ; AND RETURN TO HERE... BLKEN2::CLRB BLKACT ;CLEAR FLAG MOV (SP),NLPG ;RESTORE PREVIOUS PAGE LENGTH CMP LINEC,(SP)+ ;CHECK FOR CORRECT PAGE END BLT 10$ ;OKAY IF DIDN'T OVER FILL BEQ 5$ ;OR EXACT, BUT THEN SIGNAL NEW PAGE CALL $ERMSG ;OUTPUT ERROR MESSAGE ;chs84+ .WORD BLKERR,FNLONG ;chs84- 5$: MOV SP,$PGPSW ;SIGNAL NEW PAGE NEEDED 10$: CALL BLKSK2 ;OUTPUT BLANK LINES TSTNEB $GCISW,BLKOUT ;IF NOT REREADING FROM BUFFER... TSTNEB GCSCH,BLKOUT ;...AND IF REREAD BUFFER EMPTY... MOVB #LF,GCSCH ;...FAKE END OF LINE BR BLKOUT ;PROCESS NEXT BLOCK, IF ANY ; BLKSKP subroutine ; Purpose: Output blank lines to set block off from adjacent text ; Entry pts: BLKSKP => Break output first ; BLKSK2 => Don't break first ; On entry: BLKWHT = Number of blank lines to output BLKSKP::CALL OUTNJ ;OUTPUT LAST LINE BLKSK2: MOV BLKWHT,R2 ;GET LENGTH OF WHITE SPACE BEQ BLKSK3 ; SKIP IF NONE .IF NZ BLFIX ;chs96+ CALL SKIPNT ;SKIP LINES (MAYBE) MOV BLKWHT,SKPCNT ;SET LINE COUNT .IFF ;chs96- CALL SKIPN ;SKIP LINES .ENDC ; -NZ BLFIX ;chs96 BLKSK3: RETURN ; BLKDMP subroutine ; Purpose: Initiate output of all queued blocks ; On entry: BLKCNT = Number of blocks in queue ; On exit: Blocks all output to document ; Registers: R4 NOT changed; SP (miraculously) preserved BLKDMP::MOVB GCSCH,-(SP) ;SAVE REREAD CHARACTER MOV R4,-(SP) ;SAVE PTR TO CONVERSION ROUTINE MOV SP,QSAVE CALL 10$ ;PROCESS ALL QUEUED TEXT BLOCKS MOV (SP)+,R4 ;RESTORE PTR TO CONVERSION ROUTINE MOVB (SP)+,GCSCH ;RESTORE REREAD CHARACTER RETURN 10$: INCB BLKALL ;SET FLAG SIGNALING DUMP .IF NZ ENADIS ;chs88+ ;; BR EN$BLK ;ENABLE BLOCK OUTPUT & DO IT ;chs96 JMP EN$BLK ;ENABLE BLOCK OUTPUT & DO IT .IFF ;chs88- BR BLKOUT ;GO OUTPUT BLOCK .ENDC ; -NZ ENADIS ;chs88 .ENDC ; NZ BLKCMD ;chs78a- ; Subroutines for administering text queue ;chs78+ ; QUEBRP subroutine ; Purpose: Burp unused records from queue ; On entry: QSTART = Starting address of queue ; QEND = End address of queue ; On exit: Queue compressed ; QEND = Address of new end ; QTEMP changed ; Registers: None changed .IF NZ TXTQUE QUEBRP::MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) 10$: MOV QSTART,R2 ;POINT AT START OF QUEUE 20$: MOV R2,R3 MOV (R3),R2 ;GET FORWARD POINTER BEQ 50$ ;ALL DONE IF AT END OF QUEUE TST 2(R3) ;IS THIS RECORD EMPTY? BNE 20$ ; NO, SKIP TO NEXT RECORD ; Calculate length of unused record MOV R2,R1 ;POINTER TO NEXT RECORD SUB R3,R1 ;MINUS POINTER TO THIS RECORD ; Copy down next record 30$: MOV (R2)+,(R3) ;COPY DOWN FORWARD POINTER BEQ 10$ ;RESCAN QUEUE IF AT END SUB R1,(R3)+ ;ADJUST FORWARD POINTER FOR BURP MOV (R2)+,(R3)+ ;COPY DOWN RECORD TYPE MOV (R2),QTEMP ;SAVE END-OF-RECORD POINTER MOV (R2)+,(R3) ;COPY IT DOWN TO NEW POSITION SUB R1,(R3)+ ;ADJUST IT FOR BURP 40$: MOV (R2)+,(R3)+ ;COPY DOWN WORD OF RECORD TEXT CMP R2,QTEMP ;AT END YET? BLOS 40$ ; NO, CONTINUE COPYING BR 30$ ; YES, BUMP DOWN NEXT RECORD 50$: MOV R3,QEND ;SAVE POINTER TO END OF QUEUE MOV (SP)+,R3 MOV (SP)+,R2 MOV (SP)+,R1 JMP LINSET ;MAKE SURE LINE PARAMETERS ARE RIGHT ;; RETURN ; End of QUEBRP ; QUENEW subroutine ; Purpose: Setup pointers to store next queue record ; On entry: R1 = Record type ; QEND = Address of next available word in queue ; On exit: FOOTP1 & FOOTP2 = Pointers to text ; QTEMP = Address to receive pointer to ; Registers: R3 changed QUENEW::MOV QEND,R3 ;GET STORED POINTER TO RECORD MOV R3,-(SP) ;CHECK FOR OVERLAP OF INDEX ADD #10.,(SP) ; FROM ANTICIPATED GROWTH CMP (SP)+,XBOT ;WILL IT OVERLAP? BLO 10$ ; NO, CONTINUE CALL EXPAND ; YES, PUSH UP INDEX 10$: CLR (R3)+ ;MAKE SURE FORWARD POINTER CLEAR MOV R1,(R3)+ ;STORE RECORD TYPE MOV R3,QTEMP ;SAVE ADDRESS OF POINTER INC R3 ;POINT TO FIRST BYTE - 1 MOV R3,FOOTP1 ;SET WORKING POINTERS MOV R3,FOOTP2 RETURN ; End of QUENEW ; QUENXT subroutine ; Purpose: Setup pointers to read next (oldest) queue record ; On entry: R1 = Record type (-1 => footnote, >0 => block) ; On exit: C bit set if at end of queue ; R1 = Record-parameters word from queue ; FOOTP1 & FOOTP2 = Pointers to text ; QTEMP = Address of record-parm word for record returned ; Registers: R1 changed QUENXT::MOV R2,-(SP) MOV R3,-(SP) MOV QSTART,R3 ;POINT AT POINTER TO START OF QUEUE 10$: MOV (R3)+,R2 ;SAVE POINTER TO NEXT RECORD BEQ 40$ ; SKIP IF AT END OF QUEUE CMPEQB R1,(R3),30$ ;USE THIS RECORD IF RIGHT TYPE .IF NZ BLKCMD ;chs78a+ TST R1 ;LOOKING FOR BLOCK? BLE 20$ ; NO, THIS CAN'T BE ONE TST (R3) ;IS THIS RECORD A BLOCK? BGT 30$ ; YES, HAVE A MATCH 20$: .IFTF ;chs78a- MOV R2,R3 ;ELSE, POINT TO NEXT RECORD BR 10$ ; AND LOOK AT IT 30$: .IFT ;chs78a+ MOV (R3),R1 ;GET STORED RECORD TYPE MOV R3,QTEMP ;SAVE ADDRESS OF BLOCK PARMS WORD .ENDC ; NZ BLKCMD ;chs78a- CLR (R3)+ ;MARK RECORD AS UNUSED MOV (R3),FOOTP2 ;SET POINTER TO END OF TEXT INC R3 MOV R3,FOOTP1 ;...AND START OF TEXT - 1 BR 50$ ;TAKE NORMAL RETURN 40$: SEC ;INDICATE ERROR RETURN 50$: MOV (SP)+,R3 MOV (SP)+,R2 RETURN ; End of QUENXT .ENDC ; NZ TXTQUE ;chs78- ; REQUIRE and CHAIN commands ;chs99+ .IF NZ REQCMD ; When a REQUIRE command is encountered, a special FILO stack is used ; to save enough file data to be able to return to the interrupted ; file. The saved data consists of (in the order pushed): ; ; 1. High word of current virtual block number ; 2. Low word of current virtual block number ; 3. Number of the next byte within the block ; 4. File ID number ; 5. File sequence number ; 6. Third word of file ID (currently always 0) ; 7. Device mnemonic ; 8. Device unit number ; ; The number of files which can be suspended at one time (and thus ; saved on the stack) is set by the value of the assembly switch ; REQCMD (defined in RNPRE.MAC). If changed, only the module DATA.MAC ; needs to be reassembled (and the task rebuilt). ; ; The CHAIN command simply closes the current input file and opens the ; specified file for subsequent input. .IF NZ CHNCMD ;chs99a+ .ENABL LSB CHAIN:: MOV SP,CHNFLG ;SET FLAG INDICATING CHAIN COMMAND BR 5$ REQUIR::CLR CHNFLG ;CLEAR CHAIN FLAG 5$: .DSABL LSB .IFF ;chs99a- REQUIR:: .ENDC ; NZ CHNCMD ;chs99a CALL SKPWHT ;IGNORE WHITE SPACE CMPNEB #CR,R1,20$ ;CONTINUE IF NOT AT EOL 10$: JMP ILCM ; ELSE ERROR 20$: MOV #INBUF,R2 ;POINT AT START OF RECORD BUFFER BR 35$ 30$: CALL CCIN ;READ A CHARACTER FROM INPUT CMPEQB #CR,R1,40$ ;DONE WHEN AT EOL 35$: MOVB R1,(R2)+ ;PUT CHARACTER INTO BUFFER BR 30$ ;LOOP FOR NEXT CHARACTER 40$: SUB #INBUF,R2 ;COMPUTE STRING LENGTH .IIF NZ CHNCMD, TSTNE CHNFLG,55$ ;SKIP IF CHAIN COMMAND ;chs99a MOV REQSP,R4 ;GET SPECIAL STACK POINTER CMP R4,#REQEND ;STACK FULL? BLO 50$ ; NO, CONTINUE CALL $ERMSG ; YES, DISPLAY ERROR .WORD REQWRD,REQERR BR 120$ ;AND CONTINUE WITH OLD INPUT FILE 50$: MOV R2,-(SP) ;SAVE STRING LENGTH FOR A WHILE MOV #TTLDMY,R0 ;POINT AT INPUT FDB CALL .MARK ;RECORD POSITION IN FILE MOV R1,(R4)+ ;SAVE ON STACK MOV R2,(R4)+ MOV R3,(R4)+ MOV #TTLDMY+F.FNB+N.FID,R1 ;POINT AT FILE ID NUMBERS MOV (R1)+,(R4)+ ;SAVE FILE ID ON STACK MOV (R1)+,(R4)+ MOV (R1)+,(R4)+ MOV F.FNB+N.DVNM(R0),(R4)+ ;SAVE DEVICE MNEMONIC MOV F.FNB+N.UNIT(R0),(R4)+ ;SAVE UNIT NUMBER MOV (SP)+,R2 ;GET STRING LENGTH 55$: CSI$1 #CSIBLK,#INBUF,R2 ;CHECK SYNTAX BCS 10$ CSI$2 ,OUTPUT ;GET AN "OUTPUT" SPECIFICATION BCS 10$ CLOSE$ #TTLDMY ;CLOSE THE CURRENT INPUT FILE OPEN$R ,,#CSIBLK+C.DSDS ;OPEN NEW INPUT FILE BCC 60$ ;CONTINUE IF OKAY CALL $ERMSG ; ELSE OUTPUT ERROR .WORD REQWRD,REQOPN .IF NZ CHNCMD ;chs99a+ TSTEQ CHNFLG,100$ ;REOPEN LAST INPUT FILE IF REQUIRE CMD JMP ENDFIL ; ELSE QUIT .IFF ;chs99a- BR 100$ ;REOPEN LAST INPUT FILE .ENDC ; -NZ CHNCMD ;chs99a 60$: .IIF NZ CHNCMD, TSTNE CHNFLG,120$ ;DONE IF CHAIN COMMAND ;chs99a ; Make sure we're not getting into a recursive loop MOV R4,R3 ;COPY STACK POINTER 70$: CMPNE TTLDMY+F.FNB+N.FID,-12(R3),80$ ;OKAY IF NEW FILE ID DIFFERENT CMPNE TTLDMY+F.FNB+N.DVNM,-4(R3),80$ ;OKAY IF NEW DEVICE DIFFERENT CMPEQ TTLDMY+F.FNB+N.UNIT,-2(R3),90$ ;ERROR IF NEW UNIT SAME 80$: SUB #16.,R3 ;MOVE POINTER TO PREVIOUS DATA CMP R3,#REQSTK ;BEYOND STACK? BHI 70$ ; NO, CHECK NEXT ENTRY BR 110$ ; YES, NO DUPLICATION 90$: CALL $ERMSG ;OUTPUT RECURSION ERROR .WORD REQWRD,REQLOP 100$: MOV R4,REQSP ;SAVE STACK POINTER BR REQRET ; AND REOPEN LAST FILE ; Everything is okay; record the branch 110$: MOV R4,REQSP ;SAVE STACK POINTER 120$: RETURN ; EOF encountered in secondary file--return to previous file REQRET::MOV REQSP,R4 ;GET STACK POINTER 10$: MOV #TTLDMY,R0 ;POINT TO INPUT FB CLOSE$ ;CLOSE THE FILE MOV -(R4),F.FNB+N.UNIT(R0) ;RESTORE UNIT NUMBER MOV -(R4),F.FNB+N.DVNM(R0) ;RESTORE DEVICE MNEMONIC MOV #TTLDMY+F.FNB+N.FID+6,R1 ;POINT AT FILE ID NUMBERS + 2 MOV -(R4),-(R1) ;RESTORE FILE ID MOV -(R4),-(R1) MOV -(R4),-(R1) OFID$R R0 ;OPEN PREVIOUS INPUT FILE BCC 20$ ;CONTINUE IF OKAY CALL $ERMSG ; ELSE OUTPUT ERROR .WORD REQWRD,REQOPN SUB #6,R4 ;SKIP REST OF STACK ENTRY CMP R4,#REQSTK ;IS THERE A PREVIOUS FILE? BHI 10$ ; YES, GO BACK TO IT (MUST RESET R0) JMP ENDFIL ; NO, QUIT COMPLETELY 20$: MOV -(R4),R3 ;RESTORE POSITION POINTERS MOV -(R4),R2 MOV -(R4),R1 CALL .POINT ;MOVE TO RIGHT POSITION MOV R4,REQSP ;SAVE STACK POINTER RETURN .ENDC ; NZ REQCMD ;chs99- .IIF NZ CHNCMD, CHNFLG: .BLKW 1 ;FLAG FOR CHAIN COMMAND ;chs99a .END