Google
 

Trailing-Edge - PDP-10 Archives - bb-d868a-bm - 3-sources/please.mac
There are 31 other files named please.mac in the archive. Click here to see a list.
;<3-UTILITIES>PLEASE.MAC.6,  8-Nov-77 10:49:27, EDIT BY KIRSCHEN
;MORE COPYRIGHT UPDATING...
;<3-UTILITIES>PLEASE.MAC.5, 26-Oct-77 11:14:24, EDIT BY KIRSCHEN
;UPDATE COPYRIGHT FOR RELEASE 3
;<3-UTILITIES>PLEASE.MAC.4,  3-Oct-77 11:22:44, EDIT BY DBELL
;TELL USER IF THE OPERATOR IS NOT IN ATTENDANCE.  TCO 1870.
;<3-UTILITIES>PLEASE.MAC.3, 30-Sep-77 23:03:12, EDIT BY BORCHEK
; FIX ONE WAY PLEASE GIVING WRONG TIME
;<3-UTILITIES>PLEASE.MAC.2, 25-Aug-77 10:50:57, EDIT BY KIRSCHEN
;FIX VERSION NUMBERS FOR RELEASE 3
;<2-UTILITIES>PLEASE.MAC.5, 27-Dec-76 17:07:26, EDIT BY HURLEY
;<2-UTILITIES>PLEASE.MAC.4, 22-Dec-76 13:41:09, EDIT BY HURLEY
;<2-UTILITIES>PLEASE.MAC.3, 21-Oct-76 14:32:03, Edit by MACK
;TCO 1613 - FIX GTXT AND WAKEUP TO HANDLE ESC AND CTRL/Z PROPERLY.
;<2-UTILITIES>PLEASE.MAC.2, 14-Sep-76 21:44:30, EDIT BY OSMAN
;	TCO 1527 - REMOVE IPCF SYMBOL DEFS AND SEARCH COMSYM INSTEAD
;<1B-UTILITIES>PLEASE.MAC.12, 10-JUN-76 18:47:46, Edit by KOHN
;<1B-UTILITIES>PLEASE.MAC.11, 10-JUN-76 18:44:21, Edit by KOHN
;TCO #1399-FIX PROBLEM OF USING SAME BUFFER FOR RDTTY AND SNDTXT--TAH
;<KOHN>PLEASE.MAC.7, 10-JUN-76 18:27:05, Edit by KOHN
;<1B-UTILITIES>PLEASE.MAC.6, 21-MAY-76 12:11:55, Edit by HESS
;<EXEC>PLEASE.MAC.5, 22-APR-76 12:17:51, Edit by HESS
;	ADD .DIRECT XTABM
;<EXEC>PLEASE.MAC.4, 25-MAR-76 15:38:00, Edit by HESS
;<V-SOURCES>PLEASE.MAC.3, 23-DEC-75 12:23:59, EDIT BY LEWINE
;<UTILITIES-MACK>PLEASE.MAC.3, 18-NOV-75 11:17:05, EDIT BY HURLEY



;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 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.

	TITLE PLEASE

;THIS PROGRAM IS THE USER HALF OF THE PLEASE/OPLEASE PAIR OF PROGRAMS.  EACH
;USER WHO WANTS TO TALK TO AN OPERATOR RUNS PLEASE, SPECIFYING THE DESIRED
;OPERATOR.  THAT OPERATOR RUNS OPLEASE, AND THE TWO PROGRAMS TALK VIA IPCF
;MESSAGES.

;THE PDB'S FOR THE MESSAGES ARE SET UP IN THE USUAL WAY; I.E.,
;.IPCFL:	FLAG WORD
;.IPCFS:	SENDER'S PID
;.IPCFR:	RECEIVER'S PID
;.IFCFP:	1000,,PAGE NUMBER

;ALL MESSAGES ARE SENT IN PAGE MODE.

;THE FIRST WORD OF EACH MESSAGE CONTAINS A CODE IN THE RIGHT HALF INDICATING
;THE MESSAGE TYPE.  IN A 'TEXT" MESSAGE THE LEFT HALF CONTAINS THE NUMBER
;OF TEXT MESSAGES SENT.  IN A 'BYE' MESSAGE THE LEFT HALF CONTAINS THE NUMBER
;THAT WAS IN THE FIRST WORD OF THE LAST TEXT MESSAGE RECEIVED.  ALL OTHER
;MESSAGES HAVE ZERO IN THE LEFT HALF OF THE FIRST WORD.

;THE CONTENTS OF THE REMAINING WORDS OF A MESSAGE VARY WITH THE MESSAGE TYPE.
	SUBTTL DATA DEFINITION

	SEARCH MONSYM,MACSYM,COMSYM	;HAS JSYS DEFINITIONS, BITS, ETC.
	.REQUIRE SYS:MACREL.REL	;HAS JSERR
	SALL
	IFNDEF .PSECT,<
	.DIRECT .XTABM>

;MACRO TO RESET, HALT, RESTART IF USER CONTINUES
;RESET PREVENTS INTERRUPT ON MESSAGES SENT TO OLD PID BEFORE
;RESET AT START IS EXECUTED

	DEFINE QUIT1
	<JRST [	RESET
		HALTF
		JRST START2]>

;REGISTER USAGE

;PRIMARY USAGE - CARRIED OVER SUBROUTINE CALLS

;P1/ ADDRESS OF RECEIVE PDB
;P2/ ADDRESS OF SEND PDB
;P3/ ADDRESS OF SEND MESSAGE
;P4/ SIZE OF SEND MESSAGE
;Q1/ FLAG WORD RECEIVED
;Q2/ SENDER'S PID
;Q3/TRANSFER ADDRESS

;TEMPORARY USAGE

;P5/ASSORTED SEMI-PERMANENT VALUES
;P6/DITTO
;REGISTERS FROM ABOVE USED AS LOCAL TEMPORARY VALUES
;T1-T4 USED FOR TEMPORARY VALUES

;AC DEFINITIONS

F=0
T1=1
T2=2
T3=3
T4=4
Q1=5
Q2=6
Q3=7
P1=10
P2=11
P3=12
P4=13
P5=14
P6=15
P=17

;DEBUG SWITCH - 1 IF WANT EXTRA PRINTING. ALL DEBUG PRINTING PRECEDED BY 'D:'

DEBUG:	0

; MASKS FOR FLAG WORD RECEIVED (FIRST WORD IN PDB)

	MSKSTR(ERROR,,IP%CFE)	;ERROR FIELD IN FLAG WORD
	MSKSTR (SYSTEM,,IP%CFC)	;SYSTEM SEND FIELD IN FLAG WORD

;STACK

STKSIZ=10
STK:	BLOCK STKSIZ

;REGISTER SAVE AREA. REGISTERS ARE STORED IN ORDER IN INTERRUPT ROUTINES

REGSAV:	BLOCK 20

;ENTRY VECTOR

PRGVER==3			;VERSION NUMBER
PRGEDT==10			;EDIT NUMBER
PRGMIN==0			;MINOR VERSION
PRGCST==0			;CUSTOMER ID

ENTVEC:	JRST START		;START ADDRESS
	JRST START2		;REENTER ADDRESS
	PRGCST_^D33+PRGVER_^D24+PRGMIN_^D18+PRGEDT

;TRANSFER VECTOR BASED ON CODE RECEIVED
DEFINE TX(ADDRES,CODE)
<
IFG CODE-%%MAX,<%%MAX==CODE>
RELOC GOTAB+CODE
	ADDRES
RELOC GOTAB+%%MAX+1
>
%%MAX==0			;FINAL VALUE IS ONE LESS THAN LENGTH OF TABLE

GOTAB:	TX BYE,PLBYE			;PLBYE HAS BEEN RECEIVED
	TX TEXT,PLTXT			;PLTXT HAS BEEN RECEIVED
	TX OK,PLOK			;PLOK HAS BEEN RECEIVED
	TX CONFUS,PLCON			;PLCON HAS BEEN RECEIVED
	TX PWAIT,PLWAIT			;PLWAIT HAS BEEN RECEIVED
	TX ANSWER,PLANS			;PLANS HAS BEEN RECEIVED
TABSIZ=.-GOTAB

;BUFFER THAT HOLDS TEXT SENT BY OPERATOR

	LOC 10000
TXTBUF:	BLOCK 1000
BUFEND:
	RELOC
BUFNXT:	XWD -1,TXTBUF		;NEXT LOCATION TO WRITE INTO

;MESSAGE AREA FOR RECEIVE

;PDB

RMSGSZ=	1000
RPDB:	IP%CFB!IP%TTL!IP%CFV	;DON'T BLOCK;TRUNCATE;PAGE MODE
	block 1			;sender's pid
	BLOCK 1			;receiver's pid
	XWD RMSGSZ,RPAGE	;message length,,page number
	BLOCK 2			;DIRECTORIES AND PRIVILEGES
RPDBSZ=.-RPDB

;MESSAGE

	LOC 11000
RMSG:	BLOCK RMSGSZ		;MESSAGE AREA

	RELOC
RPAGE=RMSG/1000			;PAGE NUMBER FOR MESSAGE

;MESSAGE AREA FOR SEND at interrupt level

;PDB

SMSGSZ=1000
SPDB:	IP%CFV			;PAGE MODE
	block 1			;SENDER'S PID
	BLOCK 1			;RECEIVER'S PID
	XWD SMSGSZ,SPAGE	;MESSAGE LENGTH,,PAGE NUMBER
SPDBSZ=.-SPDB

;MESSAGE

	LOC 12000
SMSG:	BLOCK SMSGSZ		;MESSAGE AREA

	RELOC
SPAGE=SMSG/1000			;PAGE NUMBER FOR MESSAGE

;message area for send at NON-INTerrupt level

;PDB

OMSGSZ=1000
OPDB:	IP%CFV			;PAGE MODE
	block 1			;SENDER'S PID
	block 1			;RECEIVER'S PID
	XWD OMSGSZ,OPAGE	;MESSAGE LENGTH,,page NUMBER
OPDBSZ=.-OPDB

;MESSAGE

	LOC 13000
OMSG:	BLOCK OMSGSZ		;MESSAGE AREA

	RELOC
OPAGE=OMSG/1000			;PAGE NUMBER FOR MESSAGE

;THIS AREA CONTAINS TEXT TO BE SENT TO OPLEAS. INITIALLY IT CONTAINS
;<OPERATOR>OPLEASE FOLLOWED BY THE OPERATOR ID FOLLOWED IMMEDIATELY
;BY THE FIRST LINE OF TEXT.
;THE STRING '<OPERATOR>OPLEASE' CONCATENATED WITH THE ID IS SENT TO
;INFO TO GET THE PID FOR THE OPERATOR.  THE FIRST LINE OF TEXT FOLLOWS
;THE ID IMMEDIATELY.  WHEN THE USER TYPES, THE TEXT IS ADDED TO THE END OF 
;PREVIOUS LINES OF TEXT.  WHEN THE TEXT IS SENT TO OPLEAS, THE POINTER
;IS RESET TO THE BYTE IMMEDIATELY AFTER THE ID AND THE NEXT READ BEGINS
;THERE.  'TEXT" AND 'ONEWAY' MESSAGES ARE SENT BY SOUTING TO THE APPROPRIATE
;MESSAGE AREA FROM THIS PAGE.

