Trailing-Edge
-
PDP-10 Archives
-
bb-m780a-sm
-
monitor-sources/io.mac
There are 60 other files named io.mac in the archive. Click here to see a list.
; UPD ID= 374, SNARK:<5.MONITOR>IO.MAC.12, 5-Jan-82 09:02:27 by GRANT
;TCO 5.1649 - Add NSP null message checking
; UPD ID= 176, SNARK:<5.MONITOR>IO.MAC.11, 15-Sep-81 11:51:51 by MOSER
;TCO 5.1511 MOVE CODE FROM 5.1499 TO IO FROM DEVICE.
; UPD ID= 140, SNARK:<5.MONITOR>IO.MAC.10, 2-Sep-81 16:56:39 by MOSER
;TCO 5.1485 - Reference byte before going NOINT for a SIN/SINR.
; UPD ID= 125, SNARK:<5.MONITOR>IO.MAC.9, 27-Aug-81 20:15:25 by PAETZOLD
;Change TCO 5.1008X to 5.1471
; UPD ID= 114, SNARK:<5.MONITOR>IO.MAC.8, 22-Aug-81 16:09:27 by PAETZOLD
;TCO 5.1008X - Fix CHKJFN and BYTBLT for OWGBP's
; UPD ID= 92, SNARK:<5.MONITOR>IO.MAC.7, 6-Aug-81 13:58:46 by SCHMITT
;More of TCO 5.1300 - do an ILDB on pointer to avoid NonExist Ref.
; UPD ID= 1893, SNARK:<5.MONITOR>IO.MAC.6, 27-Apr-81 17:16:03 by SCHMITT
;TCO 5.1300 - Attempt to load byte before going NOINT
; UPD ID= 1524, SNARK:<5.MONITOR>IO.MAC.5, 6-Feb-81 12:46:56 by ZIMA
;TCO 5.1258 - remove historical code.
; UPD ID= 708, SNARK:<5.MONITOR>IO.MAC.4, 26-Jun-80 15:48:07 by ZIMA
;TCO 5.1084 - HAVE MEMORY TO MEMORY SIN CHECK FOR AC3 ZERO PROPERLY
; UPD ID= 655, SNARK:<5.MONITOR>IO.MAC.3, 16-Jun-80 17:00:17 by OSMAN
;tco 5.1050 - Make jfn on TTY: use fork's controlling terminal
; UPD ID= 437, SNARK:<5.MONITOR>IO.MAC.2, 13-Apr-80 15:13:30 by OSMAN
; UPD ID= 429, SNARK:<4.1.MONITOR>IO.MAC.277, 13-Apr-80 14:35:01 by OSMAN
;Reference FRKTTY instead of FKCTYP
; UPD ID= 19, SNARK:<4.1.MONITOR>IO.MAC.276, 27-Nov-79 13:25:03 by SCHMITT
;TCO 4.1.1030 - SET PASLSN IF FILE LENGTH IS LESS THAN FIVE BYTES
;<4.1.MONITOR>IO.MAC.275, 6-Nov-79 10:08:25, EDIT BY DBELL
;TCO 4.2564 - CHANGE MJFN TO RJFN AT CHKJFT
;<4.MONITOR>IO.MAC.274, 24-Oct-79 12:50:58, EDIT BY MURPHY
;UNLDIS - ITRAP IF WAIT ROUTINE ADDRESS IS 0
;<4.MONITOR>IO.MAC.273, 24-Oct-79 12:22:03, EDIT BY MURPHY
;TRPDSP IN BYTBLT
;<4.MONITOR>IO.MAC.271, 5-Oct-79 16:02:03, EDIT BY MILLER
;TCO 4.2511. DON'T DIDDLE PC IN UNLDIS FOR OVER QUOTA ERROR
;<4.MONITOR>IO.MAC.270, 4-Oct-79 14:13:44, EDIT BY OSMAN
;more 4.2256 - Don't put spurious crlf's when reading from tape to memory
;<4.MONITOR>IO.MAC.269, 19-Sep-79 09:30:36, EDIT BY OSMAN
;more 4.2256 - Prevent nulls in files copied from tape to disk
;<OSMAN.MON>IO.MAC.1, 10-Sep-79 15:35:00, EDIT BY OSMAN
;TCO 4.2412 - Move definition of BUGHLTs, BUGCHKs, and BUGINFs to BUGS.MAC
;<4.MONITOR>IO.MAC.267, 20-Aug-79 13:39:44, EDIT BY DBELL
;CHECK ACRLFF FLAG BEFORE INDEXING BY JFN IN BYTINX
;<4.MONITOR>IO.MAC.266, 27-Jul-79 15:48:17, EDIT BY ENGEL
;RETURN VALID JFN (MULITPLIED BY MLJFN) FOR ALL DESX3'S
;<4.MONITOR>IO.MAC.265, 27-Jul-79 13:48:57, EDIT BY HALL
;FIX BYTBLT TO HANDLE INDEXED BYTE POINTERS
;<4.MONITOR>IO.MAC.264, 25-Jul-79 15:12:48, EDIT BY R.ACE
;TCO 4.2345 - FIX BYTBLT WITH INDEXED BYTE POINTER
;<4.MONITOR>IO.MAC.263, 24-Jul-79 08:26:45, EDIT BY OSMAN
;MORE 4.2256 - If count used up, don't attempt crlf sequence
;<4.MONITOR>IO.MAC.262, 30-Jun-79 20:24:41, EDIT BY DBELL
;TCO 4.2318 - HAVE CHKJFN USE FORK'S CONTROLLING TERMINAL FOR 777777
;<4.MONITOR>IO.MAC.261, 19-Jun-79 08:43:51, EDIT BY MILLER
;<4.MONITOR>IO.MAC.260, 19-Jun-79 08:38:56, EDIT BY MILLER
;MAKE SIN1 MORE EFFICIENT
;<4.MONITOR>IO.MAC.259, 17-Jun-79 11:40:29, EDIT BY MILLER
;MORE DIDDLES FOR ADDING CR-LF
;<4.MONITOR>IO.MAC.258, 16-Jun-79 14:24:54, EDIT BY MILLER
;MORE FIXES FOR CR-LF CODE. MAYBE IT WILL WORK NOW
;RANDOM AND SCATTERED FIXES FOR NEW CR-LF CODE
;In BYTBLT, use DCRNXT, DLFNXT instead of CRNXT, LFNXT
;<4.MONITOR>IO.MAC.257, 12-Jun-79 18:18:31, EDIT BY MILLER
;RANDOM FIXES FOR HANDLING 0 AND 1 BYTE RECORDS
;<4.MONITOR>IO.MAC.256, 6-Jun-79 09:22:22, EDIT BY OSMAN
;tco 4.2256 - give crlf's at end-of-record for appropriate tapes
;<4.MONITOR>IO.MAC.255, 28-Mar-79 12:40:25, Edit by LCAMPBELL
; Better error code from CHKJFN when large (but potentially legal) JFN given
;<4.MONITOR>IO.MAC.254, 4-Mar-79 17:29:14, EDIT BY KONEN
;UPDATE COPYRIGHT FOR RELEASE 4
;<4.MONITOR>IO.MAC.253, 2-Feb-79 13:41:42, EDIT BY MILLER
;FIXES TO RECORD PROCESSING
;<4.MONITOR>IO.MAC.252, 20-Jan-79 14:42:45, EDIT BY MILLER
;ADD RECF CODE SO CAN RETURN A NULL RECORD
;<4.MONITOR>IO.MAC.251, 9-Jan-79 11:40:59, EDIT BY MILLER
;IF CALL TO RECOUT FAILS, DO FILABT INSTEAD OF JRST EMRET0
;<4.MONITOR>IO.MAC.250, 6-Jan-79 13:03:55, EDIT BY MILLER
;CHECK FOR EOFF AT DUMPIW
;<4.MONITOR>IO.MAC.249, 10-Dec-78 15:10:27, EDIT BY MILLER
;<4.MONITOR>IO.MAC.248, 8-Dec-78 17:25:21, EDIT BY MILLER
;ADD HLDF TEST TO UNLDIS. REMOVE SPECIAL TESTS FOR FE AND CDR
;<4.MONITOR>IO.MAC.247, 8-Dec-78 16:58:37, EDIT BY MILLER
;CHECK FOR CDBBLK AT UNLDSN AND HOLD PROCESS IN BALSET IF SO
;<4.MONITOR>IO.MAC.246, 13-Nov-78 11:22:36, EDIT BY MILLER
;PASS BLOCK PARAMETERS TO "RECORD OUT" ROUTINE
;<2MCLEAN>IO.MAC.245, 10-Oct-78 23:58:34, Edit by MCLEAN
;<2MCLEAN>IO.MAC.244, 3-Oct-78 00:13:14, Edit by MCLEAN
;<4.MONITOR>IO.MAC.244, 4-Oct-78 16:37:08, EDIT BY GILBERT
;More TCO 4.2008 - fix an editing error.
;<4.MONITOR>IO.MAC.243, 2-Oct-78 23:03:21, Edit by MCLEAN
;REMOVE CALL TO APPNUL FROM SOUTB (YOU CAN'T GET THERE WITH JFN
;BEING A STRING POINTER) ALSO OTHER SPEEDUPS.
;<4.MONITOR>IO.MAC.242, 14-Sep-78 20:55:48, EDIT BY GILBERT
;TCO 4.2008 - Make ESOUT JSYS skip CRLF if already at beginning of line.
;<4.MONITOR>IO.MAC.241, 10-Aug-78 01:12:12, Edit by MCLEAN
;FIX CO-ROUTINES TO CHECK FOR CHANGE IN JFN
;<4.MONITOR>IO.MAC.240, 10-Aug-78 01:11:47, Edit by MCLEAN
;<4.MONITOR>IO.MAC.239, 21-Jul-78 11:24:24, EDIT BY MILLER
;FIX TYPEO IN UNLDIS
;<4.MONITOR>IO.MAC.238, 21-Jul-78 08:49:22, EDIT BY MILLER
;REPLACE PSOUT IN ESOUT WITH IMCALL
;<4.MONITOR>IO.MAC.237, 20-Jul-78 14:31:20, EDIT BY MILLER
;FIX ESOUT TO DO PSOUT INTEAD OF JUMPING INTO JSYS
;<4.MONITOR>IO.MAC.236, 7-Jul-78 09:19:41, EDIT BY MILLER
;ADD SOME COMMENTS TO DMOCHK
;<4.MONITOR>IO.MAC.235, 7-Jul-78 09:15:48, EDIT BY MILLER
;USE ULKSTR TO UNLOCK STRUCTURES
;<4.MONITOR>IO.MAC.234, 29-Jun-78 11:25:21, EDIT BY MILLER
;MAKE SURE STRDMO IS NOINT WHEN IT HAS STRLOK LOCKED
;<4.MONITOR>IO.MAC.233, 22-Jun-78 14:41:46, EDIT BY MILLER
;REMOVE NOSKEDS THAT PROTECTED SDBS. USE "LOCK STRLOK"
;<4.MONITOR>IO.MAC.232, 3-Jun-78 20:24:36, Edit by JBORCHEK
;REMOVE DMPBUF TO STG
;<4.MONITOR>IO.MAC.231, 9-Mar-78 08:54:31, EDIT BY MILLER
;DON'T BACK UP PC ON QUOTA EXCEEDED IF ALREADY DONE
;<4.MONITOR>IO.MAC.230, 8-Mar-78 16:39:41, EDIT BY MILLER
;JUMP TO EMRET0 AT UNLDS1 IF ERRF SET
;<4.MONITOR>IO.MAC.229, 2-Mar-78 12:47:36, EDIT BY MILLER
;FIX NEW SINR CODE NOT TO CLOBBER A
;<3A.MONITOR>IO.MAC.4, 2-Mar-78 09:27:43, EDIT BY MILLER
;MORE FIXES FOR SINR RUNNING OUT
;<4.MONITOR>IO.MAC.227, 2-Mar-78 08:13:13, EDIT BY MILLER
;SINR CODE MUST INSURE ALL OF RECORD IS IN BEFORE ABORTING
;<4.MONITOR>IO.MAC.226, 27-Feb-78 17:15:50, EDIT BY MILLER
;REMOVE CODE FROM UNLDIS THAT CHECKS FOR JSYS. DIDN'T WORK
;<4.MONITOR>IO.MAC.225, 27-Feb-78 14:26:26, Edit by BORCHEK
;fix dumpo doing goto words wrong at dumpo4+2
;<4.MONITOR>IO.MAC.224, 18-Feb-78 16:04:38, EDIT BY MILLER
;MORE FIXES. DON'T DIDDLE PC IF PREVIOUS-CONTEXT IS MONITOR
;<4.MONITOR>IO.MAC.223, 18-Feb-78 15:39:59, EDIT BY MILLER
;FIX UNLDIS TO NOT BACK UP PC ON QUOTA ERROR IF ALREADY BACKED-UP
;<4.MONITOR>IO.MAC.222, 31-Jan-78 12:29:38, Edit by HALL
;ADDED ATSMOV
;<4.MONITOR>IO.MAC.221, 28-Jan-78 23:24:19, Edit by PORCHER
;Fix bugs in CREADF
;<4.MONITOR>IO.MAC.220, 28-Jan-78 14:46:17, EDIT BY PORCHER
;Combine TRVAR and STKVAR in SINR
;<4.MONITOR>IO.MAC.219, 27-Jan-78 09:54:58, EDIT BY PORCHER
;Add routines SREADF and CREADF for Execute-Only
;Also change CHKJFN to restrict access to single process
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1976,1977,1978,1979 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
SEARCH PROLOG
TTITLE IO
SWAPCD
;SPECIAL AC DEFINITIONS USED HEREIN
DEFAC (STS,P1) ;SEE GTJFN FOR FUNCTIONS
DEFAC (JFN,P2)
DEFAC (DEV,P4)
;BYTBLT COMMUNICATION REGISTER FLAGS:
MSKSTR(XFR2TM,D,1B0) ;TRANSFER STRING TO TERMINATOR (TURNED OFF
; WHEN TERMINATOR READ)
MSKSTR(XFRTRM,D,1B1) ;TRANSFER TERMINATOR
MSKSTR(STRSRC,D,1B2) ;SOURCE BYTE POINTER IS A STRING
;---------
MSKSTR(FLINPT,D,1B3) ;ON WHEN DOING SIN FROM FILE
MSKSTR(BBDONE,D,1B4) ;SET WHEN BYTBLT IS DONE TO EXIT SIN/SOUT LOOPS
MSKSTR(XFRLSN,D,1B5) ;SET FOR BYTBLT TO COPY LINE NUMBERS
;---------
MSKSTR(DISCRD,D,1B6) ;SET BY BYTBLT TO HAVE CALLER DISCARD THE
; TAB AFTER A LINE NUMBER.
MSKSTR(FEEDME,D,1B7) ;SET BY BYTBLT WHEN SOURCE STRING RUNS OUT WHILE
; WHILE SCANNING LINE NUMBERS OR NULLS
;---------
;NOTE: KEEP THESE TOGETHER. SEE REFS TO CRSTUF AND DCRSTF
MSKSTR(DCRNXT,D,1B8) ;TELL BYTBLT TO DELIVER A CARRIAGE RETURN NEXT
MSKSTR(DLFNXT,D,1B9) ;LINEFEED NEXT
MSKSTR(DFRSTF,D,1B10) ;THIS RECORD HAS BEEN FROSTED ALREADY
MSKSTR(DCRSTF,D,DCRNXT!DLFNXT!DFRSTF) ;COMPOSITE CR STUFF FIELD
BBLTMM==0 ;DATA DIRECTIONS - BYTBLT MON TO MON
BBLTMU==1 ;MONITOR TO USER
BBLTUM==2 ;USER TO MONITOR
BBLTUU==3 ;USER TO USER
DEFINE FILINT(N,EXTRA)<
CALL [EXTRA
MOVEI A,N
JRST DOINT]>
DEFINE FILABT(N,EXTRA)<
JRST [ EXTRA
MOVEI A,N
JRST ABTDO]>
DOINT: MOVEM JFN,ERRSAV
MOVEM A,LSTERR
TQNE <HLTF>
JRST ABTDO ;Halt on these conditions
MOVE T1,MPP ;GET BASE LEVEL PUSH DOWN LIST
MOVE T2,-1(T1) ;GET PC
MOVE T1,(T1) ;GET ADR OF JSYS+1(FLAGS)
CALL CHKERT ;IS THERE AN ERJMP OR ERCAL AFTER JSYS?
SKIPA T1,BITS+.ICDAE ;NO, GO DO INTERRUPT
RET ;YES, DONT CAUSE INTERRUPT
CALL IICSLF ;INTERRUPT THIS FORK
RET
ABTDO: MOVEM A,LSTERR
CALL UNLCKF
ITERR()
RESCD
SK3RET::AOS (P)
SK2RET::AOS (P)
AOS (P)
CPOPJ:: RET
SKPUNL:: AOS -1(P)
UNL:: CALL UNLCKF
JRST MRETN
SWAPCD
;CHECK STATUS OF JFN OR OTHER DESIGNATOR
; T1/ DESIGNATOR
; CALL CHKJFA
; RETURN +1 FAILURE, BAD DESIGNATOR. T1/ ERROR CODE
; RETURN +2 SUCCESS,
; T1/ DESIGNATOR TYPE CODE
; 0 (JF%FIL) - A REGULAR JFN
; 1 (JF%TTY) - A TTY DESIGNATOR
; 2 (JF%BYP) - A BYTE POINTER OR NULL
; T2/ THE CURRENT FILE STATUS
; T3/ UNIT NUMBER,,DEVICE DISPATCH TABLE ADDRESS
; T4/ JFN INDEX
;THIS IS MERELY A JACKET ROUTINE FOR CHKJFN WHICH FOLLOWS
;THE STANDARD SUBROUTINE CONVENTIONS.
; ***N.B.*** THIS DOES NOT LEAVE THE JFN LOCKED NOR GO NOINT.
;CODES
JF%FIL==:0 ;FILE
JF%TTY==:1 ;TTY DESIGNATOR
JF%BYP==:2 ;BYTE POINTER
CHKJFA::SAVEP
MOVE JFN,T1 ;SETUP THE JFN
CALL CHKJFN ;DO THE WORK
RETBAD () ;BAD DESIGNATOR
JRST [ MOVX T1,JF%TTY ;A TTY
JRST CHKJA1]
JRST [ MOVX T1,JF%BYP ;A BYTE POINTER
JRST CHKJA1]
CALL UNLCKF ;REGULAR JFN, UNLOCK IT
MOVX T1,JF%FIL ;REGULAR JFN
CHKJA1: MOVE T2,STS ;RETURN STATUS
MOVE T3,DEV ;AND DEVICE
MOVE T4,JFN ;AND INDEX
RETSKP
; Check tenex source/destination designator
; Call: JFN ;The designator
; CALL CHKJFN
; Return
; +1 ;Error, A has error #
; +2 ;Tty
; +3 ;Byte pointer OR NULL
; +4 ;File - REAL JFN
; In all cases, the following is set up
; LH(DEV) ;Unit number
; RH(DEV) ;Loc of device dispatch table
; P3 ;RH OF DEV
; JFN ;True jfn for files, byte pointer for same
; STS ;File status bits
; DOES NOT CLOBBER B AND C
; The file is locked if it is a file
; If previous context section (PCS) is zero OWGBPs will not be allowed
; as designators. Non-skip return will result.
;
; If PCS is non-zero then OWGBPs will be allowed. The UDX form of TTY
; designator will not be allowed from a non-zero PCS. The .TTDES form
; of TTY designator is allowed from non-zero PCS
CHKJFD::TDZA D,D ;REMEMBER TO SKIP DISMOUNTED CHECK
CHKJFN::SETO D, ;CHECK FOR DISMOUNTED STRUCTURE
CAIN JFN,.PRIIN ;PRIMARY INPUT?
HLRZ JFN,PRIMRY ;YES. GET INPUT JFN
CAIN JFN,.PRIOU ;PRIMARY OUTPUT?
HRRZ JFN,PRIMRY ;YES. GET OUTPUT JFN
SKIPLE JFN ;IS THIS A REAL JFN
CAML JFN,MAXJFN ;...
JRST CHKJFS ;NO, GO CHECK FOR OTHER LEGAL JFN FORMS
IMULI JFN,MLJFN ;GET INDEX NTO JFN TABLES
NOINT
AOSE FILLCK(JFN) ;LOCK THE JFN LOCK
JRST [ OKINT ;FAILED
JRST CHKJ3A] ;GO WAIT FOR THE LOCK TO FREE UP
MOVE STS,FILSTS(JFN) ;SET UP THE REQUIRED ACS
TQNE <FRKF> ;NO ACCESS BY OTHER FORKS?
JRST CHKJ2B ;YES, GO CHECK IF ACCESS IS LEGAL
MOVE DEV,FILDEV(JFN) ;SET UP DEV
HRRZ P3,DEV ;AND P3
CAIE P3,DSKDTB ;IS THIS A DISK?
JRST CHKJ2A ;NO, GO CHECK OTHER SPECIAL CASES
LOCK STRLOK ;PREVENT DISMOUNTING
LOAD A,FILUC,(JFN) ;GET STR UNIQUE CODE
LOAD P5,STR,(JFN) ;GET STR NUMBER
SKIPN P5,STRTAB(P5) ;GET THE SDB ADDRESS
JRST [ UNLOCK STRLOK ;DISMOUNTED
SETZB F,P5
JUMPE D,SK3RET ;IF DONT CARE, EXIT OK
JRST CHKJDM] ;OTHERWISE, GO RETURN FAILURE
LOAD CX,STRUC,(P5) ;GET UNIQUE CODE FOR THIS STR
CAME A,CX ;DO THEY MATCH?
JRST [ UNLOCK STRLOK ;NO
SETZB F,P5
JUMPE D,SK3RET ;IF DONT CARE, EXIT OK
JRST CHKJDM] ;OTHERWISE, GO RETURN FAILURE
INCR STRLK,(P5) ;LOCK THE STR LOCK
NOINT ;LEAVE THIS PROCESS NOINTED
UNLOCK STRLOK ;ALLOW DISMOUNTS NOW
SETZB F,P5
JRST SK3RET ;ALL DONE
CHKJFS: SETZB F,P5
TLNE JFN,777777 ;Lh zero?
JRST CHKJF1 ;No, some kind of byte pointer
CAIN JFN,777777 ;Controlling tty
JRST CHKJF4 ;Yes
CAIN JFN,377777 ;Nil designator
JRST CHKJFW ;Yes.
CHKJFT: CAIGE JFN,400000+NLINES ;Valid tty designator?
CAIGE JFN,400000
JRST [ JUMPLE JFN,CHKJF7 ;REJECT NONPOSITIVE VALUES
IMULI JFN,MLJFN ;CONVERT TO REAL JFN
CAIL JFN,RJFN ;COULD THIS EVER BE A JFN?
JRST CHKJF7 ;no, give invalid s/d designator return
MOVEI A,DESX3 ;yes, give JFN not assigned return
RET] ; ..
PUSH P,C ;CAN'T CLOBBER C
PUSH P,B ; OR B
MOVEI B,-.TTDES(JFN) ;B/ LINE NUMBER
CALL GTCJOB ;GET CONTROLLING JOB
JRST [ POP P,B ;NONE. RESTORE B
POP P,C ; AND C
JRST CHKJF5] ;OK TO USE
POP P,B ;RESTORE B
CAIE C,-1 ;ASSIGNED TO ANY JOB?
CAMN C,JOBNO ;YES. assigned to this job?
JRST [ POP P,C ;OK TO USE
JRST CHKJF5]
POP P,C
MOVE A,CAPENB
TRNE A,SC%WHL!SC%OPR
JRST CHKJF5
MOVEI A,-400000(JFN)
CALL PTCHKA ;TEST FOR PTY OWNER
JUMPN A,CHKJF5 ;TRUE = OK BECAUSE CONTROLLED BY PTY
MOVEI A,DESX2 ;Illegal tty designator
RET
CHKJF5: MOVEI DEV,TTYDTB ;SET DEVICE TO BE TTY
HRLI DEV,-400000(JFN) ;AND SPECIFIED UNIT
JRST CHKJT1
CHKJF4: HRRZ A,FORKN ;GET OUR JOB FORK NUMBER
LOAD JFN,FRKTTY,(A) ;GET FORK'S CONTROLLING TERMINAL
CAIE JFN,-1 ;ONE SPECIFIED?
JRST CHKJFT ;YES, GO CHECK IT
MOVE A,JOBNO ;NO, THEN USE JOB'S CONTROLLING TERMINAL
HLLZ DEV,JOBPT(A) ;GET IT
HRRI DEV,TTYDTB ;SET DEVICE TO BE TTY
CHKJT1: MOVX STS,READF!WRTF!OPNF!PASLSN
HRRZ P3,DEV
RETSKP ;Skip return
CHKJFW: MOVEI DEV,NILDTB
HRRZ P3,DEV
MOVX STS,READF!WRTF!OPNF!PASLSN
JRST SK2RET
;CHKJF3: JUMPE JFN,CHKJFB ;0 NEVER EXISTS
; IMULI JFN,MLJFN
CHKJ3A: MOVEI A,^D60 ;Try 60 times to lock file
CHKJF2: SOJL A,CHKJFB ;Then fail
NOINT
AOSE FILLCK(JFN)
JRST [ OKINT
PUSH P,A
MOVEI A,^D1000
DISMS
POP P,A
JRST CHKJF2]
CHKJ2A: MOVE STS,FILSTS(JFN)
TQNN <NAMEF>
JRST CHKJF8
TQNN <FRKF> ;Test for file restricted to one fork
JRST CHKJF9
CHKJ2B: HLRZ A,FILVER(JFN)
REPEAT 0,< ;Restricted-access now means just the current process
PUSH P,D ;SAVE ENTRY FLAG
CALL SKIIF ;OWNER INFERIOR TO THIS FORK?
JRST CHKJF8 ;NO, ACCESS ILLEGAL
POP P,D ;RESTORE ENTRY FLAG
> ;End of REPEAT 0
CAME A,FORKN ;This owning process?
JRST CHKJF8 ;No, access illegal
CHKJF9: MOVE DEV,FILDEV(JFN) ;Set up dev
HRRZ P3,DEV
SETZB F,P5
CAIN P3,TTYDTB ;IS THIS A TERMINAL?
JRST [ HLRZ A,FILDDN(JFN) ;YES, GET ADDRESS OF DEVICE NAME BLOCK
MOVE A,1(A) ;GET NAME
TRZ A,377 ;FLUSH POSSIBLE GARBAGE
CAME A,[ASCIZ /TTY/] ;IS DEVICE "TTY"?
JRST .+1 ;NO, SO DEV IS CORRECT ALREADY
MOVE A,FORKN ;YES, GET FORK NUMBER
LOAD A,FRKTTY,(A) ;GET POSSIBLE FORK'S CONTROLLING TERMINAL
HRLI DEV,-.TTDES(A) ;SET UP UNIT NUMBER
CAIN A,-1 ;IS THERE REALLY A FORK CONTROLLING TERMINAL?
HRL DEV,CTRLTT ;NO, SO USE JOB'S CONTROLLING TERMINAL
JRST .+1]
CAIE P3,PTYDTB
CAIN P3,TTYDTB
JRST [ SETOM FILLCK(JFN)
OKINT
JRST .+1]
MOVEI A,0(JFN) ;GET THE JFN
PUSH P,D ;SAVE ENTRY FLAG
CALL STRDMO ;CHECK IF DISMOUNTED AND BUMP LOCK
JRST [ POP P,D ;GET BACK ENTRY CODE
JUMPE D,SK3RET ;IF DONT CARE ABOUT DISMOUNTED STRS, EXIT
JRST CHKJDM] ;OTHERWISE, GIVE FAILURE RETURN
POP P,(P) ;CLEAN UP THE STACK
JRST SK3RET ;Triple skip return
CHKJDM: UNLOCK FILLCK(JFN) ;CLEAN UP
OKINT
RETBAD (DESX10) ;AND GIVE DISMOUNTED ERROR RETURN
CHKJF8: UNLOCK FILLCK(JFN)
OKINT
CHKJFB: MOVEI A,DESX3
RET
CHKJF1: JUMPGE JFN,CHKJF6
HLRZ A,JFN ;GET LEFT HALF
CALL SPCSNZ ;DID JSYS COME FROM A NON-ZERO SECTION?
CAIE A,600000+.DVTTY ;NO...CHECK THIS FORM OF TTY DESIGNATOR?
JRST CHKJF0 ;FROM A NONZERO SECTION OR NOT A TTY UDX
PUSH P,JFN ;YES, GAVE TTY DEVICE DESIGNATOR
MOVEI JFN,400000(JFN) ;CREATE TERMINAL DESIGNATOR
CALL CHKJFT ;CHECK THIS TERMINAL
JRST CHKBTY ;BAD TERMINAL
JRST CHKGTY ;GOOD TERMINAL
CAIA ;BYTE POINTER ISN'T A TERMINAL
JFCL ;NEITHER IS A REAL JFN
CHKBTY: POP P,JFN ;RESTORE ORIGINAL BAD DESIGNATOR
RET ;ASSUME ERROR CODE IN A
CHKGTY: POP P,JFN ;RESTORE GOOD DESIGNATOR
HRRZ P3,DEV
RETSKP
CHKJF0: CAML JFN,[777777,,0]
HRLI JFN,440700 ;Insert if lh = 777777
MOVX A,<770000,,0> ;ASSUME NON-ZERO PCS
CALL SPCSNZ ;NON-ZERO PCS?
MOVX A,<444500,,0> ;NO...ZERO PCS...OWGBPS ILLEGAL
CAMGE JFN,A ;BYTE POINTER IN RANGE
JRST CHKJF6 ;YES
CHKJF7: MOVEI A,DESX1 ;Garbage designator
RET
CHKJF6: MOVEI DEV,STRDTB ;Set up to dispatch to string routines
HRRZ P3,DEV
MOVX STS,READF!WRTF!OPNF!PASLSN
JRST SK2RET ;Double skip return
;CHECK DSK JFN - ACCEPTS ONLY JFN FOR DEVICE DSK
; JFN/ A DESIGNATOR
; CALL DSKJFN
; RETURN +1: FAILURE, ERROR CODE IN A
; RETURN +2: SUCCESS, REGISTERS SETUP AS FOR CHKJFN
DSKJFN::CALL CHKFIL ;CHECK FOR A FILE JFN
RETBAD () ;WASN'T
TQNE <ASTF> ;RULE OUT STARS
JRST [ MOVEI A,DESX7
CALLRET UNLCKF]
HRRZ B,DEV
CAIN B,DSKDTB ;DISK?
RETSKP ;YES
MOVEI A,DESX8 ;NO
CALLRET UNLCKF
;CHECK FILE JFN - REJECTS TTY OR BYTE DESIGNATORS
; JFN/ A DESIGNATOR
; CALL CHKFIL
; RETURN +1: FAILURE, ERROR CODE IN A
; RETURN +2: SUCCESS, REGISTERS SETUP AS FOR CHKJFN
CHKFIL::CALL CHKJFN
RETBAD() ;BAD DESIGNATOR
JFCL
RETBAD(DESX4) ;ILLEGAL DESIGNATOR
RETSKP
;ROUTINE TO GET PROTECTION AND DIR # OF A FILE (CALLED BY CHKAC)
;ACCEPTS IN T1/ JFN
;RETURNS +1: ERROR
; +2: T1/ DIR #
; T2/ PROT
GETFPD::SAVEPQ ;SAVE ALL PERMENANT ACS
MOVE JFN,T1 ;SET UP FOR CHKJFN
CALL DSKJFN ;MAKE SURE IT IS A DSK JFN
RETBAD ;IT ISNT
CALL GETFDB ;MAP IN FDB
RETBAD (,<ULKDIR
CALL UNLCKF>)
HRRZ T2,.FBPRT(T1) ;GET PROTECTION
LOAD T1,FILUC,(JFN) ;GET STR #
HRLZS T1
HRR T1,FILDDN(JFN) ;AND DIR #
ULKDIR ;UNLOCK DIR FROM GETFDB CALL
CALL UNLCKF ;UNLOCK THE JFN
RETSKP ;AND RETURN
; Unlock file
; Call: JFN ;Job file number
; STS ;New filsts
; CALL UNLCKF
;PRESERVES A IN CASE ERROR CODE THEREIN
UNLCKF::TLNE JFN,777777
UMOVEM JFN,1
SKIPLE JFN
CAIL JFN,RJFN
RET
PUSH P,A
MOVEI A,(DEV)
CAIE A,DSKDTB ;DISK JFN?
JRST UNLKF1 ;NO
MOVEM STS,FILSTS(JFN) ;YES, STORE STS
LOAD A,STR,(JFN) ;GET THE STR NUMBER
PUSH P,B ;SAVE AN AC
SKIPN B,STRTAB(A) ;IS THIS STR STILL THERE?
JRST UNLKF2 ;NO
LOAD B,STRUC,(B) ;GET THE UNIQUE CODE OF THE STR
LOAD CX,FILUC,(JFN) ;GET UNIQUE CODE
CAME CX,B ;MATCH?
JRST UNLKF2 ;NO
CALL ULKSTR ;YES. UNLOCK THE STR LOCK
UNLKF2: SETOM FILLCK(JFN) ;UNLOCK THE JFN
POP P,B ;RESTORE ACS
POP P,A
OKINT
RET ;ALL DONE
UNLKF1: CAIE A,PTYDTB
CAIN A,TTYDTB
JRST [ POP P,A
CAMN DEV,FILDEV(JFN) ;IS THIS THE SAME JFN?
MOVEM STS,FILSTS(JFN) ;YES. SAVE UPDATED STATUS THEN
RET]
MOVEM STS,FILSTS(JFN) ;SAVE NEW FILE STATUS BITS
MOVEI A,0(JFN) ;GET JFN
CALL LUNLKF ;DO UNLOCK
POP P,A
OKINT
RET
NOTOPN: FILABT CLSX1
IOERR:: MOVEM A,LSTERR
JRST ITRAP
;ROUTINE TO UNLOCK A FILE AND IF FILE IS ON A MOUNTABLE STRUCTURE
;TO DECREMENT THE LOCK COUNT IN THE SDB.
; ACCEPTS: 1/ JFN
LUNLKF::CALL LUNLK0 ;FREE UP FILE LOCK IN SDB
SETOM FILLCK(A) ;RELEASE LOCK
RET ;AND DONE
;ROUTINE TO RELEASE FILE LOCK FOR A JFN.
; 1/ THE JFN
LUNLK0::SAVET ;SAVE ALL REGISTERS
CALL DMOCHK ;CHECK IF MOUNTED
RET ;ITS NOT. GIVE IT UP
JUMPE B,R ;IF NOT MOUNTABLE, GIVE IT UP
LOAD A,STR,(A) ;IT IS. GET STR NUMBER
CALLRET ULKSTR ;UNLOCK STRUCTURE
;ROUTINES TO CHECK IF A STRUCTURE HAS BEEN DISMOUNTED
;STRDMO: CHECK IF A STRUCTURE IS STILL MOUNTED AND IF SO
;INCREMENTS THE LOCK COUNT IN THE SDB.
; ACCEPTS: 1/JFN
; RETURNS: +1 IF STRUCTURE HAS BEEN DISMOUNTED
; +2 IF STRUCTURE IS STILL MOUNTED. LOCK COUNT INCREMENTED
; OR IF NOT A MOUNTABLE STRUCTURE
STRDMO::SAVET ;SAVE ALL REGS
NOINT ;MAKE SURE CAN'T BE INTERRUPTED
LOCK STRLOK ;PREVENT DISMOUNTS
CALL DMOCHK ;CHECK STRUCTURE
RETBAD (DESX10,<UNLOCK STRLOK
OKINT>) ;DISMOUNTED
JUMPE B,STRDM1 ;IF NOT MOUNTABLE, JUST GO AWAY
INCR STRLK,(B) ;STILL MOUNTED. BUMP LOCK COUNT
NOINT ;MUST BE NOINT FOR EVERY LOCK HELD
STRDM1: UNLOCK STRLOK ;ALLOW DISMOUNTS NOW
OKINT ;NO LONGER HAVE THE LOCK
RETSKP ;AND RETURN
;ROUTINE TO CHECK IF A STRUCTURE IS STILL MOUNTED.
; ACCEPTS: 1/ JFN
; RETURNS: +1 IF STRUCTURE HAS BEEN DISMOUNTED
; +2 IF STRUCTURE STILL MOUNTED
; B= SDB INDEX
; OR B=0 IF A VALID JFN ON A NON-MOUNTABLE
; DEVICE
;PRESERVES A
DMOCHK::LOAD C,FILUC,(A) ;GET UNIQUE CODE
SETZ B, ;IN CASE NOT A MOUNTABLE STRUCTURE
JUMPE C,RSKP ;IF NO UNIQUE CODE, STILL MOUNTED
LOAD D,STR,(A) ;GET STRUCTURE NUMBER
SKIPN B,STRTAB(D) ;GET SDB POINTER
RET ;NONE ,STRUCTURE HAS BEEN DISMOUNTED
LOAD D,STRUC,(B) ;GET UNIQUE CODE
CAME D,C ;SAME?
RET ;NO. STRUCTURE HAS BEEN DISMOUNTED
RETSKP ;YES. STRUCTURE STILL MOUNTED
; Subroutines for Execute-Only
;
; SREADF - Set READ access and restrict access to this process
;
; Call:
; T1/ JFN
; CALL SREADF
;
; Returns:
; +1: Always
; T2/ Previous state of FRKF and READF in LH,
; process for FRKF in RH
; Clobbers T1
;
SREADF::
MOVX T2,READF!FRKF ;Get desired state of bits
HRR T2,FORKN ; and current process
; CALLRET CREADF ;Set up bits and process
;
;
; CREADF - Reset READ access and restricted access
; (Undo what SREADF did)
;
; Call:
; T1/ JFN
; T2/ Previous state of FRKF and READF in LH,
; process for FRKF in RH
;
; Returns:
; +1: Always
; Clobbers T1,T2
;
CREADF::
SAVEP ;Save all the P's
PUSH P,F ;Also save F
PUSH P,T2 ;Save argument
MOVE JFN,T1 ;Get JFN for CHKJFN
CALL CHKJFN ;Check out the JFN and lock it, etc.
JFCL ;Invalid JFN, just ignore it
JFCL ;Terminal
JRST [ ;Byte pointer
POP P,T2 ;Not a file-- just return calling argument
POP P,F ;Restore F
RET] ;And return from CREADF/SREADF
;Yes! we have a real file!
MOVE T2,STS ;Get current status
ANDX T2,<FRKF!READF> ;Clear all but restricted access and READ
HLR T2,FILVER(JFN) ;Get process (JRFN) for restricted access
EXCH T2,(P) ;Save current state on stack
; and get desired state from call
HRLM T2,FILVER(JFN) ;Set new process id
TQZ <FRKF,READF> ;Clear current state of FRKF and READF
HLLZ T2,T2 ;Get desired state of bits
TDO STS,T2 ;Set them in STS
POP P,T2 ;Restore previous state of bits and process
POP P,F ;Restore F
CALLRET UNLCKF ;Unlock JFN, restore P's, and return from SREADF/CREADF
; Bin from primary io file
; Call: 1 ;Character
; PBIN
.PBIN:: MCENT
MOVEI JFN,100
CALL BYTIN
JRST EMRET0 ;CHECK FOR ERJMP OR ERCAL AFTER JSYS
UMOVEM B,1
JRST MRETN
; Byte input jsys
; Call: 1 ;Tenex source designator
; BIN
; Return
; +1
; B ;A byte
.BIN:: MCENT
NOINT
JUMPLE 1,SLBIN
CAIE 1,.PRIIN ;PRIMARY INPUT?
CAIN 1,.PRIOU ;OR PRIMARY OUTPUT?
JRST SLBIN ;YES. DO THE IT THE SLOW WAY
CAML 1,MAXJFN ;POSSIBLY A JFN?
JRST SLBIN
IMULI A,MLJFN
TQZ <NSPNUL> ;NOT A NULL NSP MESSAGE
AOSE FILLCK(1)
JRST SLBIN0
CALL STRDMO ;VERIFY STRUCTURE
JRST SLBIN1 ;BEEN DISMOUNTED
MOVE STS,FILSTS(1)
TQNE <ACRLFF> ;ADDING CRLF'S?
JRST SLBIN1 ;YES, DO IT THE SLOW WAY, SINCE BYTIN KNOWS HOW.
TQC <OPNF,READF,FILINP>
TQCN <OPNF,READF,FILINP>
TQNE <ERRF,FRKF>
JRST SLBIN1
BIN1: SOSGE FILCNT(1)
JRST SLBIN2
AOS 2,FILBYN(1)
CAMLE 2,FILLEN(1)
JRST SLBIN3
ILDB 2,FILBYT(1)
TQNN <PASLSN> ;DOES USER WANT LINE NUMBERS?
JRST [ JUMPE 2,BIN1 ;DISCARD NULLS
HRRZ C,FILBYT(1);GET THE WORD WE'RE READING
MOVE C,0(C) ;DO INDIRECT
TXNE C,1B35 ;IS IT A LINE NUMBER?
JRST SLBIN4 ;YES, REDO READ VIA BYTIN
JRST .+1]
CALL LUNLKF ;FREE UP FILE
UMOVEM 2,2
JRST MRETN
SLBIN4: MOVX C,7B5 ;FIXUP BYTE POINTER WE WERE READING FROM
ADDM C,FILBYT(1) ; SO THAT BYTIN WORKS RIGHT
SLBIN3: SOS FILBYN(1)
SLBIN2: AOS FILCNT(1)
SLBIN1: CALL LUNLKF ;FREE UP FILE
SLBIN0: IDIVI 1,MLJFN
SLBIN: OKINT
MOVE JFN,1
CALL BYTIN ;Read the byte
JRST [ XCTU [SETZM 2] ;RETURN A ZERO IN 2
JRST EMRET0] ;GO GIVE NON-SKIP RETURN
XCTU [MOVEM B,2] ;Store in user's ac
JRST MRETN ;Restore user ac's and return
; Random input jsys
; Call: 1 ;Tenex source designator
; 3 ;Byte number
; RIN
; Returns
; +1
; 2 ;The byte
.RIN:: MCENT
TRVAR <SAVJFN>
RIN0: UMOVE JFN,1
MOVEM JFN,SAVJFN
CALL CHKJFN
JRST IOERR
JFCL
FILABT DESX4 ;Tty and byte designators are illegal
TQNN <OPNF> ;OPEN?
JRST NOTOPN ;NO
TQNN <RNDF>
FILABT IOX3 ;Illegal to change pointer
TQNN <READF>
FILABT IOX1 ;Illegal to read
CALL @JFNID(P3) ;INIT JFN FOR INPUT
UMOVE A,3
CALL SFBNR ;Set up byte pointer
JRST ABTDO
CALL BYTINA ;Get the byte
JRST RINW ;DEVICE SERVICE ROUTINE IS BLOCKING
UMOVEM B,2
CALL UNLCKF ;UNLOCK THE JFN
JRST MRETN
RINW: JUMPN A,[CALL UNLCKF ;IF ERROR, UNLOCK THE JFN
XCTU [SETZM 2] ; LEAVE BYTE AS 0
JRST EMRET0] ; AND GIVE ERROR RETURN
MOVE A,B ;GET MDISMS WORD
CALL UNLDIS ;UNLOCK THE JFN AND MDISMS
JRST RIN0 ;GO TRY AGAIN
; String input jsys'S
; Call: 1 ;Tenex source designator
; 2 ;Byte pointer (lh = 777777 will be filled in)
; 3 ;Byte count or zero
; ;If zero, the a zero byte terminates
; ;If positive then transfer the specified number
; ;Of characters, or terminate on reading a byte
; ;Equal to that given in 4
; ;If negative, then transfer the specified number
; ;Of bytes
; 4 ;(optional) if 3 is > 0, 4 has a terminating byte
; SIN (OR SINR FOR RECORD MODE)
; Return
; +1 ;Always
; 2 ;Updated string pointer
; 3 ;Updated count (always counts toward zero)
; The updated string pointer always points to the last byte read
; Unless 3 contained zero, then it points to the last non-zero byte.
.SINR:: MCENT
SETO Q2, ;MARK THAT A SINR WAS DONE
JRST SINR1 ;ENTER COMMON CODE
.SIN:: MCENT ;Become slow etc.
SETZ Q2, ;MARK THAT A SIN WAS DONE
SINR1: TRVAR <SAVJFN,SINRF,SINZF>
SETZM SINZF ;ASSUME USER AC3 ZERO
XCTU [SKIPE 3] ;BUT TEST IT
SETOM SINZF ;USER AC3 IS NONZERO
MOVEM Q2,SINRF ;SAVE SIN/SINR FLAG
MOVSI C,440700
TLC 2,-1 ;SEE IF LH = -1
TLCN 2,-1
XCTU [HLLM C,2] ;YES, TURN IT INTO ASCII POINTER
SIN0: UMOVE T3,2 ;GET USERS POINTER
XCTBU [ILDB T3,T3] ;ATTEMPT TO GET A BYTE
UMOVE JFN,1
MOVEM JFN,SAVJFN
CALL CHKJFN ;CHECK THE JFN AND LOCK UP
JRST IOERR ;GIVE THE APPROPRIATE RETURN
JRST SINTTY ;TTY
JRST [ CAIE DEV,STRDTB
JRST SINTTY ;NOT BYTE PTR, DO BYTE AT A TIME
JRST SINBYT] ;BYTE POINTER
TQNE <OPNF> ;OPENED?
TQNN <READF>
FILABT(IOX1) ;ILLEGAL READ
CALL @JFNID(P3) ;INIT JFN FOR INPUT
TQZE <NSPNUL> ;WAS THERE A NULL NSP MESSAGE?
SKIPL SINRF ;YES, WAS THIS A SINR?
JRST SIN00E ;NO
CALL UNLCKF ;YES, SINR AND NULL NSP - UNLOCK THE FILE
JRST MRETN ;GOOD RETURN
SIN00E: MOVE B,FILLEN(JFN) ;GET TOTAL FILE LENGTH
SUB B,FILBYN(JFN) ;COMPUTE BYTES LEFT IN FILE
CAMGE B,FILCNT(JFN) ;THIS BUFFER PASSES EOF?
MOVEM B,FILCNT(JFN) ;YES, REDUCE BUFFER COUNT SO EOF WILL BE SEEN
SKIPG FILCNT(JFN) ;ANY BYTES IN BUFFER?
JRST SIN1 ;NO, DO IT THE SLOW WAY
SIN00: SKIPLE SINRF ;ABORTING A SINR?
JRST [ CALL UNLCKF ;YES. UNLOCK FILE
SETZM A ;GET A ZERO
EXCH A,FILCNT(JFN) ;GET REMAINING COUNT.
ADDB A,FILBYN(JFN) ;NEW FILE POSITION
JRST SIN01] ;AND PROCEED
CALL SIORX ;TRANSFER SOME DATA
MOVE A,FILBYN(JFN) ;SEE WHERE WE'RE UP TO IN THE FILE
CAML A,FILLEN(JFN) ;IF WE'RE AT END OF RECORD,
TQNN <ACRLFF> ;AND WE'RE SUPPOSED TO AUGMENT WITH CRLF'S
CAIA ;(WE'RE NOT)
JRST [ SKIPN SINRF ;SINR?
TQNN <FROSTF> ;DON'T START FROSTING IF ALREADY FROSTED
TQNE <LFNXT> ;AND WE'RE NOT IN THE MIDDLE OF A CRLF,
JRST .+1 ;IN MIDDLE OF FROSTING OR ALREADY FROSTED
TQO <CRNXT> ;THEN TELL BYTBLT TO PUT IN CRLF SEQUENCE NOW.
TQNN <BBDONE> ;SIORX WILL MISINTERPRET A 0 IN AC3!
CALL SIORX ;SO THE CRLF FOLLOWS THE RECORD
JRST .+1]
CALL UNLCKF ;UNLOCK FILE TO ALLOW INTS
SIN03: SKIPE SINRF ;DOING A SINR JSYS?
JRST [ MOVE A,FILBYN(JFN)
CAML A,FILLEN(JFN) ;ANY BYTES LEFT?
JRST MRETN ;NO, GIVE OK RETURN
TQNN <BBDONE> ;DONE?
JRST SIN0 ;NO, GO DO SOME MORE
ADD A,FILCNT(JFN) ;PICK UP REST OF BYTES IN BUFFER
MOVEM A,FILBYN(JFN) ;NEW FILE POSITION
SETZM FILCNT(JFN)
MOVEI B,1 ;REMEMBER DOING SINR ABORT
MOVEM B,SINRF
JRST SIN01] ;AND PROCEED
TQNN <BBDONE> ;IS BYTBLT FINISHED?
JRST SIN0 ;NO, JUST KEEP GOING
JUMPN Q1,MRETN ;IF NON-ZERO COUNT SUPPLIED, NO 0.
JRST SIN2 ;PUT THE ZERO ON THE END.
;ROUTINE CALLED FROM ABOVE TO TRANSFER SOME DATA.
SIORX: MOVE A,FILBYT(JFN) ;SOURCE POINTER
MOVX D,FLINPT!BBLTMU ;FROM FILE, COPY MONITOR TO USER
LOAD B,CRSTUF ;GET CARRIAGE RETURN STUFF
STOR B,DCRSTF ;COPY FOR BYTBLT
UMOVE B,2 ;TARGET
TQNE <PASLSN> ;COPYING LINE NUMBERS FROM FILE?
TQO <XFRLSN> ;YES, HAVE BYTBLT DO ALSO
CALL SIOR2 ;SET UP REST OF ARGS AND DO BYTBLT
UMOVEM B,2 ;UPDATE POINTERS
LOAD B,DCRSTF ;GET CARRIAGE RETURN STUFF
STOR B,CRSTUF ;STORE BACK INTO STATUS
MOVEM A,FILBYT(JFN)
RET
; DO SIN FROM BYTE POINTER
SINBYT: MOVE A,JFN
UMOVE B,2
MOVX D,STRSRC!XFRLSN!BBLTUU;STRING IN USER SPACE AND SHOULDN'T HAVE LINE #'S
CALL SIOR2
UMOVEM B,2
UMOVEM A,1
JRST SIN3
;GET HERE WHEN SINR RUNS OUT. CHECK FOR DONE
; A/ CURRENT FILE POSITION
SIN01: CAMGE A,FILLEN(JFN) ;AT EOR YET?
JRST SIN0 ;NO. KEEP TRYING
SIN02: FILINT (IOX10) ;YES. GIVE INT
MOVEI A,IOX10 ;GET ERROR CODE
JRST EMRET0 ;AND GIVE UP
;SIN WHICH MUST BE DONE BYTE-AT-A-TIME
SINTTY: CALL @JFNID(P3) ;INIT JFN FOR INPUT
SINTT1: CALL BYTINA ;Read a byte from the source
JRST SINW ;SERVICE ROUTINE WANTS TO BLOCK
JUMPE B,[TQNN <EOFF>
XCTU [SKIPN 3]
JRST SIN4
JRST .+1]
XCTBUU [IDPB B,2] ;DEPOSIT THE BYTE
CALL SIONXT ;Test for end of string
JRST SINTT1 ;Not end, continue
JRST UNL ;ALL DONE
SIN1: CALL BYTINS ;Read a byte from the source
JRST SINW ;SERVICE ROUTINE WANTS TO BLOCK
TQZE <RECF> ;EOR ENCOUNTERED?
JRST [ SKIPG SINRF ;ABORTING A SINR?
JRST SIN00 ;NO. PROCEED AS USUAL THEN
CALL UNLCKF ;YES.
JRST SIN03] ;TERMINATE THEN
SKIPLE SINRF ;DOING SINR ABORT?
JRST SIN00 ;YES. GO CHECK THEN
JUMPE B,[TQNN <EOFF>
XCTU [SKIPN 3]
JRST UNL
JRST .+1]
XCTBUU [IDPB B,2] ;DEPOSIT THE BYTE
CALL SIONXT ;Test for end of string
JRST SIN00 ;NOT END
JRST UNL ;ALL DONE
SIN4: CALL UNLCKF ;UNLOCK THE LOCKS
JRST SIN2 ;GO ADD NULL TO END
SIN3: SKIPE SINZF ;NON-ZERO COUNT CASE?
MRETNG ;YES, RETURN
SIN2: SETZ B, ;GET A NULL TERMINATOR
UMOVE A,2 ;FETCH USER'S DESTINATION POINTER
XCTBU [IDPB B,A] ;DEPOSIT THE NULL
MRETNG ;RETURN FROM JSYS
SINW: JUMPN A,[CALL UNLCKF ;ERROR OCCURED
TQNN <EOFF> ;EOF SEEN?
JRST EMRET0 ;NO, BOMB OUT
SETZ B, ;APPEND A NULL
UMOVE C,2 ;GET BYTE POINTER
XCTBU [IDPB B,C] ;STORE THE NULL
JRST EMRET0]
MOVE A,B ;GET DISMIS INFO
CALL UNLDIS ;UNLOCK LOCKS AND MDISMS
JRST SIN0 ;GO START OVER AGAIN
; Check for end of string io string
; Call: B ;Character just transfered
; User 3 ;Sin/sout argument
; User 4 ;Sin/sout argument
; CALL SIONXT
; Return
; +1 ;Continue
; +2 ;NO MORE LEFT TO DO
; Updates user 3
SIONXT::TLNE JFN,777777 ;If byte pointer,
UMOVEM JFN,1 ;Restore updated jfn
XCTU [SKIPN C,3]
RET
JUMPG C,SIO2 ;Positive
XCTU [AOSGE 3]
RET
RETSKP
SIO2: XCTU [SOSLE 3]
XCTU [CAMN B,4]
RETSKP
RET
; SUBROUTINE TO SET UP REST OF SIN/SOUT AND DO BYTBLT
SIOR2: UMOVE Q1,3 ;GET COUNT
MOVM C,Q1 ;MAGNITUDE OF COUNT
SKIPL Q1 ;TERMINATING BYTE?
TQO <XFR2TM> ;YES, SET FLAG
SKIPLE Q1 ;SPECIFIC TERMINATOR?
JRST [ UMOVE Q1,4 ;YES. GET (NOTE 0 IN Q1 IF COUNT=0)
TQO <XFRTRM> ;FLAG SPECIFIC TERMINATOR
JRST .+1]
SKIPN C ;NON-ZERO COUNT
HRLOI C,77 ;NO, SET MAX COUNT
TQNE <DCRNXT,DLFNXT> ;WANT TO ADD CR OR LF?
JRST [ TQO <XFRTRM> ;YES, USE EXACT COUNT
JRST SIOR23]
TQNE <STRSRC> ;BYTE POINTER IN JFN?
JRST SIOR23 ;YES, IGNORE FILCNT
CAML C,FILCNT(JFN) ;KEEP MIN OF THIS
MOVE C,FILCNT(JFN) ;AND BYTES IN BUFFER
SKIPA Q2,FILCNT(JFN) ;GET LENGTH OF SOURCE STRING FOR LINE # REMOVER
SIOR23: MOVE Q2,C ;GET LENGTH OF SOURCE STRING
PUSH P,C ;SAVE COUNT
CALL BYTBLT ;DO THE TRANSFER
SKIPLE C ;BYTES LEFT?
JRST [ TQNE <FEEDME> ;YES. DID SOURCE RUNOUT?
JRST .+1 ;YEP. GO GET SOME MORE
TQNE <FLINPT> ;WAS FILE INPUT?
TQNE <XFRTRM> ;YES. NEED TO DO EXTRA DECREMENT?
JRST .+1 ;NO
SOJA C,.+1] ;YES, DO IT AND CONTINUE
SUB C,0(P) ;GET NEG OF BYTES TRANSFERRED
POP P,(P) ;DON'T NEED THIS NOW
TQNE <STRSRC> ;BYTE POINTER IN JFN?
JRST SIOR24
ADDM Q1,FILBYN(JFN) ;COUNT BYTES SKIPPED AS BYTES READ
MOVN Q1,Q1 ;NOW WE NEED IT NEGATIVE
ADDM Q1,FILCNT(JFN) ;AND COUNT BYTES SKIPPED AS BYTES REMOVED
ADDM C,FILCNT(JFN) ;UPDATE FILCNT
MOVN Q1,C
ADDB Q1,FILBYN(JFN)
TQNE <DISCRD> ;DISCARD A TAB?
AOS FILBYN(JFN) ;YES. THIS IS EASY, AS WE KNOW FILCNT=0
CAML Q1,FILLEN(JFN)
CALL [ MOVEM Q1,FILLEN(JFN)
CALLRET UPDLEN] ;UPDATE OFN LENGTH
SIOR24: XCTU [SKIPGE Q1,3] ;WHAT KIND OF COUNT
MOVNS C ;MAKE SIGN AGREE
JUMPE Q1,SIOR21 ;DON'T UPDATE COUNT IF 0
XCTU [ADDB C,3] ;DO UPDATE
JUMPE C,SIOR22 ;IF COUNT BECOMES 0, THEN DONE
JUMPL C,R ;STILL MORE TO DO, DON'T SAY DONE
SIOR21: TQZE <DISCRD,FEEDME> ;IF BYTBLT RETURNED 'CAUSE IT HAS TO
RET ; DISCARD A LINE NUMBER, DON'T STOP SIN.
TQNN <XFR2TM> ;FOUND THE TERMINATOR YET?
SIOR22: TQO <BBDONE> ;YES, SAY WE'RE DONE
RET
; Byte input subroutine
; Call: 1 ;Source designator
; CALL BYTIN
; Return
; +1 ;ERROR OCCURED, ERROR CODE IS IN A
; +2 ;Ok
; B ;A byte
; Clobbers most everything
BYTIN: TRVAR <SAVJFN>
MOVEM JFN,SAVJFN ;SAVE FOR BLOCK
BYTIN1: CALL CHKJFN ;Check the designator
JRST IOERR ;Bad designator
JFCL ;Tty
JFCL ;Byte pointer
CALL @JFNID(P3) ;INIT JFN FOR INPUT
CALL BYTINA ;GET A BYTE
JRST BYTINW ;SERVICE ROUTINE WANTS TO BLOCK
CALL UNLCKF ;UNLOCK THE LOCKS
RETSKP ;AND RETURN OK
BYTINW: JUMPN A,[CALLRET UNLCKF];IF ERROR, RETURN
MOVE A,B ;GET DISMIS INFO
CALL UNLDIS ;UNLOCK LOCKS AND DO MDISMS
MOVE JFN,SAVJFN ;GET JFN BACK
JRST BYTIN1 ;LOOP BACK AND TRY AGAIN
;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:
BYTINX: TQNN <READF>
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(BLKF1)
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
;ROUTINE TO UNLOCK LOCKS AND TO DO AN MDISMS
;CALLED WITH MDISMS ARGUMENT IN A
;ENTRY AT UNLDS1, WILL CHECK ERRF FIRST, AND IF SET, WILL
;GUARANTEE THAT PROCESS "SEES" INTERRUPT
UNLDS1: TQNE <ERRF> ;IS ERROR UP?
JRST [ FILINT (IOX5) ;YES. GIVE INTERRUPT
CALL UNLCKF ;ALLOW INTERRUPT TO TAKE
MOVEI A,IOX5 ;IF HE PROCEEDS...
JRST EMRET0] ; GIVE ERROR
UNLDIS::PUSH P,A ;SAVE MDISMS ARGUMENT
TQZN <XQTAF> ;QUOTA EXCEEDED?
JRST UNLDSN ;NO - GO ON
MOVE A,MPP ;YES - GET ADDRS OF JSYS+1
MOVE B,-1(A) ;GET PC
MOVE A,0(A) ;...
CALL CHKERT ;SEE IF ERJMP/ERCAL
SKIPA ;NONE - TRY INTERRUPT
EMRETN (IOX11,<CALL UNLCKF>) ;TAKE ERROR RETURN
REPEAT 0,< ;OLD, INCORRECT CODE
MOVE B,MPP ;RETURN PC POINTER
MOVE C,0(B) ;PICK UP FLAGS
TXOE C,QUOTAB ;ALREADY "BACKED UP"?
JRST UNLDS2 ;YES. DON'T DO IT AGAIN
SOS -1(B) ;DECREMENT RETURN PC
MOVEM C,0(B) ;NEW FLAGS
TLNE C,(UMODF) ;USER MODE PC?
SOS -3(B) ;YES. ONE MORE PC THEN
> ;END OF REPEAT 0
UNLDS2: MOVE A,BITS+.ICQTA ;GET CHANNEL BITS
CALL IICSLF ;CAUSE INTERUPT
UNLDSN: PUSH P,STS ;SAVE STS
TQZ <HLDF> ;NEVER STORE HLDF
CALL UNLCKF ;UNLOCK THE FILE AND DO AN OKINT
;INTERUPT WILL HAPPENED IF POSTED
POP P,STS ;RESTORE ORIGINAL STS
POP P,A ;GET BACK ARG
HRRZ B,A ;LOOK AT ROUTINE ADDRESS
JUMPE B,UNLERC ;NONE, ONLY ERROR CODE IN LH
TQNE <HLDF> ;WANT TO HOLD PROCESS IN BAL SET?
JRST UNLHLD ;YES. GO ARRANGE IT
CAIE B,MTDWT1 ;IS THIS A MAG TAPE WAIT?
CAIN B,MTAWAT
JRST UNLMTA ;YES, GO DO A HDISMS
CAIN B,MTARWT ;ANOTHER TYPE OF MTA WAIT?
JRST UNLMTA ;YES
MDISMS ;WAIT UNTIL CONDITION IS SATISFIED
RET ;RETURN TO CALLER
;HERE IF SERVICE ROUTINE DOESN'T REALLY WANT TO BLOCK, BUT RATHER TO
;RETURN A SPECIFIC ERROR CODE
UNLERC: HLRZ T1,T1 ;GET ERROR CODE
ITERR ()
UNLMTA: HDISMS (^D50) ;WAIT FOR ENOUGH TIME FOR A RECORD READ
RET
;SPECIAL BLOCK FOR FE DEVICE WAIT
;THIS CODE IS HERE TO REDUCE SCHEDULER OVERHEAD FROM THE DN64'S
;1/3 SEC POLLING CYCLE. THE WAIT TIME IS A GUESS AT HOW LONG IT TAKES
;TO CLANK THE POLLER. THE INTENDED EFFECT IS TO HELP THE SCHEDULER
;DEDUCE WAHT IS GOING ON.
UNLHLD: HDISMS (^D80) ;WAIT LONG ENOUGH FOR FE AND 3780 TO
; RESPOND
RET ;AND DONE
; Output to primary output file
; Call: 1 BYTE
; PBOUT
.PBOUT::MCENT
MOVEI JFN,101
UMOVE B,1
CALL BYTOUT
JRST MRETN
; Byte output
; Call: 1 ;Tenex destination designator
; 2 ;A byte
; BOUT
.BOUT:: MCENT
NOINT
JUMPLE 1,SLBOU
CAIE 1,.PRIIN ;PRIMARY INPUT?
CAIN 1,.PRIOU ;OR PRIMARY OUTPUT?
JRST SLBOU ;YES. DO IT THE SLOW WAY
CAML 1,MAXJFN ;Possibly a jfn?
JRST SLBOU ;Not possible
IMULI 1,MLJFN ;CONVERT TO INTERNAL INDEX
AOSE FILLCK(1)
JRST SLBOU0
MOVE C,FILSTS(1)
TXC C,OPNF!WRTF!FILOUP
TXCN C,OPNF!WRTF!FILOUP
TXNE C,FRKF!ERRF
JRST SLBOU1
SOSGE FILCNT(1)
JRST SLBOU2
CALL STRDMO ;VERIFY STRUCTURE
JRST SLBOU1 ;BEEN DISMOUNTED
AOS C,FILBYN(1)
CAMLE C,FILLEN(1)
CALL [ MOVEM C,FILLEN(1)
MOVE JFN,1 ;COPY FOR UPDLEN
HRRZ DEV,FILDEV(JFN)
MOVE STS,FILSTS(JFN)
CALLRET UPDLEN] ;UPDATE OFN LENGTH
UMOVE 2,2
IDPB 2,FILBYT(1)
CALL LUNLKF ;FREE UP FILE
JRST MRETN
SLBOU2: AOS FILCNT(1)
SLBOU1: SETOM FILLCK(1)
SLBOU0: UMOVE 1,1 ;GET BACK ORIGINAL JFN
SLBOU: OKINT
MOVE JFN,1
CALL BYTOUT ;Output the byte
SLBOUR: TQNN <ERRF> ;ERROR OCCUR?
JRST MRETN ;NO, EXIT
MOVEI A,IOX5 ;YES, GET ERROR CODE
JRST EMRET0 ;AND EXIT
SLBOUU: CALL UNLCKF ;UNLOCK THE JFN
JRST SLBOUR ;AND RETURN
; Random output jsys
; Call: 1 ;Tenex source designator
; 2 ;A byte
; 3 ;Byte number
; ROUT
.ROUT:: MCENT
TRVAR <SAVJFN>
ROUT0: UMOVE JFN,1
MOVEM JFN,SAVJFN
CALL CHKJFN
JRST IOERR
JFCL
FILABT DESX4 ;Tty and byte designators are illegal
JUMPGE STS,NOTOPN
TQNN <RNDF>
FILABT IOX3 ;Illegal to change pointer
TQNN <WRTF>
FILABT IOX2 ;Illegal write
CALL @JFNOD(P3) ;INIT JFN FOR OUTPUT
UMOVE A,3
CALL SFBNR
JRST ABTDO
UMOVE B,2
CALL BYTOUA
JRST ROUTW ;SERVICE ROUTINE WANTS TO BLOCK
JRST SLBOUU ;UNLOCK AND RETURN
ROUTW: CALL UNLDS1 ;UNLOCK THE LOCKS AND WAIT
JRST ROUT0 ;TRY AGAIN
; String output to primary io file
; Call: 1 ;String pointer, designator, or location of string
; PSOUT
.PSOUT::MCENT
TRVAR <SAVJFN>
PSOUT1: TLNE 1,777777
JUMPGE 1,PSOUT0
MOVSI C,440700
CAML 1,[777777,,0]
XCTU [HLLM C,1]
PSOUT0: MOVEI JFN,101 ;GET JFN OF PRIMARY DEVICE
MOVEM JFN,SAVJFN ;SAVE IT IN GLOBAL VARIABLE
CALL CHKJFN ;TURN IT INTO A REAL JFN
JRST IOERR ;BAD ARGUMENT
JFCL ;TTY
JFCL ;BYTE POINTER
CALL @JFNOD(P3) ;INIT JFN FOR OUTPUT
PSOUT2: XPSHUM [PUSH P,1] ;Make a copy of byte pointer
XCTBU [ILDB B,0(P)]
JUMPE B,[XPOPMU [POP P,1]
JRST SLBOUU] ;UNLOCK AND RETURN
CALL BYTOUA
JRST PSOUTW ;SERVICE ROUTINE WANTS TO BLOCK
XPOPMU [POP P,1]
JRST PSOUT2
PSOUTW: CALL UNLDS1 ;UNLOCK AND BLOCK
POP P,(P) ;REMOVE BYTE POINTER FROM STACK
JRST PSOUT0 ;START OVER AGAIN
; PRIMARY ERROR STRING OUTPUT
.ESOUT::MCENT
MOVEI T1,101
DOBE
RFPOS ;GET POSITION ON LINE
HRROI T1,[ASCIZ /
/]
TRNE T2,-1 ;ALREADY AT BEGINNING OF LINE?
PSOUT ;NO, GET THERE
MOVEI T1,"?" ;ERROR CHARACTER
PBOUT
MOVEI T1,100
CFIBF
IMCALL PSOUT ;OUTPUT THE MESSAGE
MRETNG ;AND DONE
; String output
; Call: 1 ;Tenex source designator
; 2 ;Byte pointer (lh = 777777 will be filled in)
; 3 ;Byte count or zero
; ;If zero, the a zero byte terminates
; ;If positive then transfer the specified number
; ;Of characters, or terminate on reading a byte
; ;Equal to that given in 4
; ;If negative, then transfer the specified number
; ;Of bytes
; 4 ;(optional) if 3 is > 0, 4 has a terminating byte
; SOUT
; Return
; +1 ;Always
; 2 ;Updated string pointer
; 3 ;Updated count (always counts toward zero)
; The updated string pointer always points to the last byte read
; Unless 3 contained zero, then it points to the last non-zero byte.
.SOUTR::MCENT
SETO Q2, ;MARK THAT A SOUTR WAS DONE
JRST SOUTR1 ;ENTER COMMON CODE
.SOUT:: MCENT ;Become slow etc
SETZ Q2, ;MARK THAT A SOUT WAS DONE
SOUTR1: TRVAR <SAVJFN,SOUTRF>
MOVEM Q2,SOUTRF ;SAVE SOUTR FLAG
JUMPGE 2,SOUT0
MOVSI C,440700
CAML 2,[777777,,0]
XCTU [HLLM C,2]
SOUT0: UMOVE T3,2 ;GET USERS POINTER
XCTBU [ILDB T3,T3] ;ATTEMPT TO GET A BYTE
UMOVE JFN,1 ;GET USERS JFN
MOVEM JFN,SAVJFN ;SAVE IT
CALL CHKJFN ;GET REAL JFN AND LOCK UP
JRST IOERR ;BAD ARGUMENT
JRST SOUTTY
JRST [ CAIE DEV,STRDTB
JRST SOUTTY ;NOT BYTE PTR, DO BYTE AT A TIME
JRST SOUBYT]
TQNE <OPNF> ;OPENED?
TQNN <WRTF>
FILABT(IOX2)
CALL @JFNOD(P3) ;INIT JFN FOR OUTPUT
SKIPLE SOUTRF ;NEED TO MOVE SOME BYTES?
JRST SOUTRR ;NO. GO RIGHT TO RECOUT CODE
SOUT00: SKIPG FILCNT(JFN)
JRST SOUT1 ;DO IT THE OLD WAY
MOVE B,FILBYT(JFN) ;TARGET IS FILE
UMOVE A,2 ;SOURCE IS USER
MOVX D,XFRLSN!BBLTUM ;ALWAYS PASS LSNS (THERE AREN'T ANY)
CALL SIOR2
UMOVEM A,2
MOVEM B,FILBYT(JFN)
TQNN <BBDONE> ;HAS BYTBLT FINISHED?
JRST [ CALL UNLCKF ;NO, DO SOME MORE
JRST SOUT0] ;BUT UNLOCK FIRST TO ALLOW INTERRUPTS
SOUTRR: SKIPN SOUTRF ;DOING A SOUTR JSYS?
JRST SLBOUU ;NO, JUST EXIT
XMOVEI C,BYTINB ;COMMON BLOCK ROUTINE
MOVE D,SAVJFN ;THE ORIGINAL JFN
CALL @RECOUT(P3) ;IF SOUTR, CALL SERVICE ROUTINE
JRST [ TQZE <BLKF> ;WANT TO BLOCK?
JRST [ CALL UNLDIS ;YES. SO DO IT
MOVEI T1,1 ;REMEMBER THIS HAPPENED
MOVEM T1,SOUTRF ;""
JRST SOUT0] ;AND DO IT AGAIN
FILABT (IOX5)] ;NO, ERROR
JRST SLBOUU ;UNLOCK AND EXIT
; SOUT TO STRING POINTER
SOUBYT: MOVE B,JFN
UMOVE A,2
MOVX D,STRSRC!XFRLSN!BBLTUU;FROM STRING, DON'T WORRY ABOUT LSNS,
; AND COPY USER TO USER
CALL SIOR2
UMOVEM A,2
UMOVEM B,1
MOVEM B,JFN
CALL APPNUL ;APPEND NULL
JRST SOUTRR ;AND RETURN
;SOUT WHICH MUST BE DONE BYTE-AT-A-TIME
;SOUTTY - FOR CASES WHERE WE DO NOT HAVE A REAL JFN
SOUTTY: CALL @JFNOD(P3) ;INIT JFN FOR OUTPUT
SOUTT1: CAIN P3,TTYDTB ;TTY?
JRST STTYOP ;YES DO OPTIMIZATION
CALL SOUTB ;OUTPUT THE BYTE
JRST [ JUMPN A,SOUT0 ;DEVICE BLOCKED, START OVER
JRST SOUTRR] ;ALL THROUGH
JRST SOUTT1 ;LOOP BACK FOR ALL BYTES
;OPTIMIZATION FOR SOUT TO A TTY. IT USES THE RECOUT ENTRY
;SINCE IT TRIES TO OPTIMIZE AND SOUTR IS IGNORED FOR TTY'S.
;REGISTERS USED FROM USER AS IN CALL TO SOUT
STTYOP: JUMPGE STS,NOTOPN
TQNN <WRTF>
FILABT IOX2 ;ILLEGAL WRITE
TQNE <ENDF>
FILABT IOX6 ;PAST ABS END OF FILE
TQNE <ERRF>
FILINT(IOX5) ;ERROR INTERRUPT
XMOVEI C,BYTINB ;COMMON CO-ROUTINE
CALL TTYBLO ;OUTPUT
JRST [ CALL UNLDS1 ;UNLOCK AND BLOCK
TQNN <BLKF> ;BLOCK
JRST SOUT0
JRST SLBOUU] ;UNLOCK AND EXIT
JRST SLBOUU ;UNLOCK AND EXIT
;SOUT1 - FOR CASES WHERE WE HAVE A REAL JFN, TRY FAST WAY AFTER DOING
;EACH BYTE IN CASE FILCNT IS THEN SETUP
SOUT1: CALL SOUTB ;OUTPUT THE BYTE
JRST [ JUMPN A,SOUT0 ;DEVICE BLOCKED, START OVER
JRST SOUTRR] ;ALL DONE
JRST SOUT00 ;SEE IF FILCNT IS NOW SET UP
;ROUTINE TO OUTPUT A BYTE
;CALL: CALL SOUTB
;RETURNS +1 A=TRUE MEANS DEVICE BLOCKED,START OVER
; A=FALSE MEANS ALL THROUGH
; +2 MORE BYTES TO BE DONE
SOUTB: XPSHUM [PUSH P,2]
XCTBU [ILDB B,0(P)]
XCTU [SKIPN 3]
JUMPE B,[XPOPMU [POP P,2]
JRST RFALSE] ;Don't write zero bytes if arg3 = 0
PUSH P,B
CALL BYTOUA
JRST SOUTW ;SERVICE ROUTINE WANTS TO BLOCK
POP P,B
XPOPMU [POP P,2]
CALL SIONXT
RETSKP ;GIVE SKIP RETURN BECAUSE MORE TO BE DONE
JRST RFALSE ;RETURN
SOUTW: CALL UNLDS1 ;UNLOCK AND BLOCK
POP P,B ;GET BACK BYTE
POP P,(P) ;POP OFF BYTE POINTER
JRST RTRUE ;TRY AGAIN
; 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(BLKF2)
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
; Append null to string output designator
APPNUL::PUSH P,JFN
PUSH P,C
MOVEI C,0
TLZ JFN,7700
TLO JFN,700
CAMN JFN,-1(P) ;HAVE ASCII BYTE PTR
XCTBU [IDPB C,JFN] ;YES, APPEND NULL
POP P,C
POP P,JFN
RET
;ROUTINE TO BLOCK FOR BYTOUT SERVICE ROUTINES
; Move bytes
; Call:
; A/ SOURCE POINTER
; B/ TARGET POINTER
; C/ BYTE COUNT
; D/ MODE BITS AS AS DEFINED AT START OF LISTING
; Q1/ TERMINATOR IF ANY
; Q2/ LENGTH OF SOURCE STRING (USED BY CHKTRM ONLY)
;RETURNS A-D UPDATED,
;Q1/ # OF BYTES DISCARDED AS LINE NUMBERS OR NULL
;Q2/ CLOBBERED
;NOTE: ATS CALLS THIS ROUTINE USING AN INDEXED BYTE POINTER
;INDEXING ON P1. THIS ROUTINE MUST NOT CHANGE P1.
BYTBLT::STKVAR <<TEMPA,3>,SAVQ3,SAVP6,SAVP5,SAVP3,SAVTDS,BYTREM,BYTSIZ,TRMBYT,BYTSKP,<PRG,LPRG>>
MOVEM Q1,TRMBYT ;Shuffle args
MOVEM Q3,SAVQ3 ;SAVE PERMANENT ACS
MOVEM P3,SAVP3
MOVEM P5,SAVP5
MOVEM P6,SAVP6
XMOVEI P3,BYTERR ;SETUP DISPATCH FOR ANY ILLEG REF
TXO P3,TRPIRF ; THAT MIGHT OCCUR HEREIN
EXCH P3,TRPDSP ; SAVE PREVIOUS
MOVEM P3,SAVTDS
HRRZ P5,D ;SET TYPE OF XFER
SETZM BYTSKP ;HAVEN'T SKIPPED ANYTHING YET
; Preliminaries out of the way
; Now get to work
BYTB1: TQNE <DCRNXT,DLFNXT> ;ADDING CRLF'S?
JRST CHKCRL ;YES. GO DO CR-LF STUFF
TQNE <XFRLSN> ;SKIPPING LINE NUMBERS?
TQNE <XFR2TM> ;OR UP TO A TERMINATOR?
JRST CHKTRM ;Yes TO EITHER, look for it
LDB Q1,[POINT 6,A,5] ;GET SOURCE P FIELD
LDB Q2,[POINT 6,B,5] ;GET TARGET P FIELD
CAIGE Q1,45 ;IS SOURCE A OWGBP?
CAIL Q2,45 ;NO...IS TARGET A OWGBP?
JRST BYTLP ;YES OR YES...DO A BYTE AT A TIME
TLNN B,7700 ;Zero byte size?
JRST BYTLP ;Well...if you insist
MOVE Q1,B ;Compare target
XOR Q1,A ;To source
TLNN Q1,7700 ;And if byte size differs
CAIG C,20 ;Or short transfer
JRST BYTLP ;Do byte at a time
;..
;BYTE SIZES FOR SOURCE AND DESTINATION MATCH, AND TRANSFER IS
;LONG ENOUGH TO JUSTIFY THE OVERHEAD OF TRYING TO OPTIMIZE.
;COPY A BYTE AT A TIME UNLESS THE FIRST WORD OF THE TARGET HAS
;BEEN FILLED.
;..
LDB Q2,[POINT 6,B,11] ;Get byte size
MOVEM Q2,BYTSIZ ;Save it
ROT Q2,-6 ;Position in p field
LP1: SOJL C,DONE ;Until cnt < 0
XCT LDBTB(P5) ;Do transfer bytes
XCT DPBTB(P5)
CAMG Q2,B ;Until less than 1 byte remains in tgt
JUMPGE Q2,LP1 ;Loop unless bytesize >= 32
;(once is always enough)
;ONE WORD HAS BEEN FILLED IN THE DESTINATION. MAKE SURE WE NEED
;TO TRANSFER AT LEAST ONE WORD.
BYTB2: MOVEI Q1,^D36 ;Word size
IDIV Q1,BYTSIZ ;Compute bytes/word and remainder
MOVEM Q2,BYTREM ;Save remainder
MOVE Q2,C
IDIV Q2,Q1 ;Compute words to transfer
MOVEM Q3,C ;Remaining bytes
JUMPE Q2,BYTLP ;Zero words...do byte at a time
;COMPUTE THE DIFFERENCE IN BIT POSITIONS BETWEEN THE SOURCE
;AND DESTINATION. IF THEY ARE DIFFERENT, GO OFF TO SHIFT THE SOURCE.
HLLO Q1,A ;Get source...prevent borrows
TLO Q1,77 ;MORE BORROW PROTECTION
SUB Q1,B ;When getting bit offset
ROT Q1,6
ANDI Q1,77 ;Retain just the position difference
JUMPN Q1,BYTBL1 ;Move word at a time
;..
;THE BYTE SIZES MATCH, AND THE ALIGNMENTS WITHIN THE WORDS
;MATCH, SO BLT THE DATA FROM SOURCE TO DESTINATION.
;..
DMOVEM A,TEMPA ;SAVE A-C
MOVEM C,2+TEMPA
AOS Q3,B ;CALCULATE DESTINATION ADDRS
TLZ Q3,777740 ;SAVE EFFECTIVE ADDRS
TXO Q3,<XMOVEI C,> ;CONS INSTRUCTION
XCT DMVITB(P5) ;GET ADDRS
AOS Q3,A ;CALCULATE SOURCE ADDRS
TLZ Q3,777740
TXO Q3,<XMOVEI B,> ;BUILD INSTR
XCT SMVITB(P5) ;GET ADDRS
MOVE A,Q2 ;NUMBER OF WORDS TO MOVE
ADDM Q2,TEMPA ;UPDATE SRC / DEST POINTERS
ADDM Q2,1+TEMPA
XCT BLTTB(P5) ;CORRECT BLT ROUTINE
DMOVE A,TEMPA ;RESTORE REGS
MOVE C,2+TEMPA ;...
;TRANSFER THE REMAINING (PRESUMABLY FEW) BYTES ONE AT A TIME
BYTLP: JUMPLE C,DONE ;Do rest a byte at a time
BYTLP1: XCT LDBTB(P5)
XCT DPBTB(P5)
SOJG C,BYTLP1
DONE: MOVE Q1,BYTSKP ;RETURN # BYTES SKIPPED
MOVE Q3,SAVQ3 ;RESTORE PERMANENT ACS
MOVE P3,SAVTDS ;RESTORE
MOVEM P3,TRPDSP
MOVE P3,SAVP3
MOVE P5,SAVP5
MOVE P6,SAVP6
RET
;HERE ON ANY ILLEG MEM REF IN BYTBLT
BYTERR: JRST DONE ;NOTHING SPECIAL, JUST QUIT
;HERE WHEN BYTE SIZES MATCH BUT ALIGNMENT OF BYTES WITHIN
;WORDS DIFFERS. SHIFT THE SOURCE TO LINE UP WITH THE DESTINATION
;AND COPY A WORD AT A TIME.
; T1/ SOURCE POINTER
; T2/ DESTINATION POINTER
; Q1/ POSITION OFFSET (RIGHT SHIFT AMOUNT)
; Q2/ WORD COUNT
; P5/ KIND OF TRANSFER (FROM T4 ON ENTRY)
; Bytrem/ lsh amount to right justify first word
BYTBL1: HRLI P3,PROTO ;LOAD PROTO PROGRAM ONTO STACK
HRRI P3,PRG
BLT P3,LPRG-1+PRG
DMOVEM B,1+TEMPA ;SAVE B AND C
;SET UP THE SOURCE ADDRESS
MOVE Q3,A ;COPY POINTER (SOURCE)
TLZ Q3,777740 ;CLEAR ALL BUT EFFECTIVE ADDRS
TXO Q3,<XMOVEI B,> ;BUILD INSTR
XCT SMVITB(P5) ;GET ADDRS
;FIX LSH INSTRUCTIONS TO SHIFT OUT THE BITS THAT ARE TO THE
;RIGHT OF THE LAST BYTE
HRR P3,BYTREM ;Fill in shift amount to left justify
HRRM P3,4+PRG ;STORE IN PROGRAM
MOVNS BYTREM ;Get right shift amount
HRR P3,BYTREM ;Fill in LSH
HRRM P3,2+PRG ;...
;FIGURE OUT WHICH WAY TO DO THE COMBINED SHIFT AND WHICH AC TO
;STORE FROM
MOVNS Q1 ;NEGATE OFFSET
ADD Q1,BYTREM ;Total right shift = offset + remainder
MOVE P3,4+PRG ;GET LSH INSTRUCTION
MOVE P6,5+PRG ;AND MOVEM INST
CAMG Q1,[-^D18] ;Less than half a word?
TLCA P3,(<Z Q1^!Q2,0>) ;Change ac of lsh from Q1 to Q2
TLCA P6,(<Z Q1^!Q2,0>) ;No, change ac of MOVEM to Q1
ADDI Q1,^D36 ;Leave movem Q1, change shift amount
MOVEM P3,4+PRG ;RESTORE NEW LSH INST
HRRM Q1,3+PRG ;Fill in lshc amount
MOVEM P6,5+PRG ;PUT BACK THE FIXED MOVEM
;FIX UP THE DESTINATION POINTER
MOVE Q3,1+TEMPA ;POINTER TO DESTINATION
TLZ Q3,777740 ;CLEAR ALL BUT EFFECTIVE ADDRS
TXO Q3,<XMOVEI C,> ;BUILD INSTR
XCT DMVITB(P5) ;GET ADDRS
AOS C ;START STORING IN SECOND WORD
;..
;UPDATE THE SOURCE AND DESTINATION POINTERS FOR RETURN TO THE CALLER
;..
ADDM Q2,1+TEMPA ;Update target
ADDM Q2,A ;And source
;IF TRANSFER INVOLVES USER, CHANGE PROTOTYPE PROGRAM TO DUE
;XCTU'S INSTEAD OF MOVE'S AND MOVEM'S
TRNE P5,2 ;IS THIS FROM "USER"?
JRST [ MOVE Q3,[XCTU Q3]
EXCH Q3,0+PRG ;YES, SET UP XCT INST INSTEAD
MOVE P6,[XCTU P6]
EXCH P6,1+PRG
JRST .+1]
TRNE P5,1 ;IS THIS TO "USER"?
JRST [ MOVE P3,[XCTU P3]
EXCH P3,5+PRG ;YES, SET UP PROPER XCT INST
JRST .+1]
MOVEM A,TEMPA ;Want to use A for AOBJN
MOVNS Q2 ;Make aobjn
HRLZ A,Q2 ;word in A
JRST PRG ;Do the program, return to done
;PROGRAM ON STACK COMES HERE WHEN DONE
BYTLPD: MOVE A,TEMPA ;RESTORE SOURCE POINTER
DMOVE B,1+TEMPA ;RESTORE B AND C
JRST BYTLP ;Finish up any odd bytes
; Transfer til terminator OR DISCARD LINE NUMBERS
CHKTR0: XCT LDBTB(P5) ;OUT WITH THE BAD BYTE, IN WITH THE GOOD BYTE
CHKTR1: AOS BYTSKP ;BUT REMEMBER IT AS A BYTE WE SKIPPED
CHKTRM: JUMPLE C,DONE
JUMPLE Q2,[TQO FEEDME ;ALSO END WHEN SOURCE RUNS OUT
JRST DONE]
XCT LDBTB(P5)
SOJ Q2, ;REMEMBER WE GOT IT
TQNN <XFRLSN> ;PASSING LINE NUMBERS?
JRST CHKLIN ;NOPE, CHECK THIS ONE
STOBYT: CAMN Q1,TRMBYT
JRST [ TQZN <XFR2TM> ;TELL CALLER WE GOT THE TERMINATOR
JRST .+1 ;BUT HE'S NOT INTERESTED IN THE FIRST PLACE,
; AND ONLY WANTS TO DISCARD LINE #S
TQNN <XFRTRM> ;TRANSFER TERMINATOR?
JRST DONE ;NO, SAY WE DIDN'T COPY IT
XCT DPBTB(P5)
SOJA C,DONE]
STOBT1: XCT DPBTB(P5)
SOJA C,CHKTRM ;TRY FOR SOME MORE
CHKLIN: JUMPE Q1,CHKTR1 ;DISCARDING, THEREFORE DISCARD NULLS
LDB Q3,[POINT 12,A,11] ;IS THIS THE FIRST BYTE OF A WORD?
CAIL Q2,4 ;AND ARE THERE ENOUGH DATA TO BE A LINE #?
CAIE Q3,<POINT 7,0,6>_-^D24;YES, FIRST CHARACTER?
JRST STOBYT ;NO TO EITHER, MUST BE REAL DATA
PUSH P,A ;SAVE A
HRRZS A ;ELIMINATE BYTEPOINTER BITS
XCT MOVETB(P5) ;GET THE WORD
POP P,A ;RESTORE A
TXNN Q3,1B35 ;IF BIT 35 ON, THEN A LINE #
JRST STOBYT ;OTHERWISE JUST VALID DATA
SUBI Q2,5 ;SKIP THE REST OF THE WORD AND TAB QUICKLY
TXZ A,77B5 ;"READ" THE 4 CHARS
MOVEI Q3,5 ;REMEMBER WE JUST FORGOT 5 CHARACTERS
ADDM Q3,BYTSKP
JUMPGE Q2,CHKTR0 ;IF ANY LEFT, GO DISCARD THE TAB AFTER THE LSN
TQO <DISCRD,FEEDME> ;NONE THERE - MUST LET CALLER
JRST DONE ; DISCARD IT FOR US
;HERE WHEN CALLER WANTS CR-LF ADDED TO DESTINATION STRING.
CHKCRL: TQZE <DCRNXT> ;TIME FOR A CR?
JRST [ MOVEI Q1,.CHCRT ;YES, LOAD ONE UP
XCT STOBT1 ;STASH BYTE
SOJG C,.+1 ;IF MORE BYTES DO LF NOW
TQO <DLFNXT> ;SAY THAT LF NEEDED NEXT
JRST DONE] ;AND GIVE UP FOR NOW
TQZ <DLFNXT> ;CLEAR LF NEEDED FLAG
MOVEI Q1,.CHLFD ;GET A LF
TQO <DFRSTF> ;REMEMBER THAT THIS RECORD HAS BEEN FROSTED
XCT STOBT1 ;STASH IT
SOJA C,DONE ;AND DONE
; Instruction tables for different mapping modes
; 00 -- monitor to monitor
; 01 -- monitor to user
; 10 -- user to monitor
; 11 -- user to user
LDBTB: ILDB Q1,A
ILDB Q1,A
XCTBU LDBTB
XCTBU LDBTB
DPBTB: IDPB Q1,B
XCTBU DPBTB
IDPB Q1,B
XCTBU DPBTB
BLTTB: CALL XBLTA
CALL BLTMU
CALL BLTUM
CALL BLTUU
SMVITB: XCT Q3 ;FROM MONITOR
XCT Q3 ; SAME
XCTUU Q3 ;FROM USER
XCTUU Q3 ; SAME
DMVITB: XCT Q3 ;TO MONITOR
XCTUU Q3 ;TO USER
XCT Q3 ;TO MONITOR
XCTUU Q3 ;TO USER
MOVETB: MOVE Q3,(A) ;FROM MONITOR
MOVE Q3,(A) ;DITTO
XCTU MOVETB ;FROM USER
XCTU MOVETB ;DITTO
; 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
;SPECIAL ROUTINE USED BY DECNET SERVICE TO MOVE DATA BETWEEN
;NETWORK BUFFERS AND JFN BUFFERS. IT IS MERELY AN INTERFACE TO
;BYTBLT.
;ACCEPTS: T1/ SOURCE POINTER
; T2/ DESTINATION POINTER
; T3/ COUNT
;RETURNS WITH ALL REGS UPDATED AS DESCRIBED IN BYTBLT COMMENTS
NETMOV::SAVEQ ;SAVE PERMANENT REGS
MOVX D,XFRLSN ;PASS LINE NUMBERS AND MONITOR-TO-MONITOR
CALLRET BYTBLT ;AND DO IT
;ATSMOV - SPECIAL ROUTINE USED BY ATS SERVICE TO MOVE DATA BETWEEN
;MONITOR BUFFER AND USER BUFFER.
;ACCEPTS:
; T1/ SOURCE POINTER
; T2/ DESTINATION POINTER
; T3/ COUNT
;RETURNS WITH ALL REGS UPDATED AS DESCRIBED IN BYTBLT COMMENTS
ATSMOV::SAVEQ ;SAVE PERMANENT REGS
MOVX D,XFRLSN!BBLTMU ;PASS LINE NUMBERS AND MONITOR-TO-USER
CALLRET BYTBLT ;AND DO IT
REPEAT 0,< ;HISTORICAL CODE NO LONGER USED
; Dump io
; Parameters and variables
RS(DMPASW) ;Dump buffer assignment word
RS(DMPCNT) ;Dump buffer free count
RS(DMPLCK) ;Dump buffer assignment lock
; Initialize dump io
DMPINI::MOVEI A,NDUMP
MOVEM A,DMPCNT
SETOM DMPLCK
SETCM A,[-1_<^D36-NDUMP>]
MOVEM A,DMPASW
SETZ A,
MOVEI B,DMPBUF
MOVEI C,NDUMP
CALL MSETMP ;MAKE SURE ALL PAGES INITIALLY CLEAR
RET
> ;END OF REPEAT ZERO ON HISTORICAL CODE
; Dump input
; Call: 1 ;Jfn
; 2 ;Pointer to first command
; DUMPI
; Return
; +1 ;Error
; +2 ;Ok
.DUMPI::MCENT
MOVEI P6,[TQNN <READF> ;Executed to discover file access
IOX1 ;Error number for no read access
CALL @DMPID(P3) ; Device dependent routine dispatch
040400000000] ;Memory access needed
DUMPI1: CALL DMPCKJ ;CHECK THE JFN FOR LEGALITY
RETERR () ;NOT A VALID JFN
CALL @JFNID(P3) ;INIT JFN FOR INPUT
UMOVE A,2 ;GET IOWD FOR SERVICE ROUTINE
UMOVE A,(A) ;GET COMMAND
JUMPE A,DUMPI3 ;ZERO MEANS ALL DONE
TLNN A,-1 ;GO TO COMMAND?
JRST DUMPI4 ;YES - HANDLE XFER COMMAND
XMOVEI C,DUMPB ;DUMP BLOCK CO-ROUTINE
CALL @DMPID(P3) ;DO THE DEVICE DEPENDENT STUFF
JRST DUMPIW ;SEE IF WE NEED TO BLOCK
XCTU [AOS A,2] ;STEP THE IOWD
UMOVE A,(A) ;GET NEXT COMMAND
JUMPE A,DUMPI3 ;DONE IF ZERO
TLNN A,-1 ;XFER COMMAND?
JRST DUMPI4 ;YES - HANDLE
CALL UNLCKF ;UNLOCK IN CASE OF COMMAND LIST LOOPS
JRST DUMPI1 ;LOOP
DUMPI3: CALL UNLCKF ;UNLOCK THE JFN
SMRETN ;AND GIVE SUCCESSFUL RETURN
DUMPI4: XCTU [HRRM A,2] ;STORE NEW ADDRS
CALL UNLCKF ;UNLOCK JFN
JRST DUMPI1 ;START OVER
DUMPIW: TQZE <XQTAF> ;EXCEEDED QUOTA?
RETERR (IOX11,<CALL UNLCKF>) ;YES -RETURN ERROR
TQNE <EOFF> ;EOF DETECTED?
RETERR (IOX4,<CALL UNLCKF>) ;YES. SO NOTED
TQZN <BLKF> ;NEED TO BLOCK?
RETERR (,<CALL UNLCKF>) ;NO, ERROR
CALL UNLDIS ;GO DISMIS
JRST DUMPI1 ;TRY AGAIN
; Dump output
; Call: 1 ;Jfn
; 2 ;Pointer to first command
; DUMPO
; Return
; +1 ;Error
; +2 ;Ok
.DUMPO::MCENT
MOVEI P6,[TQNN <WRTF>
IOX2
CALL @DMPOD(P3)
100000000000] ;Memory access needed
DUMPO1: CALL DMPCKJ ;CHECK THE JFN FOR LEGALITY
RETERR () ;NOT A VALID JFN
CALL @JFNOD(P3) ;INIT JFN FOR OUTPUT
UMOVE A,2 ;GET IOWD FOR SERVICE ROUTINE
UMOVE A,(A) ;GET COMMAND
JUMPE A,DUMPO3 ;ZERO MEANS ALL DONE
TLNN A,-1 ;GO TO COMMAND?
JRST DUMPO4 ;YES - HANDLE
XMOVEI C,DUMPB ;DUMP BLOCK CO-ROUTINE
CALL @DMPOD(P3) ;DO THE DEVICE DEPENDENT STUFF
JRST DUMPOW ;SEE IF WE NEED TO BLOCK
XCTU [AOS A,2] ;STEP THE IOWD
UMOVE A,(A) ;GET NEXT COMMAND
JUMPE A,DUMPO3 ;EXIT IF ZERO
TLNN A,-1 ;SEE IF XFER COMMAND
JRST DUMPO4 ;YES - HANDLE
CALL UNLCKF ;UNLOCK IN CASE OF COMMAND LIST LOOPS
JRST DUMPO1 ;SEE IF MORE TO BE DONE
DUMPO3: CALL UNLCKF ;UNLOCK THE JFN
SMRETN ;AND GIVE SUCCESSFUL RETURN
DUMPO4: XCTU [HRRM A,2] ;STORE NEW ADDRS
CALL UNLCKF ;UNLOCK JFN
JRST DUMPo1 ;START OVER
DUMPOW: TQZE <XQTAF> ;EXCEEDED QUOTA?
RETERR (IOX11,<CALL UNLCKF>) ;YES - RETURN ERROR
TQZN <BLKF> ;NEED TO BLOCK?
RETERR (,<CALL UNLCKF>) ;NO, ERROR
CALL UNLDIS ;GO DISMIS
JRST DUMPO1 ;TRY AGAIN
;ROUTINE TO CHECK THE JFN ARGUMENT ON A DUMPI/O JSYS
DMPCKJ: UMOVE JFN,1 ;GET THE JFN
CALL CHKJFN ;CHECK IT
RETBAD ()
JFCL
RETBAD (DESX4)
TQNN <OPNF> ;DEVICE OPENED?
RETBAD (DESX5,<CALL UNLCKF>)
TRC STS,17 ;OPENED IN DUMP MODE?
TRCE STS,17
RETBAD (DUMPX2,<CALL UNLCKF>) ;NO
UMOVE B,2
TXNE B,DM%NWT ;NO-WAIT REQUESTED?
TQOA <NWTF> ;YES, PASS ON BIT
TQZ <NWTF> ;NO
RETSKP ;JFN IS GOOD
;DUMP MODE BLOCK CO-ROUTINE
DUMPB: STKVAR <SAVDEV> ;SAVE DEV
MOVEM DEV,SAVDEV
CALL UNLDIS ;UNLOCK JFN
UMOVE JFN,1 ;RESTORE USER ARG
CALL CHKJFN
RETBAD ()
JFCL
JFCL
CAME DEV,SAVDEV ;CHECK FOR SAME DEVICE
RETBAD (DESX4) ;NOPE THIS IS ILLEGAL
RETSKP ;GOOD RETURN TO PROCEED
REPEAT 0,< ;HISTORICAL CODE NO LONGER USED
; Dump common code
; A/ ADR OF SERVICE ROUTINE TO CALL TO DO THE WORK
; P6/ PTR TO CONSTANTS NEEDED
DUMPC:: STKVAR <DUMPCA,DIOWD,DAOBW,LT1,LT2,LT3>
MOVEM A,DUMPCA ;SAVE ADDRESS OF ROUTINE TO CALL
DUMPC0: UMOVE A,2 ;Get command pointer
TXNE A,DM%FIN ;FINISH-ONLY REQUEST?
JRST [ SETZM DIOWD ;YES, NO BUFFERS TO SETUP
SETZM DAOBW
NOINT
JRST DMPNOP]
UMOVE B,(A) ;And command
JUMPE B,RSKP ;0 IS END OF LIST, RETURN GOOD
JUMPG B,[XCTU [HRRM B,2] ;BRANCH CMND, SET NEW LIST ADR
JRST DUMPC0] ;CONTINUE WITH LIST
MOVEM B,DIOWD ;IOWD FOR COMMAND - SAVE IT
HLRE A,B ;- word count
MOVNS A ;Word count
ADDI A,(B) ;Last address
CAILE A,777777 ;Must not cross end of memory
RETBAD(DUMPX3) ;ERROR IF HAPPENS
MOVEI B,1(B) ;First address
LSH A,-PGSFT ;Last page number
LSH B,-PGSFT ;First page number
SUBM B,A
SOS A ;-# pages
CAMGE A,[-NDUMP]
RETBAD(DUMPX3) ;TOO MANY PAGES
NOINT
DMPSE0: LOCK DMPLCK,<CALL LCKTST>
MOVSI B,400000
ASH B,1(A) ;Get a one for each page needed
HRLZ C,A ;Initial aobjn word
MOVE P3,DMPCNT ;SAVE CURRENT AVAILABLE COUNT
DMPSE1: TDNN B,DMPASW ;Are these contiguous buffers free
JRST DMPSE2 ;Yes, assign them
ROT B,-1 ;No, try next set
AOS C ;Modify aobjn word
JUMPGE B,DMPSE1 ;When low bit wraps around
UNLOCK DMPLCK ;COULDN'T GET BUFFERS, RELEASE LOCK
EXCH A,P3 ;SAVE A, GET ORIGINAL DMPCNT
MOVSI A,0(A)
HRRI 1,DMPTST
MDISMS ;Dismiss until buffers released
MOVE A,P3 ;RECOVER A
JRST DMPSE0 ;Then try again
;"AOBJN" WORD STARTS WITH -NPAGES,,MON BFR NUMBER
DMPSE2: IORM B,DMPASW ;Mark these buffers as taken
ADDM A,DMPCNT ;Decrement count of free buffers
UNLOCK DMPLCK
MOVEM C,DAOBW ;SAVE AOBJN WORD
HRRZ A,DIOWD ;Get user first address-1
AOS A
LSH A,-PGSFT ;Page number
;TOP OF LOOP TO SETUP EACH PAGE IN ONE COMMAND
DMPSE3: MOVEM A,LT1
MOVEM C,LT2 ;SAVE VULNERABLE ACS
LSH A,PGSFT ;GET ADDRESS
XSFM B ;SET FLAGS IN LEFT HALF OF B
TXNE B,PCU ;PREVIOUS CONTEXT WAS USER?
HRLI A,(1B0) ;YES
CALL FPTA ;CONSTRUCT IDENT FOR ADDRESS
DMPSE5: MOVEM A,LT3 ;SAVE IDENT
CALL MRPACS ;Read access of page
JUMPE A,[MOVE A,LT1 ;Non-existent page, create it
LSH A,PGSFT
UMOVE A,(A) ;By referencing it
MOVE A,LT3
JRST DMPSE5]
TDNN A,3(P6) ;Test against needed access
JRST DMPSE4 ;Access not permitted
TLNN A,(1B6) ;Indirect?
JRST DMPSE7 ;No.
MOVE A,LT3 ;YES, TRACK IT DOWN
CALL MRPT ;Get id of page pointed to
JRST DMPSE5 ;Not file, continue
MOVEM A,LT3 ;FILE
JRST DMPSE6
DMPSE7: TLNN A,400 ;Write copy?
JRST DMPSE6 ;No.
MOVE B,3(P6) ;YES, GET ACCESS BITS NEEDED
TLNN B,40000 ;Write?
JRST DMPSE6 ;No.
TLNN A,100000 ;Yes, can we read?
JRST DMPSE4 ;No, must fail
MOVE B,LT1
LSH B,PGSFT
XCTU [MOVES 0(B)] ;WRITE IN PAGE TO MAKE IT PRIVATE
MOVE A,LT1
MOVE C,LT2
JRST DMPSE3 ;Recompute
DMPSE6: HRRZ A,LT2 ;Get buffer number
LSH A,PGSFT
ADDI A,DMPBUF ;Convert to address
MOVE B,A
EXCH A,LT3 ;Save address, get ptn.pn
HRLI B,140000
CALL SETIOP ;MAP AND LOCK PAGE
JRST DMPSE4 ;FAILED, GIVE UP
MOVE C,LT2
MOVE A,LT1 ;RESTORE VULNERABLE ACS
AOS A ;Next page
AOBJN C,DMPSE3 ;LOOP FOR ALL PAGES IN THIS IOWD
MOVE C,DAOBW ;RECOVER AOBJN WORD
MOVEI A,DMPBUF ;Do things the hard way cause macro
ASH A,-PGSFT ;Can't divide externals
ADDI A,(C)
AOS DIOWD
DPB A,[POINT 9,DIOWD,26]; Modify iowd to address monitor buffer
SOS DIOWD
;..
; At this point the dump region has been mapped into the monitor
; Buffer region and access checked
; DIOWD has the iowd needed for the data xfer
; DAOBW has the aobjn word needed to restore buffers when finished
DMPNOP: MOVE A,1(P6) ;GET ERROR CODE
XCT 0(P6) ;TEST STATUS OF JFN
JRST DMPER1
UMOVE B,2
TXNE B,DM%NWT ;NO-WAIT REQUESTED?
TQOA <NWTF> ;YES, PASS ON BIT
TQZ <NWTF> ;NO
MOVE A,DIOWD ;GET IOWD
DMPSDO: CALL @DUMPCA ;CALL DEVICE DEPENDENT ROUTINE
OKINT
TQNE <EOFF>
RETBAD(IOX4) ;FAIL RETURN, EOF
TQNE <ERRF>
RETBAD(IOX5) ;FAIL RETURN, ERROR
RETSKP ;RETURN GOOD
;HERE ON FILE REFERENCE ERRORS (JFN NOT OPEN, ETC). ALL BUFFERS
;MUST BE RELEASED
DMPER1: EXCH A,DAOBW ;SAVE ERROR CODE, GET AOBJN WORD
CALL DMPREL
MOVE 1,DAOBW
RETBAD()
;HERE ON ERRORS SETTING UP BUFFER PAGES. RELEASE WHATEVER HAS BEEN
;ASSIGNED/LOCKED SO FAR.
DMPSE4: MOVE A,LT2
CALL DMPRL1 ;Release buffers assigned but unlocked
HLRE C,LT2
MOVNS C
HRLZS C
MOVE A,DAOBW
ADD A,C
SKIPGE A
CALL DMPREL ;Release buffers both lock and assigned
MOVEI A,DUMPX4
RETBAD() ;ACCESS ERROR
;RELEASE DUMP BUFFERS. CALLED AT INTERRUPT LEVEL AFTER TRANSFER
;COMPLETED.
; A/ IOWD OF LAST XFER
; CALL DMPDON
; RETURN +1 ALWAYS
RESCD
DMPDON::HLRE B,A ;GET COUNT
JUMPGE B,R
;CONSTRUCT "AOBJN" WORD TO IDENTIFY MONITOR BUFFERS
MOVM B,B ;GET POSITIVE COUNT
MOVEI A,1(A) ;A=FIRST ADDRESS
ADD B,A ;B=END ADDRESS
ADDI B,777 ;BUMP TO END OF PARTIAL PAGE
LSH A,-PGSFT ;A=FIRST PAGE
LSH B,-PGSFT ;B=END PAGE
SUBM A,B ;B=NEG PAGE COUNT
MOVEI C,DMPBUF
ASH C,-PGSFT ;C=FIRST MON BUFFER PAGE
SUB A,C ;REMOVE OFFSET
HRL A,B ;PAGE CNT TO LH
CALLRET DMPREL ;NOW RELEASE THEM
;RELEASE DUMP BUFFERS (WINDOW PAGES)
; A/ -NPAGES,,FIRST RELATIVE PAGE
; CALL DMPREL
; RETURN +1 ALWAYS
DMPREL: JUMPE A,R
PUSH P,A
DMPRL0: PUSH P,A
LSH A,PGSFT
MOVEI B,DMPBUF(A)
MOVEI A,0
CALL SETIOP ;UNLOCK AND UNMAP THE PAGE
BUG(DMPRLF)
POP P,A
AOBJN A,DMPRL0
POP P,A
DMPRL1: JUMPE A,R
HLRE B,A
MOVSI C,400000
ASH C,1(B)
MOVNI A,(A)
ROT C,(A)
ANDCAM C,DMPASW
MOVNS B
ADDM B,DMPCNT
RET
> ;END OF REPEAT ZERO ON HISTORICAL CODE
;LCKTST - CALLING ROUTINE FOR LCKTSS SCHEDULER TEST
RESCD
LCKTST::PUSH P,1
MOVE 1,-1(P)
HRLZ 1,-2(1)
HRRI 1,LCKTSS
MDISMS
POP P,1
RET
LCKTSS: AOSE 0(1)
JRST 0(4)
JRST 1(4)
REPEAT 0,< ;MORE HISTORICAL CODE NO LONGER USED
DMPTST: CAML 1,DMPCNT
JRST 0(4)
JRST 1(4)
> ;END OF REPEAT ZERO ON HISTORICAL CODE
SWAPCD
TNXEND
END