.TITLE GETPUT - RECORD I/O FOR TECOIO .IDENT "X0203" ; ANDREW C. GOLDSTEIN 12-FEB-78 22:30 .MCALL GET$,PUT$ .SBTTL GETBUF -- GET BUFFER FROM INPUT ;+ ; ; *** - GETBUF GET BUFFER FROM INPUT ; ; THIS ROUTINE READS THE INPUT FILE INTO THE TEXT BUFFER. WHEN CALLED, ; IT READS UNTIL EITHER: ; ; 1) THE BUFFER IS NEARLY FULL. ; 2) A FORM FEED IS ENCOUNTERED. ; 3) END OF FILE IS ENCOUNTERED. ; ; INPUTS: ; ; R0 = POINTER TO AREA TO READ INTO ; R1 = BUFFER SPACE AVAILABLE (BYTES) ; R2 = AMOUNT OF SPACE TO LEAVE FREE ; ; OUTPUTS: ; ; EOFLAG(R5) = -1 IF END OF FILE WAS REACHED ; = 0 OTHERWISE ; FFFLAG(R5) = -1 IF READ TERMINATED WITH A FORM FEED ; = 0 OTHERWISE ; ZZ(R5) = UPDATED END OF BUFFER ; ; GETBUF READS STANDARD RSX VARIABLE LENGTH RECORDS FROM THE INPUT ; FILE. IF THE FILE HAS EITHER IMPLIED OR FORTRAN CARRIAGE CONTROL, ; CARRIAGE RETURN AND LINE FEED ARE INSERTED INTO THE BUFFER AFTER ; EACH RECORD. THE EXCEPTION TO THIS IS A RECORD CONTAINING A SOLITARY ; FORM FEED. IF IT IS ENCOUNTERED IT IS NOT ENTERED INTO THE BUFFER AND THE ; READ IS TERMINATED. AFTER EACH RECORD HAS BEEN READ, IF THERE ARE ; FEWER THAN R2 CHARACTERS IN THE BUFFER, THE READ IS ALSO TERMINATED. ; ;- .PSECT CODE,RO,I .ENABL LSB GETBUF:: SAVE TST INFDB+F.BDB ; TEST FOR OPEN FILE AVAILABLE. BNE 10$ ERROR NFI,<"No file for input"> 10$: CLR FFFLAG(R5) ; CLEAR FORM FEED FLAG FOR RETURN MOV R1,R4 ; COPY AVAILABLE SPACE SIZE MOV #INFDB,R0 ; GET FDB POINTER CALL .MARK ; SAVE INPUT FILE POSITION MOV R3,-(SP) ; STASH AWAY R3 MOV SR0+2(SP),R3 ; GET THE WORKING BUFFER POINTER ; HERE TO GET NEXT INPUT RECORD MOVED INTO TECO'S TEXT BUFFER. NEXREC: SUB #2,R4 ; LEAVE ROOM FOR CR/LF GET$ R0,R3,R4 ; GET THE RECORD BCS INERR ; SOME INPUT ERROR. CMPB (R3),#FF ; WAS FIRST CHAR OF RECORD A FF ? BNE 20$ ; IF SO, THIS MIGHT END THE BUFFER. CMP F.NRBD(R0),#1 ; WAS IT A ONE CHARACTER RECORD ? BEQ 50$ ; IF NOT, DON'T TREAT AS FORM FEED. 20$: ADD F.NRBD(R0),R3 ; INCREMENT THE CHARACTER POINTER SUB F.NRBD(R0),R4 ; DECREMENT SPACE COUNT. BITB F.RATT(R0),#FD.CR!FD.FTN ; CHECK FOR IMPLIED OR FORTRAN CCL BEQ 30$ ; NEITHER MOVB #CR,(R3)+ ; INSERT CARRIAGE RETURN MOVB #LF,(R3)+ ; AND LINE FEED BR 40$ 30$: ADD #2,R4 ; CR-LF ALREADY PRESENT - PUT BACK THE SPACE 40$: CMP R4,SR2+2(SP) ; SEE HOW MUCH SPACE IS LEFT BLO IBFDON ; IF LESS THAN THRESHOLD, QUIT BR NEXREC ; GET NEXT RECORD. ; FORM FEED ENCOUNTERED IN INPUT 50$: DEC FFFLAG(R5) ; SET FF FLAG ; END OF INPUT: EITHER WE HIT A FORM FEED OR END OF FILE, OR THE BUFFER ; IS FULL. COMPUTE NUMBER OF CHARACTERS READ AND RETURN. IBFDON: SUB TXSTOR(R5),R3 ; COMPUTE TOTAL BYTE COUNT IN BUFFER MOV R3,ZZ(R5) ; SET NEW END OF BUFFER TST (SP)+ ; CLEAN THE STACK RETURN ; TO HERE ON RANDOM INPUT ERRORS. INERR: MOV F.ERR(R0),R4 ; PICK UP ERROR CODE CMPB R4,#IE.EOF ; SEE IF WE HIT END OF FILE BNE 70$ ; IF NOT, GET OUT 60$: MOV #-1,EOFLAG(R5) ; YES - SET END OF FILE FLAG BR IBFDON ; AND EXIT 70$: BITB #FA.SHR,F.FACC(R0) ; SEE IF FILE IS OPEN SHARED BNE 60$ ; BRANCH IF YES - IGNORE ALL ERRORS MOV (SP)+,R3 ; RESTORE R4 FROM MARK CALL .POINT ; RESTORE FILE POSITION TO ALLOW RECOVERY MOV R4,F.ERR(R0) ; RESTORE ERROR CODE JMP FDBERR ; AND REPORT ERROR .DSABL LSB .SBTTL PUTBUF -- PUT BUFFER IN OUTPUT FILE ;+ ; ; *** - PUTBUF PUT BUFFER IN OUTPUT FILE ; ; THIS ROUTINE OUTPUTS THE DESIGNATED PORTION OF THE BUFFER TO ; THE OUTPUT FILE CURRENTLY OPEN. THE BUFFER IS SEARCHED FOR ; CARRIAGE RETURN - LINE FEED PAIRS, WHICH ARE TAKEN TO BE ; RECORD DELIMITERS. IF THE FILE HAS NULL CARRIAGE CONTROL, THE ; CR-LF PAIRS ARE OUTPUT WITH THE RECORDS; OTHERWISE THEY ARE STRIPPED ; OFF. ANY FORM FEEDS ENCOUNTERED IN THE BUFFER ARE OUTPUT AS A SINGLE ; FORM FEED RECORD. ; ; INPUTS: ; ; R0 = POINTER TO START OF BUFFER ; R1 = NUMBER OF CHARACTERS TO OUTPUT ; R2 = -1 IF A FORM FEED IS TO BE APPENDED TO THE OUTPUT ; 0 IF OUTPUT IS TO BE DONE AS IS ; ; OUTPUTS: ; ; NONE ; ; ALL REGISTERS ARE PRESERVED. ; ;- .ENABL LSB PUTBUF:: SAVE TST OUTFDB+F.BDB ; IS THERE OPEN OUTPUT FILE? BNE 10$ ; IF YES, PROCEED ERROR NFO,<"No file for output"> 10$: MOV R0,R2 ; USE FOR POINTER TO GET CHARACTERS FROM BUFFER MOV R2,R4 ; SETUP INITIAL RECORD STARTING POINT. MOV R5,-(SP) ; ALSO SAVE R5 MOV #OUTFDB,R0 ; SET UP FDB ADDRESS CHRSCN: CLR R3 ; ZERO PREVIOUS CHARACTER SEEN 20$: MOV R3,R5 ; SAVE LAST CHARACTER SEEN DEC R1 ; COUNT OFF A CHARACTER BLT OBFDON ; NO -- OUTPUT THE LAST THEN MOVB (R2)+,R3 ; GET NEXT CHARACTER FROM CALLER'S BUFFER CMPB #FF,R3 ; FORM FEED? BEQ SETFF ; YES -- OUTPUT FORM FEED RECORD. CMPB #LF,R3 ; LINE FEED? BNE 20$ ; NO -- KEEP GOING. CMPB #CR,R5 ; IS PREVIOUS CHARACTER A CARRIAGE RETURN? BNE 20$ ; NO - KEEP SCANNING ; HERE WHEN CR/LF FOUND IN OUTPUT RECORD. ORCDON: CLR -(SP) BITB F.RATT(R0),#FD.CR!FD.FTN ; CHECK FOR IMPLIED OR FORTRAN CCL BEQ 30$ ; NEITHER MOV #2,(SP) ; SET LINE LENGTH ADJUSTMENT 30$: SUB (SP),R2 ; REMOVE CR-LF WHEN APPROPRIATE CALL OUTPUT ; OUTPUT THE RECORD FROM R4 TO R2 ADD (SP)+,R2 ; FIX END OF RECORD POINTER MOV R2,R4 ; SET TO START OF NEXT RECORD BR CHRSCN ; GO LOOK AT NEXT RECORD. ; HERE WHEN FORM FEED ENCOUNTERED IN DATA SETFF: DEC R2 ; PUT END OF RECORD PTR AT FF CMP R2,R4 ; ANYTHING ELSE IN RECORD ? BEQ 40$ ; NO -- THEN DO NOT BOTHER TO OUTPUT THEM CALL OUTPUT ; YES -- THEN OUTPUT THEM BEFORE FF RECORD 40$: INC R2 ; MOVE END OF RECORD POINTER PAST FF CALL OUTPUT ; OUTPUT FF CHARACTER. BR CHRSCN ; KEEP SCANNING CHARACTERS. ; HERE WHEN CALLER'S BUFFER IS COMPLETE OBFDON: CMP R2,R4 ; ANY CHARACTERS IN CURRENT OUTPUT RECORD? BEQ 50$ ; NO -- DO NOT OUTPUT THEN CALL OUTPUT ; YES -- THEN DO OUTPUT 50$: MOV (SP)+,R5 ; RESTORE R5 NOW TST SR2(SP) ; SHOULD BUFFER END WITH FF? BEQ 60$ ; NO PUT$ R0,#FFRECD,#1 ; OUTPUT FORM FEED RECORD BCS OUTERR 60$: RETURN ; OK RETURN ; SUBROUTINE TO DO ALL PUTS -- ON RETURN R4 REINITIALIZED. OUTPUT: MOV R2,R3 ; GET POINTER PAST END OF RECORD SUB R4,R3 ; THIS IS THE SIZE OF THE RECORD PUT$ R0,R4,R3 ; PUT IT OUT BCS OUTERR ; WHUPS! ERROR MOV R2,R4 ; SET NEW START OF RECORD. RETURN ; AND RETURN ; TO HERE ON OUTPUT ERRORS OUTERR: JMP FDBERR ; REPORT ERROR AND EXIT .DSABL LSB .END