.iif ndf rsx rsx = 1 ;Assume RSX11M .title $$getc Get characters ; ; The information in this document is subject to change ; without notice and should not be construed as a commitment ; by Digital Equipment Corporation or by DECUS. ; ; Neither Digital Equipment Corporation, DECUS, nor the authors ; assume any responsibility for the use or reliability of this ; document or the described software. ; ; Copyright (C) 1980, DECUS ; ; ; General permission to copy or modify, but not for profit, is ; hereby granted, provided that the above copyright notice is ; included and reference made to the fact that reproduction ; privileges were granted by DECUS. ; .IDENT /000006/ ;**NEW** ; ;**-1 ;+ ; ; Internal ; ; Index Get characters (internal) ; ; Usage ; ; mov #iov,r4 ;r4 -> i/o vector ; call $$getc ;Get a character ; ; RSX: ; mov #iov,r4 ;r4 -> i/o vector ; mov #buffer,r0 ;r0 -> buffer ; mov buflen,r1 ;r1 := max. buffer size ; call $$get ;Get a record ; ; VF$EOF and/or VF$ERR are set on error or end of file. ; r0 := actual record length, -1 on error or end of file. ; ; Other registers preserved. ; ; RT11: ; mov #blknbr,r0 ;r0 := block to read ; call $$get ;Get a block ; ; VF$EOF and/or VF$ERR are set on error or end of file. ; r0 is zero if success, -1 on error or end of file. ; ; Other registers preserved. ; ; ; Description ; ; $$getc is the internal "get a byte" routine. The ; next byte in the indicated file is returned in r0. ; All other registers are preserved. ; ; $$get is the internal "get a record" routine. Note that ; the maximum record size (r1) is only needed on RSX. It is fixed ; at 512. bytes on RT11. ; ; If the file is defined as "stream" (the "n" flag was not set ; when the file was opened using fopen()), the end of the line ; will be represented by the newline (\n) character, and ; NULL's will be removed. ; ; Bugs ; ; In stream files in RT11, all carriage-returns are removed. ; It would be more correct to remove carriage-return from ; or sequences. ; ; RT11 uses .ttyin to read from the user command terminal. ; It would be more correct to use .gtline as this would allow ; indirect command file tracking. ; ;- ; ; Edit history ; 000001 18-Mar-80 MM Conversion for the newer library ; 000002 27-Mar-80 MM Merged libraries. ; 000003 14-May-80 MM Dropped NULLs from stream files. ; 000004 23-Jun-80 MM Flush stdout for RT11 ; 000005 27-Jun-80 MM No more C-bit hackery, RT11 $$get returns 0 if ok ; 000006 20 Nov 1981 RVT FOPEN "RU" DOES BLOCK I/O ;**NEW** ; USE GET$S (USES LESS MEMORY) ;**NEW** ; CHANGE TO ALLOW "LOCATE" MODE. ;**NEW** ; .if ne rsx ;02 .MCALL GET$S,READ$,WAIT$ ;**NEW** ;**-1 .psect .prog. $$getc:: mov V$UGET(r4),r0 ;Is there an unget character ;04 bmi 10$ ;No mov #-1,V$UGET(r4) ;Make unget character go away return ; 10$: bit #VF$UBF,(r4) ;Is this an unbuffered stream beq 20$ ;No bis #VF$ERR,(r4) ;Yes, set error br geterr ; 20$: bit #VF$EOR,(r4) ;Any more stuff bne geterr ;Br if not 30$: BIT #VF$NOS,(R4) ; BINARY ? ;**NEW** BNE 100$ ; CORRECT, JUMP ;**NEW** ;**NEW** ; NOPE, STRIP OFF NULLS FROM CR/LF & LF/CR. APPEND TRAILING LF. ;**NEW** DEC V$BCNT(R4) ; MORE TO GET? ;**NEW** BMI 40$ ; NO, GO READ IN A NEW LINE ;**NEW** BEQ 70$ ; IF EOL, GIVE A TRAILING LF ;**NEW** movb @V$BPTR(r4),r0 ;Grab it ;**NEW** inc V$BPTR(r4) ;Fix pointer ;**NEW** bic #177400,r0 ;Mask number to 8 bits ;**NEW** BEQ 30$ ; SKIP THIS NULL ;**NEW** ;**NEW** ; DON'T DO CR/LF CHECK IF THIS IS THE LAST CHAR ;**NEW** CMP #1,V$BCNT(R4) ;**NEW** BEQ 60$ ; LAST CHAR--RETURN ;**NEW** ;**NEW** CMPB #15,R0 ; CR?? ;**NEW** BNE 35$ ;**NEW** CMPB #12,@V$BPTR(R4) ; YUP, SEE IF CR/LF ;**NEW** BEQ 30$ ; YES, IGNORE THE CR ;**NEW** RETURN ;**NEW** ;**NEW** 35$: CMPB #12,R0 ; LF? ;**NEW** BNE 60$ ;**NEW** CMPB #15,@V$BPTR(R4) ; YUP, SEE IF THIS IS LF/CR ;**NEW** BNE 60$ ;**NEW** CLRB @V$BPTR(R4) ; YES, CREAM THE CR TO A NULL ;**NEW** 60$: RETURN ;**NEW** ;**NEW** 70$: MOV #12,R0 ; IMPLIED TRAILING LF ;**NEW** RETURN ;**NEW** ;**NEW** 100$: dec V$BCNT(r4) ;Get a byte from the line ;**NEW** bmi 40$ ;Br if none ;**NEW** movb @V$BPTR(r4),r0 ;Grab it ;**NEW** inc V$BPTR(r4) ;Fix pointer ;**NEW** bic #177400,r0 ;Mask number to 8 bits ;**NEW** RETURN ;**NEW** ;**NEW** bmi 40$ ;Br if none ;**-1 movb @V$BPTR(r4),r0 ;Grab it inc V$BPTR(r4) ;Fix pointer bic #177400,r0 ;Mask number to 8 bits return ; 40$: mov V$RBUF(r4),r0 ;Address of record buffer mov r0,V$BPTR(r4) ;Buffer address mov V$RBSZ(r4),r1 ;Size of record buffer call $$get ;Get record MOV V$FDB+F.NRBD+2(R4),V$BPTR(R4) ; GET RECORD ADDR ;**NEW** mov r0,V$BCNT(r4) ;Number of bytes in record bge 30$ ;Try again ;05 geterr: mov #-1,r0 ;Return EOF return ; ; ; ; Get record. ; r0 = buffer address. ; r1 = max record size. ; ; Sets IOV on EOF or error (IOV VF$EOF and/or VF$ERR set) ; Record length in r0 -- -1 if error ; $$get:: mov r0,-(sp) ;Save registers mov r1,-(sp) ; mov r2,-(sp) ; mov r3,-(sp) ; mov r0,r2 ;r2 -> buffer ; ; Note: the record buffer address is at 6(sp) ; ; Record devices. ; bit #VF$REC,(r4) ;Record device? beq 10$ ;Br if not ; ; Standard input/standard output ; magic on a tty. ; cmp r4,stdin ;Are we reading standard input? bne 10$ ;No bit #VF$TTY,(r4) ;Yes, is it a TTY? beq 10$ ;No mov stdout,r0 ;Is the standard output bit #VF$TTY,(r0) ;Also a TTY? beq 10$ ;No mov r4,-(sp) ;Yes, flush out the mov r0,r4 ;Standard output call $$flsh ;This is all in the mov (sp)+,r4 ;Prompting ; ; Read record ; 10$: mov r4,r0 ;R0 must point to FDB add #V$FDB,R0 ;Now it does BITB #FD.RWM,F.RACC(R0) ; BLOCK-MODE? ;**NEW** BNE 15$ ;**NEW** ;**NEW** GET$S R0,R2,R1 ; NO, SEQUENTIAL GET ;**NEW** BR 17$ ;**NEW** ;**NEW** ; BLOCK-MODE READ ;**NEW** 15$: MOV R4,F.BKST(R0) ; SET UP THE IOSB ADDR ;**NEW** ADD #V$IOSB,F.BKST(R0) ;**NEW** READ$ R0,R2,R1 ;**NEW** BCS 16$ ; ERROR, PROBABLY EOF ;**NEW** WAIT$ R0 ;**NEW** 16$: MOV V$IOSB+2(R4),F.NRBD(R0) ; SET ACTUAL NUMBER OF BYTES READ ;**NEW** 17$: ;**NEW** bcc 20$ ;No problem ;**-1 bis #VF$EOF,(R4) ;Trouble, force end of file cmpb #IE.EOF,F.ERR+V$FDB(R4) ;Was it end of file? beq getxit ;Yes, exit bis #VF$ERR,(R4) ;No, real trouble br getxit 20$: mov V$FDB+F.NRBD(R4),R0 ;R0 := actual byte count ; ; Clean up the record (thank's to RSX cleverness) ; Enter with R0 := actual byte count getfix: bit #VF$NOS,(r4) ;Stream file? bne getxit ;If not, don't do newline stuff. inc r0 ; count the implied trailing LF ;**NEW** ; exit from $$Get ;**NEW** ; ;**-35 getxit: mov (sp)+,r3 ;Restore mov (sp)+,r2 ;Registers mov (sp)+,r1 ;R3 - R1 tst (sp)+ ;Keep actual byte count bit #VF$EOR,(r4) ;Error or end of file? beq 10$ ;Neither, exit mov #-1,r0 ;Yes, signal error ;05 10$: return ;and exit .iff ;02+ .MCALL .TTYIN CR = 15 .psect .data. REAERR: .BYTE E$$EOF, E$$ERR, E$$FAT .psect .prog. ; ; Enter with r4 -> iov. ; Return, all registers preserved. ; $$GETC:: MOV V$UGET(R4),R0 ; Is there an unget character BMI GETBYT ; Nope MOV #-1,V$UGET(R4) ; Yes, not any more, though RTS PC ; Back to the caller GETBYT: cmp r4,stdin ;Are we reading standard input? ;04+ bne 10$ ;No bit #VF$TTY,(r4) ;Yes, is it a TTY? beq 10$ ;No mov stdout,r0 ;Is the standard output bit #VF$TTY,(r0) ;Also a TTY? beq 10$ ;No mov r4,-(sp) ;Yes, flush out the mov r0,r4 ;Standard output call $$flsh ;This is all in the mov (sp)+,r4 ;Prompting 10$: ;04- BIT #VF$TTY,(R4) ; Is it a tty? BEQ GETFIL ; Br if not .TTYIN ; R0 = input byte CMP R0,#32 ; see if byte is "^Z" (EOF) BEQ 20$ ; Return EOF if it is CMP R0,#3 ; See if byte is CTRL/C BNE GETDON ; return R0 if not ; 20$: CLR R0 ; Error code = 0 BR GETEOF ; CTRL/C = EOF ; ; Get a byte from a file ; GETFIL: MOV R1,-(SP) ; Save work register MOV R4,R1 ; R1 -> IOV ADD #V$BCNT,R1 ; R1 -> io_bcnt DEC (R1)+ ; remaining byte count BGE 20$ ; branch if buffer not empty MOV V$BNBR(R4),R0 ; Get block to read CALL $$GET ; Go get it. TST R0 ; Success if zero in r0 BEQ 10$ ; Go on if ok MOV (SP)+,R1 ; Nope, restore r1 RTS PC ; And exit ; 10$: DEC -2(R1) ; $$get sets byte count to 512. ; 20$: CLR R0 ; return a byte to caller BISB @(R1)+,R0 ; Make sure it's unsigned INC -(R1) ; bump nextp MOV (SP)+,R1 ; Restore R1 ; ; Hack CRLF if needed -- Note: all carriage returns are removed. ; GETDON: BIT #VF$NOS,(R4) ; Not a stream file? BNE 10$ ; Br if binary CMP R0,#CR ; Stream, carriage return? BEQ GETBYT ; Restart if so TST R0 ; Not , is it ? ;03 BEQ GETBYT ; Restart if so ;03 10$: RTS PC ; Return to the caller ; ; Get one block ; $$GET:: BIT #VF$TTY,(R4) ; we're called for the tty BNE 10$ ; we just exit. MOV R0,V$BNBR(R4) ; Fseek needs to refresh block number CLR -(SP) ; make an arg block for .READW MOV #256.,-(SP) ; so the next block can be read MOV R4,-(SP) ; Get address of ADD #V$BUFF,(SP) ; Block buffer MOV R0,-(SP) ; Add the block number MOV #10 * 400,-(SP) ; .READW function BISB V$LUN(R4),(SP) ; channel MOV SP,R0 ; R0 -> arg block EMT 375 ; .READW BCS 20$ ; branch if the read failed MOV R4,R0 ; Success, get another pointer ADD #V$BCNT,R0 ; R0 -> iov_bcnt MOV #512.,(R0)+ ; 512 bytes are now left in buffer CMP (SP)+,(SP)+ ; pop some of arg block MOV (SP)+,(R0)+ ; nextp INC (R0) ; bump blockno, it points to "next" CMP (SP)+,(SP)+ ; pop rest of arg block ; 10$: CLR R0 ; Success BIC #VF$BZY,(R4) ; Buffer non-busy RTS PC ; And exit 20$: ADD #5*2,SP ; Clear the stack on errors MOVB @#52,R0 ; Get the error code ; GETEOF: ; Enter with MOV ERR_CODE,R0/BR GETEOF BEQ 10$ ; Br if end of file BIS #VF$ERR,(R4) ; Set error bit 10$: BIS #VF$EOF,(R4) ; Always set eof bit MOVB REAERR(R0),$$FERR ; Save the error code MOV #-1,R0 ; Return EOF RTS PC ; And exit .endc ;02- .END