;ROUTINE TO INPUT A BYTE FROM DEVICE DEPENDENT SEQUENTIAL INPUT ROUTINE
;CALLED WITH THE JFN ALREADY LOCKED BY CHKJFN AND JFNID(P3) HAS BEEN CALLED
;CALL: CALL BYTINA
;RETURN
; +1 IF A IS NON-ZERO, AN ERROR OCCURED
; IF A = 0, ROUTINE WANTS TO BLOCK
; ;MDISMS ARGUMENT IS IN B
; +2 ;BYTE IN B
;BYTINS USED IF MAY BE A SINR
BYTINA: SETZM T1 ;NOT A SINR
BYTINS: STKVAR <FLAGS> ;SAVE ENTRY FLAG HERE
MOVEM T1,FLAGS ;SAVE IT NOW
JUMPGE STS,NOTOPN
BYTIA1: TQZ <RECF> ;NOT END OF RECORD IF HERE
CALL BYTINX ;GET A BYTE
RET ;ERROR - PASS DOWN THE LINE
TQNE <RECF> ;END OF RECORD SEEN?
JRST [ TQNN <ACRLFF> ;ADDING CR-LF?
SKIPE FLAGS ;NO. A SINR?
RETSKP ;YES. RETURN NOW THEN
JRST BYTIA1] ;NO. GET NEXT BYTE NOW
TQNE <PASLSN> ;LETTING LINE #S THRU?
RETSKP ;YES, EASY RETURN
TQZE <SKIPBY> ;ARE WE SUPPOSED TO THROW THIS AWAY (SEE BELOW)
JRST BYTIA1 ;YEP, GO GET A REAL ONE
JUMPN B,BYTIA2 ;DISCARD LSN'S MEANS ALSO DISCARD NULLS
MOVE A,FILBYN(JFN) ;HOWEVER, IF IT'S THE FIRST BYTE OF THE FILE
SOJE A,BYTIA3 ; THEN THE FILE CAN'T HAVE LINE NUMBERS
JRST BYTIA1 ;NOT FIRST BYTE, SAFE TO DISCARD IT
BYTIA2: LDB A,[POINT 12,FILBYT(JFN),11];DID WE JUST GET THE FIRST CHARACTER OF A WORD?
MOVE C,FILCNT(JFN) ;AND BETTER MAKE SURE THERE ARE ENUF LEFT
CAIE A,<POINT 7,0,6>_-^D24;FIRST BYTE?
RETSKP ; NO, LET IT THROUGH.
CAIGE C,4 ;ENUF FOR A LINE #?
JRST BYTIA4 ; NO, POSSIBLY SKIP THIS IN FUTURE
;POSSIBLE LINE NUMBER. LET'S ALSO CHECK TO SEE IF WE ARE ON THE FIRST WORD
;OF THE FILE AND IT IT ISN'T A LINE #, THEN SET PASLSN TO SPEED THINGS UP
;IN THE FUTURE
HRRZ A,FILBYT(JFN) ;GET THE WORD WE GOT THE CHARACTER FROM
MOVE A,0(A) ;DO INDIRECT
TXNN A,1B35 ;BIT 35 ON? IF SO, CALL IT A LINE #
JRST BYTIA4 ; NOT A LINE NUM. POSSIBLY SKP THIS IN FUTURE
MOVNI A,4 ;SKIP THE REST OF THE LINE NUMBER QUICKLY
ADDM A,FILCNT(JFN) ;(WE KNOW FILCNT WAS GEQ 4 BEFORE)
MOVEI A,4 ;ALSO UPDATE FILBYN
ADDM A,FILBYN(JFN)
MOVX A,77B5 ;NOW POINT TO LAST BYTE IN WORD
ANDCAM A,FILBYT(JFN) ;TO "READ" THOSE 4
CALL BYTINX ;SKIP THE TAB AFTER THE LSN
TQOA <SKIPBY> ;OOPS, NOT THIS TIME, REMEMBER AFTER WE UNBLOCK
JRST BYTIA1 ;AND GET A REAL ONE
RET ;RETURN TO BLOCK
BYTIA4: MOVE A,FILBYN(JFN) ;NOT A LINE NUMBER. FIRST CHAR?
SOSN A ;IF SO, SKIP THIS NONSENSE IN THE FUTURE
BYTIA3: TQO <PASLSN> ;HERE IF WE DECIDE FILE ISN'T SEQUENCED
RETSKP ;RETURN CURRENT BYTE

