.TITLE RNRT11 .IDENT "V1.6" ; 13-May-81 .ENABL GBL .ENABL LC .NLIST TOC ; *********************** ; * R N R T 1 1 . M A C * ; *********************** ; ; This source module contains most of the RT-11 system dependent code for ; RUNOFF. It was written "after the fact" as part of a package of changes ; to allow the addition of RT-11 support. In the RSX/IAS/RSTS version, there ; were several modules which were totally system dependent, those which ; handled the file & terminal I/O and the command string and switch logic. ; The RUNOFF.MAC module was almost system independent. I simply conditionaled ; out the dependencies, collecting them all into this module. None of the ; other modules were changed in any way from the "M02" version. Input file ; EOF condition had to be handled in a bizarre way. See the comments for ; the RBUF routine herein. ; ; This module must be assembled with my structured macro library SMAC.MAC: ; .MACRO SMAC/LIB+RNRT11/LIS/OBJ ; The sources and the macro library image are included with the RT-11 ; RUNOFF distribution. ; ; Written by: Bob Denny, dba ; Creative System Design Co. ; 3452 E. Foothill Blvd. Suite 601 ; Pasadena, CA 91107 ; ; Revision Log: ; X1.0 29-May-80 Initial Experimental Version ; X1.1 31-May-80 Add page range and wait for page ; Y1.2 1-Jun-80 Add version number switch. ; V1.3 1-Jun-80 Fix EOF on input file bug. Release. ; V1.4 11-Oct-80 Eliminate formfeed on startup. ; V1.5 15-Oct-80 Fix recursive death bug ; V1.6 13-May-81 Change banner for M02.3 (hyphen fix) ; ;----------------------------------------------------------------------------- .MCALL .GVAL .SETTOP .LOCK .LOOKUP .ENTER .CLOSE .MCALL .READW .WRITW .PRINT .TTYIN .TTINR .TTYOUT .MCALL .SRESET .CSIGEN ; ; Initialize Structured Programming Macros ; .MCALL SMACS SMACS ;THIS SETS THE REST UP ; ; Constant Parameters ; OUTCH = 0 ;OUTPUT FILE CHANNEL INCH = 3 ;INPUT FILE CHANNEL JSW = 44 ;JOB STATUS WORD ERRBYT = 52 ;ADDRESS OF SYSTEM ERROR FLAG BYTE USRLOC = 266 ;OFFSET TO USR LOAD POINT .SBTTL RT-11 Data Base ; ; File I/O buffers. ; Descriptors are 3 words: Buffer capacity (bytes), character pointer ; and room or bytes left in buffer. ; INBUF:: .BLKB 512. ;INPUT BLOCK BUFFER HFIN:: .WORD 512.,0,0 ;INBUF DESCRIPTOR IBLK: .BLKW 1 ;BLOCK-IN-FILE OUBUF:: .BLKB 512. ;OUTPUT BLOCK BUFFER HFOUT:: .WORD 512.,0,0 ;OUTBUF DESCRIPTOR OBLK: .BLKW 1 ;BLOCK-IN-FILE ; ; Default extensions ; DEFEXT: .RAD50 "RNO" ;INPUT FILE DEFAULT EXT. .RAD50 "DOC" ;OUTPUT FILE DEFAULT EXT. .WORD 0,0 ; ; Misc. storage ; SPSAV:: .BLKW 1 ;INITIAL STACK POINTER SAVE CELL ULSWT:: .BLKB 2 ;BUFFER FOR UNDERLINE SWITCH .LIMIT ;GET VIRTUAL ADDRESS LIMITS DSPACE = . - 2 ;HANDLER LOAD POINT. HI VIRTUAL ADDRESS. FREE: .WORD DSPACE ;START OF FREE SPACE ABOVE HANDLERS OPTCNT: .BLKW 1 ;# OPTIONS ON STACK FROM CSI PRB: .BLKW 10 ;PROG. REQUEST PARAMETER PASSING AREA EFLAG: .BLKW 1 ;ENDFILE FLAG ; ; Switch action dispatch table ; SWTBL: .WORD 'B, BEGPG ;BEGINNING PAGE # TO PRINT .WORD 'E, ENDPG ;ENDING PAGE TO PRINT .WORD 'F, FFCTRL ;FORMFEED CONTROL .WORD 'H, HYCTRL ;HYPHENATION CONTROL .WORD 'I, INFO ;DISPLAY INFO .WORD 'U, ULCTRL ;UNDERLINE CONTROL .WORD 'V, VERSIO ;DISPLAY VERSION NUMBER .WORD 'W, WAITSW ;WAIT BETWEEN PAGES .WORD 0 ; -- END -- ; ; Switch status word (global) ; $SWTCH:: .WORD 0 ;(BITS DEFINED IN RUNOFF.MAC) ; ; Messages. ; .PSECT STRING RW, D, GBL, REL, CON .NLIST BEX BVLMSG: .ASCII "Bad value with /" BADVAL: .BYTE '? ;ACTUAL SWITCH CHARACTER GOES HERE .ASCIZ " switch." BSWMSG: .ASCII "Bad switch /" BADSWT: .BYTE '?, 0 ;ACTUAL SWITCH CHARACTER GOES HERE WREMSG: .ASCIZ "RNO -- ERROR ON OUTPUT FILE" RDEMSG: .ASCIZ "RNO -- ERROR ON INPUT FILE" VERMSG: .ASCIZ "RUNOFF/RT-11 Version M02.3 May 1981 /I for Info" INFMSG: .ASCII "outfile.{DOC} = infile.{RNO}"<15><12><12> .ASCII "Switches:" <15><12><12> .ASCII <11>"/B:n" <11>"Start printing with page n"<15><12> .ASCII <11>"/E:n" <11>"Stop printing on page n"<15><12><12> .ASCII <11>"/F" <11>"Simulate FF's with 66 lines/page"<15><12> .ASCII <11>"/F:n" <11>"Simulate FF's with n lines/page"<15><12><12> .ASCII <11>"/H:NO" <11>"Disable hyphenation"<15><12> .ASCII <11>"/H:YES"<11>"Enable hyphenation (default)"<15><12><12> .ASCII <11>"/I" <11>"Display useage information"<15><12><12> .ASCII <11>"/U:B" <11>"Underline with space-backspace"<15><12> .ASCII <11>"/U:L" <11>"Use overprint-underscore (default)"<15><12> .ASCII <11>"/U:N" <11>"Supress underlining"<15><12> .ASCII <11>"/U:S" <11>"Simulate with hyphen on next line"<15><12><12> .ASCII <11>"/V" <11>"Display version of this program"<15><12><12> .ASCIZ <11>"/W" <11>"Wait for between pages" .EVEN .LIST BEX .PSECT .SBTTL STARTUP & RESTART ; ; Cold start point ; $START:: MOV SP,SPSAV ;SAVE INITIAL SP .GVAL #PRB,#USRLOC ;R0 --> 1ST WORD OF USR TST -(R0) ;R0 --> LAST USEABLE CELL .SETTOP ;REQUEST ALL EXCEPT USR AREA MOV R0,XTOP ;REMEMBER WHAT WE GOT FOR TOP CELL .LOCK ;LOCK IN THE USR .PRINT #VERMSG ;TELL USER WHO WE ARE ; ; Restart Point ; RUNOFF:: MOV SPSAV,SP ;RESET THE SP .SRESET ;CLEAN UP THE CHANNELS CLR EFLAG ;RESET EOF FLAG BIS #100,@#JSW ;ALLOW .TTINR TO FUNCTION IN FB/XM MOV DSPACE,FREE ;RECLAIM HANDLER SPACE .CSIGEN DSPACE, #DEFEXT, #0 ;GET & PARSE CMD STRING MOV R0,FREE ;ADJUST FREE TO TOP OF HANDLERS MOV (SP)+,OPTCNT ;POP OPTION COUNT .LOCK ;RELOCK USR FOR F/B (AFTER .CSIGEN) CALL $INITL ;LET RUNOFF INITIALIZE & SET DEFAULTS BIS #FFDSW,$SWTCH ;ALSO DEFAULT HARDWARE FORMFEEDS MOV PNLPG,NLPG ;INITIALIZE CURRENT LINES/PAGE ;V1.5 ; ; Process the switches. Action routines decrement OPTCNT, then JMP to SWPROC. ; SWPROC: TST OPTCNT ;ANY (MORE) SWITCHES? BEQ IOINIT ;IF EQ, NO, GO INITIALIZE I/O NEXT MOV #SWTBL,R5 ;R5 --> SWITCH ACTION DISPATCH TABLE MOV (SP)+,R4 ;POP SWITCH INTO R4 .LOOP. ;STEP THROUGH THE DISPATCH TABLE CMPB R4,(R5) ;COMPARE SWITCH WITH TABLE .IF. EQ ;IF IT MATCHES... JMP @2(R5) ;...JUMP TO THE ACTION ROUTINE .ELSE. ;IF NO MATCH... ADD #4,R5 ;...STEP TO THE NEXT TABLE NODE .END. TST (R5) ;LAST NODE IN THE TABLE IS NULL .UNTL. EQ MOVB (SP),BADSWT ;NO MATCH, BAD SWITCH .PRINT #BSWMSG ;INFORM THE USER BR RUNOFF ;RESTART .SBTTL SWITCH ACTION ROUTINES ; ; Set beginning page to print. ; BEGPG: TST R4 ;WAS A VALUE GIVEN? BPL SVERR ;IF NOT, ERROR. MOV (SP)+,LOWPAG ;OK, POP VALUE INTO RUNOFF'S VARIABLE BR NEXT ;TRY FOR NEXT SWITCH ; ; Set ending page to print. ; ENDPG: TST R4 ;WAS A VALUE GIVEN? BPL SVERR ;IF NOT, ERROR. MOV (SP)+,HGHPAG ;OK, POP VALUE INTO RUNOFF'S VARIABLE BR NEXT ;TRY FOR NEXT SWITCH ; ; Formfeed simulation. Optional value sets hardware lines per page. ; Default lines per page = 66. ; FFCTRL: BIC #FFDSW,$SWTCH ;TURN ON FF SIMULATION FLAG (0=YES) TST R4 ;WAS A VALUE GIVEN? .IF. MI ;IF SO ... MOV (SP)+,LPPG ; ... PASS IT TO RUNOFF'S VARIABLE .ELSE. ;OTHERWISE ... MOV #66.,LPPG ; ... DEFAULT TO 66(10) LINES. .END. BR NEXT ;TRY FOR NEXT SWITCH ; ; Hyphenation control. /H:YES (default) enables hyphenation. ; /H:NO disables hyphenation. ; HYCTRL: TST R4 ;WAS A VALUE GIVEN? BPL SVERR ;IF NOT, ERROR. CMP (SP),#^RNO ;DID HE SAY /H:NO ? .IF. EQ ;IF SO ... BIC #HYPSW,$SWTCH ; ... TURN OFF HYPHENATION FLAG, TST (SP)+ ; POP THE VALUE .ELSE. ;IF NOT ... CMP (SP)+,#^RYES ; DID HE SAY YES? (POP) BNE SVERR ; IF NOT, ERROR. .END. BR NEXT ;TRY FOR NEXT SWITCH ; ; Display helpful information. Re-prompt. ; INFO: .PRINT #INFMSG ;PRINT THE MESSAGE JMP RUNOFF ;RESTART ; ; Underline Control. /U:B - Use spacing-backspace (LA-36 DECwriter) ; /U:L - Use overprint with underscore (default) ; /U:N - Supress underlining ; /U:S - Simulate with hyphen on next line ; ULCTRL: TST R4 ;WAS A VALUE GIVEN? BPL SVERR ;IF NOT, ERROR. CMP (SP),#^RB ;B VALUE? .IF. EQ ;IF SO, COMB $ULMSW ;SET THE FLAG .ELSE. CMP (SP),#^RN ;N VALUE? .IF. EQ ;IF SO, COMB $ULNSW ;SET THE FLAG .ELSE. CMP (SP),#^RS ;S VALUE GIVEN? .IF. EQ ;IF SO, COMB $ULSSW ;SET THE FLAG .ELSE. CMP (SP),#^RL ;L VALUE GIVEN? BNE SVERRP ;IF NOT, ILLEGAL VALUE,ERROR. .END. .END. .END. TST (SP)+ ;POP VALUE BR NEXT ; ; Display Version Number. Re-prompt. ; VERSIO: .PRINT #VERMSG ;PRINT THE MESSAGE JMP RUNOFF ;RESTART ; ; Wait between pages. /W ; WAITSW: BIS #PAUSW,$SWTCH ;TURN ON THE FLAG BR NEXT ;TRY FOR ANOTHER SWITCH ; ; Common switch value error handler. ; SVERRP: TST (SP)+ ;POP VALUE SVERR: MOVB R4,BADVAL ;INDICATE WHICH SWITCH HAD THE BADDIE .PRINT #BVLMSG ;INFORM USER JMP RUNOFF ;RESTART ; ; Get set to process the next switch on the stack. ; NEXT: DEC OPTCNT ;COUNT DOWN REMAINING SWITCHES BR SWPROC ;TRY FOR ANOTHER SWITCH .SBTTL FINAL INITIALIZATION AND RUN ; ; Open input and output files. (Channels are already open via CSI) ; IOINIT: MOV SPSAV,SP ;RESET STACK AFTER CSI CLR IBLK ;START INPUT FILE AT BLOCK 0 CLR HFIN+4 ;MARK INPUT BUFFER EMPTY CLR OBLK ;START OUTPUT FILE AT BLOCK 0 MOV HFOUT,HFOUT+4 ;MARK OUTPUT BUFFER EMPTY MOV #OUBUF,HFOUT+2 ;POINT TO 1ST CELL IN BUFFER ; ; Initialize dynamic memory. ; MOV XTOP,XBOT ;INITIALIZE INDEX POINTER MOV FREE,FOOTP1 ;AND THE FOOTNOTE AREA POINTERS MOV FREE,FOOTP2 MOV FREE,FOOTP3 CALL LINSET ;SET UP FOR LINE ;;;;; CALL FFEED ;START AT TOP OF FORM ;V1.4 CALL OPRWAT ;WAIT FOR OPERATOR IF NECESSARY ; ; Enter RUNOFF's main loop ; JMP LGO ; ; Clean up after this run, closing files, and restart. ; ENDFIL:: CALL FLUSH ;FLUSH THE OUTPUT BUFFER .CLOSE #INCH ;CLOSE FILES .CLOSE #OUTCH JMP RUNOFF ;RESTART .SBTTL I/O SUBROUTINES ; ; Routines called by RUNOFF (global) ; FOUT:: ;BUFFER THE CHAR IN R1 CMP PAGENO,LOWPAG ;SHOULD THIS PAGE BE PRINTED? BLO 10$ ;IF NOT, THIS CALL WAS A NO-OP CMP PAGENO,HGHPAG ;ARE WE DONE? BHI ENDFIL ;IF SO, JUST WRAP IT UP. ;(SORRY ABOUT THE TIME THIS TAKES) MOVB R1,@HFOUT+2 ;OK, PLACE IT IN THE BUFFER INC HFOUT+2 ;BUMP THE BUFFER POINTER DEC HFOUT+4 ;DECREMENT THE 'ROOM LEFT' COUNTER BNE 10$ ;IF THERE'S ROOM, JUST RETURN JMP WBUF ;ELSE, WRITE IT AND RETURN FROM THERE 10$: RETURN FMSG:: ;S1 --> STRING TO BUFFER MOVB @S1,R1 ;GET A CHARACTER INTO R1 BEQ 10$ ;NULL MARKS END OF STRING CALL FOUT ;BUFFER IT INC S1 ;BUMP INPUT STRING POINTER BR FMSG ;DO ANOTHER CHARACTER 10$: RETURN CRLF:: ;BUFFER A CR/LF COMBO MOV #CR,R1 ;DO THE CR CALL FOUT MOV #LF,R1 ;AND THE LF CALL FOUT RETURN FIN:: ;GET AN INPUT CHARACTER INTO R1 DEC HFIN+4 ;ANYTHING IN THE BUFFER? BGT 10$ ;BRANCH IF YES CALL RBUF ;ELSE GET ANOTHER BUFFER LOAD 10$: INC HFIN+2 ;POINT TO NEXT CHARACTER MOVB @HFIN+2,R1 ;GET IT BIC #^C<177>,R1 ;STRIP PARITY BEQ FIN ;IGNORE NULLS CMP R1,#177 ;AND RUBOUTS BEQ FIN RETURN ; ; These simulate DEC-10 TTCALLS, whatever they are. I just imitated the ; code in the RNFIO module. TTC3 is used only by $ERMSG, it assumes that ; it has been CALLed with the string address following the JSR PC,. ; TTC4N was only used by OPRWAT. RT-11's OPRWAT uses .TTYIN. ; TTC33 was used to flush out the TT buffer. It's now just a no op. ; There is a race condition in RT-11 V3B between .PRINT and .TTYOUT, so I ; have not used .PRINT. ; TTC3:: PUSH R1 ;SAVE R1 MOV @2(SP),R1 ;R1 --> ERROR MESSAGE STRING ADD #2,2(SP) ;SKIP OVER STRING ADDRESS PUSH R0 ;SAVE R0 5$: MOVB (R1)+,R0 ;GET A CHARACTER BEQ 10$ ;NULL MEANS FINISH WITH CR/LF CMPB R0,#200 ;<200> MEANS WE'RE DONE BEQ 20$ .TTYOUT ;SEND IT BR 5$ ;TRY FOR ANOTHER 10$: .TTYOUT #CR ;SEND CR/LF .TTYOUT #LF 20$: POP R0 ;RESTORE R0 POP R1 ;AND R1 RETURN TTC1:: PUSH R0 ;SAVE R0 .TTYOUT R1 ;TRANSMIT CHAR IN R1 TO TT: POP R0 ;RESTORE R0 TTC33:: OUTPUT:: ;THIS IS A NO OP TOO RETURN ;TTC1 TRANSMITS DIRECTLY TO TERMINAL ; ; Routine to wait for operator to type if the flag was set. ; OPRWAT:: BIT #PAUSW,$SWTCH ;IS THE PAUSE-BETWEEN-PAGES FLAG SET? BEQ 10$ ;IF NOT, JUST RETURN CALL FLUSH ;IF SO, FLUSH THE OUTPUT BUFFER BIS #10000,@#JSW ;READ WITH NO ECHO .TTYIN ;WAIT TILL HE TYPES SOMETHING 5$: .TTINR ;CLEAN OUT ANYTHING ELSE IN TT BUFFER BCC 5$ BIC #10000,@#JSW ;BACK TO NORMAL TT MODE. 10$: RETURN .SBTTL INTERNAL BLOCK I/O ROUTINES ; ; Read a block and reset the buffer parameters. RUNOFF looks for ctrl-Z ; to detect EOF. RT-11 doesn't work that way. To make a long story short, ; RUNOFF gets a buffer with when the physical end of file ; is detected during .READW. RBUF still gets called again, so the 2nd ; call (now EFLAG is set) after EOF forces a jump to ENDFILE to close out ; and restart properly. Unless things are done this way, the last line ; of output is lost. ; RBUF: TST EFLAG ;BEEN HERE WITH EOF YET? BEQ 5$ ;NO, GO ON JMP ENDFIL ;YES, THAT'S IT. CLOSE OUT. 5$: PUSH R0 ;SAVE R0 .READW #PRB,#INCH,#INBUF,#256.,IBLK ;READ A BLOCK BCC 10$ ;BRANCH IF READ OK TSTB @#ERRBYT ;WAS IT AN EOF? BNE 20$ ;IF NOT, ERROR INC EFLAG ;INDICATE WE'VE BEEN HERE ONCE MOVB #CR,INBUF ;SET UP STOPPER MOVB #LF,INBUF+1 MOVB #EOF,INBUF+2 ;AND A ^Z (EOF) MOV #3,HFIN+4 ;MARK IT ONLY 3 CHAR'S BR 15$ 10$: MOV HFIN,HFIN+4 ;RESET BUFFER DESCRIPTORS 15$: MOV #INBUF-1,HFIN+2 INC IBLK ;BUMP BLOCK NUMBER POP R0 ;RESTORE R0 RETURN 20$: .PRINT #RDEMSG ;ELSE, TELL USER OF TROUBLE JMP RUNOFF ;RESTART ; ; Write a block and reset the buffer parameters. ; WBUF: PUSH R0 ;SAVE R0 .WRITW #PRB,#OUTCH,#OUBUF,#256.,OBLK ;WRITE THE BLOCK BCC 10$ ;BRANCH IF WRITE OK .PRINT #WREMSG ;TELL USER OF TROUBLE JMP RUNOFF ;RESTART 10$: MOV #OUBUF,HFOUT+2 ;RESET BUFFER DESCRIPTORS MOV HFOUT,HFOUT+4 INC OBLK ;BUMP BLOCK NUMBER POP R0 ;RESTORE R0 RETURN ; ; Fill out the buffer with nulls and write it out. ; FLUSH: CMP HFOUT,HFOUT+4 ;IS THE BUFFER COMPLETELY EMPTY? BEQ 20$ ;IF SO, DON'T DO ANYTHING MORE 10$: CLRB @HFOUT+2 ;IF NOT, FILL IT WITH NULLS INC HFOUT+2 DEC HFOUT+4 BGT 10$ ;LOOP TILL FULL BR WBUF ;WRITE IT OUT AND RETURN TO CALLER 20$: RETURN .END