linesz=775			;words AVAILABLE AFTER NAME BEFORE ID ADDED
namlen=21			;LENGTH OF NAME BEFORE ID ADDED
NAMSIZ:	block 1			;SIZE OF NAME TO SEND TO INFO
				;INCLUDES ID TYPED BY USER

;keep OPRNAM AND INITXT together

	LOC 14000
OPRNAM:	ASCIZ /<OPERATOR>OPLEASE/
INITXT=.-1
	block linesz-1		;SPACE FOR REST OF ID AND TEXT

	RELOC

;THE FOLLOWING VALUE IS FIXED.

INISIZ=<LINESZ*5>-5		;BYTES AVAILABLE FOR TEXT BEFORE ID ADDED

;THE FOLLOWING ARE UPDATED AFTER THE ID IS READ.

inibeg:	block 1			;pointer to FIRST BYTE AFTER ID
				; (START OF TEXT)
TXTSIZ:	BLOCK 1			;NUMBER OF BYTES AFTER ID (SPACE
				; FOR TEXT)

;THE FOLLOWING ARE UPDATED AFTER EACH TTY READ AND RESET TO THE PRECEDING
;VALUES AFTER THE TEXT IS SENT

RDNXT:	BLOCK 1			;NEXT AVAILABLE BYTE IN BUFFER
RDLIM:	BLOCK 1			;NUMBER OF BYTES AVAILABLE IN BUFFER
;TEMPORARY BUFFER USED FOR RDTTY CALL

TBUFSZ==^D120
TBUF:	BLOCK TBUFSZ

;VARIABLES USED WHILE READING FIRST LINE

IDFLG:	0			;SET WHEN OPERATOR ID FOUND
MSGFLG:	0			;TEXT FOUND
CHCNT:	0			;NUMBER OF NON-PUNCTUATION CHARS PROCESSED
BYTCNT:	0			;NUMBER OF BYTES PROCESSED
initer:	BLOCK 1			;last character typed IN FIRST LINE OF TEXT
JOBNAM:	ASCIZ/PLEASE/		;OUR PROGRAM NAME

;PIDS

MYPID:	0			;THIS USER'S PID
OPRPID:	0			;PID OF OPERATOR TALKING TO

;MAXIMUM MESSAGE SIZE FOR THIS INSTALLATION

MAXMSG:	BLOCK 1			;DETERMINED DURING INITIALIZATION WITH MUTIL

;ASSOCIATED VARIABLE FOR NEXT MESSAGE IN IPCF QUEUE

NXTMSG:	0			;0 IF THERE WAS NO MESSAGE WAITING
				;AFTER THE LAST RECEIVE

; ARGUMENT BLOCK FOR MUTIL

MUTILD:	BLOCK 10

;FLAGS TO INDICATE STATE

INTFLG:	0			;SET WHEN INTERRUPT PROCESSED
WTFLG:	0			;SET WHEN WAITING FOR AN INTERRUPT

;FLAGS SET BASED ON MESSAGES RECEIVED

ACTFLG:	0			;SET WHEN RECEIVE OK FROM OPLEAS
				; AND TWO WAY CONVERSATION HAS BEGUN
BYEFLG:	0			;SOMEONE WANTS TO SAY GOODBYE
				; BIT 0 SET IF USER SAYS GOODBYE
				;BIT 1 SET IF OPERATOR SAYS GOODBYE
TXTFLG:	0			;TEXT FROM OPERATOR WAITING IN BUFFER

;COUNT OF TEXT MESSAGES SENT AND RECEIVED

SNDCNT:	0			;NUMBER OF MESSAGES SENT BY PLEASE
RCVCNT:	0			;NUMBER OF LAST MESSAGE RECEIVED BY PLEASE
TXTCNT:	0			;NUMBER OF LAST MESSAGE RECEIVED BY OPLEAS
NOW:	0			;CURRENT TIME

;INTERRUPT SYSTEM

; [LEVEL,,INTERRUPT ADDRESS]

CHNTAB:	XWD 1,IPCINT		;IPCF ON CHANNEL 0
	XWD 1,TINT		;^T ON CHANNEL 1
	XWD 1,CINT		;^C ON CHANNEL 2
	XWD 1,TYPINT		;INPUT BUFFER NON-EMPTY ON 3
	BLOCK ^D32		;REST OF TABLE

; [LOCATION WHERE PC STORED BY LEVEL]

LEVTAB:	PCSAV1			;LEVEL 1 PC STORAGE
	PCSAV2			;LEVEL 2 PC STORAGE
	PCSAV3			;LEVEL 3 PC STORAGE

;PC'S SAVED HERE

PCSAV1:	BLOCK 1			;PC FOR LEVEL 1 INTERRUPTS
PCSAV2:	BLOCK 1			;PC FOR LEVEL 2 INTERRUPTS (NOT USED)
PCSAV3:	BLOCK 1			;PC FOR LEVEL 3 INTERRUPTS (NOT USED)

;KLUDGE TO KEEP THE SYMBOL TABLE OUT OF MY DATA

	LOC 16000		;kludge to keep the symbol table
	-1			; out of my data
	RELOC
	SUBTTL INITIALIZATION

;HERE IF RESTARTING AFTER ERROR. INPUT WILL COME FROM ANSWERS TO QUESTIONS
;AND NOT FROM THE EXEC VIA RSCAN.

START2:	TMSG <
[Restarting]
>
	movei t1,.priin		;t1/primary input 
	cfibf			;clear input buffer (discard erroneous text)
	HRROI T1,T2		;POINT TO INTERNAL AREA
	SETZ T2,		;CLEAR IT
	RSCAN			;PUT NULL IN RESCAN BUFFER SO
				; RSCAN WILL RETURN NO CHARACTERS

;HERE FOR NORMAL START

START:	RESET			;GET RID OF PIDS, CLEAR INTERRUPTS, ETC.
	MOVE P,[IOWD STKSIZ,STK] ;SET UP THE STACK

;CLEAR VARIOUS LOCATIONS (SEE DATA DEFINITION FOR EXPLANATIONS)

	SETZM MYPID
	SETZM OPRPID
	SETZM WTFLG
	SETZM INTFLG
	SETZM TXTFLG
	SETZM ACTFLG
	SETZM BYEFLG
	SETZM NXTMSG
	SETZM PCSAV1
	SETZM IDFLG		
	SETZM MSGFLG		
	SETZM INITER
	SETZM CHCNT
	SETZM BYTCNT
	SETZM SNDCNT		
	SETZM RCVCNT		
	SETZM TXTCNT		
	CALL CLRTXT		;CLEAR BUFFER AREA FOR RECEIVED TEXT

;SET UP BUFFER FOR OPERATOR ID AND TEXT. INITIALIZE TO ASSUME
;BLANK ID.

	MOVE T1,[ASCII /SE/]	;RESTORE NULLS TO BYTES AFTER 'OPLEAS'
	MOVEM T1,INITXT
	move t1,[INITXT+1,,INITXT+2] ;CLEAR REMAINING WORDS
	setzm initxt+1
	BLT T1,INITXT+LINESZ-1
	move t1,[point 7,initxt,13] ;point to  LAST BYTE OF
	movem t1,inibeg		;NAme to send to info
	MOVEM T1,RDNXT
	MOVEI T1,INISIZ		;NUMBER OF BYTES AVAILABLE AFTER
	MOVEM T1,TXTSIZ		; NAME TO SEND TO INFO
	MOVEM T1,RDLIM

	MOVEI T1,namlen		;SIZE OF NAME SENT TO INFO
	MOVEM T1,NAMSIZ		;INITIALIZE TO ASSUME NULL ID


;FIND OUT MAXIMUM MESSAGE SIZE - USED WHEN RECEIVING IN NON-PAGE MODE

	MOVEI T1,26		;CODE: GET MAX MESSAGE
	MOVEM T1,MUTILD		;SAVE IN MUTIL AREA
	MOVEI T1,2		;T1/SIZE OF MUTIL BLOCK
	MOVEI T2,MUTILD		;T2/LOCATION OF MUTIL BLOCK
	MUTIL			;GET SIZE LIMIT
	 JSERR			;ERROR
	MOVE T1,MUTILD+1	;SAVE LIMIT
	MOVEM T1,MAXMSG

	;..
	SUBTTL FIRST - READS FIRST INPUT LINE

;THIS CODE READS THE LINE TYPED TO THE EXEC.  THIS MAY BE OF THE FORM
;@PLEASE ID:TEXT
;@PLEASE ID:
;@PLEASE TEXT
;@PLEASE
;@R PLEASE
;@START
;ETC.  IT SEARCHES FOR THE ID AND TEXT AND STORES THEM IN THE INITXT AREA.
;IT SETS IDFLG ON FINDING AN ID, MSGFLG ON FINDING TEXT.

;READ THE LINE TYPED TO THE EXEC

	;..
	MOVEI P4,INISIZ		;SPACE AVAILABLE FOR TEXT AFTER NAME
	SETZ T1,		;MOVE THE LINE TYPED TO THE EXEC INTO
	RSCAN			; THE INPUT BUFFER
	 JRST [	JSERR		;FAILED
		JRST START2]	;START OVER
	MOVEM T1,P6		;SAVE BYTE COUNT
	JUMPE P6,GTINFO		;IF NO CHARACTERS, STARTED WITH DDT.
				; OR RESTARTED FROM WITHIN

;THERE IS AT LEAST ONE CHARACTER. SEE IF IT STARTED WITH JOB NAME.
;IF SO, MAY CONTAIN ID AND TEXT. IF NOT, GO ASK FOR THEM.

	MOVE P5,[440700,,JOBNAM] ;POINT TO JOB NAME
FIRST1:	ILDB T2,P5		;GET NEXT CHARACTER IN NAME
	JUMPE T2,FIRST2		;IF ZERO, MATCHED WHOLE NAME
	PBIN			;YES. GET A CHARACTER
	SOS P6			;DECREMENT COUNT OF REMAINING CHARS
	JUMPE P6,GTINFO		;LAST CHARACTER? MUST BE BREAK
	CAMN T1,T2		;DO THEY MATCH?
	JRST FIRST1		;YES. GO LOOK AT NEXT PAIR
	JRST FIRST6		;NO. DIDN'T START WITH JOBNAME

;STARTED WITH JOB NAME.  LOOK FOR FIRST SPACE OR TAB
;JOB NAME MAY BE FOLLOWED BY RECOGNIZED FILE NAME, ETC.

FIRST2:	PBIN			;READ NEXT CHARACTER
	SOS P6			;DECREMENT REMAINING COUNT
	JUMPE P6,GTINFO		;LAST CHARACTER? MUST BE BREAK
	CAIN T1,40		;IS IT A BLANK?
	JRST FIRST3		;YES. ON TO ID AND TEXT
	CAIE T1,.CHTAB		;NO. IS IT TAB?
	JRST FIRST2		;NO. GO TO NEXT CHARACTER

;FOUND SPACE OR TAB AFTER JOBNAME.  LOOK FOR FIRST NON-SPACE,
;NON-TAB TO BEGIN ID OR TEXT.

FIRST3:	PBIN			;YES. READ ONE
	SOS P6			;DECREMENT COUNT OF REMAINING CHARS
	JUMPE P6,GTINFO		;LAST CHARACTER? MUST BE BREAK
	CAIN T1,40		;SPACE?
	JRST FIRST3		;YES. KEEP LOOKING
	CAIN T1,.CHTAB		;NO.TAB?
	JRST FIRST3		;YES. KEEP LOOKING
	CAIE T1,.CHCRT		;NO. CARRIAGE RETURN?
	JRST FIRST7		;NO.