;SUBROUTINE CALLED ONLY BY BYTINA: and TSTLSN
;BYTINX expects the original JFN to be stored in SAVJFN (via TRVAR <SAVJFN>).
BYTINX::TQNN <READF> ;[7321]Make routine BYTINX external
FILABT IOX1 ;Illegal read
TQNE <ERRF>
JRST INERR ;GO GENERATE DATA ERROR INTERRUPT
TQNE <EOFF>
JRST INEOF
TQZE <BLKF,XQTAF> ;SEE IF FLAG IS ALREADY SET
BUG.(CHK,BLKF1,IO,HARD,<BYTINA - BLKF set before calling service routine>,,<
Cause: This is a consistency check in BYTINX. The environment is in IO where
sequential input is being processed. The code is getting ready to
jump to the device dependant code. Before doing so it sees if a bit
(BLKF) is set in STS (AC 8). This bit indicates that the service
routine wants to block. Therefore, no matter what the device
dependent routines do, the process ultimately blocks. It is
unlikely that this is being done on purpose. It is more likely that
somewhere BLKF is not being cleaned up properly.
Action: If this is becoming a problem change the BUGCHK to a BUGHLT and
look at the dump. If FILSTS for the current JFN has the bit on then
the problem gets a little tricky since the previous use of it left
BLKF on. If BLKF is off in FILSTS then somewhere past the call to
CHKJFN it is being turned on.
>)
XMOVEI C,BYTINB ;BYTIN BLOCK ROUTINE
MOVE D,SAVJFN ;ORIGINAL JFN
TQZE <CRNXT> ;CR NEXT
JRST [ MOVEI B,.CHCRT ;YES, LOAD IT UP
TQO <LFNXT> ;REMEMBER THAT LF COMES NEXT
RETSKP]
TQZE <LFNXT> ;TIME FOR LF?
JRST [ MOVEI B,.CHLFD ;YES, LOAD IT UP
TQO <FROSTF> ;NOTE THAT THIS RECORD HAS BEEN FROSTED
RETSKP]
CALL @BIND(P3) ;Dispatch to DEVIce dependent code
TQNN <XQTAF> ;QUOTA EXCEEDED?
TQZE <BLKF> ;CHECK IF SERVICE ROUTINE WANTS TO BLOCK
JRST [ MOVE B,A ;YES, LEAVE DISMIS DATA IN B
JRST RETZ] ;AND RETURN WITH A=0
TQZ <FROSTF> ;NEW RECORD HASN'T BEEN FROSTED WITH CRLF YET
TQNE <ERRF>
JRST INERR
TQNE <EOFF>
JRST INEOF
MOVE B,A
TQNN <ACRLFF> ;WANT TO AUGMENT RECORDS WITH CRLFS?
RETSKP ;NO, JUST GIVE SKIP WITH LOCKS STILL SET
MOVE C,FILBYN(JFN) ;SEE HOW FAR WE'VE READ
CAMGE C,FILLEN(JFN) ;ARE WE AT END OF RECORD?
CAIA ;NOT END OF RECORD OR ALREADY FROSTED
TQO <CRNXT> ;AUGMENTING, START SEQUENCE.
RETSKP ;SKIP RETURN LEAVING LOCKS STILL SET
INEOF: MOVEI A,IOX4
MOVEM A,LSTERR
MOVEM JFN,ERRSAV
MOVE A,MPP ;GET BASE LEVEL STACK
MOVE B,-1(A) ;GET PC
MOVE A,0(A) ;GET ADR OF JSYS+1
CALL CHKERT ;SEE IF AN ERCAL OR ERJMP
SKIPA A,BITS+.ICEOF ;NO, CAUSE INTERRUPT ON CHANNEL 10
JRST INEOF1 ;YES, DONT INTERRUPT
CALL IICSLF ;ON THIS FOR
INEOF1: MOVEI B,0
RETBAD (IOX4) ;GIVE ERROR RETURN
INERR: FILINT (IOX5) ;GIVE CHANNEL 11 INTERRUPT
RETBAD (IOX5) ;AND RETURN
;ROUTINE TO HANDLE SERVICE ROUTINE BLOCK REQUEST
BYTINB::STKVAR <SAVDEV> ;SAVE DEV
MOVEM DEV,SAVDEV ;SAVE DEV
PUSH P,T2 ;SAVE JFN RETURNED
CALL UNLDIS ;UNLOCK JFN & DISMISS
POP P,JFN ;RESTORE JFN
CALL CHKJFN ;RE-VALIDATE IT
RETBAD ()
JFCL
JFCL
CAME DEV,SAVDEV ;CHECK FOR DEV MATCH
RETBAD (DESX4) ;NOT LEGAL TO CHANGE JFN'S
RETSKP ;ALLOW SERVICE ROUTINE TO PROCEED

