.TITLE GETPUT - RECORD I/O FOR TECOIO .IDENT "X0203" ; ; COPYRIGHT (C) 1976 BY DIGITAL EQUIPMENT CORPORATION, ; MAYNARD, MASSACHUSETTS ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE FOR USE ONLY ON A ; SINGLE COMPUTER SYSTEM AND MAY BE COPIED ONLY WITH THE IN- ; CLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE, OR ; ANY OTHER COPIES THEREOF, MAY NOT BE PROVIDED OR OTHERWISE ; MADE AVAILABLE TO ANY OTHER PERSON EXCEPT FOR USE ON SUCH ; SYSTEM AND TO ONE WHO AGREES TO THESE LICENSE TERMS. TITLE ; TO AND OWNERSHIP OF THE SOFTWARE SHALL AT ALL TIMES REMAIN ; IN DIGITAL. ; ; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITH- ; OUT NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY ; DIGITAL EQUIPMENT CORPORATION. ; ; DIGITAL EQUIPMENT CORPORATION ASSUMES NO RESPONSIBILITY FOR ; THE USE OR RELIABILITY OF ITS SOFTWARE ON EQUIPMENT WHICH IS ; NOT SUPPLIED BY DIGITAL. ; ; ANDREW C. GOLDSTEIN 12-FEB-78 22:30 ; MARK H. BRAMHALL 29-MAR-79 13:35 .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 PROVIDED THE RECORD DOESN'T END WITH ESCAPE, LINE FEED, ; VERTICAL TAB, OR FORM FEED. IF THE RECORD ENDS WITH FORM FEED, 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 PURE,RO,D GETDSP: .WORD NOCRLF-NOCRLF ; ESCAPE .WORD ADCRLF-NOCRLF ; CR .WORD GOTFF-NOCRLF ; FF .WORD NOCRLF-NOCRLF ; VT .PSECT CODE,RO,I PRNREC: ADD #2,R4 ; DON'T COUNT ANY CR/LF MOVB F.SEQN(R0),R1 ; GET THE "PREFIX" BEQ 60$ ; NONE BPL 10$ ; ONE, A LF COUNT MOV R1,R2 ; COPY THE CTRL CHAR BIC #^C<37>,R2 ; MAKE IT A CTRL CHAR MOV #1,R1 ; SET COUNT AS 1 BR 20$ ; AND GO DO IT 10$: TSTB CHRFLG ; FIRST TIME? BNE 20$ ; NO DEC R1 ; YES, DO ONE LESS LF INITIALLY BEQ 60$ ; NOTHING DO TO 20$: CMP R1,R4 ; ENOUGH SPACE LEFT? BHI 60$ ; NOPE, MUST PUNT... SUB R1,R4 ; YEP, BUT LESS NOW MOV R1,-(SP) ; SAVE COUNT MOV R2,-(SP) ; SAVE CTRL CHAR MOV F.NRBD(R0),R2 ; GET SIZE OF RECORD BEQ 40$ ; NULL... ADD R3,R1 ; BUILD NEW EOR POINTER 30$: MOVB -(R3),-(R1) ; MOVE RECORD UP SOB R2,30$ ; LOOP FOR WHOLE RECORD 40$: MOV (SP)+,R2 ; RESTORE CTRL CHAR MOV (SP)+,R1 ; RESTORE COUNT 50$: MOVB R2,(R3)+ ; STORE CTRL CHAR SOB R1,50$ ; ENOUGH TIMES ADD F.NRBD(R0),R3 ; FORM CORRECT NEW EOR POINTER 60$: MOVB #1,CHRFLG ; NOT THE FIRST TIME ANYMORE MOV #LF,R2 ; ASSUME LF COUNT AGAIN MOVB F.SEQN+1(R0),R1 ; GET THE "POSTFIX" BEQ 80$ ; NONE, DONE BPL 70$ ; ONE, A LF COUNT MOV R1,R2 ; COPY THE CTRL CHAR BIC #^C<37>,R2 ; MAKE IT A CTRL CHAR MOV #1,R1 ; SET COUNT AS 1 70$: TST R4 ; ROOM? BEQ 80$ ; NOPE, PUNT... DEC R4 ; YEP, BUT LESS MOVB R2,(R3)+ ; MOVE CTRL CHAR SOB R1,70$ ; AND LOOP CMP R2,#CR ; DID WE INSERT A TRAILING CR? BNE 80$ ; NOPE, DONE NEGB CHRFLG ; YEP, NEED LF IF EOF COMES UP 80$: JMP IBFCHK ; CONTINUE .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 TST EOFLAG(R5) ; ALREADY AT END-OF-FILE? BEQ 20$ ; NO RETURN ; YES, JUST EXIT 20$: 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 .DSABL LSB ; 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. ADD F.NRBD(R0),R3 ; INCREMENT THE CHARACTER POINTER SUB F.NRBD(R0),R4 ; DECREMENT SPACE COUNT MOV R1,-(SP) ; SAVE R1 MOV R2,-(SP) ; AND SAVE R2 MOV #LF,R2 ; PRE-LOAD A LINE FEED INTO HERE BITB F.RATT(R0),#FD.PRN ; PRINT FORMAT? BNE PRNREC ; YEP TST F.NRBD(R0) ; CHECK SIZE OF RECORD BEQ ADCRLF ; NULL... TSTB INBP2 ; BP2 MODE? BEQ 30$ ; NOPE CMPB -1(R3),#'& ; TRAILING "&"? BNE 30$ ; NOPE 10$: DEC R3 ; YEP, BACK UP THE POINTER 20$: DEC F.NRBD(R0) ; 1 LESS IN RECORD NOW BEQ ADCRLF ; RECORD IS NOW NULL... CMPB -(R3),#SPACE ; TRAILING SPACE? BEQ 20$ ; YEP, DELETE IT CMPB (R3)+,#TAB ; TRAILING TAB? BEQ 10$ ; YEP, DELETE THAT ALSO 30$: MOVB -1(R3),R1 ; GET THE LAST CHAR OF RECORD CMP R1,R2 ; IS IT LINE FEED? BLT ADCRLF ; NO, TOO LOW OR NEGATIVE BEQ NOCRLF ; YES MOV #GETABL,R2 ; GET THE TERMINATOR LIST (AM, CR, FF, VT) 40$: CMP R1,(R2)+ ; IN THE LIST? BLO 40$ ; NO, AND KEEP LOOKING... BEQ GETTRM ; YES; ELSE TOO HIGH, STOP LOOKING ADCRLF: BITB F.RATT(R0),#FD.CR!FD.FTN ; CHECK FOR IMPLIED OR FORTRAN CCL BEQ NOCRLF ; NEITHER MOVB #CR,(R3)+ ; INSERT CARRIAGE RETURN MOVB #LF,(R3)+ ; AND LINE FEED BR IBFCHK ; CONTINUE GETTRM: ADD GETDSP-(R2),PC ; YES, DISPATCH ON IT NOCRLF: ADD #2,R4 ; CR-LF ALREADY PRESENT - PUT BACK THE SPACE IBFCHK: MOV (SP)+,R2 ; RESTORE R2 MOV (SP)+,R1 ; AND RESTORE R1 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 GOTFF: DEC FFFLAG(R5) ; SET FF FLAG DEC R3 ; BUT DON'T ENTER FF IN BUFFER CMP (SP)+,(SP)+ ; POP SAVED R1/R2 ; 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 ; AND OUT ; 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 20$ ; IF NOT, GET OUT 10$: MOV #-1,EOFLAG(R5) ; YES - SET END OF FILE FLAG TSTB CHRFLG ; NEED TRAILING LF ON EOF? BPL IBFDON ; NOPE, JUST EXIT MOVB #LF,(R3)+ ; YEP, SO DO IT BR IBFDON ; AND EXIT 20$: BITB #FA.SHR,F.FACC(R0) ; SEE IF FILE IS OPEN SHARED BNE 10$ ; 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 .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 ; RECORD DELIMITERS WHICH ARE LINE FEED, VERTICAL TAB, FORM FEED, ; AND ESCAPE. IF THE FILE HAS NULL CARRIAGE CONTROL, THE DELIMITER ; IS OUTPUT WITH THE RECORD; OTHERWISE IF THE DELIMINTER IS LINE ; FEED AND IT IS PRECEEDED BY A CARRIAGE RETURN, THEN THE CR-LF ; PAIR IS NOT OUTPUT. ; ; 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 R5,-(SP) ; ALSO SAVE R5 MOV #OUTFDB,R0 ; SET UP FDB ADDRESS .DSABL LSB CHRSCN: CLR R3 ; ZERO PREVIOUS CHARACTER SEEN CLR -(SP) ; ZERO # OF CHARACTERS TO REMOVE INITIALLY MOV R2,R4 ; SET TO START OF NEXT RECORD 10$: 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 R3,#AM ; HIGHER THAN ESCAPE? BHI 10$ ; YES, KEEP SCANNING BEQ 20$ ; NO, ESCAPE, TERMINATE CMPB R3,#FF ; HIGHER THAN FF? BHI 10$ ; YES, KEEP SCANNING CMPB R3,#LF ; LOWER THAN LF? BLO 10$ ; YES, KEEP SCANNING BNE 20$ ; TERMINATED WITH VT OR FF CMPB R5,#CR ; LF TERMINATOR, IS PREVIOUS A CR? BNE 20$ ; NOPE, DON'T REMOVE ANYTHING BITB F.RATT(R0),#FD.CR!FD.FTN ; CHECK FOR IMPLIED OR FORTRAN CCL BEQ 20$ ; NEITHER MOV #2,(SP) ; SET LINE LENGTH ADJUSTMENT 20$: CLR R5 ; GUESS AT NORMAL OUTPUT TSTB OUBP2 ; BP2 MODE? BEQ 40$ ; NOPE TST R1 ; YEP, MORE TO COME? BLE 50$ ; NO CMPB (R2),#'0 ; YES, NEXT A DIGIT? BLO 30$ ; NO CMPB (R2),#'9 ; MIGHT BE... BLOS 40$ ; AND IT IS TOO 30$: MOV (PC)+,R5 ; SET FOR TRAILING SPACE/"&" .BYTE 40,'& 40$: SUB (SP),R2 ; REMOVE CR-LF WHEN APPROPRIATE CALL PUTOUT ; OUTPUT THE RECORD FROM R4 TO R2 ADD (SP)+,R2 ; FIX END OF RECORD POINTER BR CHRSCN ; GO LOOK AT NEXT RECORD. 50$: TST SR2+4(SP) ; WILL A FORM FEED FOLLOW? BEQ 40$ ; NOPE BR 30$ ; YEP ; HERE WHEN CALLER'S BUFFER IS COMPLETE OBFDON: CLR R5 ; GUESS AT NO FINAL FF TST SR2+4(SP) ; REALLY DO A FINAL FF? BNE 10$ ; YES CMP R2,R4 ; ANY CHARACTERS IN CURRENT OUTPUT RECORD? BEQ 30$ ; NO -- DO NOT OUTPUT THEN BR 20$ ; YES -- SO OUTPUT THEM 10$: MOV #FF,R5 ; YES, SET TO DO A FINAL FF 20$: CALL PUTOUT ; DO THE LAST PUT 30$: TST (SP)+ ; DUMP A STACK ITEM MOV (SP)+,R5 ; RESTORE R5 NOW PUTRET: RETURN ; RETURN ; SUBROUTINE TO DO ALL PUTS PUTOUT: MOVB (R2),-(SP) ; SAVE REAL LAST & POINTER TO REAL LAST MOV R2,-(SP) MOVB R5,(R2)+ ; SET NEW LAST BNE 10$ ; IT EXISTS DEC R2 ; ELSE REMOVE IT 10$: SWAB R5 ; SWITCH FOR NEXT NEW LAST MOV R2,-(SP) ; SAVE POINTER TO NEW LAST & NEW LAST MOVB (R2),-(SP) MOVB R5,(R2)+ ; SET NEW LAST BNE 20$ ; IT EXISTS DEC R2 ; ELSE REMOVE IT 20$: 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 MOVB (SP)+,@(SP)+ ; RESTORE THE NEW LAST MOV (SP)+,R2 ; RESTORE THE POINTER TO REAL LAST & REAL LAST MOVB (SP)+,(R2) BCC PUTRET ; O.K., RETURN JMP FDBERR ; REPORT ERROR AND EXIT .END