;QUIT BEFORE READING ENTIRE BUFFER. READ AND DISCARD

FIRST6:	JUMPE P6,GTINFO		;IF ZERO, HAVE READ ALL
	PBIN			;READ A CHARACTER
	SOS P6			;DECREMENT COUNT
	JRST FIRST6
;HAVE FOUND 'JOBNAME...CHARACTER'.  THE CHARACTER IS NON-BLANK.
;READ IT AND REMAINING CHARACTERS INTO INITXT AREA STARTING AT BYTE
;POINTED TO BY INIBEG

FIRST7:	MOVEI T1,.PRIIN		;BACK UP POINTER SO READ WILL INCLUDE
	BKJFN			; CHARACTER ALREADY READ
	 JRST [	JSERR		;FAILED
		JRST START2]	;START OVER
	aos p6			;add back re-read character to count
	MOVE T1,INIBEG		;DEST:BYTE AFTER 'OPLEASE' IN OPRNAM
	MOVX T2,RD%BRK!RD%BEL	;STANDARD BREAK PLUS EOL
	HRRI T2,INISIZ		;T2/SPACE AVAILABLE IN BUFFER
	HRR T4,T2		;SAVE SPACE AVAILABLE BEFORE READ
	SETZ T3,		;NO CTRL/R BUFFER
	RDTTY			;READ INPUT LINE FROM RESCAN BUFFER
	 jrst [	jserr		;read failed
		jrst start2]	;start over
	HRRM T2,RDLIM		;SAVE SPACE AFTER FIRST LINE OF TEXT
	MOVEM T1,RDNXT		;SAVE NEXT LOCATION FOR TEXT
	txnn t2,rd%btm		;did we read A BREAK CHARACTER?
	JRST [	TMSG <
?Input too long.  It has been rejected.
>				;NO. RAN OUT OF BUFFER SPACE
		JRST START2]
	MOVE T3,T4		;SPACE ORIGINALLY AVAILABLE
	movem t1,T4		;save pointer to last byte
	SUBI T3,(T2)		;COMPUTE BYTES READ FROM BYTES REMAINING
	SUB P6,T3		;NUMBER BYTES STILL IN RESCAN BUFFER
FIRST9:	SKIPE P6		;ANY MORE CHARACTERS TO BE READ?
	JRST [	PBIN		;YES. READ ONE AND DISCARD
		SOS P6		;DECREMENT THE COUNT
		JRST FIRST9]	;REPEAT UNTIL ALL READ
	MOVE P6,T4		;P6/POINTER TO LAST BYTE
	ldb p5,p6		;save last byte (WILL BE CHECKED FOR
	MOVEM P5,INITER		; CNTL/Z OR ESCAPE)
	SETZM CHCNT		;CLEAR COUNT OF NON-BLANK CHARACTERS
	SETZM BYTCNT		;CLEAR COUNT OF BYTES
	MOVE T1,INIBEG		;POINT TO BEGINNING

;LOOK THROUGH CHARACTERS LOOKING FOR ID AND TEXT

FIRST4:	ILDB P5,T1		;LOOK AT NEXT BYTE
	AOS BYTCNT		;INCREMENT BYTE COUNT
	CAMN T1,P6		;IS IT THE LAST?
	JRST FIRST8		;YES
	CAIN P5,.CHCRT		;CARRIAGE RETURN?
	
;CARRIAGE RETURN OR LAST CHARACTER. IF ANY CHARACTERS READ,
;THEY MUST BE TEXT SINCE DIDN'T END WITH COLON (LAST CHARACTER
;MUST BE BREAK).

FIRST8:	JRST [	SKIPN CHCNT	;READ ANY CHARACTERS?
		JRST GTINFO	;NO.
		SETOM IDFLG	;YES. WE HAVE AN ID
		SETOM MSGFLG	;WE HAVE A MESSAGE
		JRST GTINFO]

;NOT CARRIAGE RETURN. BLANK OR TAB?

	CAIN P5,40		;BLANK?
	JRST FIRST5		;YES.
	CAIN P5,.CHTAB		;NO.TAB?

;SPACE OR TAB.  IF THERE HAVE BEEN CHARACTERS THIS IS DELIMITER
;IN TEXT.

FIRST5:	JRST [	SKIPN CHCNT	;SPACE OR TAB. DID NON-BLANK PRECEDE?
		JRST FIRST4	;NO. KEEP LOOKING
		SETOM MSGFLG	;YES. WE HAVE A MESSAGE
		SETOM IDFLG	;WE HAVE AN ID
		JRST GTINFO]

;NOT SPACE OR TAB

	CAIE P5,72		;COLON?
	JRST [	AOS CHCNT	;NOT A COLON. INCREMENT CHAR COUNT
		SKIPN IDFLG	;DO WE ALREADY HAVE AN ID?
		JRST FIRST4	;NO. THIS IS PART OF IT
		SETOM MSGFLG	;YES. THIS IS START OF TEXT
		JRST GTINFO]

;COLON.  THIS IS END OF ID.

	SUB P4,CHCNT		;SPACE LEFT FOR TEXT AFTER NAME
	MOVEM P4,TXTSIZ		;SPACE FOR TEXT AFTER ID
	SETOM IDFLG		;COLON. THIS IS END OF ID.
	SETZM CHCNT		;RESET NON-BLANK COUNT
	MOVEM T1,INIBEG		;SAVE POINTER TO BEGINNING OF TEXT
	MOVE T2,NAMSIZ		;ADD LENGTH OF ID TO LENGTH OF NAME
	ADD T2,BYTCNT
	SOS T2			;DON'T COUNT THE COLON
	MOVEM T2,NAMSIZ
	JRST FIRST4
	SUBTTL GTINFO - GETS INFO NOT ENTERED IN CALL

;HERE AFTER PROCESSING THE LINE TYPED TO THE EXEC.  IDFLG IS SET
;IF AN OPERATOR ID WAS FOUND; MSGFLG IS SET IF TEXT WAS FOUND.
;IF EITHER IS MISSING, THIS CODE PROMPTS FOR THEM AND STORES THE
;ANSWERS IN THE INITXT AREA.

;REACHED VIA JRST 

GTINFO:	MOVEI T1,.SFOPR		;SET TO READ MONITOR FLAG
	TMON			;TO SEE IF OPERATORS ARE AROUND
	JUMPN T2,GTINF0		;IN ATTENDANCE, SKIP MESSAGE
	TMSG <
% Warning:  Operator is not in attendance.
>				;NOT AROUND, SAY SO
GTINF0:	SKIPE IDFLG		;DO WE HAVE AN OPERATOR ID?
	JRST GTINF4		;YES. DON'T ASK FOR IT
	TMSG <
What is the operator's ID? >	;NO. ASK FOR IT
	MOVE T1,INIBEG		;READ ID INTO END OF NAME
	MOVX T2,RD%BRK!RD%BEL	;STANDARD BREAK PLUS BEL
	HRRI T2,INISIZ		;SPACE AVAILABLE FOR NAME AND TEXT
	SETZ T3,		;NO CONTROL/R BUFFER
	RDTTY			;READ THE OPERATOR ID
	 jrst [	jserr		;error in reading
		jrst start2]	;start over
	txnn t2,rd%btm		;did we get all that was typed?
	jrst [	tmsg<
?INPUT TOO LONG. IT HAS BEEN REJECTED.
>				;no. tell the user
		jrst start2]	;start over
	MOVEM T1,RDNXT		;NEXT LOCATION TO READ TEXT INTO
	MOVEI T3,INISIZ		;ORIGINAL BYTES AVAILABLE
	SUBI T3,(T2)		;COMPUTE BYTES READ FROM BYTES REMAINING
	MOVEM T3,P6		;P6/ NUMBER OF BYTES READ

;USER TYPED ID OR CR.  BACK UP TO LAST CHARACTER NOT A BREAK

GTINF1:	LDB P5,T1		;LOOK AT LAST BYTE
	CAIN P5,.CHLFD		;IS IT A LINE FEED?
	JRST GTINF2		;YES.
	CAIN P5,72		;COLON?
	JRST GTINF2		;YES.
	CAIN P5,.CHCUN		;END OF LINE?
	JRST GTINF2		;YES
	CAIE P5,.CHCRT		;CARRIAGE RETURN?
	JRST GTINF3
	
;LF, COLON, EOL, OR CARRIAGE RETURN - KEEP BACKING UP

GTINF2:	SOS P6
	JUMPE P6,GTINF4		;ANY MORE CHARACTERS?
	BKJFN			;YES. BACK UP
	 JSERR
	JRST GTINF1
	
;NOT A BREAK CHARACTER

GTINF3:	MOVEM T1,INIBEG		;LAST CHAR IN ID.  SAVE POINTER TO
				; TO BEGINNING OF TEXT
	MOVE T2,NAMSIZ		;INCREASE NAME SIZE BY LENGTH
	ADD T2,P6		; OF ID
	MOVEM T2,NAMSIZ
	SUB P4,P6		;BYTES AVAILABLE FOR TEXT AFTER NAME
	MOVEM P4,TXTSIZ		;SPACE LEFT FOR TEXT AFTER ID

;GET MESSAGE IF NOT PREVIOUSLY TYPED

GTINF4:	SKIPE MSGFLG		;IS THERE TEXT?
	JRST GTINF5		;YES.
	TMSG <
Enter text: >			;NO. ASK FOR IT
	MOVE T1,INIBEG		;T1/STORE AFTER ID
	MOVX T2,RD%BRK!RD%BEL	;T2/[STANDARD BREAK PLUS END OF LINE,,
	hrr T2,p4		; number of bytes available]
	SETZ T3,		;T3/NO CNTL/R BUFFER
	RDTTY			;read the text
	 jrst [	jserr		;read fails
		jrst start2]	;start over
	txnn t2,rd%btm		;did we get all that was typed?
	JRST [	TMSG<
?Input too long. It has been rejected.
>				;NO. TELL THE USER
		JRST START2]	;YES. START OVER
	MOVEM T1,RDNXT		;NEXT LOCATION AFTER FIRST TEXT
	HRRM T2,RDLIM		;NUMBER BYTES AFTER FIRST TEXT
	LDB P5,T1		;SAVE LAST CHARACTER (WILL BE CHECKED
	MOVEM P5,INITER		; FOR CNTL/Z OR ESCAPE)

GTINF5:	JFCL

;AT THIS POINT THE FOLLOWING SHOULD BE DEFINED
;INIBEG:	FIRST LOCATION FOR TEXT (FIRST AFTER ID)
;TXTSIZ:	NUMBER BYTES FOR TEXT (AFTER NAME)
;RDNXT:		LOCATION AFTER FIRST LINE OF TEXT
;RDLIM:		NUMBER BYTES AFTER FIRST LINE OF TEXT

	;..
	SUBTTL GET A PID