; Byte output subroutine
; Call: 1 ;Source designator
; 2 ;BYTE
; CALL BYTOUT
; Return
; +1 ;Ok
; Clobbers most everything
BYTOUT::TRVAR <SAVJFN>
MOVEM JFN,SAVJFN ;SAVE ARGUMENT
BYTOU1: CALL CHKJFN ;Check the designator
JRST IOERR ;Bad designator
JFCL ;Tty
JFCL ;Byte pooutter
PUSH P,B ;SAVE BYTE
CALL @JFNOD(P3) ;INIT JFN FOR OUTPUT
MOVE B,0(P) ;GET BACK THE BYTE
CALL BYTOUA ;SEND IT OUT
JRST BYTOUW ;SERVICE ROUTINE WANTS TO BLOCK
POP P,B ;GET BACK BYTE
CALLRET UNLCKF ;UNLOCK THE LOCKS
BYTOUW: CALL UNLDS1 ;UNLOCK AND BLOCK
POP P,B ;GET BYTE BACK
MOVE JFN,SAVJFN ;GET ARG TO CHKJFN BACK
JRST BYTOU1 ;AND TRY AGAIN
;ROUTINE TO SEND A BYTE TO SERVICE ROUTINE
;CALLED WITH FILE LOCKED DOWN AND BYTE IN B AND JFNOD(P3) HAVING BEEN CALLED
BYTOUA::JUMPGE STS,NOTOPN
TQNN <WRTF>
FILABT IOX2 ;Illegal write
TQNE <ENDF>
FILABT(IOX6) ;Past abs end of file
TQNE <ERRF>
FILINT(IOX5) ;Error interrupt
MOVE A,B
TQZE <BLKF,XQTAF> ;MAKE SURE BLKF IS OFF BEFORE CALL
BUG.(CHK,BLKF2,IO,HARD,<BYTOUA - BLKF set before call to service routine>,,<
Cause: This is a consistency check in BYTOUA. The environment is in IO just
before it gets ready to call the device dependent routines to do
output. Bit BLKF in STS (AC 8) is on. It should be off. It causes
the process to block. It is unlikely that this sort of knowledge
is available. It is more likely that this is an error.
Action: If the problem persists change the BUGCHK to a BUGHLT and look at
the dump. If FILSTS for the current JFN has the BLKF bit on then
the last one to user the JFN left it in that state. A hard problem
to find. If BLKF is off in FILSTS then somewhere after the call to
CHKJFN the bit is being set on not reset.
>)
XMOVEI C,BYTINB ;COMMON CO-ROUTINE
MOVE D,SAVJFN
CALL @BOUTD(P3) ;Dispatch to DEVIce dependent code
TQZN <BLKF> ;DOES SERVICE ROUTINE WANT TO BLOCK?
TQNE <ERRF,XQTAF> ;GOT AN ERROR?
RET ;YES, TAKE NON-SKIP RETURN
RETSKP ;NO, SKIP RETURN WITHOUT UNLOCKING

; Prototype byte blt program
; Note that address designated by .-. are filled in at run time
; also, the LSH and MOVEM instructions at PROTO +4 and +5 have their
; ac fields modified depending on where the LSHC is made to shift right
; or left. Only one of these instructions is modified in either case
; thus the two instruction end up using Q1 if shift left and Q2 if right
; Furthermore, the MOVE's and MOVEM's may be changed to UMOVE or
; UMOVEM's depending on the address space of A and B respectively
PROTO: MOVE Q1,(B) ;Note most rh's are filled at run time
MOVE Q2,1(B) ;Pick up next word
LSH Q1,.-. ;Right justify first word
LSHC Q1,.-. ;Shift to target position+unused bits
LSH Q2,.-. ;Shift back to clear unused bits
MOVEM Q1,(C) ;Store
AOS B
AOS C
AOBJN A,PRG ;Loop
JRST BYTLPD ;Done
LPRG==.-PROTO
ENDSV.