;THIS CODE GETS A PID FOR THIS USER USING MUTIL.  IT SAVES THE
;PID IN MYPID AND IN THE APPROPRIATE WORD OF THE 3 PDB'S.

	;..
	MOVEI T1,.MUCRE		;CREATE A PID
	MOVEM T1,MUTILD		;FUNCTION CODE
	MOVE T1,[0,,.FHSLF]	;MY FORK
	MOVEM T1,MUTILD+1	;TO MUTIL AREA
	MOVEI T1,3		;T1/LENGTH
	MOVEI T2,MUTILD		;T2/LOCATION
	MUTIL			;GET A PID
	 JRST [	JSERR		;FAILED
		QUIT1]		;QUIT
	MOVE T1,MUTILD+2	;RETRIEVE THE PID FROM MUTIL AREA
	MOVEM T1,MYPID		; AND SAVE
	MOVEI T2,RPDB		;SAVE MY PID IN RECEIVER FIELD FOR
	MOVEM T1,.IPCFR(T2)	; RECEIVES
	MOVEI T2,SPDB		;SAVE IN SENDER FIELD FOR INTERRUPT
	MOVEM T1,.IPCFS(T2)	; LEVEL SENDS
	MOVEI T2,OPDB		;SAVE IN SENDER FIELD FOR NON-INTERRUPT 
	MOVEM T1,.IPCFS(T2)	; LEVEL SENDS
	SKIPE DEBUG		;DEBUGGING?
	JRST [	TMSG <
D:User's PID is >		;YES. PRINT USER'S PID
		MOVEI T1,.PRIOU	;T1/PRIMARY OUTPUT
		MOVE T2,MYPID	;T2/USER'S PID
		MOVX T3,1B0+10B35 ;MAGNITUDE,OCTAL
		NOUT		;PRINT THE PID
		 JSERR
		TMSG <
>
		JRST .+1]

	;..
	SUBTTL ASK INFO

;THIS CODE SENDS A MESSAGE TO INFO CONTAINING <OPERATOR>OPLEASE FOLLOWED
;BY THE OPERATOR'S ID. IT ASKS FOR THE PID ASSOCIATED WITH THAT
;NAME AND WAITS FOR THE ANSWER FROM INFO. IF SAVES THE ANSWER
;IN OPRPID

	;..
ASKINF:	MOVEI P2,OPDB		;P2/ADDRESS OF SEND PDB
	MOVEI P3,OMSG		;P3/ADDRESS OF SEND MESSAGE
	SETZM .IPCFR(P2)	;RECEIVER'S PID (0 FOR INFO)
	MOVE T1,[1,,.IPCIW]	;CODE,,FIND PID
	MOVEM T1,.IPCI0(P3)	; INTO MESSAGE
	SETZM .IPCI1(P3)	;NO DUPLICATE REPLY
	HRROI T1,.IPCI2(P3)	;TRANSFER NAME TO MESSAGE
	HRROI T2,OPRNAM		; FROM OPRNAM
	MOVN T3,NAMSIZ		;T3/NEGATIVE BYTE COUNT
	SOUT			;TRANSFER, UPDATING POINTERS
	MOVEI P4,OPDBSZ		;P4/SIZE OF SEND PDB
	CALL SNDMSG		;SEND THE MESSAGE
	 JRST [	CALL NOINFO	;SEND FAILED. PRINT MESSAGE
		JRST START2]	;START OVER

;READ ALL MAIL UNTIL GET ANSWER FROM INFO.

ASKIN1:	MOVEI P1,RPDB		;P1/LOCATION OF RECEIVE PDB
	MOVX T1,IP%TTL		;BLOCK, TRUNCATE, no page mode
	MOVEM T1,.IPCFL(P1)	;FLAG WORD
	MOVE T1,[RMSGSZ,,RMSG]	;MAX MESSAGE SIZE,,LOCATION
	MOVEM T1,.IPCFP(P1)	;TO PDB
	MOVEI T1,RPDBSZ		;T1/LENGTH OF PDB
	MOVEI T2,RPDB		;T2/LOCATION OF PDB
	MRECV			;WAIT FOR MESSAGE AND RECEIVE
	 JRST ASKIN5		;RECEIVE FAILED

;RECEIVE SUCCEEDED.  SEE WHO SENT IT.

	MOVE Q1,.IPCFL(P1)	;FLAG BITS
	JXE Q1,IP%CFC,ASKIN1	;SENT BY SYSTEM? IF NO, IGNORE
	LOAD T2,SYSTEM,Q1	;YES. FIND OUT WHO SENT IT
	CAME T2,.IPCCF		;FROM INFO?
	JRST ASKIN1		;NO. IGNORE IT.
	JXE Q1,IP%CFE,ASKIN3	;FROM INFO. ERROR?
	LOAD T2,ERROR,Q1	;YES. GET ERROR CODE
	CAIN T2,.IPCNN		;NAME UNKNOWN?
	JRST [	TMSG<
?operator job to service please requests is not running.
[Waiting.]
>				;YES.
		MOVEI T1,^D60000 ;TIME TO WAIT: ONE MINUTE
		DISMS		;WAIT A WHILE
		JRST ASKINF]	;GO TRY AGAIN

;ERROR FROM INFO BUT NOT NAME UNKNOWN

	SKIPE DEBUG		;DEBUGGING?
	JRST [	TMSG <
D:Error from INFO: >		;YES
		MOVEI T1,.PRIOU	;T1/PRIMARY OUTPUT
		MOVX T3,10B35	;OCTAL
		NOUT		;PRINT THE ERROR CODE
	 	 JSERR		;FAILED
		TMSG <
>
		JRST .+1]
	JRST ASKIN1		;GO READ NEXT MESSAGE

;FROM INFO WITH NO ERROR CODE.  TEST FOR UNDELIVERED MAIL

ASKIN3:	JXE Q1,IP%CFM,ASKIN4	;NO ERROR.UNDELIVERED?
	TMSG <
?System jobs not running.
>				;YES. PRINT MESSAGE 
	JRST START2		;START OVER

;MAIL IS FROM INFO WITH NO ERRORS. SHOULD CONTAIN OPERATOR'S PID

ASKIN4:	MOVE T1,[1,,.IPCIW]	;GET CODE
	CAME T1,RMSG		;SAME CODE,,FUNCTION?
	JRST ASKIN1		;NO. IGNORE.
	MOVE T1,RMSG+1		;YES. GET ANSWER
	MOVEM T1,OPRPID		;SAVE OPERATOR'S PID
	JRST INTERR

;RECEIVE FAILED. IF PAGE MODE, READ AND DISCARD

ASKIN5:	CAIE T1,IPCF16		;DATA MODE PROBLEM?
	JRST ASKIN6		;NO. SOME OTHER ERROR
	MOVX T2,IP%CFB!IP%TTL!IP%CFV ;PAGE MODE, TRUNCATE, DON'T BLOCK
	MOVEM T2,.IPCFL(P1)	;TO PDB
	HRRZI T1,RPAGE		;ZERO LENGTH,,USUAL PAGE
	MOVEM T1,.IPCFP(P1)	;TO PDB
	MOVEI T1,RPDBSZ		;T1/SIZE OF PDB
	MOVEI T2,RPDB		;T2/LOCATION OF PDB
	MRECV			;RECEIVE IT
	 JRST ASKIN6		;DIDN'T SOLVE THE PROBLEM
	JRST ASKIN1		;GO GET NEXT MESSAGE

;NOT A PAGE PROBLEM

ASKIN6:	JSERR			;SOME OTHER ERROR. PRINT MESSAGE.
	JRST ASKIN1		;GO GET NEXT MESSAGE
	SUBTTL SET UP INTERRUPTS

;THIS CODE SETS UP FOR INTERRUPTS ON THE FOLLOWING CHANNELS:
;0-IPCF MESSAGE RECEIVED
;1-CTRL/T
;2-CTRL/C
;3-INPUT BUFFER GOES FROM EMPTY TO NON-EMPTY
;IT ACTIVATES CHANNEL 0 BUT DOESN'T ENABLE ANY CHANNELS.  THUS AN
;IPCF INTERRUPT IS DELAYED UNTIL THE INTERRUPTS ARE ENABLED.

;REACHED VIA JRST

INTERR:	CIS			;CLEAR THE INTERRUPT SYSTEM
	MOVEI T1,.MUPIC		;ASSOCIATE PID WITH CHANNEL
	MOVEM T1,MUTILD		;FUNCTION CODE
	MOVE T1,MYPID		;PID FOR OPLEASE
	MOVEM T1,MUTILD+1	;PID TO ASSOCIATE WITH CHANNEL
	SETZM MUTILD+2		;CHANNEL 0
	MOVEI T1,3		;T1/LENGTH OF ARGUMENT BLOCK
	MOVEI T2,MUTILD		;T2/LOCATION OF ARGUMENT BLOCK
	MUTIL			;ASSOCIATE CHANNEL WITH PID
	 JRST [	JSERR		;CAN'T SET UP CHANNEL. QUIT
		SKIPN DEBUG	;DEBUGGING?
		QUIT1		;NO. GIVE UP
		TMSG <
D:Trying to associate PID >	;YES. PRINT PID
		MOVEI T1,.PRIOU	;T1/PRIMARY OUTPUT
		MOVE T2,MYPID	;T2/PID USED IN MUTIL
		MOVX T3,1B0+10B35 ;T3/MAGNITUDE, OCTAL
		NOUT		;PRINT THE PID
		 JSERR
		TMSG < with channel 0
>
		QUIT1]		;GIVE UP
	MOVE T1,[.TICCT,,1]	;CTRL/T ON CHANNEL 1
	ATI			;ASSIGN CTRL/T TO CHANNEL 1
	MOVX T1,.FHSLF		;T1/MY FORK
	RPCAP			;GET PRESENT CAPABILITIES
	txnn t2,sc%ctc		;can we enable ctrl/c?
	JRST [	TMSG<
% CTRL/C NOT ENABLED.  ABORTING WITH CTRL/C WILL NOT WARN OPERATOR>
		jrst chan]	;no. don't try
	TXO T3,SC%CTC		;ALLOW CTRL/C INTERRUPTS
	EPCAP			;ENABLE THIS PLUS EXISTING
	MOVE T1,[.TICCC,,2]	;CTRL/C ON CHANNEL 2
	ATI			;ASSIGN CTRL/C TO CHANNEL 2
chan:	mOVE T1,[.TICTI,,3]	;INPUT BUFFER NON-EMPTY
	ATI			;ASSIGN BUFFER NON-EMPTY TO 3
	MOVX T1,.FHSLF		;T1/ MY FORK
	MOVE T2,[LEVTAB,,CHNTAB] ;T2/ ADDRESSES OF TABLES
	SIR			;SET UP INTERRUPT TABLES
	MOVX T1,.FHSLF		;T1/MY FORK
	MOVX T2,1B0		;T2/CHANNel TO ACTIVATE
	aic			;activate ipcf channel

	;..
	SUBTTL SEND FIRST MESSAGE

;THIS CODE SENDS 'ONEWAY' TO OPLEAS IF TEXT ENDED WITH 
;ESCAPE OR CTRL/Z.  OTHERWISE, IT SENDS 'HELLO'

	;..
	MOVE T1,INITER		;GET TERMINATOR
	CAIE T1,.CHCNZ		;CTRL/Z?
	CAIN T1,.CHESC		;NO. ESCAPE?

;MESSAGE ENDED WITH CTRL/Z OR ESCAPE. SEND ONEWAY TO OPLEAS

	JRST [	CALL SNDONE	;SEND ONEWAY AND TYPE MESSAGE
		 JRST START2	;FAILED. START OVER
		QUIT1]		;QUIT

; SEND 'HELLO' TO OPLEAS

	MOVEI P2,OPDB		;P2/LOCATION OF PDB
	MOVE T1,OPRPID
	MOVEM T1,.IPCFR(P2)	;RECEIVER IS OPLEAS
	MOVEI T1,PLHEL		;CODE IS 'HELLO'
	MOVEM T1,OMSG
	MOVEI P4,OPDBSZ		;P4/ SIZE OF PDB
	CALL SNDMSG		;SEND THE MESSAGE
	 JRST [	CALL ERR1	;RETRY IF POSSIBLE
		 JRST START2	;RETRY FAILED OR COULDN'T RETRY
		JRST .+1]

;ACTIVATE CTRL/C,CTRL/T, AND INPUT BUFFER CHANNELS.
;ENABLE INTERRUPT SYSTEM

	movei t1,.fhslf		;t1/my fork
	movx T2,1b1!1b2!1b3	;t2/channels to activate
	aic			;activate ctrl/t,ctrl/c,input buffer
	MOVEI T1,.FHSLF		;T1/MY FORK
	EIR			;ENABLE INTERRUPTS

;CAUSE AN INTERRUPT ON THE IPCF CHANNEL IN CASE THERE WAS A MESSAGE
;IN THE QUEUE WHEN THE CHANNEL WAS ACTIVATED.  INTERRUPT ROUTINE
;WILL IGNORE THE INTERRUPT IF THE MRECV FAILS.

	MOVEI T1,.FHSLF		;T1/MY FORK
	MOVX T2,1B0		;CHANNEL 0 (IPCF)
	IIC			;CAUSE INTERRUPT 

	;..
	SUBTTL WAKEUP

;THIS IS THE MAIN NON-INTERRUPT LEVEL ROUTINE.  IT IS STARTED FOR THE
;FIRST TIME AFTER THE FORCED IPCF INTERRUPT.  IT CLEARS INTFLG
;WHEN IT STARTS.  WHEN IT HAS NOTHING TO DO, IT CHECKS INTFLG.
;IF IT IS SET, AN INTERRUPT HAS OCCURRED SINCE WAKEUP BEGAN, SO IT
;STARTS OVER. OTHERWISE, IT SETS WTFLG AND SLEEPS.
;EACH INTERRUPT ROUTINE DECIDES WHERE TO RETURN BASED ON WTFLG.  IF
;IT IS SET, THE ROUTINE RETURNS TO WAKEUP.  OTHERWISE, IT RETURNS TO 
;THE NEXT LOCATION TO BE EXECUTED WHEN THE INTERRUPT
;OCCURRED.

;REACHED VIA DEBRK

	;..
WAKEUP:
	SETZM INTFLG		;CLEAR INTERRUPT FLAG
	SETZM WTFLG		;CLEAR WAIT FLAG

;IF TEXT HAS COME IN FROM OPLEASE, IT IS STORED IN TXTBUF.  PRINT IT.
;THE MESSAGES ARE CONCATENATED.  A NULL FOLLOWS THE LAST MESSAGE.

	MOVEI T1,.FHSLF		;T1/MY FORK
	DIR			;NO INTERRUPTS WHILE READING BUFFER
	SKIPE TXTFLG		;ANY MESSAGES WAITING TO BE TYPED?
	CALL PRNTXT		;YES. PRINT THE TEXT
	MOVEI T1,.FHSLF		;T1/MY FORK
	EIR

;IF THE USER HAS TYPED ON THE TERMINAL, READ IT

	MOVEI T1,.PRIIN		;T1/PRIMARY INPUT
	SIBE			;HAS USER TYPED ANYTHING?
	JRST WAKE1 		;YES.

;USER IS NOT TYPING BUT TEXT MAY BE IN BUFFER TO BE SENT.
;IF TEXT IS THERE AND OK HAS BEEN RECEIVED, SEND IT

	SKIPN ACTFLG		;ARE WE IN TWO-WAY CONVERSATION?
	JRST WAKE3		;NO. DON'T SEND TEXT
	MOVE T1,INIBEG		;POINT TO START OF BUFFER
	CAME T1,RDNXT		;IS NEXT FREE LOCATION AT START OF BUFFER?
	JRST [	CALL SNDTXT	;NO. SEND TEXT IN BUFFER
		 JRST START2	;FAILED
		JRST .+1]	;SUCCEEDED
	JRST WAKE3	 
;USER HAS TYPED, READ IT

WAKE1:	CALL GTXT		;GET TEXT
	 JRST WAKE11
;READ ENDED ON BUFFER FULL.  USER WANTS TO SEND MORE.  IF ACTIVE,
;SEND THIS MUCH AND GO READ THE REST. IF NOT, SEND AS ONEWAY.

	MOVEI T4,.CHCRT		;ADD A CARRIAGE RETURN
	IDPB T4,T1
	MOVEI T4,.CHLFD		;ADD LINE FEED
	IDPB T4,T1	
	SETZ T4,		;ADD NULL
	IDPB T4,T1
	SKIPN ACTFLG		;ARE WE IN TWO-WAY CONVERSATION
	JRST [	TMSG <
%Text exceeds maximum for one message. Message sent as one-way.
>				;NO. OK NOT RECEIVED
		CALL SNDONE	;SEND A ONEWAY
		 JRST START2	;FAILED
		QUIT1]		;GO QUIT
	TMSG <
%Text exceeds maximum for one message. Message being sent.
>				;YES. SEND AS MUCH AS WE READ
	CALL SNDTXT		;SEND TEXT
	 JRST START2		;FAILED
	JRST WAKE1		;SUCCEEDED. GO READ REST

;entire message read. check terminator for goodbye

WAKE11:	MOVE P5,INITER		;P5/ LAST BYTE READ
	CAIE P5,.CHCNZ		;TERMINATED ON CTRL/Z?
	CAIN P5,.CHESC		;no. ESCAPE?
	JRST WAKE2		;CNTL/Z OR ESCAPE

;DIDN'T END WITH CTRL/Z OR ESCAPE.  SEND TEXT IF TWO-WAY, STORE
;OTHERWISE.

	SKIPN ACTFLG		;NO. ARE WE IN TWO-WAY?
	JRST WAKEUP		;NO. GO SEE IF THERE'S MORE TO READ
	CALL SNDTXT		;YES. SEND TEXT
	 JRST START2		;FAILED
	JRST WAKEUP		;GO SEE IF THERE IS MORE TO READ
;ENDED WITH CTRL/Z OR ESCAPE.  SEND ONEWAY IF NOT ACTIVE, TEXT AND
;BYE IF ACTIVE

WAKE2:	SKIPN ACTFLG		;TWOWAY?
	JRST [	CALL SNDONE	;NO. SEND ONE-WAY AND PRINT MESSAGE
		 JRST START2	;FAILED. START OVER
		QUIT1]		;SUCCEEDED. QUIT
	CALL SNDTXT		;YES. SEND TEXT
	 JRST START2		;FAILED
	MOVX T2,1B0		;SET BYEFLG SAYING USER QUIT
	IORM T2,BYEFLG

;SEE IF ANYONE HAS SAID GOODBYE

WAKE3:	SKIPN P6,BYEFLG		;HAS ANYONE SAID GOODBYE? LOAD P6
	JRST WAKE5		;NO.

;SOMEONE HAS SAID GOODBYE. IF TEXT HAS BEEN RECEIVED AND NOT
;PRINTED, DUMP THE BUFFER

	MOVEI T1,.FHSLF		;T1/MY FORK
	DIR			;DISABLE INTERRUPTS
	MOVE P5,RCVCNT		;SAVE NUMBER OF LAST MESSAGE RECEIVED
	SKIPE TXTFLG		;ANY MESSAGES WAITING TO BE TYPED?
	CALL PRNTXT		;YES. PRINT THEM
	MOVEI T1,.FHSLF		;T1/MY FORK
	EIR			;ENABLE INTERRUPTS

;SEE WHO SAID GOODBYE

	TXNE P6,1B1		;WAS IT THE OPR? 
	JRST WAKE10		;YES.
	TXNN P6,1B0		;NO. WAS IT USER? 
	JRST WAKE5		;NO.

;USER HAS SAID GOODBYE AND OPERATOR HAS NOT. SEND 'GOODBYE'.

	MOVEI P2,OPDB		;P2/ADDRESS OF SEND PDB
	MOVE T1,OPRPID		;SEND TO OPLEASE'S PID
	MOVEM T1,.IPCFR(P2)
	MOVEI T1,PLBYE		;CODE IS GOODBYE
	MOVEM T1,OMSG		;SAVE IN FIRST WORD OF MESSAGE
	HRLM P5,OMSG		;SEND NUMBER OF LAST MESSAGE RECEIVED
	MOVEI P4,OPDBSZ		;P4/LENGTH OF PDB
	CALL SNDMSG		;SEND GOODBYE TO OPLEASE
	 JRST [	CAIE T1,IPCFX7	;RECEIVER OVER QUOTA?
		JRST .+1	;NO. IGNORE
		MOVEI T1,^D1000	;TIME TO WAIT
		DISMS		;WAIT A WHILE
		CALL SNDMSG	;RESEND
		 JFCL		;FAILED AGAIN. GIVE UP
		JRST .+1]	;SUCCEEDED SECOND TIME
	JRST WAKE4		;GO PRINT MESSAGE
;OPERATOR SAID GOODBYE.  SEE IF ALL THE MESSAGES WE SENT GOT THERE

WAKE10:	MOVE T1,TXTCNT		;T1/NUMBER OF LAST MESSAGE RECEIVED BY OPLEAS
	CAMN T1,SNDCNT		;SAME AS NUMBER SENT?
	JRST WAKE4		;YES. GOOD
	TMSG <
%Part of your message was not transmitted.
>				;NO. PRINT MESSAGE
	SKIPN DEBUG		;DEBUGGING?
	JRST WAKE4		;NO. DON'T PRINT NUMBERS
	TMSG <
D:Number of messages sent: >	;YES. PRINT NUMBERS COMPARED
	MOVEI T1,.PRIOU		;T1/PRIMARY OUTPUT
	MOVE T2,SNDCNT		;T2/NUMBER SENT
	MOVX T3,12B35		;T3/DECIMAL RADIX
	NOUT			;PRINT THE NUMBER SENT
	 JSERR
	TMSG <
D:Number of messages received: >
	MOVEI T1,.PRIOU		;T1/PRIMARY OUTPUT
	MOVE T2,TXTCNT		;T2/NUMBER OF MESSAGES RECEIVED BY UPLEASE
	MOVX T3,12B35		;T3/DECIMAL RADIX
	NOUT			;PRINT THE NUMBER RECEIVED
	 JSERR

;PRINT MESSAGE INDICATING CONVERSATION IS FINISHED

WAKE4:	TMSG <
[Finished at >
	MOVX T1,.PRIOU		;T1/PRIMARY OUTPUT
	SETOM T2		;T2/PRINT CURRENT TIME
	MOVX T3,1B0+1B17	;T3/TIME ONLY, NO COLUMNATION
	ODTIM			;PRINT THE TIME
	TMSG < ]
>
	QUIT1
;IF INTERRUPTS HAVE COME IN, REPEAT WAKEUP CODE. IF NOT, WAIT FOR
;ANOTHER INTERRUPT

WAKE5:	SETOM WTFLG		;SET FLAG INDICATING WAITING
	SKIPE INTFLG		;HAS AN INTERRUPT BEEN PROCESSED?
	JRST WAKEUP		;YES. SEE WHAT NEEDS TO BE DONE
	WAIT			;NO. WAIT FOR SOMETHING TO HAPPEN

;SHOULDN'T BE HERE. PRINT MESSAGE IF DEBUGGING. IGNORE OTHERWISE.

	SKIPN DEBUG		;DEBUGGING?
	JRST WAKEUP		;NO. IGNORE THE PROBLEM
	TMSG <
D:At HALT after WAIT.
>
	JRST WAKEUP
	SUBTTL SNDONE - SEND ONEWAY MESSAGE

;USER HAS TYPED CTRL/Z OR ESCAPE.  SEND TEXT STORED IN INITXT AREA
;AS A ONEWAY MESSAGE.  SINCE PID WILL GO AWAY, OPLEASE WON'T BE
;ABLE TO IDENTIFY JOB, SO SEND IDENTIFYING INFORMATION

;REACHED VIA CALL SNDONE FROM NON-INTERRUPT LEVEL ROUTINE

;RETURNS +1:SEND SUCCEEDED
;        +2:SEND FAILED

SNDONE:
	MOVEI T1,PLONE		;CODE IS ONEWAY
	MOVEM T1,OMSG		;TO FIRST WORD OF MESSAGE
	GTAD			;GET CURRENT TIME
	MOVEM T1,OMSG+1		;TO SECOND WORD OF MESSAGE
	MOVEM T1,NOW		;ALSO SAVE IT HERE
	GJINF			;GET JOB INFORMATION
	MOVEM T1,OMSG+2		;LOGGED IN DIRECTORY TO 3RD WORD
	MOVEM T4,OMSG+3		;LINE NUMBER TO 4TH WORD
	HRROI T1,OMSG+4		;DESTINATION:5TH WORD AND FOLLOWING
	MOVE T2,INIBEG		;SOURCE:TEXT BUFFER AREA
	MOVEI T3,<OMSGSZ-4>*5	;NUMBER OF BYTES AVAILABLE
	SETZ T4,		;STOP ON NULL
	SOUT			;TRANSFER MESSAGE TO MESSAGE AREA
	MOVEI P2,OPDB		;P2/ADDRESS OF PDB
	MOVE T1,OPRPID		;OPERATOR'S PID
	MOVEM T1,.IPCFR(P2)	;TO RECEIVER FIELD
	MOVEI P4,OPDBSZ		;P4/PDB SIZE
	CALL SNDMSG		;SEND ONEWAY
	 JRST [	CALL ERR1	;SEND FAILED. RETRY IF POSSIBLE
		 RET		;RETRY FAILED OR COULDN'T RETRY
		JRST .+1]	;RETRY SUCCEEDED
	MOVEI T1,.FHSLF		;DISABLE INTERRUPTS TO PREVENT [NOTIFIED]
	DIR			; FROM COMING OUT IN MIDDLE OF THIS MESSAGE
	TMSG <
[One-way sent at >
	MOVEI T1,.PRIOU		;T1/PRIMARY OUTPUT
	MOVE T2,NOW		;TIME SENT WITH MESSAGE
	MOVX T3,1B0!1B17	;T3/TIME ONLY, NO COLUMNATION
	ODTIM			;PRINT THE TIME SENT WITH MESSAGE
	TMSG <]
>
	MOVEI T1,.FHSLF		;RESTORE INTERRUPTS
	EIR
	RETSKP			;SUCCESSFUL RETURN
	SUBTTL SNDTXT - SEND TEXT MESSAGE

;USER IS IN TWO-WAY CONVERSATION WITH THE OPERATOR AND HAS TYPED
;TEXT.  SEND TEXT, STORED IN INITXT AREA, AS A TEXT MESSAGE.

;REACHED VIA CALL SNDTXT FROM NON-INTERRUPT LEVEL ROUTINE

;RETURNS: +1 SEND SUCCEEDED
;         +2 SEND FAILED

SNDTXT:	MOVEI P2,OPDB		;P2/LOCATION OF SEND PDB
	MOVE T1,OPRPID		;OPLEASE'S PID
	MOVEM T1,.IPCFR(P2)	;SEND TO OPERATOR'S PID
	MOVEI T1,PLTXT		;MESSAGE IS 'TEXT'
	MOVEM T1,OMSG		;TO FIRST WORD OF MESSAGE
	AOS T1,SNDCNT		;INCREMENT COUNT OF TEXT MESSAGES SENT
	HRLM T1,OMSG		;SEND WITH MESSAGE
	HRROI T1,OMSG+1		;DESTINATION:2ND WORD OF MESSAGE
	MOVE T2,INIBEG		;SOURCE:TEXT BUFFER AREA
	MOVEI T3,<OMSGSZ-1>*5	;T3/NUMBER BYTES AVAILABLE
	SETZ T4,		;T4/STOP ON NULL
	SOUT			;COPY TEXT TO MESSAGE AREA
	MOVEI P4,OPDBSZ		;P4/LENGTH OF SEND PDB
	CALL SNDMSG		;SEND THE TEXT
	 JRST [	CALL ERR1	;SEND FAILED. RETRY IF POSSIBLE
		 RET		;RETRY FAILED OR COULDN'T RETRY
		JRST .+1]	;RETRY SUCCEEDED
	MOVE T1,INIBEG		;RESTORE POINTER TO BEGINNING OF BUFFER
	MOVEM T1,RDNXT		; FOR NEXT READ
	MOVE T1,TXTSIZ		;RESET BYTE LIMIT FOR NEXT READ
	MOVEM T1,RDLIM
	RETSKP			;SUCCESSFUL RETURN
	SUBTTL SNDMSG

;SEND A MESSAGE WHOSE PDB AND MESSAGE AREA HAVE BEEN SET UP.

;ACCEPTS
;P2/ ADDRESS OF SEND PDB
;P4/ SIZE OF SEND PDB

;REACHED VIA CALL SNDMSG FROM ROUTINE AT EITHER INTERRUPT OR NON-
;NON-INTERRUPT LEVEL

;RETURNS: +1 SEND FAILED
;         +2 SEND SUCCEEDED

SNDMSG:	MOVE T1,P4		;T1/ SIZE OF SEND PDB
	MOVE T2,P2		;T2/ LOCATION OF SEND PDB
	MSEND
	 JRST SNDMS1		;FAILED
	RETSKP			;SUCCEEDED

;FAILED. PRINT INFO IF DEBUGGING.

SNDMS1:	SKIPN DEBUG		;DEBUGGING?
	RET			;NO. NO MESSAGES.
TMSG <
D:Failed on send to PID >
	MOVX T1,.PRIOU		;T1/PRIMARY OUTPUT
	MOVE T2,.IPCFR(P2)	;T2/RECEIVER
	MOVE T3,[1B0+10B35]	;T3/MAGNITUDE,OCTAL
	NOUT			;PRINT PID SENT TO
	 JSERR
	TMSG <
D:First word of message: >
	MOVX T1,.PRIOU
	MOVE T2,SMSG		;T2/FIRST WORD OF MESSAGE
	NOUT			;PRINT IT
	 JSERR			; FAILED
	TMSG <
>
	RET
	SUBTTL PRNTXT

;PRINT TEXT THAT HAS COME IN AND IS WAITING IN THE BUFFER
;INTERRUPTS ARE DISABLED BY CALLING ROUTINE

;REACHED VIA CALL PRNTXT BY NON-INTERRUPT LEVEL ROUTINE

;RETURNS +1 ALWAYS

PRNTXT:	SETZM TXTFLG		;CLEAR TEXT FLAG
	HRROI T1,TXTBUF		;POINT TO BEGINNING OF BUFFER
	PSOUT			;PRINT TEXT
	call clrtxt		;clear text area and reset bufnxt
	RET










	subttl clrtxt

;clears txtbuf area - contains text that has been received but not
;typed out.  called at initialization and after all characters have
;been typed.  clears the area and resets bufnxt to point to start
;INTERRUPTS HAVE BEEN DISABLED BY CALLING ROUTINE

;REACHED VIA CALL PRNTXT BY NON-INTERRUPT LEVEL ROUTINE

;RETURNS +1 ALWAYS

clrtxt:	setzm txtbuf
	move t1,[txtbuf,,txtbuf+1]
	blt t1,bufend-1
	hrroi t1,txtbuf
	movem t1,bufnxt
	RET
	SUBTTL IPCF INTERRUPT PROCESSING

;THIS IS THE MAIN ROUTINE FOR PROCESSING IPCF INTERRUPTS.  IT IS INVOKED
;WHENEVER THE NUMBER OF MESSAGES WAITING TO BE RECEIVED GOES FROM 
;ZERO TO NON-ZERO.
;IT RECEIVES A MESSAGE AND JUMPS TO THE CODE TO PROCESS THE MESSAGE.
;WHEN THERE ARE NO MORE MESSAGES WAITING, IT RETURNS.

;REACHED VIA INTERRUPT ON CHANNEL 0.

IPCINT:	SETOM INTFLG		;SET INTERRUPT FLAG
	MOVEM 17,REGSAV+17	;SAVE REGISTER 17
	MOVEI 17,REGSAV		;SET UP FOR BLT OF 0 TO REGSAV
	BLT 17,REGSAV+16	;MOVE 0-16 TO REGSAV
	MOVE 17,REGSAV+17

;SET UP FOR RECEIVE

IPCIN1:	MOVEI T4,RPDB		;T4/ADDRESS OF RECEIVE PDB
	MOVX T1,IP%CFB!IP%TTL!IP%CFV ;DON'T BLOCK,TRUNCATE,PAGE MODE
	MOVEM T1,.IPCFL(T4)	;FLAG WORD
	MOVE T1,[RMSGSZ,,RPAGE]	;PAGE SIZE, PAGE NUMBER
	MOVEM T1,.IPCFP(T4)	;STORE IN PDB 
	MOVEI T1,RPDBSZ		;T1/LENGTH OF PDB
	MOVEI T2,RPDB		;T2/LOCATION OF PDB
	MRECV			;RECEIVE NEXT MESSAGE
	 JRST IPCIN2		;FAILED
	JRST IPCIN5		;SUCCEEDED

;RECEIVE FAILED. IF PROBLEM IS THAT MESSAGE IS NOT IN PAGE MODE
;TRY RECEIVING WITHOUT PAGE MODE BIT SET.  RECEIVE INTO THE SAME PAGE
;AS IN PAGE MODE.


IPCIN2:	CAIE T1,IPCF16		;DATA MODE PROBLEM?
	JRST IPCIN3		;NO.
	MOVX T2,IP%CFB!IP%TTL	;NO PAGE MODE
	MOVEM T2,.IPCFL(T4)	;TO PDB
	MOVE T1,[MAXMSG,,RMSG]	;MESSAGE SIZE,LOCATION
	MOVEM T1,.IPCFP(T4)	;TO PDB (size already set)
	MOVEI T1,RPDBSZ		;T1/SIZE OF PDB
	MOVEI T2,RPDB		;T2/LOCATION OF PDB
	MRECV			;READ MESSAGE AND DISCARD
	 JRST IPCIN3		;STILL FAILS
	JRST IPCIN5		;SUCCEEDS. GO PROCESS IT

;NOT A PAGE PROBLEM.  IF THERE WAS NO MESSAGE, IGNORE THE INTERRUPT.
;OTHERWISE, PRINT THE ERROR AND RETRY.

IPCIN3:	CAIE T1,IPCFX2		;NO MESSAGE?
	JRST IPCIN4		;NO.
	SETZM NXTMSG		;YES. CLEAR ASSOCIATED VARIABLE
	JRST ENDINT		;IGNORE THE INTERRUPT
IPCIN4:	JSERR			;UNKNOWN ERROR
	JRST IPCIN1		;SEE IF THERE ARE ANY MORE
;RECEIVE SUCCEEDED.  CHECK FOR UNDELIVERED MAIL AND ERRORS.
;IGNORE ALL OTHER MESSAGES EXCEPT THOSE FROM OPLEASE

IPCIN5:	MOVEM T1,NXTMSG
	MOVEI P1,RPDB		;P1/LOCATION OF RECEIVE PDB
	MOVE Q2,.IPCFS(P1)	;Q2/SENDER'S PID
	MOVE Q1,.IPCFL(P1)	;Q1/FLAG WORD RECEIVED
	JXN Q1,IP%CFM,UNDEL	;UNDELIVERED MAIL?
	JXN Q1,IP%CFE,RCVERR	;NO. ERROR?
	JXN Q1,IP%CFC,ENDINT	;FROM SYSTEM?  IGNORE
	CAME Q2,OPRPID		;FROM OPERATOR?
	JRST ENDINT		;NO. IGNORE
	
;FROM OPLEASE. TRANSFER ACCORDING TO CODE SENT

	HRRZ P6,RMSG		;P6/CODE SENT IN MESSAGE
	MOVEI P2,SPDB		;P2/LOCATION OF SEND PDB
	CAIGE P6,TABSIZ		;LEGAL CODE?
	JRST @GOTAB(P6)		;YES. GO PROCESS

; RECEIVED BAD CODE FROM OPLEASE

	SKIPN DEBUG		;DEBUGGING?
	JRST ENDINT		;NO. IGNORE.
	TMSG <
D:Received code >
	MOVEI T1,.PRIOU		;T1/PRIMARY OUTPUT
	MOVE T2,P6		;T2/FIRST WORD OF MESSAGE
	MOVX T3,1B0+10B35	;T3/MAGNITUDE,,OCTAL
	NOUT			;PRINT THE CODE
	 JSERR
	TMSG < from PID >
	MOVEI T1,.PRIOU		;T1/PRIMARY OUTPUT
	MOVE T2,Q2		;T2/SENDING PID
	NOUT			;PRINT THE PID
	 JSERR
	TMSG <
>

	;..
;MESSAGE HAS BEEN PROCESSED.  IF THERE WAS ANOTHER MESSAGE WAITING
;WHEN THIS ONE WAS RECEIVED, NXTMSG IS NON-ZERO.  GO RECEIVE THE NEXT
;ONE.  IF NXTMSG IS ZERO, ANY MESSAGE THAT HAS COME IN SINCE THE
;LAST RECEIVE WILL CAUSE A NEW INTERRUPT.

	;..
ENDINT:	SKIPE NXTMSG		;ANY MORE MESSAGES IN QUEUE?
	JRST IPCIN1		;GO RECEIVE THE NEXT MESSAGE

;NO MORE TO RECEIVE.  IF CAME FROM WAIT, WAKE UP.  IF NOT,
;RETURN TO WHERE WE WERE BEFORE THE INTERRUPT.

	HRLZI 17,REGSAV		;RESTORE REGISTERS
	BLT 17,17
	SKIPN WTFLG		;CAME FROM A WAIT?
	 DEBRK			;NO. RETURN TO WHERE WE WERE
	MOVEI T1,WAKEUP		;YES. START WAKE-UP PROCEDURE
	MOVEM T1,PCSAV1
	MOVE T1,REGSAV+1	;RESTORE T1
	DEBRK

;SOMETHING FAILED. START OVER.

RESTRT:	MOVEI T1,START2		;DEBRK TO RESTART LOCATION
	MOVEM T1,PCSAV1
	DEBRK
	SUBTTL OK

;'OK' RECEIVED. OPLEASE IS READY TO TALK. SEND THE PREVIOUSLY TYPED TEXT

;ACCEPTS:
;P2/ ADDRESS OF SEND PDB
;Q2/ PID OF SENDER

;REACHED VIA JRST FROM IPCINT

;JRSTS TO ENDINT ON SUCCESSFUL SEND OF TEXT
;         RESTRT ON FAILURE OF SEND

OK:	SETOM ACTFLG		;SET INDICATOR THAT OK WAS RECEIVED.
	TMSG <
[Operator has been notified]
>				;TELL THE USER

;send text as read from tty.

	MOVEI P4,SPDBSZ		;P4/SIZE OF SEND PDB
	MOVE T1,OPRPID		;RECEIVER IS OPLEASE
	MOVEM T1,.IPCFR(P2)
	MOVEI T1,PLTXT		;CODE IS 'TEXT'
	MOVEM T1,SMSG	
	hrroi t1,smsg+1		;destination: send message area
	move t2,inibeg		;source: first line typed
	movei t3,<smsgsz-1>*5	;maximum bytes available
	SETZ T4,		;STOP ON NULL
	sout			;transfer text to smsg area
	CALL SNDMSG		;SEND THE TEXT
	 JRST [	CALL ERR1	;FAILED. RETRY IF POSSIBLE
		 JRST RESTRT	;RETRY FAILED OR COULDN'T RETRY
		JRST .+1]
	MOVE T1,INIBEG		;RESTORE POINTER TO BEGINNING OF BUFFER
	MOVEM T1,RDNXT		; FOR NEXT READ
	MOVE T1,TXTSIZ		;RESET BYTE LIMIT FOR NEXT READ
	MOVEM T1,RDLIM

;if first line ended with ^z or escape, set up for goodbye

	move t4,initer		;terminating character
	caIE t4,.chcnz		;ctrl/Z?
	CAIN T4,.CHESC		;NO. ESCAPE?
	JRST SETBYE		;CNTL/Z OR ESCAPE. SET FLAG
	JRST ENDINT		;NO.

setbye:	movx t3,1b0		;^z or esc. set flag indicating
	IOrm t3,byeflg		; user said goodbye
	JRST ENDINT
	SUBTTL TEXT

;'TEXT' RECIEVED.  STORE TEXT IN TXTBUF AREA.  APPEND TO PREVIOUS
;TEXT IF THERE IS ANY.  SET FLAG TO INDICATE TEXT IS WAITING TO BE PRINTED.

;ACCEPTS:
;Q2/ PID OF SENDER
;P1/ ADDRESS OF RECEIVE PDB
;P2/ ADDRESS OF SEND PDB

;REACHED VIA JRST FROM IPCINT

;JRSTS TO ENDINT ALWAYS 

TEXT:
	HLRZ T1,RMSG		;SAVE NUMBER OF THIS MESSAGE
	MOVEM T1,RCVCNT		; TO SEND BACK WITH 'BYE'
	HRROI T2,RMSG+1		;POINT TO FIRST WORD OF TEXT
	MOVE T1,BUFNXT		;POINT TO NEXT AVAILABLE LOCATION
				; IN BUFFER
	MOVEI T3,BUFEND		;END OF BUFFER
	HRRZ T4,BUFNXT		;NEXT AVAILABLE LOCATION
	SUB T3,T4		;MAX WORDS REMAINING
	JUMPLE T3,TEXT1		;ERROR IF NO ROOM
	SOS T3			;ROUND DOWN 
	IMULI T3,5		;MAXIMUM BYTES
	SETZ T4,		;STOP ON NULL BYTE
	SOUT			;TRANSFER TEXT TO OUTPUT AREA
	BKJFN			;BACKUP THE POINTER TO OVERWRITE THE
	 JFCL			; NULL NEXT TIME (T1 CONTAINS POINTER)
	MOVEM T1,BUFNXT		;SAVE UPDATED POINTER
	SETOM TXTFLG		;SET FLAG TO INDICATE BUFFER NON-EMPTY
	JUMPE T3,TEXT1		;END OF BUFFER?
	JRST ENDINT		;NO.

TEXT1:	TMSG<
%Text deleted from incoming message.
>				;YES. TELL USER
	JRST ENDINT
	SUBTTL BYE

;'BYE' RECEIVED. SET BYEFLG TO INDICATE OPERATOR QUIT.
;SAVE NUMBER OF LAST TEXT MESSAGE RECEIVED BY OPLEASE.

;REACHED VIA JRST FROM IPCINT

;JRSTS TO ENDINT ALWAYS

BYE:	MOVX T1,1B1		;BIT 1 FOR OPERATOR QUIT
	IORM T1,BYEFLG
	HLRZ T1,RMSG		;LAST MESSAGE RECEIVED BY OPLEASE
	MOVEM T1,TXTCNT		;SAVE TO CHECK AGAINST OUR COUNT
	JRST ENDINT

;HERE TO READ FROM TERMINAL

GTXT:	HRROI T1,TBUF		;POINT TO BUFFER
	MOVEI T2,TBUFSZ*5
	CAMLE T2,RDLIM		;SKIP IF LOTS OF SPACE LEFT
	HRRZ T2,RDLIM		;GET LESSER OF TWO
	HRLI T2,(RD%BRK!RD%BEL)
	SETZ T3,
	RDTTY
	 JSERR
	LDB T2,T1		;GET TERMINATING CHARACTER
	MOVEM T2,INITER		;SAVE FOR PROCESSING BY WAKEUP
	MOVEI T1,.FHSLF
	DIR			;DISABLE INTERRUPTS
	MOVE T1,RDNXT		;CURRENT POINTER
	HRROI T2,TBUF		;START OF TEMP BUFFER
	HRRZ T3,RDLIM
	MOVEI T4,0
	SOUT
	MOVEM T1,RDNXT		;SET POINTER
	MOVEI T1,.FHSLF		;OWN FORK
	EIR
	MOVEM T3,RDLIM		;LIMIT OF BYTES LEFT
	JUMPE T3,RSKP
	RET
	SUBTTL WAIT

;'WAIT' RECEIVED. TELL THE USER TO WAIT

;REACHED VIA JRST FROM IPCINT

;JRSTS TO ENDINT ALWAYS

PWAIT:	TMSG<
[Operator is busy. Please wait.]
>

	JRST ENDINT
	SUBTTL ANSWER

;RECEIVED 'AMSWER' IN RESPONSE TO OUR 'QUESTION' MESSAGE.
;(USER TYPED CTRL/T).  CONTAINS 0 IF USER NOT IN QUEUE, -1 IF CURRENT USER.
;OTHERWISE, CONTAINS
; (NUMBER ENTRIES IN QUEUE,,THIS USER'S POSITION)
;PRINT THE ANSWER

;REACHED VIA JRST FROM IPCINT

;JRSTS TO ENDINT ALWAYS

ANSWER:	TMSG<
[>
	MOVEI T1,.PRIOU		;T1/PRIMARY OUTPUT
	SETOM T2		;T2/CURRENT TIME
	MOVX T3,1B0!1B17	;T3/TIME ONLY, NO COLUMNATION
	ODTIM			;PRINT CURRENT TIME
	TMSG <   >
	MOVE T4,RMSG+1		;T4/RANK IN QUEUE
	jumpe T4,answr1		;IF ZERO, NOT IN QUEUE
	JUMPL T4,ANSWR2		;NEGATIVE IF CURRENT PID
	HLRZ T2,RMSG+1		;T2/NUMBER IN QUEUE
	MOVEI T1,.PRIOU		;T1/PRIMARY OUTPUT
	MOVX T3,12B35		;T3/DECIMAL RADIX
	NOUT			;PRINT NUMBER IN QUEUE
	 JSERR
	CAIN T2,1		;IS THERE JUST ONE?
	JRST [	TMSG < user waiting. You are number >
		JRST ANSWR3]	;YES. PRINT SINGULAR
	TMSG < users waiting. You are number > ;NO. PRINT USUAL MESSAGE
ANSWR3:	MOVEI T1,.PRIOU		;T1/PRIMARY OUTPUT
	HRRZ T2,T4		;T2/ USER'S RANK IN QUEUE
	MOVX T3,12B35		;T3/DECIMAL RADIX
	NOUT
	 JSERR
	TMSG < ]
>
	JRST ENDINT

ANSWR1:	TMSG <You are not in the queue.]
>
	jrst endint

ANSWR2:	TMSG<You are the current user.]
>
	JRST ENDINT
	SUBTTL CONFUS

;'CONFUSED' RECEIVED FROM OPLEASE.  WE HAVE SENT IT A BAD MESSAGE

;REACHED VIA FJRST FROM IPCINT

;JRSTS TO ENDINT ALWAYS


CONFUS:	SKIPN DEBUG		;DEBUGGING?
	JRST ENDINT		;NO. IGNORE IT
	TMSG<
D:Received 'Confused' from OPLEASE.>
	TMSG<
D:Last message sent (not necessarily the bad one):>
	MOVEI T1,.PRIOU		;T1/PRIMARY OUTPUT
	MOVE T2,SMSG		;T2/CODE
	MOVE T3,[1B0+10B35]	;MAGNITUDE,OCTAL
	NOUT			;PRINT THE CODE SNT
	 JSERR
	TMSG <
>
	JRST ENDINT
	SUBTTL INTERRUPT ON TELETYPE INPUT 

;INPUT BUFFER WENT FROM EMPTY TO NON-EMPTY.  SET INTERRUPT FLAG.
;IF CAME FROM WAIT, WAKE UP.  IF NOT, RETURN TO WHERE WE WERE BEFORE
;THE INTERRUPT.  
;NOTE: IF USING DDT, TYPING TO IT WILL CAUSE INTERRUPT.  SINCE DDT
;WILL HAVE READ THE CHARACTERS, INPUT BUFFER WILL BE EMPTY.  IN
;THAT CASE, IGNORE THE INTERRUPT.

;REACHED VIA INTERRUPT ON CHANNEL 3

;DEBRKS TO WAKEUP IF CAME FROM WAIT
;          CURRENT LOCATION OTHERWISE

TYPINT:	MOVEM T1,REGSAV+1	;SAVE T1
	MOVEI T1,.PRIIN		;T1/PRIMARY INPUT DEVICE
	SIBE			;IGNORE INTERRUPT IF DDT READ IT
	SKIPA 			;INPUT BUFFER NOT EMPTY
	JRST TYPIN2		;INPUT BUFFER IS EMPTY

;THERE ARE CHARACTERS TO BE READ.  SET FLAG

TYPIN1:	SETOM INTFLG		;INDICATE INTERRUPT OCCURRED
	SKIPN WTFLG		;CAME FROM WAITING?
	JRST TYPIN2		;NO. GO BACK TO WHERE WE WERE
	MOVEI T1,WAKEUP		;YES. START THE WAKEUP ROUTINE 
	MOVEM T1,PCSAV1		;CHANGE THE PC

TYPIN2:	MOVE T1,REGSAV+1	;RESTORE T1
	DEBRK
	SUBTTL CTRL/T INTERRUPT

;USER TYPED CTRL/T - WANTS TO KNOW RANK IN QUEUE
;SEND A MESSAGE TO OPLEASE ASKING FOR IT

;REACHED VIA INTERRUPT ON CHANNEL 1

;DEBRKS TO START2 IF SEND FAILED
;          CURRENT LOCATION OTHERWISE

TINT:	MOVEM 17,REGSAV+17	;SAVE ALL REGISTERS
	MOVEI 17,REGSAV
	BLT 17,REGSAV+16
	MOVE 17,REGSAV+17
	MOVEI P2,SPDB		;P2/LOCATION OF SEND PDB
	MOVEI P4,SPDBSZ		;P4/SIZE OF SEND PDB
	MOVE T1,OPRPID		;RECEIVER: OPLEASE
	MOVEM T1,.IPCFR(P2)	;STORE IN PDB
	MOVEI T1,PLQUES		;MESSAGE IS 'QUESTION'
	MOVEM T1,SMSG		;STORE IN FIRST WORD OF MESSAGE
	CALL SNDMSG		;SEND THE MESSAGE
	 JRST [	CALL ERR1	;FAILED.RETRY IF POSSIBLE
		 JRST TINT1	;RETRY FAILED OR COULDN'T RETRY
		JRST .+1]	;RETRY SUCCEEDED
	HRLZI 17,REGSAV		;RESTORE REGISTERS
	BLT 17,17
	DEBRK			;RETURN TO WHERE WE WERE

;SEND FAILED.  START OVER

TINT1:	TMSG<
?Operator contact lost.
>				;TELL THE USER
	MOVEI T1,START2		;FIX THE DEBRK LOCATION
	MOVEM T1,PCSAV1
	DEBRK
	SUBTTL CTRL/C INTERRUPT

;USER WANTS TO QUIT.SEND A GOODBYE BUT DON'T RETRY IF FAILED.

;REACHED VIA INTERRUPT ON CHANNEL 2

;DEBRKS TO WAKE4 FOR [FINISHED] MESSAGE AND EXIT

CINT:	MOVEM 17,REGSAV+17	;SAVE THE REGISTERS
	MOVEI 17,REGSAV		
	BLT 17,REGSAV+16
	MOVE 17,REGSAV+17
	MOVEI P2,OPDB		;P2/LOCATION OF SEND PDB
	MOVE T1,OPRPID		;SEND TO OPERATOR
	MOVEM T1,.IPCFR(P2)	;OPERATOR'S PID TO RECEIVER'S FIELD
	MOVEI T1,PLBYE		;MESSAGE IS 'BYE'
	HRL T1,RCVCNT		;NUMBER OF LAST MESSAGE RECEIVED.
	MOVEM T1,OMSG		;SAVE IN FIRST WORD OF MESSAGE
	MOVEI P4,OPDBSZ		;P4/SIZE OF SEND PDB
	CALL SNDMSG		;SEND THE GOODBYE MESSAGE
	 JFCL			;IGNORE FAILURE
	MOVEI T1,WAKE4		;GO TO REGULAR QUIT CODE
	MOVEM T1,PCSAV1		;SAVE RETURN LOCATION FOR INTERRUPT
	HRLZI 17,REGSAV		;RESTORE REGISTERS
	BLT 17,17
	DEBRK			;RETURN TO QUIT CODE
	SUBTTL UNDEL

;UNDELIVERED MAIL RECEIVED.  MESSAGE THAT WE SENT WAS SENT BACK
;BECAUSE PID WASN'T THERE TO RECEIVE IT.  IF MESSAGE WAS SENT TO
;OPERATOR, QUIT.  OTHERWISE, IGNORE IT.

;REACHED VIA JRST FROM IPCINT

;ACCEPTS:
;Q2/ SENDER'S PID

;JRSTS TO ENDINT IF MESSAGE NOT FROM OPERATOR
;         RESTRT IF MESSAGE FROM OPERATOR

UNDEL:	CAME Q2,OPRPID		;FROM OPERATOR?
	JRST ENDINT		;NO. IGNORE
	TMSG <
?Operator contact lost.
>				;TELL THE USER
	JRST RESTRT		;START OVER
	SUBTTL ERROR RECEIVED

;MESSAGE HAS BEEN RECEIVED WITH ERROR FIELD SET IN FLAG WORD.  PRINT 
;MESSAGE ONLY IF DEBUGGING.

;Q1/ FLAG WORD RECEIVED

;REACHED VIA JRST FROM IPCINT

;JRSTS TO ENDINT ALWAYS

RCVERR:	LOAD P5,ERROR,Q1	;LOAD ERROR FIELD
	CAIN P5,.IPCSN		;IS THIS 'SEND INFO YOUR NAME'?
	JRST ENDINT		;YES. IGNORE IT
	SKIPN DEBUG		;UNKNOWN ERROR. DEBUGGING?
	JRST ENDINT		;NO. IGNORE IT
	TMSG<
D:Error received: >
	MOVX T1,.PRIOU		;T1/PRIMARY OUTPUT
	MOVE T3,[1B0+10B35]	;T3/MAGNITUDE,OCTAL
	MOVE T2,P5		;T2/ERROR CODE
	NOUT			;PRINT THE ERROR RECEIVED
	 JSERR			;NOUT FAILED
TMSG <
>
	JRST ENDINT
	SUBTTL NO <SYSTEM>INFO

;SEND TO <SYSTEM>INFO FAILED.  PRINT MESSAGE

;ACCEPTS:
;T1/ERROR CODE FROM MSEND

;REACHED VIA CALL NOINFO

;RETURNS +1 ALWAYS

NOINFO:	CAIE T1,IPCF19		;NO PID FOR INFO?
	JRST [	JSERR		;NO. SOME OTHER ERROR
		RET ]
	TMSG <
?System jobs not running.
>				;YES. PRINT MESSAGE
	RET
	SUBTTL MSEND ERROR

;AN ERROR OCCURRED IN SENDING A MESSAGE
;IF RECEIVER HAS EXCEEDED RECEIVE QUOTA, WAIT AND RETRY. 
;OTHERWISE, ASSUME OPERATOR QUIT.

;ACCEPTS:
;T1/ERROR CODE AS RETURNED FROM MSEND
;P2/ADDRESS OF PDB (SENT TO SNDMSG)
;P4/SIZE OF PDB (SENT TO SNDMSG)

;REACHED VIA CALL ERR1 FROM INTERRUPT OR NON-INTERRUPT LEVEL ROUTINE

;RETURNS: +1 NOT A QUOTA PROBLEM OR RETRY FAILED
;         +2 SEND SUCCEEDED ON FIRST OR SECOND TRY

ERR1:	CAIE T1,IPCFX7		;RECEIVER OVER QUOTA?
	JRST ERR1A		;NO. SOME OTHER ERROR
	MOVEI T1,^D1000		;YES. SET TIME TO WAIT
	DISMS			;WAIT A WHILE
	CALL SNDMSG		;TRY AGAIN
	 JRST ERR1A		;RETRY FAILED
	RETSKP			;RETRY SUCCEEDED
ERR1A:	CAIE T1,IPCFX4		;PID NOT THERE?
	JRST ERR1B		;NO. SOME OTHER ERROR.
	TMSG <
?Operator contact lost.
>				;YES.
	RET

;UNKNOWN ERROR

ERR1B:	JSERR			;PRINT THE ERROR
	RET
	SUBTTL LITERALS
	LIT
	END <3,,ENTVEC>