Google
 

Trailing-Edge - PDP-10 Archives - TOPS-20_V6.1_DECnetDistr_7-23-85 - decnet-sources/server.mac
There are 11 other files named server.mac in the archive. Click here to see a list.
; UPD ID= 146, SNARK:<6.1.UTILITIES>SERVER.MAC.23,  19-Jun-85 22:31:00 by MELOHN
; UPD ID= 129, SNARK:<6.1.UTILITIES>SERVER.MAC.22,  23-May-85 16:53:19 by MELOHN
;Change message supported fields to not support 0,
;Set speed on indeterminate lines to 9600 for VMS,
;correctly initialize terminal width, wrap, length, and page mode.
; UPD ID= 123, SNARK:<6.1.UTILITIES>SERVER.MAC.21,   3-May-85 22:20:53 by GLINDELL
;  More work on PMR
; UPD ID= 122, SNARK:<6.1.UTILITIES>SERVER.MAC.20,   3-May-85 20:22:34 by GLINDELL
;  Change FTPMR default to be OFF
; UPD ID= 121, SNARK:<6.1.UTILITIES>SERVER.MAC.19,   3-May-85 20:15:47 by GLINDELL
;  Support poor mans routing - use CTDNCN (DNCONN for CTERM-SERVER)
; UPD ID= 112, SNARK:<6.1.UTILITIES>SERVER.MAC.18,   9-Apr-85 19:45:57 by MELOHN
; Fix from last edit - make normal echo BIN% terminator work properly.
; UPD ID= 110, SNARK:<6.1.UTILITIES>SERVER.MAC.17,   4-Apr-85 14:36:45 by MELOHN
; Fix input count routine to not echo the BIN% to get the first waiting char.
; Add cell TRMFLG, set when TEXTI% has echoed a terminator when echo terminator
; was disabled. In this case, we attempt to throw away the next write message
; in the hope that it was echoing the terminator that we have already echoed.
; UPD ID= 109, SNARK:<6.1.UTILITIES>SERVER.MAC.16,  29-Mar-85 15:45:01 by MELOHN
; Clean up stuff from the last edit. If QUIET, try NRT on illegal nodenames.
; UPD ID= 107, SNARK:<6.1.UTILITIES>SERVER.MAC.10,  28-Mar-85 22:57:33 by MELOHN
; Add routine to set the program name to the name of the connected node.
; Add QUIET cell to keep server connection/error msgs to a mimimum(default OFF)
; Make error msgs returned to users identify CTERM-SERVER as the source of err.
; Remove timout on initial connect since 6.1 systems will do it for us.
; UPD ID= 98, SNARK:<6.1.UTILITIES>SERVER.MAC.9,  18-Mar-85 17:02:03 by MELOHN
; Fix parsing of nodename to accept :: at the end of the string.
; UPD ID= 72, SNARK:<6.1.UTILITIES>SERVER.MAC.8,  27-Jan-85 22:57:40 by MELOHN
; Make default no input escape recognition to fix DECalc problem on VMS.
; UPD ID= 71, SNARK:<6.1.UTILITIES>SERVER.MAC.7,  25-Jan-85 21:08:19 by MELOHN
; Fix terminal settings restoration to correctly restore terminal len and wid
; UPD ID= 68, SNARK:<6.1.UTILITIES>SERVER.MAC.5,  16-Jan-85 20:23:41 by MELOHN
; Add a new entry in the entry vector for the EXEC to use when running the
; server via the SET HOST command. Using this vector will suppress the error
; messages usually supplied by the server to the user, since the EXEC will 
; handle that for us.
;
; Add code to set error code NSPX20 when no CTERM destination process so that
; the EXEC can go and try running NRT with the SET HOST command.
;
; Remove special handling code for freelfs in OUPENT, since it was eating
; messages with only CRLF in them.
;
;WORK:<MELOHN.CTS>SERVER.MAC.11 27-Nov-84 15:56:50, Edit by MELOHN
;
;   If a read is terminated because of underflow, check to see if it is a
;    continuation read.  If so, re-read the editing character and send it
;    to the host.
;
;   Change the edit number, not the version number.
;
; UPD ID= 24, SNARK:<6.1.UTILITIES>SERVER.MAC.2,   8-Aug-84 12:08:39 by WEISBACH
;   Add routines TRMSTX and TRMRTX to save and restore the terminal
;    characteristics for the case that the TEXTI is interrupted (by
;    out-of-band character PSI) and later restarted.
TITLE SERVER
SEARCH MACSYM,MONSYM,CMD
.REQUIRE SYS:MACREL,SYS:CMD

SALL

;Feature switches
IFNDEF FTPMR,<FTPMR==:0>
DEFINE $PMR,<IFN FTPMR,>
DEFINE $NOPMR,<IFE FTPMR,>
IF1,<IFN FTPMR,<PRINTX -- Building with PMR support -->>

;If FTPMR is non-zero, then CTERM-SERVER will be built with CTDNCN.  That
;is a modified version of DNCONN, which is the PMR support module.
	SUBTTL	Table of Contents


;		Table of Contents for SERVER
;
;
;			   Section			      Page
;   1. VERSION NUMBER AND ENTRY VECTOR. . . . . . . . . . . .    4
;   2. DEFINITIONS
;        2.1.   REGISTERS . . . . . . . . . . . . . . . . . .    5
;        2.2.   MACROS. . . . . . . . . . . . . . . . . . . .    6
;   3. NUMBER TO BIT MASK TABLE AND SWAP BYTE TABLE . . . . .   10
;   4. DEFINITIONS
;        4.1.   NAMES FOR FIELD VALUES  . . . . . . . . . . .   11
;        4.2.   CHARACTER ATTRIBUTES      . . . . . . . . . .   12
;        4.3.   DEBUG PROCESS . . . . . . . . . . . . . . . .   13
;        4.4.   TERMINAL STORAGE. . . . . . . . . . . . . . .   15
;        4.5.   MESSAGE TEMPLATES . . . . . . . . . . . . . .   18
;        4.6.   INPUT PROCESS . . . . . . . . . . . . . . . .   20
;        4.7.   OUTPUT PROCESS. . . . . . . . . . . . . . . .   24
;        4.8.   TIMER PROCESS . . . . . . . . . . . . . . . .   25
;        4.9.   DECNET LAYER. . . . . . . . . . . . . . . . .   26
;        4.10.  FOUNDATION LAYER. . . . . . . . . . . . . . .   27
;        4.11.  CTERM LAYER . . . . . . . . . . . . . . . . .   28
;        4.12.  CHARACTERISTICS DATA BASE . . . . . . . . . .   29
;        4.13.  PSI SYSTEM. . . . . . . . . . . . . . . . . .   30
;   5. MISCELLANEOUS STORAGE AND DEFINITIONS. . . . . . . . .   31
;   6. PROTOCOL ERROR HANDLER . . . . . . . . . . . . . . . .   32
;   7. STKVAR SUPPORT ROUTINE . . . . . . . . . . . . . . . .   33
;   8. INITIALIZE STORAGE . . . . . . . . . . . . . . . . . .   34
;   9. ENTRY. . . . . . . . . . . . . . . . . . . . . . . . .   35
;  10. DECNET LAYER
;       10.1.   INITIALIZATION. . . . . . . . . . . . . . . .   36
;       10.2.   Poor Mans Routing . . . . . . . . . . . . . .   37
;       10.3.   LINK DOWN . . . . . . . . . . . . . . . . . .   38
;       10.4.   SEND AND RECEIVE MESSAGE. . . . . . . . . . .   39
;       10.5.   DATA AVAILABLE INTERRUPT. . . . . . . . . . .   40
;  11. FOUNDATION LAYER
;       11.1.   INITIALIZATION. . . . . . . . . . . . . . . .   41
;       11.2.   OS NAME TABLE . . . . . . . . . . . . . . . .   42
;       11.3.   RECEIVE MESSAGE
;            11.3.1.     ENTRY AND SHORT ROUTINES . . . . . .   43
;            11.3.2.     COMMON DATA OR MODE DATA . . . . . .   44
;  12. CTERM LAYER
;       12.1.   INITIALIZATION. . . . . . . . . . . . . . . .   45
;       12.2.   SET CTERM DEFAULTS. . . . . . . . . . . . . .   46
;       12.3.   MESSAGE RECEIVED
;            12.3.1.     ENTRY AND SHORT MESSAGES . . . . . .   48
;            12.3.2.     START-READ . . . . . . . . . . . . .   49
;            12.3.3.     WRITE  . . . . . . . . . . . . . . .   51
;            12.3.4.     READ CHARACTERISTICS . . . . . . . .   52
;            12.3.5.     CHARACTERISTICS  . . . . . . . . . .   59
;            12.3.6.     CHECK INPUT  . . . . . . . . . . . .   65
;  13. PREINPUT PROCESS
;       13.1.   OUT OF BAND CHARACTER INTERRUPT ROUTINES. . .   66
;       13.2.   OUT OF BAND INTERRUPT PROCESSING. . . . . . .   68
;            13.2.1.     SIMULATE ECHO. . . . . . . . . . . .   69
;       13.3.   CONTROL-O AND CONTROL-X . . . . . . . . . . .   70
;       13.4.   SET CHARACTER ATTRIBUTES. . . . . . . . . . .   71
;            13.4.1.     PSI CHARACTER. . . . . . . . . . . .   72
;            13.4.2.     SET UP PSI . . . . . . . . . . . . .   73
;            13.4.3.     CLEAR OUT PSI. . . . . . . . . . . .   74
;            13.4.4.     SET ECHO . . . . . . . . . . . . . .   75
;            13.4.5.     SPECIAL FLAG . . . . . . . . . . . .   76
;  14. OUTPUT PROCESS
;       14.1.   WRITE MESSAGE
;            14.1.1.     ENTRY. . . . . . . . . . . . . . . .   77
;       14.2.   WRTE MESSAGE
;            14.2.1.     HANDLE LOCK  . . . . . . . . . . . .   78
;       14.3.   WRITE MESSAGE
;            14.3.1.     BEGINNING SEGMENT. . . . . . . . . .   79
;            14.3.2.     ENDING SEGMENT . . . . . . . . . . .   80
;            14.3.3.     PREFIX AND POSTFIX . . . . . . . . .   81
;       14.4.   UTILITY ROUTINES. . . . . . . . . . . . . . .   82
;  15. INPUT PROCESS
;       15.1.   POKE. . . . . . . . . . . . . . . . . . . . .   84
;       15.2.   INITIALIZATION. . . . . . . . . . . . . . . .   85
;       15.3.   START A READ. . . . . . . . . . . . . . . . .   86
;            15.3.1.     MOVE PROMPT. . . . . . . . . . . . .   87
;            15.3.2.     SET UP RAISE . . . . . . . . . . . .   88
;            15.3.3.     SET UP ECHO. . . . . . . . . . . . .   89
;            15.3.4.     SET UP BREAK MASK. . . . . . . . . .   90
;            15.3.5.     HANDLE FORMAT FLAG . . . . . . . . .   91
;            15.3.6.     CHECK FOR SINGLE CHARACTER READ. . .   92
;       15.4.   SEND INPUT STATE MESSAGE. . . . . . . . . . .   93
;       15.5.   TERMINAL INPUT AVAILABLE. . . . . . . . . . .   94
;            15.5.1.     RESTART  . . . . . . . . . . . . . .   95
;            15.5.2.     ORDINARY . . . . . . . . . . . . . .   96
;            15.5.3.     SINGLE CHARACTER READ. . . . . . . .   97
;            15.5.4.     READ RETURNED. . . . . . . . . . . .   98
;            15.5.5.     TERMINATOR CHARACTER . . . . . . . .   99
;            15.5.6.     START QUOTE. . . . . . . . . . . . .  100
;            15.5.7.     START ESCAPE SEQUENCE RECOGNITION. .  101
;            15.5.8.     QUOTE IN PROGRESS. . . . . . . . . .  102
;            15.5.9.     ESCAPE SEQUENCE  . . . . . . . . . .  103
;       15.6.   CLEAR INPUT BUFFER. . . . . . . . . . . . . .  108
;       15.7.   TERMINATE A READ. . . . . . . . . . . . . . .  109
;            15.7.1.     RESTORE TTY STATE. . . . . . . . . .  110
;       15.8.   DISPLAY INPUT BUFFER. . . . . . . . . . . . .  111
;  16. TIMER PROCESS
;       16.1.   THE TIMER . . . . . . . . . . . . . . . . . .  112
;       16.2.   CLEARING AND SETTING THE TIMER. . . . . . . .  113
;  17. UTILITY ROUTINES
;       17.1.   TURN OFF SINGLE CHARACTER INTERRUPTS. . . . .  114
;       17.2.   TURN ON SINGLE CHARACTER INTERRUPTS . . . . .  115
;       17.3.   SET UP PSI SYSTEM . . . . . . . . . . . . . .  116
;       17.4.   SAVE CTERM TERMINAL STATE . . . . . . . . . .  117
;       17.5.   SAVE ORIGINAL TERMINAL STATE. . . . . . . . .  118
;       17.6.   SAVE TERMINAL STATE FOR TEXTI RESTART . . . .  119
;       17.7.   SET UP TERMINAL . . . . . . . . . . . . . . .  120
;       17.8.   RESTORE ORIGINAL TERMINAL STATE . . . . . . .  121
;       17.9.   RESTORE CTERM TERMINAL STATE. . . . . . . . .  122
;       17.10.  RESTORE TERMINAL STATE FOR TEXTI RESTART. . .  123
;       17.11.  EXIT WITH REENTRY ALLOWED . . . . . . . . . .  124
;       17.12.  ERROR ROUTINES. . . . . . . . . . . . . . . .  125
;       17.13.  STRING LENGTH . . . . . . . . . . . . . . . .  126
;       17.14.  GET INTERRUPT SEQUENCE. . . . . . . . . . . .  127
;       17.15.  GET THE RSCAN BUFFER. . . . . . . . . . . . .  128
;       17.16.  NODE NAMES. . . . . . . . . . . . . . . . . .  129
;  18. DEBUG PROCESS
;       18.1.   ENTRY . . . . . . . . . . . . . . . . . . . .  130
;       18.2.   SET LOGGING FILE. . . . . . . . . . . . . . .  131
;       18.3.   HELP COMMAND. . . . . . . . . . . . . . . . .  132
;       18.4.   SHOW COMMAND. . . . . . . . . . . . . . . . .  133
;       18.5.   DISPLAY BUG . . . . . . . . . . . . . . . . .  134
	SUBTTL VERSION NUMBER AND ENTRY VECTOR

VEDIT==^D4
VMAJOR==1
VMINOR==0
VWHO==0
SCVN==<VWHO>B2+<VMAJOR>B11+<VMINOR>B17+VEDIT

;Entry vector
ENTVEC: JRST START 
	JRST [HALTF%
	      JRST .-1]
VERSIN:	SCVN
	JRST EXCSRT	; Entry for SET HOST command
	SUBTTL DEFINITIONS -- REGISTERS
;General temporary registers
T1=:1
T2=:2
T3=:3
T4=:4

;General preserved registers
Q1=:5
Q2=:6
Q3=:7

;Special purpose preserved registers
OOBAC1=:10			;For out of band interrupt
ESCSTA=:11			;Input escape sequence parsing state
BUGREG=:12			;Debug flags
INPSTA=:13			;Input state
P6=:15				;Frame pointer for TRVARs
CX=:16				;Very temporary register - used by macros
P=:17				;Stack pointer

;Free registers
FREE2==0 			
FREE1==14		       

        
	SUBTTL DEFINITIONS -- MACROS
;Save temporary register
DEFINE SAVET <
	JSP CX,.SAVT
>
.SAVT:	ADJSP P,4
	DMOVEM T1,-3(P)
	DMOVEM T3,-1(P)
	CALL (CX)
	TRNA
	AOS -4(P)
	DMOVE T1,-3(P)
	DMOVE T3,-1(P)
	ADJSP P,-4
	RET

;A skippable call to the error handler
;MSG is the error message
DEFINE PROERR (MSG)<
	JSP T2,[ HRROI T1,[ASCIZ\MSG\]
	         JRST PERRHN]
>

;****Alternative definition.
;DEFINE PROERR (MSG)<
;	CALL [	PUSH P,T1
;		PUSH P,T2
;		PUSH P,T3
;		TMSG <
;** CTERM-Server Protocol error.  >
;		HRROI T1,[ASCIZ\MSG\]
;	        PSOUT%
;		TMSG < **
;>
;		POP P,T3
;		POP P,T2
;		POP P,T1
;		RET]
;>

;Get one byte from a message, with error check
;PTR - byte pointer to current byte of message
;COUNT - number of bytes left in the message
;REG - register where next byte is to go.
;Updates PTR, COUNT, and REG
DEFINE GET1BY (PTR,COUNT,REG)<
	SOSGE COUNT
	PROERR <Parse error in getting a byte, no bytes left>
	ILDB REG,PTR
>;END GET1BY

;Get a two byte value (PDP-11 style) from a message, with error check
;PTR - byte pointer to current byte of message
;COUNT - number of bytes left in the message
;REG - register where next byte is to go.
;Updates PTR, COUNT, and REG
DEFINE GET2BY (PTR,COUNT,REG)<
	SOS COUNT
	SOSGE COUNT
	PROERR <Parse error in getting two bytes, not enough bytes>
	ILDB CX,PTR
	ILDB REG,PTR
	LSH REG,10
	IOR REG,CX
>;END GET2BY

;Insert a two byte value (PDP-11 style) into a CTERM message
;Preserves PTR which is assumed to be a DPB pointer
;REG - register containing the value to be inserted
;PTR - byte pointer into message
;Nonskippable
DEFINE PUT2BY (REG,PTR)<
	MOVE CX,PTR
	DPB REG,CX 
	LSH REG,-10
	IDPB REG,CX 
>;END PUT2BY
 
;Like PUT2BY, except that PTR is a IDPB pointer and is updated, and COUNT
;is updated
DEFINE IPT2BY (REG,PTR,COUNT)<
	IDPB REG,PTR
	LSH REG,-10
	IDPB REG,PTR
	AOS COUNT
	AOS COUNT
>;END IPT2BY

;Like IPT2BY, except for being a one byte field
DEFINE IPT1BY (REG,PTR,COUNT)<
	IDPB REG,PTR
	AOS COUNT
>;END IPT1BY
;Send bytes to the terminal - use this macro for any data sent to the
;terminal as a result of a START-READ or WRITE message. This is used
;to keep track of the last character sent to the terminal so that
;the format flag of the START-READ message can be implemented
;Nonskippable
;Uses only ACs T1,T2,T3
DEFINE $PSOUT (PTR,COUNT)<
	IFN PTR-3,<
	   MOVN T3,COUNT 	;;Get negative of source count
	   IFN PTR-2,<MOVE T2,PTR> ;;Get source pointer, if needed
	>
	IFE PTR-3,<
	   IFN COUNT-2,<MOVE T2,PTR> ;;Source pointer
	   IFE COUNT-2,<EXCH T2,T3> ;;Source pointer and count
	   MOVN T3,COUNT 	;;Get negative of source count
	>
	MOVEI T1,.PRIOU		;;Destination
	IFN. T3
	  SOUT%			;;Do it.
	  LDB T3,T2		;;Get last character
	  MOVEM T3,OUPCR	;;Save it
	ENDIF.
>;END $PSOUT

;As above, but for a single byte
;Nonskippable
DEFINE $PBOUT (THEBYT)<
 	IFN THEBYT-1,<MOVE T1,THEBYT>
	PBOUT%
	MOVEM T1,OUPCR
>;END $PBOUT
;Command parsing macro
;Parse a keyword - value is in T1
;  KEYTAB is address of the keyword table, 
;  FAIL is the address to go to on failure.
;Nonskippable. 
;Returns value of key in T1
DEFINE KEYWRD (KEYTAB)<
	MOVEI T1,[FLDDB.(.CMKEY,,KEYTAB)] ;;Address of function descriptor block
	CALL RFIELD		;;Do work.
	HRRZ T1,(T2)		;;Get value of key
>;END OF KEYWRD

COMMENT #

    This  macro  generates  the  action  codes  and  the  corresponding
dispatch  tables.  CODPRE  is  the first three characters of the action
code names, RTNPRE is  the  first  three  characters  of  the  dispatch
routines. CODLST is a list of three character suffixes for the names of
the action codes which will also serve as the suffixes for the names of
the dispatch routines.

#

DEFINE DSPGEN (CODTYP,RTNTYP,CODLST)<

IRP CODLST,<IFIW ! RTNTYP'CODLST>
.ZZ==0
IRP CODLST,<
	CODTYP'CODLST==.ZZ
	.ZZ==.ZZ+1
    >
>;END OF DSPGEN
;Generate bit number to bit mask translation table
DEFINE BITIT <
	XLIST
	.ZZ==^D35
	REPEAT ^D36,<
	    EXP 1_.ZZ
	    .ZZ==.ZZ-1
	LIST
	>
>;END OF BITIT

;Generate 8 bit byte swap table
;The CTERM termination bit map is flipped w.r.t. the TOPS20 style of numbering
;bits, and it is more convenient for this program to used the TOPS20 style.
DEFINE SWAPIT <
	XLIST
	.ZZ==0   		;;Current index
	REPEAT ^D256,<
	  .YY==0		;;Current bit
	  .XX==0		;;Result
	  REPEAT 8,<
	    IFN <.ZZ & <1_.YY>>,<.XX==<.XX ! 1_<7-.YY>>> ;;Generate swapped bit
	    .YY==.YY+1		;;Step bit
	  >			;;end of inner loop
	  EXP .XX		;;Make table entry
	  .ZZ==.ZZ+1		;;Step index
	LIST
	>			;;end of outer loop
>;END OF SWAPIT

;Generate BUG messages.
;FLAG - which trace flag controls this bug
;MSG - message to be printed
;PTR - pointer to string to be displayed (optional, ASCIZ string unless COUNT 
;      is present.
;COUNT - count to string to be displayed (optional)
;NOTE - the data that PTR points to may not be in the ACs
;Skippable
DEFINE BUGMSG (FLAG,MSG,PTR,COUNT)<
JUMPN BUGREG,[ TXNN BUGREG,FLAG		;;Is this flag set ?
	      JRST .+1			;;No. Go away
	      PUSH P,BUGREG
	      HRROI BUGREG,[ASCIZ\MSG\]
	      MOVEM BUGREG,BUGMPT
	      MOVE BUGREG,PTR
	      MOVEM BUGREG,BUGDPT
	      MOVE BUGREG,COUNT
	      MOVEM BUGREG,BUGCNT
	      POP P,BUGREG
	      CALL BUGDSP		;;Call display routine
	      JRST .+1]		        ;;Done.
>;END OF BUGMSG
	SUBTTL NUMBER TO BIT MASK TABLE AND SWAP BYTE TABLE
;Table to translate bit number to bit mask
BITS:  BITIT 


;Table to swap 8 bit bytes around for bit maps.
SWPBYT:	SWAPIT 
	SUBTTL DEFINITIONS -- NAMES FOR FIELD VALUES 
;Out of band characteristic
OB.CLR==1			;Clear out of band
OB.DEF==2			;Deferred clear out of band
OB.HEL==3			;Hello out of band

;Echo characteristic
EC.NON==0			;No echo
EC.SLF==1			;Echo as self
EC.STD==2			;Standard echo
EC.FMT==3			;Simulate format action

;Terminate on underflow field in START-READ message
TM.IGN==0			;Ignore underflow
TM.BEL==1			;Send bell to terminal
TM.TRM==2			;Terminate on underflow
	SUBTTL DEFINITIONS -- CHARACTER ATTRIBUTES      
;Out of band character attributes
BEGSTR OB
	FILLER ^D29		;right justify
	FIELD SPC,1		;Special flag
	FIELD ECH,2		;Control character echoing characteristics
	FIELD DSC,1		;Output discard state flag
	FIELD INC,1		;Include flag
	FIELD OOB,2		;Out of band type
ENDSTR 


;Out of band characteristics
OOBCHA:	BLOCK ^D32

;DELETE characteristics
DELCHA:	BLOCK 1


;Interrupt handling routines & PSI channel assignments
OOBTAB:	OOB0
	OOB1
	OOB2
  	OOB3
	OOB4
	OOB5
	OOB6
	OOB7
	OOB8
	OOB9
	OOB10
	OOB11
	OOB12
	OOB13
	OOB14
	OOB15
	OOB16
	OOB17
	OOB18
	OOB19
	OOB20
	OOB21
	OOB22
	OOB23
	OOB24
	OOB25
	OOB26
	OOB27
	OOB28
	OOB29
	OOB30
	OOB31

DELTAB:	OOBDEL

OOBMSG:	POINT 7,[ASCIZ/Control-@/]
	POINT 7,[ASCIZ/Control-A/]
	POINT 7,[ASCIZ/Control-B/]
	POINT 7,[ASCIZ/Control-C/]
	POINT 7,[ASCIZ/Control-D/]
	POINT 7,[ASCIZ/Control-E/]
	POINT 7,[ASCIZ/Control-F/]
	POINT 7,[ASCIZ/Control-G/]
	POINT 7,[ASCIZ/Control-H/]
	POINT 7,[ASCIZ/Control-I/]
	POINT 7,[ASCIZ/Control-J/]
	POINT 7,[ASCIZ/Control-K/]
	POINT 7,[ASCIZ/Control-L/]
	POINT 7,[ASCIZ/Control-M/]
	POINT 7,[ASCIZ/Control-N/]
	POINT 7,[ASCIZ/Control-O/]
	POINT 7,[ASCIZ/Control-P/]
	POINT 7,[ASCIZ/Control-Q/]
	POINT 7,[ASCIZ/Control-R/]
	POINT 7,[ASCIZ/Control-S/]
	POINT 7,[ASCIZ/Control-T/]
	POINT 7,[ASCIZ/Control-U/]
	POINT 7,[ASCIZ/Control-V/]
	POINT 7,[ASCIZ/Control-W/]
	POINT 7,[ASCIZ/Control-X/]
	POINT 7,[ASCIZ/Control-Y/]
	POINT 7,[ASCIZ/Control-Z/]
	POINT 7,[ASCIZ/ESCAPE   /]
	POINT 7,[ASCIZ/Control-\/]
	POINT 7,[ASCIZ/Control-]/]
	POINT 7,[ASCIZ/Control-^/]
	POINT 7,[ASCIZ/Control-_/]
	BLOCK .CHDEL-^D31-1
	POINT 7,[ASCIZ/DELETE/]
	SUBTTL DEFINITIONS -- DEBUG PROCESS
DEBUG:	BLOCK 1			;Debug is on.
BUGACS:	BLOCK 20		;Storage for DDT
BUGFIL:	BLOCK 1			;The tracing file JFN
BUGMPT:	BLOCK 1			;BUG message pointer
BUGDPT: BLOCK 1			;BUG data pointer
BUGCNT:	BLOCK 1			;BUG data count
SETHOS: BLOCK 1			;Entry was via EXEC SET HOST command
QUIET: BLOCK 1			;Don't print connection msgs.
BG.ALL==777776			;All flags except enable.
BG.ENA==1B35			;Debugging enabled.
BG.OOB==1B34			;OUT-OF-BAND processing	flag
BG.MSI==1B33			;RECEIVED-DECNET-MESSAGES flag
BG.MSO==1B32			;SENT-DECNET-MESSAGES flag
BG.CTR==1B21			;RECEIVED-CTERM-MESSAGES flag
BUGJFN:	BLOCK 1			;The interim file JFN
;The main command keyword table - right half contains routine address
KEYMAI:	10,,10
	XWD [ASCIZ\CONTINUE\],BUGCON
	XWD [ASCIZ\DDT\],BUGDDT
	XWD [ASCIZ\EXIT\],BUGEXI
	XWD [ASCIZ\HELP\],BUGHLP
	XWD [ASCIZ\LOG\],BUGLOG
	XWD [ASCIZ\SHOW\],BUGSHO
	XWD [ASCIZ\TRACE\],BUGTRC
	XWD [ASCIZ\UNTRACE\],BUGUNT

;The trace keyword table - right half contains mask
KEYTRC:	5,,5
	XWD [ASCIZ\ALL\],BG.ALL
	XWD [ASCIZ\OUT-OF-BANDS\],BG.OOB
	XWD [ASCIZ\RECEIVED-CTERM-MESSAGES\],BG.CTR
	XWD [ASCIZ\RECEIVED-DECNET-MESSAGES\],BG.MSI
	XWD [ASCIZ\SENT-DECNET-MESSAGES\],BG.MSO

;This is a macro from CMD to generate needed COMND% storage 
CMDSTG
	SUBTTL DEFINITIONS -- TERMINAL STORAGE
;Terminal characteristics of interest
BEGSTR TM
	FIELD VID,1		;Video
	FIELD MFF,1		;Mechanical form feed
	FIELD MTB,1		;Mechanical tab
	FIELD LOW,1		;Lower case
ENDSTR 

;Original terminal state storage.
OLDCOC:	BLOCK 2			;The CCOC words 
OLDRFM:	BLOCK 1			;The JFN mode word
OLDMOD:	BLOCK 1			;The pause on end of page mode
OLDWID:	BLOCK 1			;The terminal page width
OLDLEN:	BLOCK 1			;The terminal page length
OLDRTI:	BLOCK 2			;The terminal interrupt mask for the process.
OLDRTJ:	BLOCK 1			;The terminal interrupt mask for the job.
OLDSWI:	BLOCK 1			;Two character switch sequence
OLDTYP:	BLOCK 1			;Terminal type

;Current terminal state storage (for reentry).
CTMCOC:	BLOCK 2			;The CCOC words 
CTMRFM:	BLOCK 1			;The JFN mode word
CTMMOD:	BLOCK 1			;The pause on end of page mode
CTMWID:	BLOCK 1			;The terminal page width
CTMLEN:	BLOCK 1			;The terminal page length
CTMRTI:	BLOCK 2			;The terminal interrupt mask for the process.
CTMRTJ:	BLOCK 1			;The terminal interrupt mask for the job.
CTMSWI:	BLOCK 1			;Two character switch sequence
CTMTYP:	BLOCK 1			;Terminal type

;Terminal state storage (for TEXTI restart)
TXTCOC:	BLOCK 2			;The CCOC words
TXTRFM:	BLOCK 1			;The JFN mode word
TXTFW:	BLOCK 1			;The field width
TXTMSK:	BLOCK 5			;The character break mask


;Terminal characteristics kept in this program
LINWID:	BLOCK 1			;Line width
LINWRP:	BLOCK 1			;Line wrap characteristic
CHRIEX:	BLOCK 1			;Input escape recognition characteristic
CHROEX:	BLOCK 1			;Output escape recognition characteristic
CHRATP:	BLOCK 1			;Auto prompt characteristic
CHRICT:	BLOCK 1 		;Input count state characteristic


;Translation table from TOPS20 terminal type (as returned from GTTYP%)
;to characteristics of interest (currently only one - video)
TRMTAB:	0			;TTY model 33
	TMMFF+TMMTB		;TTY model 35
	TMLOW			;TTY model 37
	TMLOW			;TI/EXECUPORT
	REPEAT 4,<0>		;(reserved for customer)
	TMLOW			;Default
	TMMFF+TMMTB+TMLOW	;Ideal
	TMVID+TMMTB		;VT05
	TMVID			;VT50
	0			;LA30
	TMLOW			;GT40
	TMLOW			;LA36
	TMVID+TMMTB		;VT52
	TMVID+TMMTB		;VT100
	TMMTB+TMLOW		;LA38
	TMMFF+TMMTB+TMLOW	;LA120
	REPEAT <.TT125-.TT120-1>,<0> ;Gap in table
	TMMTB+TMVID		;VT125
	TMMTB+TMVID		;VK100
	TMMTB+TMVID		;VT102
	TMMTB+TMVID		;H19
	TMMTB+TMVID		;VT131
	TMMTB+TMVID		;VT200
TRMTBL==.-TRMTAB		;Length of table
;Translation table from terminal name string to TOPS20 terminal type number
TTYTBL:	TTYTLL,,TTYTLL
	[ASCIZ\GT40\],,.TTG40
	[ASCIZ\H19\],,.TTH19
	[ASCIZ\LA120\],,.TT120
	[ASCIZ\LA30\],,.TTL30
	[ASCIZ\LA36\],,.TTL36
	[ASCIZ\LA38\],,.TTL38
	[ASCIZ\LT33\],,.TT33
	[ASCIZ\LT35\],,.TT35
	[ASCIZ\LT37\],,.TT37
	[ASCIZ\VT05\],,.TTV05
	[ASCIZ\VK100\],,.TTK10
	[ASCIZ\VT100\],,.TT100
	[ASCIZ\VT102\],,.TT102
	[ASCIZ\VT125\],,.TT125
	[ASCIZ\VT131\],,.TT131
	[ASCIZ\VT200\],,.TT200
	[ASCIZ\VT50\],,.TTV50
	[ASCIZ\VT52\],,.TTV52
TTYTLL==.-TTYTBL-1
;Translation table from TOPS20 terminal type (as returned from GTTYP%)
;to length and name of terminal
TRMSTB:	4,,[ASCIZ\LT33\]	;TTY model 33
	4,,[ASCIZ\LT35\]	;TTY model 35
	4,,[ASCIZ\LT37\]	;TTY model 37
	1,,[0]			;TI/EXECUPORT
	REPEAT 4,<1,,[0]>	;(reserved for customer)
	1,,[0]			;Default
	1,,[0]			;Ideal
	4,,[ASCIZ\VT05\]	;VT05
	4,,[ASCIZ\VT50\]	;VT50
	4,,[ASCIZ\LA30\]	;LA30
	1,,[0]			;GT40
	4,,[ASCIZ\LA36\] 	;LA36
	4,,[ASCIZ\VT52\]	;VT52
	5,,[ASCIZ\VT100\]	;VT100
	4,,[ASCIZ\LA38\]	;LA38
	5,,[ASCIZ\LA120\]   	;LA120
	REPEAT <.TT125-.TT120-1>,<1,,[0]> ;Gap in table
	5,,[ASCIZ\VT125\]	;VT125
	5,,[ASCIZ\VK100\]	;VK100
	5,,[ASCIZ\VT102\]	;VT102
	3,,[ASCIZ\H19\]		;H19
	5,,[ASCIZ\VT131\]	;VT131
	5,,[ASCIZ\VT200\]	;VT200


;A number LARGER than the length of any string
TRMMAX==6

TRMTYP:	BLOCK 1			;TOPS20 Terminal type 
TRMCHA:	BLOCK 1			;Terminal characteristics

CCCODE:	BYTE (2)2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 ;CCOC words at initialization

ESCCHR:	BLOCK 1			;First character of switch sequence
	SUBTTL DEFINITIONS -- MESSAGE TEMPLATES
;****************************************
;Note that all pointers are DPB pointers.
;****************************************

;Template for the foundation BIND-ACCEPT message
;
BNDACS==^D17			;Size of BIND-ACCEPT message
BNDACX:	BYTE (8)4,2,0,0		;TYPE,VERSION,ECO,MOD
	BYTE (8)10,0,"6","."	;OPSYS1,OPSYS2,REV1,REV2
	BYTE (8)"1","B","L","1" ;REV3,REV4,REV5,REV6
BNDACZ: BYTE (8)".","0",0,0	;REV7,REV8,ID1,ID2
	BYTE (8)0		;OPTIONS
BNDACP:	POINT 8,BNDACZ,23	;Pointer to terminal id.
BNDPTR:	POINT 8,BNDACX		;Pointer to message

;CTERM initiate message
INISIZ==^D28 			;Size of message
INIMSX:	BYTE (8)11,0,30,0	;FOUND-TYPE,FLAGS,SIZE1,SIZE2
	BYTE (8)1,0,1,4		;CTERM-TYPE,FLAGS,VERSION,ECO
	BYTE (8)0,"6",".","1"	;MOD,REV1,REV2,REV3
	BYTE (8)"B","L","1","." ;REV4,REV5,REV6,REV7
       	BYTE (8)"0",1,2,0  	;REV8,MAX-LENGTH-PROTOCOL-MESSAGE(3)
	BYTE (8)5,2,1,377   	;MAX-LENGTH-ST(3),MESSAGES-SUPP(1)
	BYTE (8)3,2,376,177	;MESSAGES-SUPP(3)
INIPTR:	POINT 8,INIMSX		;Pointer to message

;Template CTERM read message.
REDMAX==3*1000  		;Max size of read data
REDHDR==4   			;Size of foundation header
REDCSZ==10 			;Size of fixed part of CTERM message
REDSIZ==REDMAX+REDHDR+REDCSZ 	;Max size of buffer in bytes
READX1: BYTE (8)11,0,0,0	;FOUND-TYPE,FLAGS,SIZE1,SIZE2
READX2:	BYTE (8)3,0,0,0		;CTERM-TYPE,FLAGS,LOW-WATER(2)
READX3:	BYTE (8)0,0,0,0		;VERTICAL-CHANGE,HORZONTAL-CHANGE,TERMINATOR-POS(2)
READX4:	BLOCK <REDSIZ-14>/4	;Read data storage

REDSPT:	POINT 8,READX1,23	;Pointer to size bytes
REDCPT:	POINT 4,READX2,15	;Pointer to "completion code" field
REDTPT:	POINT 1,READX2,11	;Pointer to "more typeahead data" field
REDLPT:	POINT 8,READX2,23	;Pointer to LOW-WATER bytes
REDVPT:	POINT 8,READX3,7 	;Pointer to VERTICAL-POS byte
REDHPT:	POINT 8,READX3,15	;Pointer to HORIZONTAL-POS byte
REDPPT: POINT 8,READX3,23	;Pointer to TERMINATOR-POS bytes
REDDPT:	POINT 8,READX4

REDPTR:	POINT 8,READX1		;Pointer to the buffer
;Template for CTERM out-of-band message
OOBSIZ==7			;Size of out-of-band message
OOBMSX:	BYTE (8)11,0,3,0	;FOUND-TYPE,FLAGS,SIZE1,SIZE2
OOBXXX:	BYTE (8)4,0,0   	;CTERM-TYPE,FLAGS,O-O-B-CHAR
OOBP:	POINT 8,OOBXXX,23	;Pointer to where out-of-band character goes 
OOBP1:  POINT 8,OOBXXX,15	;Pointer to where flags go
OOBPTR:	POINT 8,OOBMSX		;Pointer to message

;Template for CTERM discard state message
DSCSIZ==6 			;Size of out-of-band message
DSCMSX:	BYTE (8)11,0,2,0 	;FOUND-TYPE,FLAGS,SIZE1,SIZE2
DSCXXX:	BYTE (8)11,0    	;CTERM-TYPE,DISCARD-FLAGS
DSCP:	POINT 8,DSCXXX,15	;Pointer to where new requested state goes
DSCPTR:	POINT 8,DSCMSX		;Pointer to message

;Template for CTERM input count message
CNTSIZ==9 			;Size of out-of-band message
CNTMSX:	BYTE (8)11,0,4,0 	;FOUND-TYPE,FLAGS,SIZE1,SIZE2
CNTXXX:	BYTE (8)15,0,0,0	;CTERM-TYPE,FLAGS,COUNT1,COUNT2
CNTYYY: BYTE (8)0		;CHAR1 (VMS-CTERM "Extension")
CNTPC:	POINT 8,CNTYYY,7	;Pointer to CHAR1
CNTP:	POINT 8,CNTXXX,23	;Pointer to where count bytes goes.
CNTPTR:	POINT 8,CNTMSX		;Pointer to message

;Template for CTERM input state message
INSSIZ==6 			;Size of out-of-band message
INSMSX:	BYTE (8)11,0,2,0 	;FOUND-TYPE,FLAGS,SIZE1,SIZE2
INSXXX:	BYTE (8)16,1    	;CTERM-TYPE,INPUT-STATE
INSPTR:	POINT 8,INSMSX		;Pointer to message

;Template for CTERM write completion message
WRCSIZ==^D10			;Size of write-completion message
WRCMSX:	BYTE (8)11,0,6,0	;FOUND-TYPE,FLAGS,SIZE-1,SIZE-2
WRCXXX:	BYTE (8)10,0,0,0	;CTERM-TYPE,STATUS,HPOS1,HPOS2
WRCYYY:	BYTE (8)0,0          	;VPOS1,VPOS2
WRCFLG:	POINT 8,WRCXXX,15	;Pointer to status byte
WRCHPS:	POINT 8,WRCXXX,23	;Pointer to horizontal position bytes
WRCVPS:	POINT 8,WRCYYY,7	;Pointer to vertical position bytes
WRCPTR:	POINT 8,WRCMSX		;Pointer to start of message

;Template for CTERM characteristics message
CHAHDR==4   			;Size of foundation header
CHACSZ==2  			;Size of fixed part of CTERM message
CHAMSX:	BYTE (8)11,0,0,0	;FOUND-TYPE,FLAGS,SIZE-1,SIZE-2
CHAXXX:	BYTE (8)13,0,0,0	;CTERM-TYPE,FLAGS,SELECTOR-VALUE fields
CHAYYY:	BLOCK 100      		;
CHASZZ:	POINT 8,CHAMSX,23	;Pointer to SIZE bytes
CHAVAL:	POINT 8,CHAYYY		;Pointer to VALUE field
CHASL1:	POINT 8,CHAXXX,23	;Pointer to characteristics identifier
CHASL2:	POINT 8,CHAXXX,31	;Pointer to identifier type
CHAPTR:	POINT 8,CHAMSX		;Pointer to start of message
	SUBTTL DEFINITIONS -- INPUT PROCESS
RDACTV:	BLOCK 1			;A read is active

;Storage and definitions for parsing START-READ message
INPFPT:	POINT 8,.+1    		;Pointer to flags
INPFLG:	BLOCK 1			;Storage for flags
INPLEN:	BLOCK 1			;MAX-LENGTH
INPEOD:	BLOCK 1			;END-OF-DATA
INPTIM:	BLOCK 1			;TIMEOUT 
INPEOP:	BLOCK 1			;END-OF-PROMPT 
INPSOD:	BLOCK 1			;START-OF-DISPLAY 
INPLOW:	BLOCK 1			;LOW-WATER 
INPTML==^D8
INPTBM:	BLOCK INPTML		;TERMINATOR-SET
INPBPT:	BLOCK 1			;DATA-POINTER
INPBCT:	BLOCK 1			;DATA-COUNT

;START-READ flags
BEGSTR RD
;first byte
	FIELD RAI,2		;raise input
	FIELD CON,1		;continuation read
	FIELD VTF,1		;terminate on vertical change
	FIELD FMT,1		;Formatting
	FIELD CLT,1		;Clear typeahead
	FIELD UND,2		;Underflow
;second byte
	FIELD TRM,2		;non-default terminator
	FIELD TIM,1		;timeout
	FIELD TEC,1		;echo terminator
	FIELD NEC,1		;no-echo
	FIELD DCD,3		;disable control definition
;third byte
	FILLER 6
	FIELD ESS,2		;escape sequence recognition
ENDSTR


;Input dispatch table and action codes
YYYY:	BLOCK 100
INPDSP:	DSPGEN .IN,INP,<ORD,ESC,QUT,BIN>

COMMENT #
 Input process states
 .INORD==0			;Put into input buffer, and echo.
 .INESC==1			;Start escape sequence 
 .INQUT==2 			;Quote character
 .INBIN==3			;Single character read
#
INPIGN:	BLOCK 1			;"Ignore input" flag.
INPQOT:	BLOCK 1			;"Quote character (control-V) enabled" flag
INPTMO:	BLOCK 1			;"Timeout enabled" flag
INPRAI:	BLOCK 1			;"Restore raise on completion" flag
INPECH:	BLOCK 1			;"Restore echo on completion" flag
INPCTL:	BLOCK 1			;"Enable character interrupts on completion" flag
INPTIW:	BLOCK 2			;Terminal interrupt words, if needed.
INPESR:	BLOCK 1			;"Input esc seq recognition enabled" flag
INPUBM:	BLOCK 4			;"Unediting" break mask.
INPEBM: BLOCK 4			;"Editing" break mask.
INPSEE:	BLOCK 1			;A character has been seen during this read.
INPCHR: BLOCK 1			;First input char from input count message

INPUNX==1B<.CHBSP>+1B<.CHTAB>+1B<.CHCNR>+1B<.CHCNU>+1B<.CHCNW>
INPUNV:	-1 ^! INPUNX		;Universal CTERM break mask
	0
	0
	0

;Flags always set in TEXTI% argument block - 
;JFNs in .RDJFN, return on input empty, 
;return on backup limit reached, disable editing characters in break mask
TXTFLG==RD%JFN+RD%RIE+RD%BEG+RD%NED 

INPXBM: BLOCK 4			;TEXTI% break mask

;TEXTI% argument block with the permanent data filled in.
INPBLK:	.RDBKL   		;.RDCWB - count of words in block
	TXTFLG               	;.RDFLG - flags
	.PRIIN,,.PRIOU		;.RDJFN - input JFN and output JFN
	0			;.RDDBP - destination string buffer pointer
	0			;.RDDBC - number of bytes in destination string
	0             		;.RDBFP - destination string buffer start ptr
	POINT 8,INPPMT		;.RDRTY - CTRL/R buffer pointer
	INPXBM			;.RDBRK - address of break mask
	0			;.RDBKL - backup limit pointer

INPPMT:	BLOCK 100		;Storage for prompt.

;Read termination codes
.TMTRM==^D0			;Termination character
.TMVES==^D1			;Valid escape sequence
.TMIES==^D2			;Invalid escape sequence
.TMOOB==^D3			;Out of band character
.TMFUL==^D4			;Input buffer full
.TMTIM==^D5			;Timeout
.TMUNR==^D6			;Unread
.TMUND==^D7			;Underflow
.TMABS==^D8 			;Absentee token
.TMVRT==^D9 			;Vertical position change
.TMBRK==^D10			;Line break *
.TMFRM==^D11 			;Frame error *
.TMPAR==^D12			;Parity error *
.TMRUN==^D13			;Receiver overrun *
;* - not detected by this implementation
;Input escape sequence parsing variables
ESCMAX==40			;Maximum size of escape sequence in bytes
ESCBUF:	POINT 8,.+1		;Escape sequence buffer starting pointer
	BLOCK <ESCMAX+3>/4
ESCPTR:	BLOCK 1			;Pointer into escape sequence buffer
ESCCNT:	BLOCK 1			;Count of characters in escape sequence buffer
ESCMOD:	BLOCK 1			;Saved JFN mode word.

;State dispatch table for input escape sequence parsing.
;T1/ character
TSTATE:	IFIW ! @ESCST0(T1)	;Initial state 
	IFIW ! @ESCST1(T1)	;VT52 sequence starting with ";","?"
	IFIW ! @ESCST2(T1)	;VT52 sequence starting with "O" or ANSI sequence intermediate character. 
	IFIW ! @ESCST3(T1)	;VT52 sequence starting with "Y", 1st char
	IFIW ! @ESCST4(T1)	;VT52 sequence starting with "Y", 2nd char
	IFIW ! @ESCST5(T1)	;ANSI sequence parameter
	IFIW ! VALDON		;Valid escape sequence already parsed.

	XLIST
;Character dispatch tables for each state
;State 0 -  initial state
ESCST0:	REPEAT ^D32,<IFIW ! INVALD> ;0.-31. Invalid
	REPEAT ^D16,<IFIW ! STATE1> ;32.-47. Continue at state 1
	REPEAT ^D11,<IFIW ! VALID>  ;48.-58. Valid.
	IFIW ! STATE1		;59. (";") Continue at state 1
	REPEAT ^D3,<IFIW ! VALID>;60.-62. Valid.
	IFIW ! STATE1		;63. ("?") Continue at state 1
	REPEAT ^D15,<IFIW ! VALID> ;64.-78. Valid
	IFIW ! STATE2		;79. ("O") Continue at state 2
	REPEAT ^D9,<IFIW ! VALID> ;80.-88. Valid
	IFIW ! STATE3		;89. ("Y") Continue at state 3
	IFIW ! VALID		;90. valid
	IFIW ! STATE5		;91. ("[") Continue at state 5
	REPEAT ^D35,<IFIW ! VALID> ;92.-126. Valid
	IFIW ! INVALD		;127. Invalid.

;State 1 -  VT52 sequence starting with ";","?"
ESCST1:	REPEAT ^D32,<IFIW ! INVALD> ;0.-31. Invalid
	REPEAT ^D16,<IFIW ! RSKP> ;32.-47. Continue at same state
        REPEAT ^D79,<IFIW ! VALID> ;48.-126. Valid escape sequence
	IFIW ! INVALD		;127. Invalid
;State 2 - VT52 sequence starting with "O" or ANSI sequence intermediate character.
ESCST2:	REPEAT ^D32,<IFIW ! INVALD> ;0.-31. Invalid
	REPEAT ^D16,<IFIW ! RSKP> ;32.-47. Continue at same state
	REPEAT ^D16,<IFIW ! INVALD> ;48.-63. Invalid
	REPEAT ^D63,<IFIW ! VALID> ;64.-126. Valid escape sequence
	IFIW ! JRST INVALD	;127. Invalid 
;State 3 - VT52 sequence starting with "Y", first character
ESCST3:	REPEAT ^D32,<IFIW ! INVALD> ;0.-31. Invalid
	REPEAT ^D95,<IFIW ! STATE4> ;32.-126. Continue at state 4
	IFIW ! INVALD 		;127. Invalid
;State 4 - VT52 sequence starting with "Y", second character
ESCST4:	REPEAT ^D32,<IFIW ! INVALD> ;0.-31. Invalid
	REPEAT ^D95,<IFIW ! VALID>  ;32.-126. Valid
	IFIW ! INVALD 		;127. Invalid
;state 5 - ANSI sequence parameter
ESCST5:	REPEAT ^D32,<IFIW ! INVALD> ;0.-31. Invalid
	REPEAT ^D16,<IFIW ! STATE2> ;32.-47. Continue at state 2
	REPEAT ^D16,<IFIW ! RSKP> ;48.-63. Continue at same state
	REPEAT ^D63,<IFIW ! VALID> ;64.-126. Valid
	IFIW ! INVALD		;127. Invalid

	LIST
COMMENT #
	State diagram for escape sequence parsing
       				      
       				     +-+(32-47)
       				     | | 
            <ESC>     	  ";","?"    | |    (48-126)
         * --------> (0) ----------> (1) -------------> [VALID]
		     /|\	       \
[INVALID]           / | \		\   (0-31,127)
  ^             "Y"/  |  \"O"  		 \------------> [INVALID]
  |(0-31,127)     /   V   \
  +----<---- (3)<+    |    \
              |	      |	    \_____     
      (32-126)|	      |"["        \	  +-+(32-47)
              V	      |	           \	  | | 
   (0-31,127) |       |             \     | |    (64-126)
  +----------(4)      +----+         \--> (2) --------------> [VALID]
  V           |	           |              / \
[INVALID]     |  (48-63)/\ |	(32-47)	 /   \  (0-31,48-63,127)
	      V	       /  (5)---->------/     \------------------> [INVALID]
      (32-126)|	       \_/ |\	(0-31,127)
  +------<----+	           | \--->-------------------------------> [INVALID]
  V	      	  	   |	(64-126)
[VALID]			   +--->---------------------------------> [VALID]

#
	SUBTTL DEFINITIONS -- OUTPUT PROCESS
;Storage and definitions for CTERM WRITE message parsing
WRFLAG:	BLOCK 1			;Storage for flags
WRFPTR:	POINT 8,WRFLAG
OUPSKP:	BLOCK 1			;Skip-next-line-feed
OUPCR:	BLOCK 1			;Last character sent to terminal OR
				; 0 if it wasn't CR.
FREELF:	BLOCK 1			;Free LF was supplied by TOPS20.
TRMFLG: BLOCK 1			;non-zero if we echoed a terminator by mistake.

BEGSTR WR
    	FIELD PFX,2		;Prefix code
	FIELD EOM,1		;End of message
     	FIELD BOM,1		;Beginning message
        FIELD DSC,1		;Set output discard state
        FIELD NWL,1		;Newline flag
	FIELD LOK,2		;Lock handling definition
     	FILLER 4
	FIELD TRN,1		;Transparent output
	FIELD CMP,1		;Completion status requested
	FIELD PSX,2		;Postfix code
	FIELD PFC,8		;Prefix character/count
	FIELD PSC,8		;Postfix character/count
ENDSTR


;Fields from WRITE message
OUPLOK:	BLOCK 1			;Lock definition
OUPNWL:	BLOCK 1			;Newline flag
OUPOUT:	BLOCK 1			;Allow input echoing
OUPBOM:	BLOCK 1			;BEGINNING-OF-MESSAGE 
OUPEOM:	BLOCK 1			;END-OF-MESSAGE
OUPPFX:	BLOCK 1			;Prefix code
OUPPFC:	BLOCK 1			;Prefix character/count
OUPPSX:	BLOCK 1			;Postfix code
OUPPSC:	BLOCK 1			;Postfix character/count
OUPCMP:	BLOCK 1			;Completion status requested
OUPTRN:	BLOCK 1			;Transparent output 
OUPBPT:	BLOCK 1 		;Data byte pointer
OUPBCT:	BLOCK 1 		;Data byte count

OUPIPT:	BLOCK 1			;Point to queued input data
OUPICT:	BLOCK 1			;Negative count of queued input data
OUPLCK:	BLOCK 1			;Output is locked against echoing.

;Output discard states - 1 means "do not discard."
OUPDS1:	BLOCK 1			;Requested output discard state
OUPDS2:	BLOCK 1			;Real output discard state 
	SUBTTL DEFINITIONS -- TIMER PROCESS
TIMDSP:	DSPGEN .TM,TIM,<NUL,STT,TIK>

COMMENT #

;Timer states
.TMNUL==0			;Off
.TMSTT==1			;Set request
.TMTIK==2			;Ticking

#

TIMSTA:	BLOCK 1			;Timer state
TIMOUT:	BLOCK 1			;Timeout period.
JOBNO:	BLOCK 1			;Job number
	SUBTTL DEFINITIONS -- DECNET LAYER
;CTERM host DECnet object type
CTHOBJ==^D42			;The number
CTHOBA:	ASCIZ\-42\		;In ascii, for the connection.

;Network JFN
NETJFN:	BLOCK 1 		

;Storage for the remote file specification for NETJFN
NODSPC:	BLOCK 5

;DECnet buffer for message from remote
REMBSZ==10*400			;Buffer size in bytes
REMPTR:	POINT 8,.+1   		;Byte pointer to start of buffer
       	BLOCK REMBSZ/4		;The buffer

;Pointer to and storage for escape sequence
TCESIZ==^D80
TCEPTR:	POINT 7,.+1
	BLOCK TCESIZ/5

;Pointer to and storage for remote node name
NODPTR:	POINT 7,.+1   		;Pointer to node name
       	BLOCK 2			;Node name buffer
;Waiting interval time
LPVAL:	^D300
	SUBTTL DEFINITIONS -- FOUNDATION LAYER
;Dispatch table for received message on faoundation message type
FNDDSP:	DSPGEN .FN,FND,<ILL,BND,UNB,REB,BAC,ENT,EXI,CFM,NOM,COM,MOD>
FNDDSL==.-FNDDSP		;dispatch table length
COMMENT #

Foundation message types
.FNILL - illegal message type
.FNBND - bind message
.FNREB - rebind message (not implemented)
.FNUNB - unbind message
.FNBAC - bind accept message (never received)
.FNENT - enter mode message (not implemented)
.FNEXI - exit mode message  (not implemented)
.FNCFM - confirm mode message (never received)
.FNNOM - no mode message (never received)
.FNCOM - common data message
.FNMOD - mode data message

#
REMVER:	BLOCK 1			;Remote's version number
REMECO:	BLOCK 1			;Remote's ECO number
REMMOD:	BLOCK 1			;Remote's modification number
REMOS:	BLOCK 1			;Remote's OS code
REMTID:	BLOCK 1			;Remote's terminal id
REMRVP:	BLOCK 8			;Remote's revision field

.FNDBN==1			;BIND-REQUEST message type
CM%PRO==1B31			;CTERM protocol supported flag
	SUBTTL DEFINITIONS -- CTERM LAYER
;Dispatch table on received CTERM message type
CTMDSP:	DSPGEN .CT,CTM,<ILL,INT,STR,RED,OOB,UNR,CLI,WRI,WRC,DSC,RDC,CHA,CKI>
CTMDSL==.-CTMDSP		;Length of dispatch table

COMMENT #

CTERM message types
.CTILL - Illegal message type
.CTINT - INITIATE message
.CTSTR - START-READ message
.CTRED - READ message (never received)
.CTOOB - OUT-OF-BAND message (never received)
.CTUNR - UNREAD message (never received)
.CTCLI - CLEAR-INPUT message 
.CTWRI - WRITE message 
.CTWRC - WRITE-COMPLETE message (never received)
.CTDSC - DISCARD-STATE message (never received)
.CTRDC - READ-CHARACTERISTICS message 
.CTCHA - CHARACTERISTICS message 
.CTCKI - CHECK-INPUT message 
#

;State of CTERM layer - nonzero means initializing
CTMSTA:	BLOCK 1			 
	SUBTTL DEFINITIONS -- CHARACTERISTICS DATA BASE 
;Writing 
ACCESW:	IFIW ! @PHYCHW(T1)	;Physical
	IFIW ! @LOGCHW(T1)	;Logical
	IFIW ! @HANCHW(T1)	;Handler
ACCESL==.-ACCESW-1		;Largest identifier type

;Writing - physical characteristics
PHYCHW:	IFIW ! RTN   		;Illegal characteristic selector
	IFIW ! CHWINP		;Input speed (integer) 
	IFIW ! CHWOUP		;Output speed (integer) 
	IFIW ! CHWINT		;Character size (integer) - not writeable
	IFIW ! CHWBOL		;Parity enabled	(boolean) - not writeable
	IFIW ! CHWINT		;Parity type (integer) - not writeable
	IFIW ! CHWBOL		;Modem present (boolean) - not writeable
	IFIW ! CHWBOL		;Auto baud detect (boolean) - not writeable
	IFIW ! CHWBOL		;Management guaranteed (boolean) - not writeable
	IFIW ! CHWSW1		;Switch character 1 (string)
	IFIW ! CHWSW2		;Switch character 2 (string)
	IFIW ! CHWBOL		;Eight bit (boolean) - not writeable
	IFIW ! CHWBOL		;Terminal management enabled (boolean) - not writeable
PHYCHL==.-PHYCHW-1		;Largest characteristic identifier

;Writing - logical characteristics
LOGCHW:	IFIW ! RTN   		;Illegal characteristic selector
	IFIW ! CHWBOL		;Mode writing allowed (boolean) - not writeable
	IFIW ! CHWINT		;Terminal attributes (integer) - not writeable
	IFIW ! CHWSTG		;Terminal type (string) 
	IFIW ! CHWOFC		;Output flow control (boolean)
	IFIW ! CHWOPS		;Output page stop (boolean)
	IFIW ! CHWBOL		;Flow character passthrough (boolean) - not writeable
	IFIW ! CHWBOL		;Input flow control (boolean) - not writeable
	IFIW ! CHWBOL		;Loss notification (boolean) - not writeable
	IFIW ! CHWWID		;Line width (integer)
	IFIW ! CHWPGL		;Page length (integer)
	IFIW ! CHWPGL		;Stop length (integer)
	IFIW ! CHWINT		;CR fill (integer) - not writeable
	IFIW ! CHWINT		;LF fill (integer) - not writeable
	IFIW ! CHWWRP		;Wrap (integer)
	IFIW ! CHWINT 		;Horizontal tab	(integer) - not writeable
	IFIW ! CHWINT		;Vertical tab (integer) - not writeable
	IFIW ! CHWINT		;Form feed (integer)
LOGCHL==.-LOGCHW-1		;Largest characteristic identifier

;Writing - handler characteristics
HANCHW:	IFIW ! RTN   		;Illegal characteristic selector
	IFIW ! CHWIGN		;Ignore input (boolean)
	IFIW ! CHWCHR		;Character characteristic (compound)
	IFIW ! CHWBOL		;Control-O passthrough (boolean) - not writeable
	IFIW ! CHWRAI		;Raise input (boolean)
	IFIW ! CHWECH		;Normal echo (boolean)
	IFIW ! CHWIES		;Input escape sequence recognition (boolean)
	IFIW ! CHWOES		;Output escape sequence recognition (boolean)
	IFIW ! CHWICS		;Input count state (integer)
	IFIW ! CHWAP		;Auto prompt (boolean)
	IFIW ! CHWBOL		;Error processing (boolean) - not writeable
HANCHL==.-HANCHW-1		;Largest characteristic identifier

;Table of highest legal characteristic identifiers for each identifier type
ACCLEG:	PHYCHL			;Physical
	LOGCHL			;Logical
	HANCHL			;Handler

;Reading 
ACCESR:	IFIW ! @PHYCHR(T1)	;Physical
	IFIW ! @LOGCHR(T1)	;Logical
	IFIW ! @HANCHR(T1)	;Handler

;Reading - physical characteristics
PHYCHR:	IFIW ! CHRILL		;Illegal characteristic selector
	IFIW ! CHRINP		;Input speed (integer)
	IFIW ! CHROUP		;Output speed (integer)
	IFIW ! CHRSIZ		;Character size (integer) - always seven.
	IFIW ! CHRFLS    	;Parity enabled (boolean) - always false
	IFIW ! CHRZRO		;Parity type (integer) - always zero
	IFIW ! CHRFLS		;Modem present (boolean) - always false
	IFIW ! CHRFLS		;Auto baud detect (boolean) - always false
	IFIW ! CHRTRU		;Management guaranteed (boolean) - always true
	IFIW ! CHRSW1		;Switch character 1 (string)
	IFIW ! CHRSW2		;Switch character 2 (string)
	IFIW ! CHRFLS 		;Eight bit (boolean) - always false
	IFIW ! CHRTRU		;Management enabled (boolean) - always true

;Reading - logical characteristics
LOGCHR:	IFIW ! CHRILL		;Illegal characteristic selector
	IFIW ! CHRTRU		;Mode writing allowed (boolean) - always true
	IFIW ! CHRVID		;Terminal attributes (integer)
	IFIW ! CHRTYP		;Terminal type (string)
	IFIW ! CHROFC		;Output flow control (boolean) 
	IFIW ! CHROPS		;Output page stop (boolean) 
	IFIW ! CHRFLS		;Flow character passthrough (boolean) - always false
	IFIW ! CHRTRU		;Input flow control (boolean) - always true
	IFIW ! CHRTRU		;Loss notification (boolean) - always true
	IFIW ! CHRWID		;Line width (integer)
	IFIW ! CHRPGL		;Page length (integer)
	IFIW ! CHRPGL		;Stop length (integer)
	IFIW ! CHRZRO		;CR fill (integer) - always zero
	IFIW ! CHRZRO		;LF fill (integer) - always zero
	IFIW ! CHRWRP		;Wrap (integer) 
	IFIW ! CHRONE		;Horizontal tab (integer) - always one
	IFIW ! CHRONE		;Vertical tab (integer) - always one
	IFIW ! CHRONE		;Form feed (integer) - always one

;Reading - handler characteristics
HANCHR:	IFIW ! CHRILL		;Illegal characteristic selector
	IFIW ! CHRIGN		;Ignore input (boolean)
	IFIW ! CHRCHR		;Character characteristic (compound)
	IFIW ! CHRFLS		;Control-O passthrough (boolean) - always false
	IFIW ! CHRRAI		;Raise input (boolean) 
	IFIW ! CHRECH		;Normal echo (boolean) 
	IFIW ! CHRIES		;Input escape sequence recognition (boolean) 
	IFIW ! CHROES		;Output escape sequence recognition (boolean) 
	IFIW ! CHRICS		;Input count state (integer)
	IFIW ! CHRAP		;Auto prompt (boolean) 
	IFIW ! CHRFLS		;Error processing (boolean) - always false
	SUBTTL DEFINITIONS -- PSI SYSTEM
;Permanent PSI channel definitions
DNCHAN==0			;DECnet data available
TTCHAN==1			;Terminal data available
ESCCHN==2			;Two character escape channel

SWILEV==1			;Switch sequence level.
OOBLEV==2			;Out of band level.
DATLEV==3			;DECnet and terminal input level.

;PSI system storage. 
LEV1PC:	BLOCK 1
LEV2PC:	BLOCK 1
LEV3PC:	BLOCK 1

LEVTAB:	LEV1PC
	LEV2PC
	LEV3PC

CHNTAB:	XWD DATLEV,MSGINT		;DECnet interrupt
	XWD DATLEV,INPENT		;Terminal data available interrupt
	XWD SWILEV,REENTR		;Switch sequence channel
	BLOCK ^D33

;Pointer to free PSI channel list
PSIPTR:	0        

;Allocatable PSI channel table.
PSITAB:	BLOCK ^D36
	SUBTTL MISCELLANEOUS STORAGE AND DEFINITIONS

RESCAN:	BLOCK 1 		;RSCAN% flag
RSCCNT:	BLOCK 1			;RSCAN count
RSCPTR:	POINT 7,.+1		;RSCAN buffer pointer
	BLOCK 20		;RSCAN buffer

STSIZ==200
STACK:	BLOCK STSIZ

DDTMOD:	BLOCK 1			;Storage for JFN mode word for DDT command.

FULMSK:	777777,,777760		;Break mask word with all bits on.


RSKP:	AOS 0(P)
RTN:	RET

;Pointer to CRLF
CRLFPT:	POINT 7,[BYTE(7).CHCRT,.CHLFD,0] ;Pointer to CRLF.

;Operating system types
OS.VMS==7
OS.T20==10
OS.T10==11
OS.UTX==22	;Ultrix

;Connect block for DNCONN to do poor mans routing
CONBLK:	0			;Flag word
	BLOCK 1			;Node name pointer is stored here
	CTHOBJ			;CTERM object #
	0			;Local object #
	^D8			;Byte size
  Repeat 6,<
	0
  >
  Repeat 3,<
	.PRIOU			;Output designator
  >
	SUBTTL PROTOCOL ERROR HANDLER
;Protocol error handler
;CALL PERRHN with 
;	T1/  byte pointer to error string
;	T2/  PC of error
;Never returns.
PERRHN:	STKVAR <PERR,PC>
	MOVEM T1,PERR		;Save pointer to error text
	MOVEM T2,PC		;Save PC
;Print out helpful message
	TMSG <
CTERM-SERVER Protocol error, >
	MOVE T1,PERR
	PSOUT%
;Print out PC
	TMSG <
PC = >
	MOVEI T1,.PRIOU
	MOVEI T3,8
	MOVE T2,PC
	NOUT%
	 TRN
	JRST FATAL
	SUBTTL STKVAR SUPPORT ROUTINE
.XSTKS:	ADJSP P,@(CX)
	PUSH P,(CX)
	CALL 1(CX)
	IFSKP.
	  POP P,CX
	  MOVNS CX
	  ADJSP P,(CX)
	  RETSKP
	ENDIF.
	POP P,CX
	MOVNS CX
	ADJSP P,(CX)
	RET
	SUBTTL INITIALIZE STORAGE
INISTO:	SETZM OOBCHA
	MOVE T1,[OOBCHA,,OOBCHA+1]
	BLT T1,OOBCHA+^D31
	MOVEI T1,OOBDEL
	MOVEM T1,DELTAB
	MOVSI T1,-^D32
	DO.
	  HRRZS OOBTAB(T1)
	  AOBJN T1,TOP.
	ENDDO.
	SETZM OLDCOC
	MOVE T1,[OLDCOC,,OLDCOC+1]
	BLT T1,CHRICT
	SETZM RDACTV
	SETZM INPIGN
	MOVE T1,[INPIGN,,INPIGN+1]
	BLT T1,INPSEE
	SETZM OUPSKP
	SETZM OUPCR
	SETZM NETJFN
;Initialize CHNTAB
	SETZM CHNTAB+3
	MOVE T1,[CHNTAB+3,,CHNTAB+4]
	BLT T1,CHNTAB+^D35
;Initialize the allocatable part of the PSI table
	MOVEI T1,PSITAB+3	;Free pointer
	MOVEM T1,PSIPTR
	MOVE T1,[3,,PSITAB+4]	;Link up the first three
	MOVEM T1,PSITAB+3
	MOVE T1,[4,,PSITAB+5]
	MOVEM T1,PSITAB+4
	MOVE T1,[5,,PSITAB+^D23]
	MOVEM T1,PSITAB+5
	MOVSI T1,-^D12		;Link up the next twelve
	MOVE T2,[^D23,,PSITAB+^D24]
	DO.
	  MOVEM T2,PSITAB+^D23(T1)
	  ADD T2,[1,,1]
	  AOBJN T1,TOP.
	ENDDO.
	HRLZI T1,^D35		;Make the last oen the end of the list.
	MOVEM T1,PSITAB+^D35
	SETZM RESCAN		;Some state variables 
	SETZM RDACTV		
	SETZM OUPLCK
	SETZM OUPSKP
	SETZM OUPCR
	SETZM FREELF
	SETZM CTMSTA
	RET
	SUBTTL ENTRY
EXCSRT:	SETOM SETHOS		; Entry via the EXEC SET HOST command
START:	RESET%
	MOVE P,[IOWD STSIZ,STACK] ;Initialize the stack
	CALL INISTO		;Initialize storage
	CALL GETRSC		;Get the RSCAN buffer, if any.
	CALL TRMSAV		;Save the current terminal state.
	CALL TRMSTP		;Save the current CTERM terminal state.
	CALL CMDINI		;Initialize COMND% stuff
 	CALL GETINS		;Get CTERM switch sequence.
 	CALL GETNOD		;Get remote node name.
	SKIPE DEBUG 		;Debugging turned on ?
	CALL BUGENT		;Yes. Run debug process.
 	CALL MSGINI		;Initialize DECnet
	CALL PSIINI		;Initialize the PSI system.
	CALL TRMINI		;Initialize the terminal for CTERM
 	CALL FNDINI		;Initialize foundation and CTERM layers.
	CALL TIMINI		;Run in the timer process (turn on PSIs)
	HALTF%			;Should not return.
	JRST .-1
	SUBTTL DECNET LAYER -- INITIALIZATION
;Initialization of the DECnet layer
;Make DECnet connection, then call foundation layer init.
;CALL MSGINI with no arguments
;Returns +1 always
MSGINI:	HRROI T1,NODSPC		;Point to the file spec storage.
	HRROI T2,[ASCIZ\DCN:\]	;DECnet device
	SETZ T3,
	SOUT%
	MOVE T2,NODPTR 		;Remote node name
	SOUT%
	HRROI T2,CTHOBA       	;Object type
	SOUT%

	MOVX T1,<GJ%SHT>	;Get the associated JFN
	HRROI T2,NODSPC
	GTJFN%
	 ERJMP [SKIPE QUIET	;Are we quiet? If so, we dont print errors.
		JRST TRYNRT	;Yes, let NRT: try and parse it.
		JRST ERR]	;No, Print the error and exit.
	MOVEM T1,NETJFN

	MOVE T2,[OF%WR+OF%RD+FLD(^D8,OF%BSZ)] ;Open the JFN
	OPENF%
	 ERJMP [SKIPE QUIET	;Are we quiet? If so, we dont print errors.
		JRST TRYNRT	;Yes, let NRT: try and parse it.
   $NOPMR <JRST ERR>
   $PMR <
		CAIE T1,NSPX24	;Node name not assigned?
		JRST ERR	;No, Print the error and exit.
		MOVE Q1,T1	;Save error code
		MOVE T1,NETJFN	;Get rid of
		RLJFN%		; JFN
		ERJMP MSGIN1	;Ignore error
MSGIN1:		SETO T1,	;Flag that TRYPMR should type message
		CALL TRYPMR	;See if PMR will do it
		IFNSK.		;No,
		  MOVE T1,Q1	;Retrieve error code
		  JRST ERR	;Print the error and exit
		ENDIF.
		JRST MSGCON	;Proceed in success path
   >
		]
	SKIPE QUIET		;we don't want msgs.
	IFSKP.
	TMSG <
[Attempting a connection, >
	ENDIF.
;Wait for connect
	DO.
	  MOVE T1,LPVAL		;Get time to wait
	  DISMS%
	  MOVE T1,NETJFN	;Get link status
	  MOVEI T2,.MORLS
	  MTOPR%
	  TXNE T3,MO%CON	;Is it connected ?
	  EXIT.			;Yes. 
	  TXNN T3,MO%ABT+MO%SYN ;Is it disconnected ?
	  IFSKP.
	    MOVE T1,NETJFN	;Get JFN
	    TXO T1,CZ%ABT	;Abort
	    CLOSF%		;Close JFN
	    ERJMP .+1		;Ignore error
	    HRRZS T3		;Get disconnect reason code.
   $PMR <
	    CAIE T3,47		;Node unreachable?
	    IFSKP.		;Yes, try PMR
	      SETZ T1,		;No message needed
	      CALL TRYPMR	;Yes, see if PMR will do it
	      SKIPA		;No
	      JRST MSGCON	;Yes, PMR did it, continue
	      CAIN T1,4		;PMR failed because of no CTERM at remote?
	      MOVEI T3,4	;Yes, indicate that we should try with NRT
	    ENDIF.
   >
	    SKIPE QUIET		;Don't print msgs.
	    IFSKP.
	      TMSG <
CTERM Connect failed - >
	    ENDIF.
	    SKIPN QUIET		;If we aren't printing status msgs
	    CAIN T3,4		;Or if disconnect reason is no dest process
	    SKIPN SETHOS	;And SET HOST command was issued - try NRT.
	    JRST MSGHLT		;nope, just print the error code and exit.
	    JRST TRYNRT		;yes, seter the correct code and exit.
	  ENDIF.
          LOOP.	 		;No. Wait some more.
	ENDDO.
MSGCON:	SKIPE QUIET		;Don't print msgs.
	IFSKP.
	TMSG <connect OK, ]>    ;Succeeded.
	CALL SETPNM		;Set the program name to the node name.
	ENDIF.
	RET
	SUBTTL DECNET LAYER -- Poor Mans Routing

;Here to try poor mans routing
;CALL TRYPMR with
;	T1/ non-zero if a "connectin..." message is needed
;
;Returns +1 on failure with error code in T1,
;	 +2 on success with NETJFN containing new JFN
;Preserves T3

   $PMR <
	EXTERN .DNINI,.DNCON	;Entry points to DNCONN
TRYPMR:	SAVEAC <T3,Q1>		;Preserve T3 and Q1
	MOVE Q1,T1		;Save output message flag
	MOVE T1,NODPTR		;Get pointer to node name
	MOVEM T1,CONBLK+1	;Save in connect block for DNCONN
	MOVEI T1,CONBLK		;Load address of connect block
	CALL .DNINI		;Initialize DNCONN
	  JRST NOPMR		;Failed, take fail return
	MOVE T2,NODPTR		;T1 points to host table
	TBLUK%			;Is our destination in tables?
	ERJMP NOPMR		;Fail return on error
	TXNN T2,TL%EXM		;Match?
	JRST NOPMR		;No, just return, no point in trying PMR
	HRRZ T1,(T1)		;Point to route string block
	ADDI T1,2		;Move to route string
	SKIPN (T1)		;Make sure non-zero
	JRST NOPMR		;Bad, don't do PMR
	HRLI T1,(POINT 7,0)	;Make byte pointer to route string
	MOVE T2,NODPTR		;Get pointer to node name
	EXCH T1,T2		;Get AC's for STCMP%
	STCMP%			;Compare them
	ERJMP NOPMR		;Bad, don't do PMR
	SKIPE T1		;Identical or
	TXNE T1,SC%SUB		;not substring?
	JRST NOPMR		;Yes, means no real routing, don't do PMR
	SKIPN Q1		;Want message?
	IFSKP.			;Yes
	TMSG <
[Attempting a connection, >
	ENDIF.
	MOVEI T1,CONBLK		;Load argument for .DNCON
	CALL .DNCON		;Try to connect to remote
	RET			;Fail with error code in T1
	HRRZM T1,NETJFN		;Save network JFN
	RETSKP			;Success return

NOPMR:	SETO T1,		;Indicate failure
	RET

   >
	SUBTTL DECNET LAYER -- LINK DOWN
;Here when the link has gone
;CALL MSGHLT with:
;	T3/ Link status word
;Does not return.
MSGHLT:	HRRZS T3		;Get disconnect reason code.
	HRRO T1,MSGDSC(T3)	;Get the corresponding message
	PSOUT%			;Print it out
	JRST FATAL		;Go away

MSGDSC:	[ASCIZ\No special error\]
	[ASCIZ\Resource allocation failure\]
        [ASCIZ\Destination node does not exist\]
	[ASCIZ\Node shutting down\]
	[ASCIZ\Destination process does not exist\]
	[ASCIZ\Invalid name field\]
	[ASCIZ\Destination process queue overflow\]
	[ASCIZ\Unspecified error\]
	[ASCIZ\Third party aborted link\]
	[ASCIZ\User abort\]
	REPEAT 1,<[ASCIZ\Undefined disconnect code\]>
	[ASCIZ\Undefined error code\]
	REPEAT 9,<[ASCIZ\Undefined disconnect code\]>
	[ASCIZ\Connect initiate with illegal destination address\]
	[ASCIZ\Connect confirm with illegal destination address\]
	[ASCIZ\Connect initiate or confirm with zero source address\]
	[ASCIZ\Flow control violation\]
	REPEAT 7,<[ASCIZ\Undefined disconnect code\]>
	[ASCIZ\Too many connections to node\]
	[ASCIZ\Too many connections to destination process\]
	[ASCIZ\Access not permitted\]
	[ASCIZ\Logical link services mismatch\]
	[ASCIZ\Invalid account\]
	[ASCIZ\Segment size too small\]
	[ASCIZ\Process aborted\]
	[ASCIZ\No path to destination node\]
	[ASCIZ\Link aborted due to data loss\]
	[ASCIZ\Destination process does not exist\]
	[ASCIZ\Confirmation of disconnect initiate\]
	[ASCIZ\Image data field too long\]
	SUBTTL DECNET LAYER -- SEND AND RECEIVE MESSAGE
;Get a DECnet message.
;CALL MSGGET with: 
;	T1/ byte pointer to buffer
;	T2/ max byte count
;On failure, HALTF%s
;ON success, returns +1 with: 
;	T1/ byte pointer to start of message
;	T2/ number of bytes received
MSGGET:	STKVAR <COUNT,PTR>
	MOVEM T2,COUNT		;Save count
	MOVEM T1,PTR		;Save pointer
	MOVN T3,T2		;Max count for SINR%
	MOVE T2,T1		;Byte pointer
	MOVE T1,NETJFN		;JFN
	SINR%			;Get that message
	 ERJMP ERR
	ADD T3,COUNT		;Compute byte count of message
	MOVE T2,T3		; in proper register.
	MOVE T1,PTR		;Byte pointer
	BUGMSG (BG.MSI,<Received DECnet message>,T1,T2)
	RET

;Send a DECnet message
;CALL MSGPUT with: 
;	T1/ byte pointer to buffer
;	T2/ byte count
;On failure, HALTF%s
;On success, returns +1 with T2/ updated byte pointer
MSGPUT:	BUGMSG (BG.MSO,<Sending DECnet message>,T1,T2)
	MOVN T3,T2		;Byte count
	MOVE T2,T1		;Byte pointer
	MOVE T1,NETJFN		;JFN
	SOUTR%			;Put the message
	 ERJMP ERR
	RET			;Done
	SUBTTL DECNET LAYER -- DATA AVAILABLE INTERRUPT
;Here on DECnet data available PSI - process received DECnet message
;On failure HALTF%s
;On success DEBRK%s
MSGINT:	CALL MSGIN0		;Do work
	DEBRK%

MSGIN0:	SAVET			;Save temporary registers
	DO.
	  MOVEI T1,.FHSLF	;Turn off
	  DIR%			; interrupts
       	  MOVE T1,NETJFN	;Get link status - link may be down.
	  MOVEI T2,.MORLS
	  MTOPR%
	  TXNN T3,<MO%SYN+MO%ABT> ;Is link down ?
	  IFSKP.
	          		;Yes.
	    TMSG <
[Connection broken, back at node >
	    CALL PRTNOD
	    TMSG <]
%Link broken - >
	    JRST MSGHLT
	  ENDIF.
       	  SIBE%			;Anything here ?
	  IFSKP.
	    MOVEI T1,.FHSLF	;No. Turn on
            EIR%		; interrupts
	    RET   		;Done.
	  ENDIF.
;Here when there is a message (or at least one segment of a message)
          MOVE T1,REMPTR	;Point to buffer
	  MOVX T2,REMBSZ	;Buffer size
	  CALL MSGGET		;(T1,T2/T1,T2) Get a message (may block if multisegment message)
	  CALL FNDGET		;(T1,T2) Tell foundation about it.
	  MOVEI T1,.FHSLF	;Turn on
          EIR%			; interrupts
	  LOOP.
	ENDDO.
	SUBTTL FOUNDATION LAYER -- INITIALIZATION
;Initialization of the foundation layer
;CALL FNDINI with 
;	DECnet link connected, 	
;	The interrupt system disabled
;Returns +1 always
FNDINI:	MOVE T1,REMPTR		;Get the first message.
	MOVEI T2,REMBSZ
	CALL MSGGET		;(T1,T2/T1,T2)
;Parse the BIND-REQUEST message
	GET1BY T1,T2,T3		;Get the first byte
	CAIE T3,.FNDBN		;Is the type BIND-REQUEST ?
	PROERR <Expected BIND-REQUEST> ;No. Protocol error.
	GET1BY T1,T2,T3		;Yes. Get the version number.
	MOVEM T3,REMVER		; and save it.
	GET1BY T1,T2,T3		;Get the ECO number.
	MOVEM T3,REMECO		; and save it.
	GET1BY T1,T2,T3		;Get the customer modification number.
	MOVEM T3,REMMOD		; and save it.
	GET2BY T1,T2,T3		;Get the OSTYPE
	MOVEM T3,REMOS		; and save it.
	GET2BY T1,T2,T3		;Get the protocols supported
	TXNN T3,CM%PRO		;Is CTERM present ?
	PROERR <Remote does not support CTERM> ;No. Protocol error.
	SUBI T2,10		;Account for REVISION field
	SKIPGE T2
REPEAT 0,<
 	PROERR <Parse error, count is zero>
     	MOVE T4,[POINT 8,REMRVP] ;Point to revision field
	MOVEI Q1,10		;The length.
	DO.
          ILDB T3,T1
	  IDPB T3,T4
	  SOJG Q1,TOP.
	ENDDO.
	GET2BY T1,T2,T3		;Get remote terminal id.
	MOVEM T3,REMTID
>
;Tell user about remote system
	TRN
	SKIPE QUIET		;Don't print msgs.
	IFSKP.
	  TMSG <
[Remote host is a >
	  MOVE T1,REMOS
	  HRRO T1,OSNAM(T1)
	  PSOUT%
          TMSG < system]>
	ENDIF.
	TMSG <
[TYPE >
	CALL PRTINS
	TMSG < to return to node >
	CALL PRTNOD
	TMSG <]
>
;Construct the BIND-ACCEPT message 
	HRROI T1,[ASCIZ\TTY:\]	;Get the 
	STDEV%			; TTY
	HRRZS T2		; number
	PUT2BY T2,BNDACP	;Put into message
	MOVE T1,BNDPTR		;Pointer to the BIND-ACCEPT message
	MOVEI T2,BNDACS		;Byte count
	CALL MSGPUT		;(T1,T2) Send it off.
;ENTER-MODE, CONFIRM-MODE exchange would take place here.
	CALL CTMINI		;Now initialize CTERM
	MOVE T1,REMPTR		;Point to buffer
	MOVEI T2,REMBSZ		;Buffer size
	CALL MSGGET		;(T1,T2/T1,T2) Get next message
	CALLRET FNDGET		;And parse it.
	SUBTTL FOUNDATION LAYER -- OS NAME TABLE
OSNAM:	[ASCIZ\unspecified\]
	[ASCIZ\RT-11\]
	[ASCIZ\RSTS/E\]
	[ASCIZ\RSX-11S\]
	[ASCIZ\RSX-11M\]
	[ASCIZ\RSX-11D\]
	[ASCIZ\IAS\]
	[ASCIZ\VMS\]
	[ASCIZ\TOPS-20\]
	[ASCIZ\TOPS-10\]
	[ASCIZ\OS-8\]
	[ASCIZ\RTS-8\]
	[ASCIZ\RSX-11M+\]
	[ASCIZ\Ultrix\]
OSNAML==.-OSNAM
	SUBTTL FOUNDATION LAYER -- RECEIVE MESSAGE -- ENTRY AND SHORT ROUTINES
;Here when foundation message has been received.
;CALL FNDGET with:
;	T1/ byte pointer
;	T2/ byte count
;Returns +1 always 
FNDGET:	GET1BY T1,T2,T3		;Get the foundation message type.
	CAIG T3,FNDDSL		;Range check.
	JRST @FNDDSP(T3)	;(T1,T2,T3) Dispatch on type.
	JRST FNDILL		;Range check failure.

;Illegal or unsupported message 
FNDILL:	PROERR <Invalid foundation message type received>
FNDBND:	PROERR <Illegal foundation message type received - bind>
FNDREB:	PROERR <Invalid foundation message type received>
FNDBAC:	PROERR <Illegal foundation message type received - bind accept>
FNDENT:	PROERR <Unsupported foundation message type received - enter mode>
FNDEXI:	PROERR <Unsupported foundation message type received - exit mode>
FNDCFM:	PROERR <Illegal foundation message type received - confirm mode>
FNDNOM:	PROERR <Illegal foundation message type received - no mode>

;Here when UNBIND message received
;T1/ byte pointer to message
;T2/ byte count of message
FNDUNB:	GET1BY T1,T2,T3		;Get reason code
	TMSG <
[Connection broken by remote - >
	CAILE T3,0      	;Range 
	CAILE T3,FNDUBL		; check
	PROERR <reason out of range> ;Failed.
	HRRO T1,FNDUBT(T3)	;Get message
	PSOUT%			;Print it.
	TMSG <]>
	JRST FATAL		;Go away

;Unbind reason code to string translation table.
FNDUBT:	[ASCIZ\?\]
	[ASCIZ\incompatible versions\]
	[ASCIZ\no portal available\]
	[ASCIZ\user unbind request\]
	[ASCIZ\terminal disconnected\]
	[ASCIZ\selected logical terminal or portal is in use\]
	[ASCIZ\selected logical terminal or portal does not exist\]
	[ASCIZ\selected logical terminal or portal not in REBIND-WAIT state\]
	[ASCIZ\rebind collision\]
FNDUBL=.-FNDUBT
	SUBTTL FOUNDATION LAYER -- RECEIVE MESSAGE -- COMMON DATA OR MODE DATA 
;Here when a COMMON DATA or MODE DATA message is received 
;T1/ byte pointer
;T2/ byte count
FNDMOD:
FNDCOM:	STKVAR <PTR,COUNT>
       	GET1BY T1,T2,T3		;FILL field
	DO.
       	  GET2BY T1,T2,T3	;LENGTH
	  CAMLE T3,T2		;Is LENGTH larger than message length ?
	  PROERR <LENGTH field larger than count> ;Yes. Fail.
	  MOVE T4,T3		;No. Find pointer past 
	  ADJBP T4,T1		; this CTERM message
	  MOVEM T4,PTR		; and save it.
	  EXCH T2,T3		;T2/ LENGTH of this CTERM message
	  SUB T3,T2		;T3/ remaining bytes after this CTERM message
	  MOVEM T3,COUNT 	;Save remainder
	  CALL CTMGET		;(T1,T2) Give it to CTERM layer
	  SKIPN COUNT		;Any other CTERM messages packed in here ?
	  RET			;No. Done.
	  MOVE T1,PTR		;Yes. Get the pointer to it.
	  MOVE T2,COUNT		; and the count
	  LOOP.    		;Continue.
	ENDDO.

	ENDSV.			;END STKVAR
	SUBTTL CTERM LAYER -- INITIALIZATION
;CALL CTMINI with foundation already initialized
;Returns +1 always
CTMINI:	SETOM CTMSTA		;Initializing.
	CALL CTMDEF		;Initialize data base
;Send off CTERM INITIATE message
	MOVE T1,INIPTR		
	MOVEI T2,INISIZ		
	CALL MSGPUT		;(T1,T2)
	RET
	SUBTTL CTERM LAYER -- SET CTERM DEFAULTS
;Here to set up the default CTERM characteristics for the terminal
;CALL CTMDEF with no arguments and PSI system initialized.
;Returns +1 always
CTMDEF: SAVEAC <Q1>
;Set up special flag for the special characters
	MOVEI T1,.CHCNO		;Control-O
	MOVX T2,OBSPC		
	CALL PRECHR
	MOVEI T1,.CHCNR		;Control-R
	MOVX T2,OBSPC		
	CALL PRECHR
	MOVEI T1,.CHCNU		;Control-U
	MOVX T2,OBSPC		
	CALL PRECHR
	MOVEI T1,.CHCNV		;Control-V
	MOVX T2,OBSPC		
	CALL PRECHR
	MOVEI T1,.CHCNW		;Control-W
	MOVX T2,OBSPC		
	CALL PRECHR
	MOVEI T1,.CHCNX		;Control-X
	MOVX T2,OBSPC		
	CALL PRECHR
	MOVEI T1,.CHDEL		;DELETE
	MOVX T2,OBSPC		
	CALL PRECHR
;Set up output discard states
	MOVEI T1,1		;"1" means do not discard output.
	MOVEM T1,OUPDS1
	MOVEM T1,OUPDS2
;Set up default echo characteristics for control characters.
	MOVEI Q1,^D31		;Loop index
	DO.
	  MOVE T1,Q1		;Get character
	  MOVE T2,OOBCHA(T1)	;Get current characteristics
	  MOVEI T3,EC.STD	;Get standard echo value
	  STOR T3,OBECH,+T2	;Pass it down.
	  CALL PRECHR		;(T1,T2)
	  SOJGE Q1,TOP.
	ENDDO.
	MOVEI T1,1		;Set up characteristics - 
	SETZM CHRIEX		; Seems to work better under VMS.
;	MOVEM T1,CHRIEX		; input escape sequence recognition
	MOVEM T1,CHROEX		; output escape sequence recognition
	MOVEM T1,CHRICT		; input count state (do not send)
	MOVEI T1,4		;Set
	MOVEM T1,LINWRP		; line wrap to wrap
	MOVEI T1,.CHESC		;Set no echo
	MOVEI T2,EC.NON		; for escape (since esc seq rec is on)
	CALL PREECH		;(T1,T2)
	CALL CTMSPC		;Set system-specific defaults
	RET
;Here for setting up system specific defaultss for those systems which are
;ignorant of the architecturally defined defaults.
;CALL CTMSPC with no arguments
;Returns +1 always
CTMSPC:	SAVEAC <Q1>
	MOVE T1,REMOS		;Get remote OS type
	CAIE T1,OS.VMS
	RET
;Set up control characters to not echo.
	MOVEI Q1,^D31		;Loop index
	DO.
	  MOVE T1,Q1		;Get character
	  MOVE T2,OOBCHA(T1)	;Get current characteristics
	  MOVEI T3,EC.NON	;Get standard echo value
	  STOR T3,OBECH,+T2	;Pass it down.
	  CALL PRECHR		;(T1,T2)
	  SOJGE Q1,TOP.
	ENDDO.
;There are some characters that echo.
	MOVEI T1,.CHLFD		;Get LF
	MOVE T2,OOBCHA(T1)	;Get current characteristics
	MOVEI T3,EC.SLF		;Get self code
	STOR T3,OBECH,+T2	;Pass it down.
	CALL PRECHR		;(T1,T2) Set it.
	MOVEI T1,.CHCRT		;Get CR
	MOVE T2,OOBCHA(T1)	;Get current characteristics
	MOVEI T3,EC.SLF		;Get self code
	STOR T3,OBECH,+T2	;Pass it down.
	CALL PRECHR		;(T1,T2) Set it.
	MOVEI T1,.CHFFD		;Get FF
	MOVE T2,OOBCHA(T1)	;Get current characteristics
	MOVEI T3,EC.STD		;Get standard code
	STOR T3,OBECH,+T2	;Pass it down.
	CALL PRECHR		;(T1,T2) Set it.
	MOVEI T1,.CHTAB		;Get TAB
	MOVE T2,OOBCHA(T1)	;Get current characteristics
	MOVEI T3,EC.SLF		;Get self code
	STOR T3,OBECH,+T2	;Pass it down.
	CALL PRECHR		;(T1,T2) Set it.
	MOVEI T1,.CHCNW		;Get control-W
	MOVE T2,OOBCHA(T1)	;Turn off the special flag
	SETZ T3,
	STOR T3,OBSPC,+T2
	CALL PRECHR		;(T1,T2) Set it.
	RET
	SUBTTL CTERM LAYER -- MESSAGE RECEIVED -- ENTRY AND SHORT MESSAGES
;Here when a CTERM message was received.
;CALL CTMGET with
; 	T1/ byte pointer to CTERM message
;	T2/ byte count
;Returns +1 always
CTMGET: BUGMSG (BG.CTR,<Received CTERM message>,T1,T2)
	GET1BY T1,T2,T3		;Get CTERM type
	CAIGE T3,CTMDSL		;Range check.
	JRST @CTMDSP(T3)	;Go do it.
	JRST CTMILL		;Fail.

;Here when invalid or illegal message received
CTMRED:
CTMOOB:
CTMWRC:
CTMDSC:
CTMILL:	PROERR< Illegal or invalid CTERM message type received>

;Here when a INITIATE message was received
;CALL CTMINT with
;	T1/ byte pointer
;	T2/ byte count
;Returns +1 always
CTMINT:	SKIPN CTMSTA		;Are we initializing ?
	PROERR <Initiate message received in wrong state>
	SETZM CTMSTA		;Yes. Finished init.
	RET

;Here when a CLEAR-INPUT message was received
;CALL CTMCLI with
;	T1/ byte pointer
;	T2/ byte count
;Returns +1 always
CTMCLI:	MOVEI T1,.PRIIN		;() Clear 
	CFIBF%			; typeahead buffer
	CALLRET INPCIB		;() Clear input buffer

;Here when an UNREAD message was received
;CALL CTMUNR with
;	T1/ byte pointer
;	T2/ byte count
;Returns +1 always
CTMUNR:	SKIPN RDACTV		;Is there a READ active ?
	RET			;No. That's OK, just ignore it.
	GET1BY T1,T2,T3		;Yes. Get flags byte
	TRNN T3,1		;Test the flag
	IFSKP.
	  MOVEI T1,.PRIIN	;It is set. Is typeahead buffer empty ?
	  SIBE%
	  IFSKP.
	    SKIPN INPSEE  	;Yes. Now check the input buffer.
	    RET			;It is empty.
	  ENDIF.
	ENDIF.
	MOVEI T1,.TMUNR		;Terminate the read with an unread
	SETZ T2,		;No terminator
	CALLRET INPEND		;(T1,T2)
	SUBTTL CTERM LAYER -- MESSAGE RECEIVED -- START-READ 
;Here when a START-READ message was received
;Parse it.
;CALL CTMSTR with
;	T1/ byte pointer
;	T2/ byte count
;Returns +1 always
CTMSTR:	SKIPE RDACTV		;Is there a read active ?
 	PROERR <START-READ message received when READ is active>
	MOVE T4,INPFPT		;Get pointer to flags storage
	GET1BY T1,T2,T3		;Get first flag byte
	IDPB T3,T4		;Save first flag byte
	GET1BY T1,T2,T3		;Get second flag byte
	IDPB T3,T4		;Save it
	GET1BY T1,T2,T3		;Get third flag byte
	IDPB T3,T4		;Save it
	GET2BY T1,T2,T3		;Get MAX-LENGTH
	MOVEM T3,INPLEN		;Save it
	GET2BY T1,T2,T3		;Get END-OF-DATA
	MOVEM T3,INPEOD		;Save it
	GET2BY T1,T2,T3		;Get TIMEOUT
	MOVEM T3,INPTIM		;Save it.
	GET2BY T1,T2,T3		;Get END-OF-PROMPT
	MOVEM T3,INPEOP		;Save it.
	GET2BY T1,T2,T3		;Get START-OF-DISPLAY
	MOVEM T3,INPSOD		;Save it.
	GET2BY T1,T2,T3		;Get LOW-WATER.
	MOVEM T3,INPLOW		;Save it.
	CALL CTMTMG		;(T1,T2/T1,T2) Get TERMINATOR-SET.
	MOVEM T1,INPBPT		;Save pointer to data.
	MOVEM T2,INPBCT		;Save count of data.
	SETOM RDACTV		;Say there's a read active.
	CALL INPSTR		;Inform input process.
	RET
;Here to interpret the TERMINATOR-SET of a received START-READ message
;CALL CTMTMG with
;	T1/ byte pointer
;	T2/ byte count
;Uses T1-T4
;Returns +1 always with T1 and T2 updated
CTMTMG:	SAVEAC <Q1,Q2>
	OPSTR <SKIPN Q1,>,RDTRM,+INPFLG ;Using previous read's terminators ?
	IFSKP.
  	  SETZM INPTBM		;No. Clear out the terminator set
	  MOVE T3,[XWD INPTBM,INPTBM+1] 
	  BLT T3,INPTBM+INPTML-1
	ENDIF.
	GET1BY T1,T2,T3		;Get length of terminator set in message
	CAIE Q1,1		;Using terminator set in message ?
	IFSKP.
	  JUMPE T3,RTN		;Yes. If no set, done.
	  MOVE Q2,[POINT 8,INPTBM] ;Point to input process's terminator set.
  	  DO.					     
	    GET1BY T1,T2,T4	;Yes. Get a byte.
	    MOVE T4,SWPBYT(T4)	;Swap the bits around
	    IDPB T4,Q2     	;Save it
 	    SOJG T3,TOP.  	;Continue.
	  ENDDO.
	ELSE.
	  CAMGE T2,T3		;Not using terminator set. Message parse error ?
	  PROERR <Parse error in terminator set, no bytes left> ;Yes.
	  SUB T2,T3		;No. Update count
	  ADJBP T3,T1		;Update 
	  MOVE T1,T3		; pointer
	  CAIE Q1,2		;Using universal terminator set ?
	  IFSKP.
	    MOVE T4,INPUNV	;Yes. Get it (in first word only)
	    MOVEM T4,INPTBM	; and set it.
	  ENDIF.
	ENDIF.
	RET
	SUBTTL CTERM LAYER -- MESSAGE RECEIVED -- WRITE 
;Here when a WRITE message was received
;CALL CTMWRI with
;	T1/ byte pointer
;	T2/ byte count
;Returns +1 always
CTMWRI:	MOVE T4,WRFPTR
	GET1BY T1,T2,T3		;Get flags (1)
	IDPB T3,T4		;Save
	GET1BY T1,T2,T3		;Get flags (2)
	IDPB T3,T4		;Save         
	GET1BY T1,T2,T3		;Get prefix
	IDPB T3,T4		;Save         
	GET1BY T1,T2,T3		;Get postfix
	IDPB T3,T4		;Save         
	MOVEM T2,OUPBCT		;Save count of data
	MOVEM T1,OUPBPT		;Save pointer to data
	LOAD T1,WRDSC,+WRFLAG	;Get discard state flag
	MOVEM T1,OUPOUT		;Stash it
	LOAD T1,WRBOM,+WRFLAG	;Get BOM flag
	MOVEM T1,OUPBOM		;Stash it
	LOAD T1,WREOM,+WRFLAG	;Get EOM flag
	MOVEM T1,OUPEOM		;Stash it
	SKIPN OUPBOM		;Beginning of message ?
	IFSKP.
	  LOAD T1,WRLOK,+WRFLAG ;Yes. Set up the rest of the flags. The lock
	  MOVEM T1,OUPLOK	; definition
	  LOAD T1,WRPFX,+WRFLAG ;The 
	  MOVEM T1,OUPPFX	; prefix code
	  LOAD T1,WRPFC,+WRFLAG ;The
	  MOVEM T1,OUPPFC	; prefix character/count
	  LOAD T1,WRPSX,+WRFLAG ;The 
	  MOVEM T1,OUPPSX	; postfix code
	  LOAD T1,WRPSC,+WRFLAG ;The 
	  MOVEM T1,OUPPSC	; postfix character/count
	  LOAD T1,WRTRN,+WRFLAG ;The 
	  MOVEM T1,OUPTRN	; transparent flag,
	  LOAD T1,WRCMP,+WRFLAG ;The 
	  MOVEM T1,OUPCMP	; completion requested flag
	  LOAD T1,WRNWL,+WRFLAG ;The 
	  MOVEM T1,OUPNWL	; newline flag
	ENDIF.
	CALL OUPENT		;Give to output process
	RET
	SUBTTL CTERM LAYER -- MESSAGE RECEIVED -- READ CHARACTERISTICS 
;Here when a READ-CHARACTERISTICS message was received
;CALL CTMRDC with
;	T1/ byte pointer
;	T2/ byte count
;Returns +1 always
;Note: unknown characteristics are ignored.
CTMRDC:	TRVAR <INPTR,INCNT,OUTPTR,OUTCNT> ;Used by all subroutines.
	MOVEM T1,INPTR		;Initialize pointer to incoming message
	MOVEM T2,INCNT		;Initialize count to incoming message
	MOVEI T1,CHACSZ		;Size of CTERM header
	MOVEM T1,OUTCNT		;Initialize outgoing message count
	HRROI T1,-1		;Get ILDB pointer
	ADJBP T1,CHASL1		; to first field
	MOVEM T1,OUTPTR		;Initialize outgoing message pointer
	GET1BY INPTR,INCNT,T1	;Go past flag byte
	DO.
	  GET1BY INPTR,INCNT,T1	;Get characteristic identifier
	  GET1BY INPTR,INCNT,T2	;Get identifier type
	  CAILE T2,ACCESL	;Is identifier type legal ?
	  IFSKP.
	    SKIPE T1		;Yes. Is
	    CAMLE T1,ACCLEG(T2)	; characteristic identifier legit ?
	    IFSKP.
	      IDPB T1,OUTPTR	;Yes. Put char id into outgoing message 
	      AOS OUTCNT	;Update count
	      IDPB T2,OUTPTR	;Put ident type into outgoing message 
	      AOS OUTCNT	;Update count
	      CALL @ACCESR(T2)	;(T1,T2) Handle VALUE field; update the TRVARs
	    ENDIF.
	  ENDIF.
	  SKIPLE INCNT		;Any more ?
	  LOOP.			;Yes.
	ENDDO.
	MOVE T2,OUTCNT		;Get count of CTERM message
	PUT2BY T2,CHASZZ	;Stick into message
	MOVE T1,CHAPTR		;Point to message
	MOVE T2,OUTCNT		;Add in size of
	ADDI T2,CHAHDR		; foundation header/
	CALL MSGPUT		;(T1,T2) Send out message
	RET

;Here when an illegal READ-CHARACTERISTICS message was received
;CALL CHRILL with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRILL:	PROERR <Illegal READ-CHARACTERISTICS message was received>
	SETZM INCNT
	RET

;Here when a READ-CHARACTERISTICS message was received, for which the 
;characteristic is boolean and always false
;CALL CHRFLS with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
;VALUE field set in CHARACTERISTICS message
CHRFLS:	SETZ T1,		;VALUE field is false
	IPT1BY T1,OUTPTR,OUTCNT	;Put into message
	RET

;Here when a READ-CHARACTERISTICS message was received, for which the 
;characteristic is boolean and always true
;CALL CHRTRU with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRTRU:	MOVEI T1,1		;VALUE field is true
	IPT1BY T1,OUTPTR,OUTCNT	;Put into message
	RET
;Here when a READ-CHARACTERISTICS message was received, for which the 
;characteristic is integer and always zero
;CALL CHRZRO with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRZRO:	SETZ T1,		;VALUE field is zero
	IPT2BY T1,OUTPTR,OUTCNT ;Put into message
	RET

;Here when a READ-CHARACTERISTICS message was received, for which the 
;characteristic is integer and always one
;CALL CHRONE with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRONE:	MOVEI T1,1		;VALUE field is one
	IPT2BY T1,OUTPTR,OUTCNT	;Put into message
	RET

;Here when a READ-CHARACTERISTICS message was received, for the character size
;CALL CHRSIZ with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRSIZ:	MOVEI T1,7		;VALUE field is seven
	IPT2BY T1,OUTPTR,OUTCNT	;Put into message
	RET

;Here when a READ-CHARACTERISTICS message was received for input speed
;CALL CHRINP with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRINP:	MOVEI T1,.PRIIN		;Get speed
	MOVEI T2,.MORSP
	MTOPR%
	HLRZ T1,T3		;Isolate input speed
	CAIN T1,777777		;Speed "indeterminate"?
	MOVEI T1,^D9600		;Set to 9600; keeps VMS happy.
	IPT2BY T1,OUTPTR,OUTCNT	;Put into message
	RET
;Here when a READ-CHARACTERISTICS message was received for output speed
;CALL CHROUP with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHROUP:	MOVEI T1,.PRIIN		;Get speed
	MOVEI T2,.MORSP
	MTOPR%
	HRRZS T3		;Isolate output speed
	CAIN T3,777777		;Speed "indeterminate"?
	MOVEI T3,^D9600		;Set to 9600; keeps VMS happy.
	IPT2BY T3,OUTPTR,OUTCNT	;Put into message
	RET

;Here when a READ-CHARACTERISTICS message was received for switch character 1
;CALL CHRSW1 with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRSW1:	MOVEI T1,.PRIIN		;Get switch sequence
	MOVEI T2,.MORTC
	MTOPR%
	MOVEI T1,1		;Get length of string
	IPT1BY T1,OUTPTR,OUTCNT	;Put into message
	LDB T1,[POINT 7,T3,28]	;Get first character
	IPT1BY T1,OUTPTR,OUTCNT	;Put into message
	RET

;Here when a READ-CHARACTERISTICS message was received for switch character 2
;CALL CHRSW2 with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRSW2:	MOVEI T1,.PRIIN		;Get switch sequence
	MOVEI T2,.MORTC
	MTOPR%
	MOVEI T1,1		;Get length of string
	IPT1BY T1,OUTPTR,OUTCNT	;Put into message
	IPT1BY T3,OUTPTR,OUTCNT	;Put character into message
	RET
;Here when a READ-CHARACTERISTICS message was received for terminal type
;CALL CHRTYP with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRTYP:	MOVE T2,TRMTYP		;Get terminal name
	HLRZ T1,TRMSTB(T2)	; length
	IPT1BY T1,OUTPTR,OUTCNT ;Put into message
	HRRO T2,TRMSTB(T2)	;Get pointer to terminal name
	MOVN T3,T1     		;Get negative length of name 
	ADDM T1,OUTCNT		;Update message count
	MOVE T1,OUTPTR		;Point to message
	SOUT%			;Move string.
	MOVEM T1,OUTPTR 	;Update message pointer
	RET

;Here when a READ-CHARACTERISTICS message was received for output flow control
;CALL CHROFC with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHROFC:	MOVEI T1,.PRIIN		;Get JFN mode word
	RFMOD%
	LOAD T1,TT%PGM,+T2	;Get output flow control field
	IPT1BY T1,OUTPTR,OUTCNT	;Put into message
	RET

;Here when a READ-CHARACTERISTICS message was received for output page stop
;CALL CHROPS with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHROPS:	MOVEI T1,.PRIIN		;Get output page stop
	MOVEI T2,.MORXO
	MTOPR%
	IPT1BY T3,OUTPTR,OUTCNT	;Put into message
	RET

;Here when a READ-CHARACTERISTICS message was received for page width
;CALL CHRWID with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRWID:	MOVE T1,LINWID		;Get page width
	IPT2BY T1,OUTPTR,OUTCNT	;Put into message
	RET
;Here when a READ-CHARACTERISTICS message was received for page length
;CALL CHRPGL with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRPGL:	MOVEI T1,.PRIIN		;Get page length
	MOVEI T2,.MORLL
	MTOPR%
	IPT2BY T3,OUTPTR,OUTCNT ;Put into message
	RET

;Here when a READ-CHARACTERISTICS message was received for wrap
;CALL CHRWRP with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRWRP:	MOVE T1,LINWRP		;Get the characteristic
	IPT2BY T1,OUTPTR,OUTCNT	;Put into message
 	RET

;Here when a READ-CHARACTERISTICS message was received for ignore input
;CALL CHRIGN with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRIGN:	MOVE T1,INPIGN		;Get the characteristic
	IPT1BY T1,OUTPTR,OUTCNT	;Put into message
	RET

;Here when a READ-CHARACTERISTICS message was received for character attributes
;CALL CHRCHR with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRCHR:	GET1BY INPTR,INCNT,T3		;Get the character
      	IPT1BY T3,OUTPTR,OUTCNT	;Put character into message
	SETZ T2,		;Mask is always zero - also use for char'istics
	IPT1BY T2,OUTPTR,OUTCNT	;Put mask into message. 
	CAIL T3,^D32		;Is character a control character ?
	IFSKP.
	  MOVE T2,OOBCHA(T3)	;Yes. Get characteristics,
	ELSE.
	  CAIN T2,.CHDEL	;No. Is it DELETE ?
	  MOVE T2,DELCHA    	;Yes. Get characteristics.
	ENDIF.
	IPT1BY T2,OUTPTR,OUTCNT	;Put characteristics into message
	RET
;Here when a READ-CHARACTERISTICS message was received for raise input
;CALL CHRRAI with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRRAI:	MOVEI T1,.PRIIN		;Get the characteristic
	RFMOD%
	LOAD T1,TT%LIC,+T2	
	IPT1BY T1,OUTPTR,OUTCNT	;Put into message
	RET

;Here when a READ-CHARACTERISTICS message was received for echo
;CALL CHRECH with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRECH:	MOVEI T1,.PRIIN		;Get the characteristic
	RFMOD%
	LOAD T1,TT%ECO,+T2	
	IPT1BY T1,OUTPTR,OUTCNT	;Put into message
	RET

;Here when a READ-CHARACTERISTICS message was received for input esc seq recog
;CALL CHRIES with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRIES:	MOVE T1,CHRIEX		;Get the characteristic
	IPT1BY T1,OUTPTR,OUTCNT	;Put into message
	MOVEI T1,.CHESC		;Set up echo for escape
	SKIPN CHRIEX		;Is escape recognition on ?
	IFSKP.
	  MOVEI T2,EC.NON	;Yes. Turn echo off.
	ELSE.
	  LOAD T2,OBECH,+OOBCHA(T1) ;No. Get echo characteristic.
	ENDIF.
	CALL PREECH		;(T1,T2). Set echo.
	RET

;Here when a READ-CHARACTERISTICS message was received for output esc seq recog
;CALL CHROES with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHROES:	MOVE T1,CHROEX		;Get the characteristic
	IPT1BY T1,OUTPTR,OUTCNT	;Put into message
	RET

;Here when a READ-CHARACTERISTICS message was received for input count state
;CALL CHRICS with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRICS:	MOVE T1,CHRICT		;Get the characteristic
	IPT2BY T1,OUTPTR,OUTCNT	;Put into message
	RET
;Here when a READ-CHARACTERISTICS message was received for auto prompt
;CALL CHRAP with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRAP:	MOVE T1,CHRATP		;Get the characteristic
	IPT1BY T1,OUTPTR,OUTCNT	;Put into message
	RET

;Here when a READ-CHARACTERISTICS message was received for terminal attributes
;CALL CHRVID with
;	INPTR, INCNT, OUTPTR, OUTCNT set up
;Returns +1 always with INPTR, INCNT, OUTCNT, OUTPTR updated and
;value inserted at OUTPTR
CHRVID:	LOAD T1,TMVID,+TRMCHA	;Get video flag
	LSH T1,1		;Put into position
	IORI T1,1		;Set "known" flag.
	IPT2BY T1,OUTPTR,OUTCNT	;Put into message
	RET

	ENDTV.			;End TRVAR in CTMRDC
	SUBTTL CTERM LAYER -- MESSAGE RECEIVED -- CHARACTERISTICS 
;Here when a CHARACTERISTICS message was received
;CALL CTMCHA with
;	T1/ byte pointer
;	T2/ byte count
;Returns +1 always
;Note: unknown characteristics cause rest of message to be ignored.
CTMCHA: TRVAR <PTR,CNT>      	;Used by all subroutines.
	MOVEM T1,PTR		;Initialize pointer to incoming message
	MOVEM T2,CNT		;Initialize count to incoming message
	GET1BY PTR,CNT,T1	;Go past flag byte
	DO.
	  GET1BY PTR,CNT,T1	;Get characteristic identifier
	  GET1BY PTR,CNT,T2	;Get identifier type
	  CAILE T2,ACCESL	;Is identifier type legal ?
	  RET			;No. Give up.
	  SKIPE T1		;Yes. Is
	  CAML T1,ACCLEG(T2)	; characteristic identifier legit ?
	  RET			;No. Give up.
	  CALL @ACCESW(T2)	;(T1,T2) Uses and update the above TRVARs
	  SKIPLE CNT		;Any more ?
	  LOOP.			;Yes.
	ENDDO.
	RET			;Done.
;Here to eat up a non writeable boolean (1 byte) characteristic
;CALL CHWBOL
;	PTR, CNT set up
;Returns +1 always with PTR and CNT updated.
CHWBOL:	GET1BY PTR,CNT,T1
	RET

;Here to eat up a non writeable integer characteristic
;CALL CHWINT
;	PTR, CNT set up
;Returns +1 always with PTR and CNT updated.
CHWINT:	GET2BY PTR,CNT,T1
	RET

;Here to set up terminal type
;CALL CHWSTG
;	PTR, CNT set up
;Returns +1 always with PTR and CNT updated.
CHWSTG:	STKVAR <<STRNG,2>>
	GET1BY PTR,CNT,T1	;Get count byte
	CAIL T1,^D9 		;Check size
	PROERR <Terminal type too large>
	MOVEI T2,STRNG
	HRLI T2,(POINT 7,0)
	DO.			;Suck up the string.
	  SOJL T1,ENDLP.
	  GET1BY PTR,CNT,T3
	  IDPB T3,T2
	  LOOP.
	ENDDO.
	SETZ T3,
	IDPB T3,T2		;Null terminate string
	MOVEI T2,STRNG		;Point to string.
	HRLI T2,(POINT 7,0)
	MOVEI T1,TTYTBL		;Point to terminal type table
	TBLUK%			;(T1,T2/T1,T2)
	TXNN T2,TL%EXM		;Got a match ?
	IFSKP.
	  HRRZ T2,(T1)		;Yes. Get type.
	  MOVEI T1,.PRIIN	
	  STTYP%		;(T1,T2) Set the type
	ENDIF.
	RET

;Here to set the input speed characteristic
;CALL CHWINP with
;	PTR, CNT set up
;Returns +1 always with PTR and CNT updated.
CHWINP:	GET2BY PTR,CNT,T4	;Get desired speed
	MOVEI T1,.PRIIN		;Get current speed
	MOVEI T2,.MORSP
	MTOPR%			;(T1,T2/T3)
	HRL T3,T4		;Set input speed
	MOVEI T2,.MOSPD		
	MTOPR%			;(T1,T2,T3)
	RET

;Here to set the output speed characteristics
;CALL CHWOUP with
;	PTR, CNT set up
;Returns +1 always with PTR and CNT updated.
CHWOUP:	GET2BY PTR,CNT,T4	;Get desired speed
	MOVEI T1,.PRIIN		;Get current speed
	MOVEI T2,.MORSP
	MTOPR%			;(T1,T2/T3)
	HRR T3,T4		;Set input speed
	MOVEI T2,.MOSPD		
	MTOPR%			;(T1,T2,T3)
	RET

;Here to set switch character 1
;CALL CHWSW1 with
;	PTR, CNT set up
;Returns +1 always with PTR and CNT updated.
CHWSW1:	GET1BY PTR,CNT,T4	;Get length of string (1)
	GET1BY PTR,CNT,T4	;Get character
	MOVEI T1,.PRIIN		;Get current switch sequence
	MOVEI T2,.MORTC
	MTOPR%			;(T1,T2/T3)
	DPB T4,[POINT 7,T3,28]  ;Set first character
	MOVEI T2,.MOTCE		
	MTOPR%			;(T1,T2,T3)
	RET

;Here to set switch character 2
;CALL CHWSW2 with
;	PTR, CNT set up
;Returns +1 always with PTR and CNT updated.
CHWSW2:	GET1BY PTR,CNT,T4	;Get length of string (1)
	GET1BY PTR,CNT,T4	;Get desired character
	MOVEI T1,.PRIIN		;Get current switch sequence
	MOVEI T2,.MORTC
	MTOPR%			;(T1,T2/T3)
	DPB T4,[POINT 7,T3,35]  ;Set second character
	MOVEI T2,.MOTCE		
	MTOPR%			;(T1,T2,T3)
	RET
;Here to set output flow control
;CALL CHWOFC with
;	PTR, CNT set up
;Returns +1 always with PTR and CNT updated.
CHWOFC:	GET1BY PTR,CNT,T4	;Get setting
	MOVEI T1,.PRIIN		;Get current JFN mode word
	RFMOD%			;(T1/T2)
	STOR T4,TT%PGM,+T2	;Change it
	STPAR%			;(T1,T2)
	RET

;Here to set output page stop 
;CALL CHWOPS with
;	PTR, CNT set up
;Returns +1 always with PTR and CNT updated.
CHWOPS:	GET1BY PTR,CNT,T3	;Get setting
	MOVEI T1,.PRIIN		;Set it
	MOVEI T2,.MOXOF
	MTOPR%			;(T1,T2,T3)
	RET

;Here to set page width
;CALL CHWWID with
;	PTR, CNT set up
;Returns +1 always with PTR and CNT updated.
CHWWID:	GET2BY PTR,CNT,T3	;Get width
	MOVEM T3,LINWID		;Set our copy of characteristic
	MOVE T4,LINWRP		;Get wrap characteristic
	CAIE T4,1		;Is it 
	CAIN T4,2		; no wrap ?
	RET			;Yes. Done.
	MOVEI T1,.PRIIN		;It is wrap. So set it.
	MOVEI T2,.MOSLW		
	MTOPR%			;(T1,T2,T3)
	RET

;Here to set page length
;CALL CHWPGL with
;	PTR, CNT set up
;Returns +1 always with PTR and CNT updated.
CHWPGL:	GET2BY PTR,CNT,T3	;Get width
	MOVEI T1,.PRIIN
	MOVEI T2,.MOSLL		
	MTOPR%			;(T1,T2,T3) Set it.
	RET

;Here to set ignore input
;CALL CHWIGN with
;	PTR, CNT set up
;Returns +1 always with PTR and CNT updated.
CHWIGN:	GET1BY PTR,CNT,T3	;Get setting
	MOVEM T3,INPIGN		;Save it 
	RET			;Done.

;Here to set the input count state
;CALL CHWICS with
;	PTR, CNT set up
;Returns +1 always with PTR and CNT updated.
CHWICS:	GET2BY PTR,CNT,T3	;Get setting
	MOVEM T3,CHRICT		;Set it.
	RET			;Done.
;Here to set line wrap
;CALL CHWWRP with
;	PTR, CNT set up
;Returns +1 always with PTR and CNT updated.
CHWWRP:	GET2BY PTR,CNT,T4	;Get setting
	MOVEM T4,LINWRP		;Set wrap characteristic.
	SETZ T3,		;Assume nowrap (set line width to zero)
	CAIE T4,1		;Is it 
	CAIN T4,2		; wrap ?
	IFSKP.
	  MOVE T3,LINWID	;Yes. Get width.
	ENDIF.
	MOVEI T1,.PRIIN		;Set monitor's line width
	MOVEI T2,.MOSLW	
	MTOPR%			;(T1,T2,T3)
	RET
;Here to set a character's attributes
;CALL CHWCHR with
;	PTR, CNT set up
;Returns +1 always with PTR and CNT updated.
CHWCHR:	GET1BY PTR,CNT,T1	;Get character.
	CAIL T1,^D32		;Is it a control character ?
	IFSKP.
	  MOVE T4,OOBCHA(T1)	;Yes. Get current characteristic.
	ELSE.
	  CAIN T3,.CHDEL	;No. Is it DELETE ?
	  MOVE T4,DELCHA     	;Yes. Get current characteristic.
	ENDIF.
	GET1BY PTR,CNT,T3	;Get change mask.
	GET1BY PTR,CNT,T2	;Get new characteristic.
	AND T2,T3		;Mask out unchanged fields in new
	ANDCA T3,T4		;Mask out changed fields in old
	IOR T2,T3		;Combine for new setting.
	CALL PRECHR		;(T1,T2) Set characteristic.
	RET
;Here to set raise input
;CALL CHWRAI with
;	PTR, CNT set up
;Returns +1 always with PTR and CNT updated.
CHWRAI:	GET1BY PTR,CNT,T3	;Get setting
	MOVEI T1,.PRIIN		;Get current JFN mode word setting
	RFMOD%			;(T1/T2)
	STOR T3,TT%LIC,+T2	;Change
	STPAR%			;(T1,T2) it
	RET			;Done.

;Here to set normal echo
;CALL CHWECH with
;	PTR, CNT set up
;Returns +1 always with PTR and CNT updated.
CHWECH:	GET1BY PTR,CNT,T3	;Get setting
	MOVEI T1,.PRIIN		;Get current JFN mode word setting
	RFMOD%			;(T1/T2)
	STOR T3,TT%ECO,+T2	;Change
	STPAR%			;(T1,T2) it
	RET			;Done.

;Here to set input escape sequence recognitin
;CALL CHWIES with
;	T1/ byte pointer into CHARACTERISTICS message
;	T2/ byte count 
CHWIES:	GET1BY PTR,CNT,T3	;Get setting
	MOVEM T3,CHRIEX		;Set it.
	RET			;Done.

;Here to set output escape sequence recognition
;CALL CHWOES with
;	T1/ byte pointer into CHARACTERISTICS message
;	T2/ byte count 
CHWOES:	GET1BY PTR,CNT,T3	;Get setting
	MOVEM T3,CHROEX		;Set it.
	RET			;Done.

;Here to set auto prompt
;CALL CHWAP with
;	T1/ byte pointer into CHARACTERISTICS message
;	T2/ byte count 
CHWAP: 	GET1BY PTR,CNT,T3	;Get setting
	MOVEM T3,CHRATP		;Set it.
	RET			;Done.
	SUBTTL CTERM LAYER -- MESSAGE RECEIVED -- CHECK INPUT 
;Here when a CHECK-INPUT message was received
;CALL CTMCKI with no arguments
;Returns +1 always, sending the INPUT-COUNT message to the host
CTMCKI:	MOVEI T1,.PRIIN		;Get typeahead buffer count
	SIBE%			;(T1/T2)
	 TRNA
	SETZ T2,
	SKIPN RDACTV		;Is there a read active ?
	IFSKP.
	  ADD T2,INPLEN		;Yes. Add in input buffer count
	  SUB T2,INPBLK+.RDDBC
	ENDIF.
	MOVE T3,T2		;Save count
	PUT2BY T2,CNTP		;Put count in the message
	SKIPN T3		;Are there any characters waiting?
	IFSKP.
	  RFMOD%
	  TXZE T2,TT%ECO	;Yes. Force echo off - was it on ?
 	  SETOM INPECH		;Yes. Must restore it after the read completes.
	  SFMOD%
	  EXCH T2,T3		;Save JFN mode word for use later
	  BIN%			;Get the first character &
	  MOVEM T2,INPCHR	;store it away for use in the READ TEXTI%
	  EXCH T3,T2		;Restore JFN mode word
	  SKIPE INPECH		;Is ECHO to be restored ?
	  TXO T2,TT%ECO		;Yes.
	  SFMOD%			;Restore mode.
	ENDIF.
	DPB T3,CNTPC		;put the character in the message.
	MOVE T1,CNTPTR		;Get pointer to message
	MOVEI T2,CNTSIZ		;Get size of message
	CALL MSGPUT		;(T1,T2) Send it out
	RET			;Done.
 	SUBTTL PREINPUT PROCESS -- OUT OF BAND CHARACTER INTERRUPT ROUTINES
;Here when an out of band character is typed in.
OOB0:	MOVEI OOBAC1,^D0
	JRST PREOOB
OOB1:	MOVEI OOBAC1,^D1
	JRST PREOOB
OOB2:	MOVEI OOBAC1,^D2
	JRST PREOOB
OOB3:	MOVEI OOBAC1,^D3
	JRST PREOOB
OOB4:	MOVEI OOBAC1,^D4
	JRST PREOOB
OOB5:	MOVEI OOBAC1,^D5
	JRST PREOOB
OOB6:	MOVEI OOBAC1,^D6
	JRST PREOOB
OOB7:	MOVEI OOBAC1,^D7
	JRST PREOOB
OOB8:	MOVEI OOBAC1,^D8
	JRST PREOOB
OOB9:	MOVEI OOBAC1,^D9
	JRST PREOOB
OOB10:	MOVEI OOBAC1,^D10
	JRST PREOOB
OOB11:	MOVEI OOBAC1,^D11
	JRST PREOOB
OOB12:	MOVEI OOBAC1,^D12
     	JRST PREOOB
OOB13:	MOVEI OOBAC1,^D13
	JRST PREOOB
OOB14:	MOVEI OOBAC1,^D14
	JRST PREOOB
OOB15:	MOVEI OOBAC1,^D15
	JRST PREOOB
OOB16:	MOVEI OOBAC1,^D16
	JRST PREOOB
OOB17:	MOVEI OOBAC1,^D17
  	JRST PREOOB
OOB18:	MOVEI OOBAC1,^D18
	JRST PREOOB
OOB19:	MOVEI OOBAC1,^D19
	JRST PREOOB
OOB20:	MOVEI OOBAC1,^D20
	JRST PREOOB
OOB21:	MOVEI OOBAC1,^D21
	JRST PREOOB
OOB22:	MOVEI OOBAC1,^D22
	JRST PREOOB 
OOB23:	MOVEI OOBAC1,^D23
	JRST PREOOB
OOB24:	MOVEI OOBAC1,^D24
	JRST PREOOB
OOB25:	MOVEI OOBAC1,^D25
	JRST PREOOB
OOB26:	MOVEI OOBAC1,^D26
	JRST PREOOB
OOB27:	MOVEI OOBAC1,^D27
	JRST PREOOB
OOB28:	MOVEI OOBAC1,^D28
	JRST PREOOB
OOB29:	MOVEI OOBAC1,^D29
	JRST PREOOB
OOB30:	MOVEI OOBAC1,^D30
	JRST PREOOB
OOB31:	MOVEI OOBAC1,^D31
	JRST PREOOB
OOBDEL:	MOVEI OOBAC1,.CHDEL
	JRST PREOOB
	SUBTTL PREINPUT PROCESS -- OUT OF BAND INTERRUPT PROCESSING
;Common routine to handle out of band character interrupt
;JRST PREOOB with
;	OOBAC1/ character
;DEBRK%s always
PREOOB:	CALL PREOB0		;Do work.
	DEBRK%			;Done.

PREOB0:	SAVET			;Save temporary registers
	MOVEI T1,.FHSLF		;Turn off
        DIR%			; interrupts
	CALL PREOB1		;Do work
	MOVEI T1,.FHSLF		;Turn on 
	EIR%			; interrupt
	RET


PREOB1:	BUGMSG (BG.OOB,<Out of band interrupt - >,<OOBMSG(OOBAC1)>,[^D10])
	HRRZ T1,LEV2PC		;Get interrupted PC
	CAIE T1,INPORX		;Is it the TEXTI% ?
	CAIN T1,INPBIX		; or the PBIN% ?
	IFNSK.
  	  MOVEI T1,INPREC	;Yes. Restart 
	  MOVEM T1,LEV2PC	; it.
	ENDIF.
	MOVE T4,OOBCHA(OOBAC1)	;Get its characterisitics
	CAIN OOBAC1,.CHDEL	;But wait, is it DELETE ?
	MOVE T4,DELCHA		;Yes. Get its characteristics
	MOVE T1,OOBAC1		;Get character.
	LOAD T2,OBECH,+T4       ;Get the echo characteristic
	CALL @PRESEC(T2)	;(T1) Simulate echo, if needed.
	OPSTR <SKIPN >,OBSPC,+OOBCHA(OOBAC1) ;Is this a special ?
	IFSKP.
	  CAIN OOBAC1,.CHCNX	;Yes. Control-X ?
	  JRST PRECTX		;Yes. Go do it.
	  CAIN OOBAC1,.CHCNO	;No. Control-O ?
	  JRST PRECTO		;Yes. Go do it.
	ENDIF.
	LOAD T1,OBOOB,+T4 	;Get the out of band type
	CAIE T1,OB.CLR		;Is it clear or
	CAIN T1,OB.DEF		; deferred clear out of band ?
	IFNSK.
	  MOVEI T1,.PRIIN	;Yes. Clear the 
	  CFIBF%		; typeahead buffer
	  CALL OUPULK		;Unlock output if needed.
	ENDIF.
	TXNN T4,OBDSC  		;Is it a discard out of band ?
	IFSKP.
	  CALL OUPSTP		;Yes. Set the output state to "discard".
	  MOVEI T4,1		; set "discard" in the out of band message.
	ELSE.
	  SETZ T4,		;Clear "discard" in the out of band message.
	ENDIF.
	DPB OOBAC1,OOBP  	;Set the character in the out of band message
	DPB T4,OOBP1  		;Set the flags in the out of band message
	MOVE T1,OOBPTR		;Send 
	MOVEI T2,OOBSIZ		; the 
	CALL MSGPUT		;(T1,T2) out of band message 
	LOAD T1,OBOOB,+OOBCHA(OOBAC1) ;Get the out of band type
	CAIE T1,OB.CLR		;Is it clear or
	CAIN T1,OB.DEF		; deferred clear out of band ?
	IFNSK.
	  SKIPN RDACTV		;Yes. Is there a read active ?
	  RET			;No. Done.
	  MOVEI T1,.TMOOB	;Yes. Terminate the read with out of band
	  SETZ T2,		;Size of terminator.
	  CALL INPEND		;(T1,T2)
	ENDIF.
	RET			;Done.
	SUBTTL PREINPUT PROCESS -- OUT OF BAND INTERRUPT PROCESSING -- SIMULATE ECHO
;Routines to simulate echo of out of band
;CALL @PRESEC(T2) with
;T1/ character
;Returns +1 always
PRESEC:	IFIW ! RTN  		;If no echo then done.
	IFIW ! PRESE1		;Straight echo.
	IFIW ! PRESE2		;Standard form
	IFIW ! PRESE3		;Simulate format action

;Echo the character
;CALL PRESE1
;Uses no ACs
;Returns +1 always
PRESE1:	$PBOUT (T1)
	RET

;Echo in standard form
;CALL PRESE2
;Uses T1,T2 only
;Returns +1 always
PRESE2:	CAIE T1,.CHCRT		;Carriage return or
	CAIN T1,.CHLFD		; line feed ?
	IFSKP.
	  CAIE T1,.CHESC	;No. Escape ?
	  IFSKP.
	    MOVEI T1,"$"   	;Yes.
	  ELSE.
	    MOVE T2,T1		;No. Save character
	    MOVEI T1,"^"        ;Put out
	    $PBOUT (T1)		; marker
	    MOVE T1,T2		;Restore character
	    XORI T1,100		;Convert to visible
	  ENDIF.
	  $PBOUT (T1)		;Put it out
	ELSE.
	  $PSOUT (CRLFPT,<[2]>) ;Put out CRLF 
	ENDIF.
	RET

;Simulate format action
;CALL PRESE3 
;Uses T1,T2,T3
;Returns +1 always
PRESE3:	MOVE T3,T1		;Save character
	CALL PRESE2		;(T1) Echo in standard form
	$PBOUT (T3)		;Echo as self.
	RET
	SUBTTL PREINPUT PROCESS -- CONTROL-O AND CONTROL-X
;Here when a control-O was typed in, and control-O is enabled for 
;its special function (discard output)
;Preserves all ACs and DEBRK%s
PRECTO:	BUGMSG (BG.OOB,<Control-O>,[0],[0])
	CALL OUPTOG		;Toggle the output discard state.
	RET

;Here when a control-X was typed in, and control-X is enabled for
;its special function (clear typeahead and input buffers
;Preserves all ACs and DEBRK%s
PRECTX:	BUGMSG (BG.OOB,<Control-X>,[0],[0])
	MOVEI T1,.PRIIN		;Clear typeahead 
	CFIBF%			; buffer
	SKIPN RDACTV		;Read active ?
	RET			;No. Done.
	MOVX T2,.CHCNU		;Yes. Convert to control-U
	STI%			;(T1,T2) and send to terminal.
 	RET
	SUBTTL PREINPUT PROCESS -- SET CHARACTER ATTRIBUTES
;Set up a character's characteristics
;CALL PRECHR with
;	T1/ character
;	T2/ new characteristics
;Returns +1 always.
;Uses T1-T4
PRECHR:	SAVEAC <Q1,Q2,Q3>
	JUMPL T1,RTN		;Negatives not allowed.
	CAIE T1,.CHDEL		;Delete is allowed 
	CAIG T1,^D31		; and so are control characters
	TRNA
	RET			;Not allowed.
	MOVE Q1,T1		;Put character in a safe place
	MOVE Q3,T2		;Put new characteristics in a known place
	CAIE Q1,.CHDEL		;Is this character DELETE ?
	IFSKP.
	  MOVE Q2,DELCHA	;Yes. Get its old characteristics
	  MOVEM Q3,DELCHA	;Set its new characteristics
	ELSE.
	  MOVE Q2,OOBCHA(Q1)	;No. Get the old characteristics
	  MOVEM Q3,OOBCHA(Q1)	;Set the new characteristics
	ENDIF.
	LOAD T2,OBOOB,+Q3	;Get the new out of band definition
	OPSTR <SKIPN>,OBSPC,+Q3 ;Is the special flag set ?
	IFSKP.
	  CAIE Q1,.CHCNO	;Yes. Is this character control-O
	  CAIN Q1,.CHCNX	; or control-X ?
	  IFNSK.
	    MOVEI T2,OB.CLR	;Yes. Force clear out of band.
	  ENDIF.
	ENDIF.
	CALL PRESOB		;(T1,T2) Make the change.
	MOVE T1,Q1		;Get character
	LOAD T2,OBECH,+Q3	;Get the new echo definition
	CALL PREECH     	;(T1,T2) Make the change.
	MOVE T1,Q1		;Get character.
	LOAD T2,OBSPC,+Q3	;Get new special definition.
	CALL PRESPC		;(T1,T2) Make the change.
	RET
	SUBTTL PREINPUT PROCESS -- SET CHARACTER ATTRIBUTES -- PSI CHARACTER
;Set the characteristics that involve the PSI system - out of band and 
; "special" flag for control-O and control-X.
;CALL PRESOB with
;	T1/ character
;	T2/ PSI characteristic - OB.xxx
;Returns +1 always
PRESOB:	SAVEAC <Q1>
	CAILE T1,.CHESC		;Legal out of band character ?
	CAIN T1,.CHDEL
	TRNA
	RET			;No. Leave now.
	HLRZ T3,OOBTAB(T1)	;Get PSI channel this character has (0 if none)
	CAIN T1,.CHDEL		;Is the character DELETE ?
	HLRZ T3,DELTAB		;Yes. Get PSI channel this character has (0 if none)
	IFG. T2			;Need a PSI channel ?
	  SKIPN T3		;Yes. Have one ?
	  CALL PREPSA		;(T1) No. Get one and hook it up to character.
	  CAIE T2,OB.DEF	;Is this a deferred interrupt ?
	  IFSKP.
	    SETO Q1,		;Yes. Flag it.
	  ELSE.
	    SETZ Q1,		;No. Flag it.
	  ENDIF.
	  MOVE T4,T1		;Put character in a safe place.
 	  MOVE T4,BITS(T4)	;Get terminal interrupt mask for this character.
	  CAIN T1,.CHDEL	;Is the character DELETE ?
	  MOVX T4,1B<.TICRB>	;Yes. Get its terminal interrupt mask
	  MOVX T1,<ST%DIM+.FHSLF> ;Must set up deferred terminal interrupt word
	  RTIW%			;First get them.
	  IFN. Q1		;Deferred interrupt ?
	    IORM T4,T3		;Yes. Set bit in deferred word.
	  ELSE.
	    ANDCAM T4,T3	;No. Clear bit in deferred word.
	  ENDIF.
	  STIW%			;Set the interrupt words.
	ELSE.
	  SKIPE T3		;Don't need a PSI channel. Have one ?
	  CALL PREPSD		;(T1,T3) Yes. Clear out PSI channel.
	ENDIF.
	RET
	SUBTTL PREINPUT PROCESS -- SET CHARACTER ATTRIBUTES -- SET UP PSI
;Set up a PSI channel for an out of band character
;CALL PREPSA with
;	T1/ character
;Returns +1 always 
;Preserves all registers
PREPSA:	SAVEAC <T1,T2,T3>
	SKIPE T2,PSIPTR		;No. Need a channel. Any channels left ?
	IFSKP.
	  TMSG <
== SERVER: out of band resource failure ==
>
	  RET			;No. Just go away
	ENDIF.
	HRRZ T3,(T2)		;Yes. Get address of next entry
	MOVEM T3,PSIPTR		; and update free pointer.
	HLRZ T2,(T2)		;Get channel.
	CAIE T1,.CHDEL		;Is character DELETE ?
	IFSKP.
	  HRLM T2,DELTAB    	;Remember channel number
	  HRRZ T3,DELTAB    	;Get routine address
	ELSE.
	  HRLM T2,OOBTAB(T1)	;Remember channel number
	  HRRZ T3,OOBTAB(T1)	;Get routine address
	ENDIF.
	HRLI T3,OOBLEV		;Get PSI level.
	MOVEM T3,CHNTAB(T2)	;Put entry in the channel table
	CAIN T1,.CHDEL		;Is the character DELETE ?
	MOVEI T1,.TICRB		;Yes. Get its terminal code. 
	MOVE T4,T1		;Save it
	MOVE T3,T2		;Save channel number
	MOVEI T1,-5		;Get job wide terminal interrupt word
	RTIW%
	IOR T2,BITS(T4)		;Add in this one.
	STIW%			;Set it.
	HRLZ T1,T4		;Set up for ATI% - terminal code in LH.
	HRR T1,T3		;PSI channel number in RH
	ATI%			;Associate terminal code and PSI channel.
	MOVEI T1,.FHSLF		;Activate 
	MOVE T2,BITS(T3)	; the
	AIC%			; channel.
	CAME T4,ESCCHR		;Is this the first character of the switch seq ?
	RET			;No. Done.
	TMSG < 
== WARNING FROM SERVER: MUST TYPE ">
	MOVE T1,T4
	CALL PRESE2
	TMSG <" TWICE TO MAKE IT WORK ==>
	RET
	SUBTTL PREINPUT PROCESS -- SET CHARACTER ATTRIBUTES -- CLEAR OUT PSI
;Clear out PSI channel for a newly disabled out of band
;CALL PREPSD with
;	T1/ character
;	T3/ PSI channel
;Returns +1 always
PREPSD:	SETZM CHNTAB(T3)	;Clear out this channel table entry
	MOVE T2,PSIPTR		;Update 
	HRRM T2,PSITAB(T3)	; the
	MOVEI T2,PSITAB(T3)	; free
	MOVEM T2,PSIPTR		; list
	SETZ T2,
	CAIE T1,.CHDEL		;Is the character DELETE ?
	IFSKP.
	  HRLM T2,DELTAB	;Yes. Forget it here.
	  MOVEI T1,.TICRB	; and get its terminal code. 
	ELSE.
	  HRLM T2,OOBTAB(T1)	;No. Forget it here.
	ENDIF.
	DTI%			;Disassociate terminal code and PSI channel.
	MOVE T4,T1		;Save terminal code
	MOVEI T1,-5		;Get job wide terminal interrupt word.
	RTIW%
	MOVE T4,BITS(T4)	;Clear 
	ANDCAM T4,T2		; out this
	STIW%	 		; code. (If I'm not using it. nobody can)
	MOVEI T1,.FHSLF		;Deactivate 
	MOVE T2,BITS(T3)	; the 
	DIC%			; channel.
	RET			;Done.
	SUBTTL PREINPUT PROCESS -- SET CHARACTER ATTRIBUTES -- SET ECHO
;Set up echo characteristics
;CALL PREECH with
;	T1/ character
;	T2/ CTERM echo code 
;Returns +1 always
PREECH:	SAVEAC <Q1,Q2>
	CAIN T1,.CHDEL		;DELETE ?
	RET			;Yes. Nothing to do.
	MOVE Q1,T1		;No. Save character
	CALL @PREECT(T2)	;(T1/T2) Convert CTERM code to CCOC code.
	MOVE Q2,T2		;Save the code
	MOVEI T1,.PRIIN		;Get current CCOC words.
	RFCOC%
	MOVE T4,[POINT 2,T2]	;Byte pointer to CCOC words
	ADJBP Q1,T4		;Number of bytes to adjust by = character.
	IDPB Q2,Q1		;Set that field
	SFCOC%			;Set the CCOC words
	RET			;Done.

;Dispatch on CTERM echo codes
;T2/ character
;Returns +1 always with T2/ code
PREECT:	IFIW ! RTN
  	IFIW ! PRECD1 
	IFIW ! PRECD2 
	IFIW ! PRECD3 

PRECD1:	MOVEI T2,2
	RET

PRECD3: MOVEI T2,3
	RET

;CR, LF, ESC translate to 3. All others translate to 1.
PRECD2:	MOVEI T2,3		;Assume CR or LF.
	CAIE T1,.CHCRT		;Is it CR
	CAIN T1,.CHLFD		; or LF ?
	IFSKP.
	  CAIE T1,.CHESC	;No. Is it ESC ?
	  MOVEI T2,1		;No. Code is 1
	ENDIF.
	RET
	SUBTTL PREINPUT PROCESS -- SET CHARACTER ATTRIBUTES -- SPECIAL FLAG
;Process the "special" flag for the editing characters.
;CALL PRESPC with
;	T1/ character
;	T2/ new value of special flag
PRESPC:	CAIE T1,.CHDEL		;Is character DELETE ?
        IFSKP.
          MOVEI T3,.CHDEL-3*32 	;Yes. Bit position.
          MOVEI T4,3		;Word offset
        ELSE.
	  CAIE T1,.CHCNR	;Check the character. Control-R or
	  CAIN T1,.CHCNU	; control-U ?
	  IFSKP.
  	    CAIE T1,.CHCNV	;No. Control-V or
	    CAIN T1,.CHCNW	; control-W ?
	    TRNA		;Yes.
	    RET			;No. Go away.
	  ENDIF.
          SETZ T4,		;Word offset
          MOVE T3,T1		;Bit position
        ENDIF.
        MOVE T3,BITS(T3)	;Mask.
	IFN. T2			;Enable special character ?
          IORM T3,INPEBM(T4)	;Yes. Update editing break mask
          ANDCAM T3,INPUBM(T4) 	;Update unediting break mask			  
	ELSE.
          ANDCAM T3,INPEBM(T4) 	;No. Update editing break mask
          IORM T3,INPUBM(T4)	;Update unediting break mask			  
	ENDIF.
	RET
	
	SUBTTL OUTPUT PROCESS -- WRITE MESSAGE -- ENTRY
;Here to process a WRITE message received from the host.
;CALL OUPENT with WRITE message parsed
; Returns +1 always
OUPENT:	SKIPN TRMFLG		;Is this the termination echo write msg?
	IFSKP.			;Ayup.
	  SETZM TRMFLG		;Clear it and dont process this message
	  RET			;since we have already echoed the terminator.
	ENDIF.
	SKIPN OUPOUT		;"output discard" field set ?
	IFSKP.
	  MOVEI T1,1		;Yes.
	  MOVEM T1,OUPDS1	;Set requested state to do not discard
	  MOVEM T1,OUPDS2	;Set real state to do not discard
	ENDIF.
	SKIPN OUPTRN		;transparent output ?
	IFSKP.
	  MOVEI T1,.PRIOU	;Yes. Get mode word
	  RFMOD%
	  MOVEI T3,.TTBIN	;Set data mode to binary.
	  STOR T3,TT%DAM,+T2
	  SFMOD%
	  STPAR%
	ENDIF.
	SKIPE OUPBOM		;Beginning segment ?
	CALL OUPBEG		;Yes. Handle it.
	SKIPN OUPDS2		;Discarding output ?
	IFSKP.
	  $PSOUT (OUPBPT,OUPBCT) ;No. Send bytes to terminal
	ENDIF.
	SKIPE OUPEOM		;End of message ?
	CALL OUPEND		;Yes. Handle postfix, newline, and completion status.
	SKIPN OUPTRN		;transparent output ?
	IFSKP.
	  MOVEI T1,.PRIOU	;Yes. Get mode word.
	  RFMOD%
	  MOVEI T3,.TTATE	;Set data mode back to "translate echo".
	  STOR T3,TT%DAM,+T2
	  SFMOD%
	  STPAR%
	ENDIF.
	SKIPN OUPEOM		;End of message ?
	RET			;No. Done.
	MOVE T1,OUPLOK		;Get locking parameter.
	CALL OUPDOL		;(T1) Handle it.
	RET
	SUBTTL OUTPUT PROCESS -- WRTE MESSAGE -- HANDLE LOCK 
;here to handle lock parameter at end message 
;CALL OUPDOL with
;	T1/ lock parameter
;Returns +1 always
OUPDOL:	CAIG T1,1		;If it was "unlock" or "lock" there is
	RET			; nothing to do.
	CALL OUPULK		;Unlock output
	MOVE T1,OUPLOK		;Get back locking parameter.
	CAIN T1,3		;Was it "redisplay on completion" ?
	SKIPN RDACTV		;Yes. AND is there a read active ?
	RET 			;No to either. Done.
	CALL INPDPL		;Yes to both. Display input buffer.
	RET			;Done.
	SUBTTL OUTPUT PROCESS -- WRITE MESSAGE -- BEGINNING SEGMENT
;Handle beginning segment of a WRITE
;CALL OUPBEG 
;returns +1 always
OUPBEG: SKIPG T4,OUPLOK		;Lock field significant ?
	IFSKP.
	  SETOM OUPLCK		;Yes. Set the lock.
;	  MOVEI T1,.FHSLF
;	  MOVX T2,1B<TTCHAN> 	;Deactivate terminal input interrupts
;	  DIC%
	ENDIF.
	MOVE T1,OUPPFX		;Get prefix code
	MOVE T2,OUPPFC		;Get prefix count
	SKIPN OUPSKP		;Skip-next-line-feed set ?
	SKIPE FREELF		;No. Free LF set ?
	IFNSK.
	  IFN. T1		;Yes to one. Is there a prefix ?
	    CAIN T1,1		;Yes. Is it line feed(s) ?
	    SOS T2		;Yes. Take one away.
	    SETZM FREELF	;Clear the free LF.
	  ENDIF.
	ENDIF.
	SKIPE T1		;Any prefix ?
	CALL OUPFIX		;(T1,T2) Yes. Go do it.
	RET
	SUBTTL OUTPUT PROCESS -- WRITE MESSAGE -- ENDING SEGMENT
;Handle ending segment of WRITE message
;CALL OUPEND 
;Returns +1 always
;Note: No way of telling if any output was discarded due to control-O.
OUPEND:	STKVAR <LFSKP>
	SETZM LFSKP		;Initialize LF skip flag
	SKIPN OUPTRN		;Transparent output ?
	SETZM OUPSKP		;No. Reset skip next line feed flag
	MOVE T2,OUPPSC		;Get postfix character/count
	SKIPE T1,OUPPSX		;Get postfix code
 	CALL OUPFIX		;(T1,T2) Go do it, if code nonzero.
	SKIPN OUPNWL		;Newline flag set ?
	IFSKP.
	  MOVE T1,OUPBCT	;Yes. Get size of data.
	  IFE. T1		;No data ?
	    SKIPN FREELF	;Yes. And was free LF already given ?
	    IFSKP.
	      SETOM LFSKP	;Yes. Don't put out the newline,
	      SETZM FREELF	; and that uses up the free LF,
	      SETZM OUPCR	; and the last character output was LF.
	    ENDIF.
	  ENDIF.		;END OF NO-DATA IF.
	  CAIE T1,1		;Single character write ?
	  IFSKP.
	    MOVE T1,OUPBPT
	    ILDB T1,T1    	;Yes. Get the character.
	    CAIN T1,.CHCRT	;Is it CR ?
	    SKIPN FREELF	;Yes. And was free LF already given ?
	    IFSKP.
	      SETOM LFSKP	;Yes to all. Don't put out the newline,
	      SETZM FREELF	; and that uses up the free LF,
	      SETZM OUPCR	; and the last character output was LF.
	    ENDIF.
	  ENDIF.		;END OF SINGLE CHARACTER IF
	  SKIPE LFSKP		;Is it OK to put out the newline ?
	  IFSKP.
	    $PBOUT ([.CHLFD])	;Yes. Do so.
	  ENDIF.
	  SETOM OUPSKP		;Set skip-next-line-feed flag
	ENDIF.			;END OF NEWLINE IF.
	MOVE T1,OUPBCT		;Get count of write
	MOVE T2,OUPBPT		;Initialize.
	ILDB T2,T2    		;Get first character, if any.
	SKIPN T1		;Are there characters ?
	IFSKP.
	  CAIN T1,1		;Yes. Single character write
	  CAIE T2,.CHCRT	; and the character is CR ?
	  IFNSK.
	    SKIPN OUPTRN	;No. Transparent output ?
	    SETZM FREELF	;No. Free LF has been used up.
	  ENDIF.
	ENDIF.
	SKIPN OUPCMP		;Completion status requested ?
	RET			;No. Done.
	MOVEI T1,.PRIOU		;Get horizontal and vertical positions
	RFPOS%
	HLRZ T3,T2		;Vertical
	HRRZS T2		;Horizontal
	PUT2BY T2,WRCHPS	;Put it in the message
	PUT2BY T3,WRCVPS	;Put it in the message
	MOVE T1,WRCPTR		;Send off 
	MOVEI T2,WRCSIZ		; the
	CALL MSGPUT		;(T1,T2) message
	RET
	ENDSV.			;End STKVAR
	SUBTTL OUTPUT PROCESS -- WRITE MESSAGE -- PREFIX AND POSTFIX
;Output post- or prefix.
;CALL OUPFIX with
;	T1/ code
;	T2/ character/count
;Returns +1 always
OUPFIX:	JUMPE T1,RTN		;If none, do nothing.
	SKIPN OUPDS2		;Discarding output ?
	RET			;Yes. Do nothing
	CAIE T1,1		;Newline repetitions ?
        IFSKP.
	  MOVE T4,T2		;Yes. Put out CRLFs
          DO.
            SOJL T4,ENDLP.	
            $PSOUT (CRLFPT,[2])
            LOOP.
          ENDDO.
        ELSE.
          $PBOUT(T2)           	;No, it's a character, put it out.
        ENDIF.
	RET
	SUBTTL OUTPUT PROCESS -- UTILITY ROUTINES
;Toggle the output discard state
;CALL OUPTOG with no arguments
;Returns +1 always
OUPTOG: MOVEI T1,1		;Toggle the 
	SUB T1,OUPDS1		; requested output 
	MOVEM T1,OUPDS1		; discard state
	IFE. T1			;Is it now "discard" ?
	  SETZM OUPDS2		;Yes. Make real output discard state "discard"
	  CALL OUPULK		; and unlock output if it was locked.
 	ENDIF.
	DPB T1,DSCP		;Set the discard state in the message
	MOVE T1,DSCPTR		;Send off
	MOVEI T2,DSCSIZ		; the 
	CALL MSGPUT		;(T1,T2) DISCARD-STATE message
	RET

;Set output discard state to do not discard
;CALL OUPSTP with no arguments
;Uses T1
OUPGO:	MOVEI T1,1
	MOVEM T1,OUPDS1
	MOVEM T1,OUPDS2
	RET

;Set output discard state to discard
;CALL OUPSTP with no arguments
;Preserves all registers
OUPSTP:	SETZM OUPDS1
	SETZM OUPDS2
	RET

;Unlock output, if needed
;CALL OUPULK with no arguments
;Returns +1 always
;Preserves all ACs
OUPULK:	SAVET
	SKIPN OUPLCK		;Is it locked ?
	RET			;No. Done.
	SETZM OUPLCK		;Yes. Unlock it.
	SKIPE RDACTV		;Is there a read active ?
	SKIPN OUPICT		;Yes. Is there queued input to be displayed ?
	IFSKP.			
	  $PSOUT (OUPIPT,OUPICT);Yes. Display it
	  SETZM OUPICT		;No more queued input.
	ENDIF.
	CALL INPPOK		;Poke input process
	RET			;Done.
;Display input process's prompt and initial data
;CALL OUPDSP with
; 	T1/ pointer
;	T2/ count
OUPDSP:	JUMPLE T2,RTN		;Eliminate trivialities
	MOVE CX,REMOS		;Get remote OS type
	CAIN CX,OS.T20		;Is it Tops-20?
	RET			;Yup, no need to print prompt
	SKIPN OUPLCK		;Output locked ?
	IFSKP. 
	  MOVE T3,T2		;Yes. Queue request - get count
	  MOVE T2,T1		;Get pointer
	  MOVE T1,OUPICT	;Point past what it already
	  ADJBP T1,OUPIPT	; queued
	  ADDM T3,OUPICT	;Update count.
	  MOVNS T3		;Get negative of count
	  SOUT%			;Move request.
	ELSE.
	  $PSOUT (T1,T2)	;No. Send data to terminal
	ENDIF.
	RET 
	SUBTTL INPUT PROCESS -- POKE
;Poke input process
;CALL INPPOK with no arguments
;Returns +1 always
INPPOK:	MOVEI T1,.FHSLF		;Poke 
	MOVE T2,BITS+TTCHAN	; input 
	IIC%			; process. 
	RET
	SUBTTL INPUT PROCESS -- INITIALIZATION
;Initialize the input process
;CALL INPINI with no arguments
;Returns +1 always
INPINI:	RET
	SUBTTL INPUT PROCESS -- START A READ
;START-READ message received
;CALL INPSTR with message parsed.
;Returns +1 always
INPSTR:	CALL OUPGO		;Set output discard state to "do not discard"
	SETZM INPSEE		;Input buffer is now empty.
	MOVX T1,TXTFLG		;Get "always on" flags for TEXTI% arg block
	MOVEM T1,INPBLK+.RDFLG	;Set them.
	MOVE T1,REDDPT		;Set up pointer to TEXTI%
	MOVEM T1,INPBLK+.RDBFP	; data storage area.
	CALL INPMVP		;Move prompt to TEXTI% prompt storage area
	MOVE T1,INPBLK+.RDBFP	;Point to TEXTI% data storage area
	MOVE T3,INPEOP		;Negative size of 
	SUB T3,INPEOD		; initial data
	SKIPE T3		;If there is initial data,
	SOUT%			;(T1,T2,T3) move it.
;	SKIPN T2,INPCHR		;Was a character read for input-count message?
;	IFSKP.			;Yes,
;	  DPB T2,T1		;put this character into the data storage area
;	  SETZM INPCHR		;and zero its old location.
;	ENDIF.
	MOVEM T1,INPBLK+.RDDBP	;Set up destination string pointer for TEXTI%
	MOVE T1,INPBLK+.RDBFP	;Point to TEXTI% data storage area
	MOVE T2,INPLOW		;LOW-WATER count
	SUB T2,INPEOP		;Make it relative to data area
	ADJBP T2,T1		;Convert to pointer
	MOVEM T2,INPBLK+.RDBKL  ;Set backup limit pointer for TEXTI%
	MOVE T2,INPLEN		;Compute count
	SUB T2,INPEOD		; of space 
	ADD T2,INPEOP		; left in buffer.
	MOVEM T2,INPBLK+.RDDBC	;Set space count for TEXTI%
	LOAD T1,RDTIM,+INPFLG	;Put timeout flag in 
       	MOVEM T1,INPTMO		; its own word.
	LOAD T1,RDUND,+INPFLG	;Get underflow flag
	CAIE T1,TM.TRM		;Is it terminate on underflow ?
	IFSKP.
	  SETONE RD%RND,+INPBLK+.RDFLG ;Yes. Make TEXTI% return on underflow.
	ELSE.
	  SETZRO RD%RND,+INPBLK+.RDFLG ;No. Make TEXTI% handle underflow.
	ENDIF.
	MOVEI T1,.PRIOU		;Get JFN mode
	RFMOD%			;(T1/T2) word. 
	CALL INPDOR		;(T1,T2/T1,T2) do the raise set up
	CALL INPDEC		;(T1,T2/T1,T2) do the echo/noecho set up
	SFMOD%			;(T1,T2) Set the 
	STPAR%			;(T1,T2) characteristics
	CALL INPSBM		;Set up TEXTI% break mask and related things
	CALL INPFMT		;Handle format flag and display prompt & 
				; initial data
	CALL INPPOK		;Poke input process
	MOVE T1,INPTIM		;Get timeout period
	SKIPE INPTMO		;Timeout enabled ?
	CALL TIMSET		;(T1) Yes. Set timer.
	CAIN INPSTA,.INESC	;Still parsing escape sequences ?
  	JRST @TSTATE(ESCSTA)	;Yes. Dispatch on state & terminate read.
	CALL INPISB		;No. Check for single character read
	IFSKP.
	  MOVEI INPSTA,.INBIN	;It is. Set the state
	ELSE.
	  MOVEI INPSTA,.INORD	;No. State is ordinary.
	  CALL TRMSTX		;Save terminal characteristics.
	ENDIF.
	RET			;Done.
	SUBTTL INPUT PROCESS -- START A READ -- MOVE PROMPT
;Move prompt to TEXTI% storage area, moving nulls to end.
;CALL IMPMVP 
;Returns +1 always
INPMVP:	SAVEAC <Q1>
	SETZ T4,		;Null counter
	MOVE T1,INPBLK+.RDRTY	;Point to TEXTI% prompt storage area
	MOVE T2,INPBPT		;Point to prompt in START-READ message
	SKIPG T3,INPEOP		;Size of prompt 
	IFSKP.
	  DO.			;Move bytes
	    ILDB Q1,T2		;Get byte
	    IFN. Q1		;Is it null ?
	      IDPB Q1,T1	;No. Put byte.
	    ELSE.
 	      AOS T4		;Yes. Increment counter
	    ENDIF.
	  SOJG T3,TOP.
	  ENDDO.
	ENDIF.
	SETZ Q1,		;Get a null.
	DO.			;Null terminate and move trailing nulls 
	  IDPB Q1,T1		;Put a null.
	  SOJGE T4,TOP.  	;Do some more.
	ENDDO.
	RET			;Done.
	SUBTTL INPUT PROCESS -- START A READ -- SET UP RAISE
;Set up raise characteristics
;CALL INPDOR with 
; 	T1/ JFN
;	T2/ Current mode word
;Returns +1 always with
; 	T1/ JFN
;	T2/ New mode word
INPDOR:	SETZM INPRAI		;Assume term no raise is already true.
	LOAD T3,RDRAI,+INPFLG 	;Get raise flag.
	CAIE T3,1		;No raise for this read only ?
	IFSKP.
	  TXZE T2,TT%LIC	;Yes. Force no raise. Was it raise ?
	  SETOM INPRAI		;Yes. Mark change.
	ENDIF.
	CAIE T3,2		;Raise for this read only ?
	IFSKP.
	  TXON T2,TT%LIC	;Yes. Force raise. Was it no raise ?
	  SETOM INPRAI		;Yes. Mark change.
	ENDIF.
	RET
	SUBTTL INPUT PROCESS -- START A READ -- SET UP ECHO
;Set up echo/noecho stuff and underflow
;CALL INPDEC 
; 	T1/ JFN
;	T2/ Current mode word
;Returns +1 always with
; 	T1/ JFN
;	T2/ New mode word
INPDEC:	STKVAR <JFN,MODWRD>
	SETZM INPECH		;Initialize.
	OPSTR <SKIPN>,RDNEC,+INPFLG ;No echo for this read only ?
	IFSKP.
	  TXZE T2,TT%ECO	;Yes. Force echo off - was it on ?
 	  SETOM INPECH		;Yes. Must restore it after the read completes.
	ENDIF.
	LOAD T3,RDUND,+INPFLG	;Get underflow flag
	CAIN T3,TM.TRM		;Is it not "terminate" ?
	IFSKP.
	  MOVEM T1,JFN		;Yes. Save JFN 
	  MOVEM T2,MODWRD	; and mode word
	  MOVX T2,EC.NON	;Yes. Assume it is "ignore".
	  CAIE T2,TM.IGN	;Is it ?
	  MOVX T2,EC.SLF	;No. It is "bell".
	  MOVX T1,.CHBEL	;The character.
	  CALL PREECH     	;(T1,T2) Make the change.
	  MOVE T1,JFN		;Restore JFN 
	  MOVE T2,MODWRD	; and mode word
	ENDIF.
	RET
	ENDSV.
	SUBTTL INPUT PROCESS -- START A READ -- SET UP BREAK MASK
;Set up TEXTI% break mask, quote flag, input esc rec flag, 
; and restore character interrupts flag
;CALL INPSBM
;Returns +1 always
INPSBM:	MOVE T1,[INPTBM,,INPXBM] ;Set up TEXTI% 
	BLT T1,INPXBM+3		; break mask - CTERM terminator set.
	MOVE T1,INPUBM		;Unediting break mask - break on 
	IORM T1,INPXBM		; editing characters that have lost
	MOVE T1,INPUBM+3	; their 
	IORM T1,INPXBM+3	; functions
	MOVE T1,INPEBM		;Editing break mask - don't break on 
	ANDCAM T1,INPXBM	; editing character that still have
	MOVE T1,INPEBM+3	; their 
	ANDCAM T1,INPXBM+3	; functions
	MOVX T1,<1B<.CHLFD>+1B<.CHCRT>+1B<.CHCNV>> ;Control-V and CR/LF
	IORM T1,INPXBM		; are always in the break mask.
	MOVX T3,1B<.CHESC>	;Assume ESCAPE should be on in the break mask.
	OPSTR <SKIPE T2,>,RDESS,+INPFLG	;INPUT-ESCAPE-SEQUENCE-RECOGNITION flag
	IFSKP.
	  SKIPN CHRIEX		;Not set. Is characteristic set ?
	  SETZ T3,           	;No.
	ELSE.
	  CAIE T2,2		;Does flag say yes ?
	  SETZ T3,           	;No.
	ENDIF.
	IORM T3,INPXBM		;Set break mask.
	MOVEM T3,INPESR		;Set recognition flag.

	LOAD T1,OBSPC,+OOBCHA+.CHCNV ;Set quote enabled flag.
	MOVEM T1,INPQOT

	SETZM INPCTL		;Initialize the "restore control char" flag
	OPSTR <SKIPN T1,>,RDDCD,+INPFLG ;Get disable control character field.
	RET			;There is none.

        MOVX T2,1B<.CHCNU>+1B<.CHCNR> ;Disable control-U and control-R
	IORM T2,INPXBM		; by setting the TEXTI% break mask
	SOJE T1,RTN		;Done ?
	MOVX T2,1B<.CHCNV>+1B<.CHCNW> ;No. Disable control-V and control-U
	IORM T2,INPXBM		; by setting the TEXTI% break mask
	MOVX T2,1B<.CHDEL-3*^D32> ; and disable DELETE
	IORM T2,INPXBM+3	; by setting the TEXTI% break mask
	SETZM INPQOT		;Clear quote enabled flag
	SOJE T1,RTN		;Done ?
	CALL PSINSC		;No. Must disable out of bands
	SETOM INPCTL		;Set the restore flag.
	SETZM INPESR		;Clear input escape recognition.
	RET
	SUBTTL INPUT PROCESS -- START A READ -- HANDLE FORMAT FLAG
;CALL INPFMT
;Returns +1 always
INPFMT:	STKVAR <PRMPTR,PRMCNT,DATPTR,DATCNT,LFFLAG>
	SETZM LFFLAG		;Initialize free LF flag (assume no free LF)
	MOVE T1,INPBLK+.RDRTY	;Initialize prompt 
	MOVEM T1,PRMPTR		; pointer
	MOVE T1,INPEOP		;Initialize prompt
	MOVEM T1,PRMCNT		; count
	MOVE T1,INPBLK+.RDBFP	;Initialize data
	MOVEM T1,DATPTR		; pointer
 	MOVE T1,INPEOD		;Initialize 
	SUB T1,INPEOP		; data
	MOVEM T1,DATCNT		; count
	MOVE T1,OUPCR  		;Get last character output
	OPSTR <SKIPE>,RDFMT,+INPFLG ;Format flag set ?
	CAIE T1,.CHCRT		;Yes. Was last character CR ?
	IFSKP.
	  SKIPG INPEOD  	;Yes. Is there prompt/initial data ?
	  IFSKP.
	    SKIPG INPEOP  	;Yes. Is there a prompt ?
	    IFSKP.
	      MOVE T2,PRMPTR    ;Yes. Point to prompt.
	      MOVEI T3,PRMPTR   ;Get address of the pointer
	      MOVEI T4,PRMCNT	;Get address of the count
	    ELSE.
	      MOVE T2,DATPTR    ;Yes. Point to prompt.
	      MOVEI T3,DATPTR   ;Get address of the pointer
	      MOVEI T4,DATCNT	;Get address of the count
	    ENDIF.
	    ILDB T1,T2          ;Get the first byte.
	    CAIE T1,.CHCRT	;Is it a carriage return ?
	    IFSKP.
	      ILDB T1,T2        ;Yes. Get the next byte
	      SOSLE (T4)	;Update count - assume next byte is LF.
	      CAIE T1,.CHLFD	;Is next byte LF ?
	      IFSKP.
	        MOVEM T2,(T3)	;Yes. Wipe out CR/LF from the display this time
		SOS (T4)
	      ELSE.
		AOS (T4)	;Wrong assumption. Restore count.
              ENDIF.
            ELSE.
              CAIE T1,.CHLFD	;No. Is first byte LF ?
	      IFSKP.
	        MOVEM T2,(T3)	;Yes. Wipe out LF from the display this time
	        SOS (T4)
	      ENDIF.
	    ENDIF.
	    SETOM LFFLAG	;No. Do free LF by hand.
	  ELSE.
	    OPSTR <SKIPN>,RDNEC,+INPFLG ;No prompt/initial data - echoing on ?
	    SETOM LFFLAG	;Yes. Do free LF by hand.
	  ENDIF.
	ENDIF.
;Here to output the "free" line feed
	SKIPN FREELF		;Did we already do a LF ?
	SKIPN LFFLAG		;No. Output the free LF by hand ?
	IFSKP.
	  MOVE T1,[POINT 8,[BYTE(8).CHLFD,0]] ;Yes. Do it.
	  MOVEI T2,1		;Count
	  CALL OUPDSP		;(T1,T2)
	  SETZM OUPCR		;Clear flag
	ENDIF.
	SETZM FREELF		;Clear the free LF flag.
 	MOVE T1,PRMPTR       	;Send prompt 
 	MOVE T2,PRMCNT		; data to the terminal.
 	CALL OUPDSP		;(T1,T2)
 	MOVE T1,DATPTR       	;Send initial
 	MOVE T2,DATCNT		; data to the terminal.
 	CALL OUPDSP		;(T1,T2)
	MOVEI T1,.PRIIN		;Initialize line position
	RFPOS%
	HRRZS T2
	SFPOS%
	RET
	ENDSV.			;End STKVAR
	SUBTTL INPUT PROCESS -- START A READ -- CHECK FOR SINGLE CHARACTER READ
;CALL INPISB 
;Returns +2 if a single character read
;Returns +1 otherwise
INPISB:	MOVE T1,INPBLK+.RDDBC	;Get max buffer size.
	CAILE T1,1		;Is it small enough ?
	IFSKP.
	  LOAD T1,RDDCD,+INPFLG	;Yes. Get flags
	  CAIL T1,2		;Editing character disabled ?
	  RETSKP		;Yes. It is a single character read
	ENDIF.
	DMOVE T1,INPTBM		;Get first two words of terminator set.
	CAMN T1,FULMSK		;All bits on 
	CAME T2,FULMSK		; on ?
	RET   			;No.
	DMOVE T1,INPTBM+2	;Get last two words of terminator set.
	CAMN T1,FULMSK		;All bits on 
	CAME T2,FULMSK		; on ?
	RET   			;No.
	RETSKP			;Yes. It is a single character read
	SUBTTL INPUT PROCESS -- SEND INPUT STATE MESSAGE
;Here when the buffer has newly become non empty
;CALL INPICT
;Returns +1 always
INPICT:	MOVE T1,CHRICT		;Get input count state characteristic
	CAIN T1,1		;Is it IGNORE ?
	RET			;Yes. Done.
	SKIPE RDACTV		;Is there a read active ?
	CAIE T1,2		;Yes. AND is it NO-READ-SEND ?
	TRNA 			;No to either
	RET			;Yes to both. Done.
	MOVE T1,INSPTR		;Point to message
	MOVEI T2,INSSIZ		;Size of message
	CALLRET MSGPUT		;(T1,T2) Send it off.
	SUBTTL INPUT PROCESS -- TERMINAL INPUT AVAILABLE
;Here on PSI for terminal input available 
;CALL INPENT
;Saves all ACs, DEBRK%s always
INPENT:	CALL INPEN0		;Do work.
	DEBRK%

INPEN0:	SAVET			;Save temporary registers
	MOVEI T1,.FHSLF		;Turn off
        DIR%			; interrupts
	CALL INPEN1		;Do work
	MOVEI T1,.FHSLF		;Turn on 
	EIR%			; interrupts
	RET

INPEN1:	SKIPN INPIGN		;Ignoring input ?
	IFSKP.
	  MOVEI T1,.PRIIN	;Yes. Clean out 
	  CFIBF%		; input bufffer
	  RET			;Done.
	ENDIF.
	SKIPE INPSEE		;Was buffer empty ?
	IFSKP.
	  MOVEI T1,.PRIIN	;Yes. 
	  SIBE%			;Is it nonempty now ?
	  IFNSK.
	    CALL INPICT		;Yes. Send INPUT-COUNT state message, maybe.
	    SETOM INPSEE	;Input buffer is now not empty.
	  ENDIF.
	ENDIF.
	SKIPN OUPLCK		;Is terminal unlocked against echoing ?
	SKIPN RDACTV		;Yes. Is there a read active ?
	RET   			;No or no. Done.
;Loop while read is active and input is available
       	DO.
	  CALL @INPDSP(INPSTA)	;No. Dispatch on input state. Read active ?
	  IFSKP.
	    MOVEI T1,.PRIIN	;Yes. Any more
	    SIBE%		; input ?
	    LOOP.      		;Yes. Go get it.
	  ENDIF.
	ENDDO. 
	RET			;Done.
	SUBTTL INPUT PROCESS -- TERMINAL INPUT AVAILABLE -- RESTART 
INPREC:	POP P,(P)		;Pop return address off stack
	CAIN INPSTA,.INORD	;If input state = ordinary, TEXTI% will restart
	CALL TRMRTX		; so restore original terminal characteristics.
	JRST INPEN1		;Start over
	SUBTTL INPUT PROCESS -- TERMINAL INPUT AVAILABLE -- ORDINARY
;Here when the input state is ordinary. 
;CALL INPORD with no arguments
;Returns +2 if read is still active.
;Returns +1 if read has been terminated.
;This routine is optimized because it is the critical path.
INPORD:	MOVEI T1,.FHSLF		;Turn on interrupts
	EIR%
	MOVEI T1,INPBLK		;Address of argument block
	TEXTI%			;Get available data
;Label is for out of band process detecting restart necessary
INPORX:	 ERJMP ERR
	MOVEI T1,.FHSLF		;Turn off interrupts
	DIR%
	MOVE T1,INPBLK+.RDFLG	;Get flags
	ANDX T1,<RD%BLR+RD%BTM+RD%BFE> ;Isolate returned flags.
	JUMPN T1,INPOFL		;If any set, handle them. 
INPOR1: SKIPG INPBLK+.RDDBC	;Input buffer full ?
	JRST [ MOVEI T1,.TMFUL	;Yes. Terminate read with input buffer full 
	       SETZ T2,		;size of terminator.
	       CALLRET INPEND]	;(T1,T2)
	SKIPN INPTMO		;Is this read timeout controlled ?
	RETSKP			;No. Done.
	MOVE T1,INPTIM		;Yes. Set
	CALL TIMSET		;(T1) timer.
	RETSKP			;Done.
	SUBTTL INPUT PROCESS -- TERMINAL INPUT AVAILABLE -- SINGLE CHARACTER READ
;CALL INPBIN with no arguments
;Returns +2 if read is still active.
;Returns +1 if read has been terminated.
;This routine is optimized because it is the critical path.
INPBIN:	MOVEI T1,.PRIIN		;Any characters available ?
	SIBE%
	TRNA
 	JRST INPOR1         	;No. Finish up.
	OPSTR <SKIPE>,RDTEC,+INPFLG ;Is terminator to be echoed ?
	IFSKP.
	  RFMOD%
	  TXZE T2,TT%ECO	;Yes. Force echo off - was it on ?
 	  SETOM INPECH		;Yes. Must restore it after the read completes.
	  SFMOD%
	ENDIF.
	MOVEI T1,.FHSLF		;Yes. Turn on interrupts
	EIR%
	PBIN%			;Get character
;Label is for out of band process detecting restart necessary
INPBIX:	MOVE T3,T1		;Save it.
	MOVEI T1,.FHSLF		;Turn off interrupts
	DIR%
	IDPB T3,INPBLK+.RDDBP	;Put character into buffer.
	SOS INPBLK+.RDDBC	;Account for it.
        IDIVI T3,^D32		;Get word offset and bit offset
        MOVE T4,BITS(T4)	;Change bit offset to mask
        TDNN T4,INPXBM(T3)	;Is this character in the TEXTI% break mask ?
        JRST INPOR1		;No. Must be buffer full.
        MOVX T1,RD%BTM		;Yes. Terminate the read just like
	JRST INPOFL		; INPORD does.
	SUBTTL INPUT PROCESS -- TERMINAL INPUT AVAILABLE -- READ RETURNED
;Here when flags returned from the TEXTI% (or INPBIN) are nonzero
;JRST INPOFL with T1/ flags 
;Returns +2 if read is still active.
;Returns +1 if read has been terminated.
INPOFL:	TXNN T1,RD%BTM		;Break character terminated read ?
	IFSKP.
	  SETZM FREELF		;Initialize the free LF given flag
	  LDB T3,INPBLK+.RDDBP	;Yes. Get last character
	  CAIE T3,.CHCRT	;Is character CR ?
	  IFSKP.
	    PBIN%		;No. Eat the LF.
	    OPSTR <SKIPN>,RDNEC,+INPFLG ;Is echo on ?
	    SETOM FREELF	;Yes. Free LF was output.
	  ENDIF.
	  CAIN T3,.CHESC	;Is it escape 
	  SKIPN INPESR		; AND is input escape sequence recognition on ?
	  IFSKP.		
	    CALLRET INPDES	;Yes to both, set up escape sequence recognition
	  ELSE.
	    CAIN T3,.CHCNV	;No. Is it the quote character ?
	    SKIPN INPQOT	; AND is quoting enabled for this read ?
	    IFSKP.
	      CALLRET INPDOQ	;Yes to both, set up for quoting.
	    ENDIF.
	  ENDIF.
	  CAIE T3,.CHCNQ	;Is it control-Q or
	  CAIN T3,.CHCNS	; control-S ?
	  IFNSK.
  	    HRROI T1,-1		;Yes. Ignore it.
	    ADJBP T1,INPBLK+.RDDBP
	    MOVEM T1,INPBLK+.RDDBP
	    AOS INPBLK+.RDDBC
	    JRST INPOR1		;Keep trying
	  ENDIF.
	  IDIVI T3,^D32		;Get word offset and bit offset
	  MOVE T4,BITS(T4)	;Change bit offset to mask
	  TDNE T4,INPTBM(T3)	;Is this character in the CTERM terminator set ?
	  JRST INPTRD		;Yes. Terminate the read with terminator char.
	  JRST INPOR1		;No. Keep trying
	ENDIF.
	TXNN T1,RD%BFE		;Underflow occurred ?
	IFSKP.
	  MOVE T1,INPFLG	;Get the START-READ flags
	  TXNN T1,RDCON		;Is it a continuation read also?
	  IFSKP.		;Yes. Must be handled by the host.
	    MOVEI T1,.PRIIN	;Backup and re-read the
	    BKJFN%		; editing character
	    MOVEI T1,.PRIIN	; to be sent to the
	    PBIN%		; host.
	    IDPB T1,INPBLK+.RDDBP;Deposit in the message buffer.
	    MOVEI T1,.TMTIM	;Termination reason is timeout(none other fits)
	    SOS INPBLK+.RDDBC	;Account for the character
	  ELSE.			;No continuation read.
	    MOVEI T1,.TMUND	;Terminate read with condition "underflow"
	  ENDIF.
	  SETZ T2,		;No terminator
	  CALLRET INPEND	;(T1,T2)
	ENDIF.
;Must be backup limit reached 
	MOVE T1,INPBLK+.RDDBP 	;Yes. Reset 
	HRROI T2,-1		; backup 
	ADJBP T2,T1		; limit 
	MOVEM T2,INPBLK+.RDBKL 	; pointer
	RETSKP
	SUBTTL INPUT PROCESS -- TERMINAL INPUT AVAILABLE -- TERMINATOR CHARACTER
;Here to terminate read with reason terminator character
;and to remember the last character sent to the terminal (OUPCR)
;CALL INPTRD with no arguments
;returns +1 always
INPTRD:	LDB T3,INPBLK+.RDDBP	;Get last input character 
	MOVEI T1,.PRIIN		;Get current mode.
	RFMOD%			
	TXNN T2,TT%ECO		;Was echo on ?
	IFSKP.
	  CAIE T3,.CHCRT	;Yes. Is the character CR ?
	  IFSKP.
	    LOAD T2,OBECH,+OOBCHA(T3) ;Yes. Get echo characteristic
	    CAIN T2,EC.STD	;Is it standard format ?
	    MOVEI T3,.CHLFD	;Yes. Last character sent to terminal was LF.
	  ENDIF.
	  MOVEM T3,OUPCR	;Save last character echoed.
	  CAIL T3,.CHSPC	;Was it a control character?
	  CAIN T3,.CHDEL	;or DEL?
	  IFSKP.		;No, the terminator might have been echoed.
	    OPSTR <SKIPE>,RDTEC,+INPFLG ;should terminator have been echoed?
	    IFSKP.		;No.
	      CAIN INPSTA,.INORD;Was the input mode normal (TEXTI% used)?
	      SETOM TRMFLG	;Yes. Set flag that we echoed the terminator
	    ENDIF.		;by "mistake" so that we can toss the echo
	  ENDIF.		;message sent by the host. (ugly but effective)
	ENDIF.
	MOVEI T1,.TMTRM		;Terminate read with terminator reason.
	MOVEI T2,1
	CALLRET INPEND		;(T1,T2)
	SUBTTL INPUT PROCESS -- TERMINAL INPUT AVAILABLE -- START QUOTE
;Here when quoting is starting.
;CALL INPDOQ
;Returns +2 if the read is still active.
;Returns +1 if the read was terminated
INPDOQ:	CALL PSINSC		;Turn off single character interrupts.
	MOVEI INPSTA,.INQUT	;Change state to "quote in progress"
	MOVE T1,INPBLK+.RDDBC	;Is there room in the ?
	SUBI T1,2		; buffer for the next char 
	JUMPGE T1,RSKP		;Yes. Read is still active.
	MOVEI T1,.TMABS		;No. Terminate read with absentee token.
	SETZ T2,		;No terminator.
	CALLRET INPEND		;(T1,T2)
	SUBTTL INPUT PROCESS -- TERMINAL INPUT AVAILABLE -- START ESCAPE SEQUENCE RECOGNITION
;Here when input escape recognition is starting.
;CALL INPDES
;Returns +2 always since the read is still active.
INPDES:	MOVEI T1,.PRIIN		;Get mode 
	RFMOD%			; word
	MOVEM T2,ESCMOD		;Save it.
	TXZ T2,TT%ECO		;Turn off 
	SFMOD%			; echoing
	STPAR%
	MOVEI INPSTA,.INESC	;Set state to "parsing escape sequence parsing"
	HRROI T1,-1		;Remove 
	ADJBP T1,INPBLK+.RDDBP 	; escape 
	MOVEM T1,INPBLK+.RDDBP	; from
	AOS INPBLK+.RDDBC	; buffer.
	SETZ ESCSTA,      	;Initialize the state 
	MOVEI T1,ESCMAX		;Initialize the 
	MOVEM T1,ESCCNT		; count
	MOVE T1,ESCBUF          ;Initialize the 
	MOVEM T1,ESCPTR		; pointer.
	MOVEI T1,.CHESC		;Put in the
	IDPB T1,ESCPTR		; ESCAPE
	SOS ESCCNT		;Account for it.
	RETSKP			;Done.
	SUBTTL INPUT PROCESS -- TERMINAL INPUT AVAILABLE -- QUOTE IN PROGRESS
;Here when the input state is quote in progress.
;CALL INPQUT with no arguments
;Returns +2 if read is still active
;Returns +1 if read was terminated
INPQUT:	MOVEI INPSTA,.INORD	;Put state back to ordinary.
	MOVEI T1,.CHCNV		;Get the quote character
	IDPB T1,INPBLK+.RDDBP	;Put it into the buffer
	SOS INPBLK+.RDDBC	;Account for it.
	PBIN%			;Get the next character
	IDPB T1,INPBLK+.RDDBP	;Put it into the buffer
	SOS INPBLK+.RDDBC	;Account for it. 
	CALL PSIRSC		;Restore single character interrupts.
	SKIPLE INPBLK+.RDDBC	;Is buffer full ?
	RETSKP			;No. Read is still active
	MOVEI T1,.TMFUL		;Yes. Terminate read with buffer full
	SETZ T2,		;No terminator
	CALLRET INPEND		;(T1,T2)
	SUBTTL INPUT PROCESS -- TERMINAL INPUT AVAILABLE -- ESCAPE SEQUENCE 
;Here when the input state is escape sequence parsing in progress.
;CALL INPESC with no arguments
;Returns +2 if read is still active
;Returns +1 if read was terminated
INPESC:	PBIN%			;Get byte
	IDPB T1,ESCPTR		;Save it
	SOSLE ESCCNT		;Account for it. Out of space ?
	JRST @TSTATE(ESCSTA)	;No. Invoke the state machine.
	CALLRET INVALD		;Yes. Terminate read - invalid escape sequence

;The intermediate state machine routines - just change the state
;Transition to state 1
STATE1:	MOVEI ESCSTA,1		;Set the state and
	RETSKP     		; continue

;Transition to state 2		
STATE2:	MOVEI ESCSTA,2		;Set the state and
	RETSKP     		; continue

;Transition to state 3		
STATE3:	MOVEI ESCSTA,3		;Set the state and
	RETSKP     		; continue

;Transition to state 4		
STATE4:	MOVEI ESCSTA,4		;Set the state and
	RETSKP     		; continue

;Transition to state 5		
STATE5:	MOVEI ESCSTA,5		;Set the state and
	RETSKP     		; continue
;Here on invalid escape sequence
;Clean up and terminate the read with absentee token or invalid escape sequence
INVALD:	MOVEI T1,.PRIIN		;Restore the 
	MOVE T2,ESCMOD		; state of
	SFMOD%			; the echo.
	STPAR%

;Common entry for terminating with invalid escape sequence
INVAL1:	SAVEAC <Q1>
	MOVEI T3,ESCMAX		;Compute how many characters 
	SUB T3,ESCCNT		; are in the escape buffer.
	MOVE Q1,INPBLK+.RDDBC	;Compute how much room will be
	SUB Q1,T3		; left in the input buffer.
	IFL. Q1			;Will it even fit ?
	  MOVE T3,INPBLK+.RDDBC	;No. Put in as many as will fit.
	  MOVE T4,Q1		;Get pointer to
	  ADJBP T4,ESCPTR	; leftovers
	  MOVEI T1,.PRIIN	;Put the leftovers back.
	  DO.
	    ILDB T2,T4		;Get byte
 	    STI%		;Put it back.
	    AOJL Q1,TOP. 	;If more, continue.
	  ENDDO.
	ENDIF.
	MOVEI T1,.TMIES		;Invalid escape sequence code.
	CALL ESCTRM		;(T1,T3) termination.
	MOVEI T1,.PRIIN		;Now put the leftovers back.
	DO.
	  AOJG Q1,RTN		;If done, leave.
	  ILDB T2,Q2		;Get byte
 	  STI%
	  LOOP.
	ENDDO.
;Here on valid escape sequence
VALID: 	MOVEI T1,.PRIIN		;Restore the 
	MOVE T2,ESCMOD		; state of
	SFMOD%			; the echo.
	STPAR%
 	MOVEI T3,ESCMAX		;Compute the 
	SUB T3,ESCCNT		; count.
	CAMG T3,INPBLK+.RDDBC	;Will it fit in input buffer ?
	IFSKP.
	  MOVE T3,INPBLK+.RDDBC	;No. Is the input 
	  CAML T3,INPLEN	; buffer empty ?
	  JRST INVAL1		;Yes. Terminate with invalid escape sequence.
	  MOVEI ESCSTA,6	;No. Set state to retry later and
	  MOVEI T1,.TMABS	;terminate with absentee token.
	  SETZ T2,		;no terminator
	  CALLRET INPEND	;(T1,T2)
	ENDIF.
	MOVEI T1,.TMVES		;Valid escape sequence
	CALLRET ESCTRM		;(T1,T3) termination
;Here to move characters from the escape buffer to the read message
;and terminate the read
;CALL ESCTRM with
;T1/ termination reason code
;T3/ count of character to move
;Returns +1 always
ESCTRM:	SAVEAC <Q1>
	MOVE Q1,T1    		;Save reason code
	MOVEI INPSTA,.INORD	;Put input state back to ordinary.
	MOVE T1,INPBLK+.RDDBP	;The destination
	MOVE T2,ESCBUF		;The source
	MOVE T4,T3		;Save count
	MOVNS T3               	;The negative of the count.
	ADDM T3,INPBLK+.RDDBC	;Update the count
	SOUT%
	MOVEM T1,INPBLK+.RDDBP	;Update the destination
	MOVE T2,T4		;Size of terminator
	MOVE T1,Q1    		;Restore reason code.
	CALLRET INPEND		;(T1,T2)
;Here when there is a valid escape sequence, and a brand new read was issued 
;for it
;CALL VALDON with no arguments
VALDON:	MOVEI T3,ESCMAX		;Get length of
	SUB T3,ESCCNT		; sequence
	CAMLE T3,INPBLK+.RDDBC	;Is it too big ?
	JRST INVAL1		;Yes. Terminate with invalid esc seq
	MOVEI T1,.TMVES		;No.
	CALLRET ESCTRM		;(T1,T3) Terminate with valid esc seq
	SUBTTL INPUT PROCESS -- CLEAR INPUT BUFFER
;CALL INPCIB with no arguments
;Returns +1 always
INPCIB:	SKIPN RDACTV		;Is there a read active ?
	RET			;No. Done.
	MOVE T1,INPBLK+.RDBFP	;Get start of buffer
	MOVEM T1,INPBLK+.RDDBP	;Make the destination the start. 
	MOVE T1,INPLEN		;Get size of buffer
	MOVEM T1,INPBLK+.RDDBC
	RET
	SUBTTL INPUT PROCESS -- TERMINATE A READ
;Construct the READ message from the input process data base.
;CALL INPEND with 
;	T1/ completion code
;	T2/ size of terminator in bytes.
; and terminator, if any, in the input buffer
;Returns +1 always
INPEND:	STKVAR <TRMSIZ>
	MOVEM T2,TRMSIZ		;Save size of terminator
	DPB T1,REDCPT		;Stash away the completion code.
	SETZ T2,		;Assume no more data
	MOVEI T1,.PRIIN		;Is there 
	SIBE%			; more data ?
	MOVEI T2,1		;Yes. 
	DPB T2,REDTPT		;Stash the more typeahead flag 
	MOVEM T2,INPSEE		; and remember for later.
	MOVE T1,INPBLK+.RDBKL	;Get low water pointer
	MOVE T2,INPBLK+.RDBFP	;Get starting pointer
	CALL CHDIFF		;(T1,T2/T1) Compute low water position
	SKIPGE T1		;Is it negative ?
	SETZ T1,		;Yes. Make it zero.
	PUT2BY T1,REDLPT	;Put into message
	MOVEI T1,.PRIIN		;Get horizontal and
	RFPOS%			; vertical positions
	DPB T2,REDHPT		;Put horizontal into message
	HLRZ T3,T2		;Get vertical
	DPB T3,REDVPT		;Put vertical into message
	MOVE T1,INPLEN		;Compute number of data bytes in message
	SUB T1,INPBLK+.RDDBC
	MOVE T2,T1		;Copy it
	SUB T1,TRMSIZ		;Compute terminator position
	PUT2BY T1,REDPPT	;Put into message
	ADDI T2,REDCSZ		;Add in size of rest of CTERM message
	MOVE T1,T2		;Copy it
	PUT2BY T1,REDSPT	;Put into message
	ADDI T2,REDHDR		;Add in size of foundation header
	MOVE T1,REDPTR		;Point to message
	CALL MSGPUT		;(T1,T2/T2) Send it off.
	CALL INPTTY		;Restore the state of the terminal
	SETZM RDACTV		;Read is no longer active.
	CALL TIMCLR		;Reset the timer
	RET			;Done.
	SUBTTL INPUT PROCESS -- TERMINATE A READ -- RESTORE TTY STATE

;Restore the state of the terminal - raise, echo, control-G echoing.
;CALL INPTTY with no arguments
;Returns +1 always
INPTTY:	MOVEI T1,.PRIIN		;Get mode word.
	RFMOD%			;(T1/T2)
	SKIPN INPRAI		;Was RAISE changed ?
	IFSKP.
	  TXZN T2,TT%LIC	;Yes. Assume it was RAISE - restore NO RAISE
	  TXO T2,TT%LIC		;No, it was NO RAISE - restore RAISE
	ENDIF.
	SKIPE INPECH		;Is ECHO to be restored ?
	TXO T2,TT%ECO		;Yes.
	SFMOD%			;Restore mode.
	STPAR%
	MOVX T1,.CHBEL		;Restore ^G 
	LOAD T2,OBECH,+OOBAC1+.CHBEL ; echo 
	CALL PREECH     	;(T1,T2) characteristic. 
	SKIPN INPCTL		;Do control characters need to be reenabled ?
	IFSKP.
	  CALL PSIRSC		;Restore single character interrupts
	  SETZM INPCTL		;Done.
	ENDIF.
	RET
	SUBTTL INPUT PROCESS -- DISPLAY INPUT BUFFER
;Display the input buffer
;CALL INPDPL with no arguments
INPDPL:	$PSOUT (<INPBLK+.RDRTY>,INPEOP) ;Prompt
	MOVE T2,INPLEN		;Data - compute
	SUB T2,INPBLK+.RDDBC	; count
	$PSOUT (<INPBLK+.RDBFP>,T2)
	RET			
	SUBTTL TIMER PROCESS -- THE TIMER
;This routine implements the timer for the timeout option on the START-READ
;as well as being the idle loop for this program
;CALL TIMINI with no arguments
;Never returns.
TIMINI:	SETOM T1		;Get 
	MOVE T2,[-1,,JOBNO]	; my
	MOVE T3,.JIJNO		; job
	GETJI%			; number
	 TRN
	MOVEI T1,.FHSLF
	DIR%			;No interrupts.
	CALL TIMNUL		;(/T1) Start off in state "off"
;Infinite loop
	DO.
	  MOVE T2,T1		;Save timeout period
	  MOVEI T1,.FHSLF	;Allow
       	  EIR%			; interrupts
	  MOVE T1,T2		;Get sleep time
       	  THIBR%		;Sleep
	   TRN
	  MOVEI T1,.FHSLF	;No interrupts
	  DIR%			; allowed
	  MOVE T1,TIMSTA	;Get the timer state
	  CALL @TIMDSP(T1)	;(/T1) Dispatch per state
	  LOOP.     		;Go back to sleep
	ENDDO.

;Dispatch routine - here when the state is "ticking" 
;CALL TIMTIK 
;Returns +1 always with T1/ sleep time
TIMTIK:	MOVEI T1,.TMTIM	;Yes. Terminate the read with timeout
	SETZ T2,		;No terminator
	CALL INPEND		;(T1,T2)
	MOVEI T1,.TMNUL		;Set the timer's state 
       	MOVEM T1,TIMSTA		; to off.
	HRRZI T1,777777		;Set up to sleep for a long time
        RET                     ;Done

;Dispatch routine - here when the state is "off" 
;CALL TIMNUL 
;Returns +1 always with T1/ sleep time
TIMNUL:	HRRZI T1,777777		;Set up to sleep for a long time
	RET			;Done

;Dispatch routine - here when the state is "set request"
;CALL TIMSTT 
;Returns +1 always with T1/ sleep time
TIMSTT:	MOVEI T1,.TMTIK		;Set the state 
	MOVEM T1,TIMSTA		; to ticking
	MOVE T1,TIMOUT		;Get the timeout interval
	RET			;Done
	SUBTTL TIMER PROCESS -- CLEARING AND SETTING THE TIMER
;This routine clears the timer 
;CALL TIMCLR with no arguments
;Returns +1 always
TIMCLR:	MOVEI T1,.TMNUL		;Set the state of the timer
	MOVEM T1,TIMSTA		;to "off"
       	RET          		;Done.

;This routine sets up the timer	for the timeout option on the START-READ
;CALL TIMSET with T1/ number of seconds timer is to be set for
;Returns +1 always
;Uses T1 only
TIMSET:	MOVEM T1,TIMOUT		;Set the timeout period
	MOVEI T1,.TMSTT		;Set the state of the timer "set request"
       	MOVEM T1,TIMSTA		;Set the state
       	MOVE T1,JOBNO		;Get my job number
	TWAKE%			;Wake the timer up to process the request
	 TRN
	RET			;Done
	SUBTTL UTILITY ROUTINES -- TURN OFF SINGLE CHARACTER INTERRUPTS
;CALL PSINSC with no arguments
;Returns +1 always
PSINSC:	MOVEI T1,-5             ;Get terminal 
	RTIW%			; interrupt word
	MOVEM T2,INPTIW		;Save it.
	TDZ T2,[777777,,777700] ;Clear all single character interrupts.
	STIW%			
	RET
	SUBTTL UTILITY ROUTINES -- TURN ON SINGLE CHARACTER INTERRUPTS
;CALL PSIRSC with no arguments
;Returns +1 always
PSIRSC:	MOVEI T1,-5             ;Get terminal 
	MOVE T2,INPTIW		;Get saved word.
	IORI T2,<1B<.TICTI>+1B<.TITCE>> ;Plus two character interrupts and data 
				; available.
	STIW%			;Restore it.
	RET
	SUBTTL UTILITY ROUTINES -- SET UP PSI SYSTEM
;Set up the PSI system 
;CALL PSIINI with 
;	NETJFN/ DECnet JFN.
;Returns +1 always
PSIINI:	MOVX T1,.FHSLF		;Set up the interrupt system
	MOVE T2,[LEVTAB,,CHNTAB]
	SIR%
	MOVX T2,1B<ESCCHN>+1B<DNCHAN>+1B<TTCHAN> ;Activate channels 
 	AIC%			; that are always on.
	MOVEI T1,-5            	;Allow only two character switch sequence & 
	MOVX T2,<1B<.TITCE>+1B<.TICTI>>	; input buffer nonempty interrupts.
	STIW%
 	MOVE T1,[XWD .TITCE,ESCCHN] ;Hook up switch sequence
 	ATI%
  	MOVE T1,[XWD .TICTI,TTCHAN] ;Hook up terminal input available  
  	ATI%			; 
 	MOVE T1,NETJFN		;Hook up DECnet channel -
 	MOVEI T2,.MOACN		; data available & disconnect interrupt.
 	MOVX T3,<FLD (DNCHAN,MO%DAV)>
 	MTOPR%			;Don't enable PSIs (EIR%) until later 
	RET
	SUBTTL UTILITY ROUTINES -- SAVE CTERM TERMINAL STATE
;Save the terminal state just before exiting (in case of reentry)
;CALL TRMSTP with no arguments
;Returns +1 always
TRMSTP:	MOVEI T1,.PRIIN		;Get the CCOC words
	RFCOC%
	DMOVEM T2,CTMCOC	;Save them
	MOVEI T1,.PRIIN
	RFMOD%			;Get the JFN mode word
	MOVEM T2,CTMRFM		;Save it.
	MOVX T2,.MORLW		;Get the terminal page width
	MTOPR%
	MOVEM T3,CTMWID		;Save it.
	MOVX T2,.MORLL		;Get the terminal page length
	MTOPR%
	MOVEM T3,CTMLEN		;Save it.
	MOVX T2,.MORXO		;Get the end of page mode
	MTOPR%
	MOVEM T3,CTMMOD		;Save it.
	MOVX T2,.MORTC		;Get two character switch sequence
	MTOPR%
	MOVEM T3,CTMSWI		;Save it.
	GTTYP%			;Get terminal type
	MOVEM T2,CTMTYP		;Save it.
	MOVX T1,RT%DIM+.FHSLF	;Get the terminal interrupt mask 
	RTIW%
	DMOVEM T2,CTMRTI	;Save it.
	MOVEI T1,-5		;Get the job wide terminal interrupt mask.
	RTIW%
	MOVEM T2,CTMRTJ		;Save it.
	RET			;Done.
	SUBTTL UTILITY ROUTINES -- SAVE ORIGINAL TERMINAL STATE
;Save the original terminal state.
;CALL TRMSAV with no arguments
;Returns +1 always
TRMSAV:	MOVEI T1,.PRIIN		;Get the CCOC words
	RFCOC%
	DMOVEM T2,OLDCOC	;Save them
	MOVEI T1,.PRIIN
	RFMOD%			;Get the JFN mode word
	MOVEM T2,OLDRFM		;Save it.
	MOVX T2,.MORLW		;Get the terminal page width
	MTOPR%
	MOVEM T3,OLDWID		;Save it.
	MOVX T2,.MORLL		;Get the terminal page length
	MTOPR%
	MOVEM T3,OLDLEN		;Save it.
	MOVX T2,.MORXO		;Get the end of page mode
	MTOPR%
	MOVEM T3,OLDMOD		;Save it.
	MOVX T2,.MORTC		;Get two character switch sequence
	MTOPR%
	MOVEM T3,OLDSWI		;Save it.
	GTTYP%			;Get terminal type
	MOVEM T2,OLDTYP		;Save it.
	MOVX T1,RT%DIM+.FHSLF	;Get the terminal interrupt mask 
	RTIW%
	DMOVEM T2,OLDRTI	;Save it.
	MOVEI T1,-5		;Get the job wide terminal interrupt mask.
	RTIW%
	MOVEM T2,OLDRTJ		;Save it.
	HRROI T1,[ASCIZ\TTY:\]  ;Get terminal type
	STDEV%			;(T1/T2)
	 ERJMP ERR
	MOVE T1,T2
	GTTYP%			;(T1/T2)
	 ERJMP ERR
	CAILE T2,TRMTBL		;In range ?
	SETZ T2,
	MOVEM T2,TRMTYP		;Save the TOPS20 terminal type.
	CAIL T2,0		;Range 
	CAIL T2,TRMTBL		; check
	RET			;Failed.
	MOVE T2,TRMTAB(T2)      ;Get the characteristics
	MOVEM T2,TRMCHA		;Save them.
	RET			;Done.
	SUBTTL UTILITY ROUTINES -- SAVE TERMINAL STATE FOR TEXTI RESTART
;Save the terminal state before a TEXTI% JSYS in case it is interrupted
;by an out-of-band interrupt.
;CALL TRMSTX with no arguments
;Returns +1 always
TRMSTX:	MOVEI T1,.PRIIN		;Get the CCOC words
	RFCOC%
	DMOVEM T2,TXTCOC	;Save them
	MOVEI T1,.PRIIN
	RFMOD%			;Get the JFN mode word
	MOVEM T2,TXTRFM		;Save it.
	MOVX T2,.MORFW		;Get the field width
	MTOPR%
	MOVEM T3,TXTFW		;Save it
	MOVEI T2,4		;Argument block length
	MOVEM T2,TXTMSK
	MOVEI T2,.MORBM		;Get the break mask
	MOVEI T3,TXTMSK		;Save it here.
	MTOPR%
	RET			;Done.
	SUBTTL UTILITY ROUTINES -- SET UP TERMINAL
;Set up the terminal for CTERM processing 
;CALL TRMINI with no arguments
;Returns +1 always
TRMINI:	MOVEI T1,.PRIIN		;Make all control characters
	MOVE T2,CCCODE		; give 
	MOVE T3,CCCODE		; their code.
	SFCOC%			;(T1,T2,T3)
	MOVEI T1,.PRIIN		;Get the mode word
	RFMOD%			;(T1/T1,T2)
;ALlow echo, form-feed, mech-tab, lower-case, pause on command, if they already exist.
	ANDX T2,<TT%ECO+TT%MFF+TT%TAB+TT%LCA+TT%LEN+TT%WID+TT%PGM>
	MOVX T3,.TTATE		;Set data mode to 
	STOR T3,TT%DAM,+T2	; translate echo only.
	SFMOD%			;(T1,T2)
	STPAR%			;(T1,T2)
	MOVX T2,.MOXOF		;Disable pause on end of page
	MOVX T3,.MOOFF
	MTOPR%			;(T1,T2,T3)
	MOVX T2,.MORLW		;Read line width
	MTOPR%
	MOVEM T3,LINWID		;Set up line width characteristic
	CFIBF%			;(T1)
	RET
	SUBTTL UTILITY ROUTINES -- RESTORE ORIGINAL TERMINAL STATE

;Restore the original terminal state
;CALL TRMRST with no arguments
;Returns +1 always
TRMRST:	MOVEI T1,.PRIIN		;CCOC words
	MOVE T2,OLDTYP		;Set terminal type
	STTYP%
	DMOVE T2,OLDCOC		
	SFCOC%
	MOVEI T1,.PRIIN		;JFN mode word
	MOVE T2,OLDRFM
	SFMOD%
	STPAR%
	MOVX T2,.MOXOF		;Pause on end of page
	MOVE T3,OLDMOD
	MTOPR%
	MOVX T2,.MOSLW		;Terminal page width
	MOVE T3,OLDWID
	MTOPR%
	MOVX T2,.MOSLL		;Terminal page width
	MOVE T3,OLDLEN
	MTOPR%
	MOVX T2,.MOTCE		;Set two character switch sequence
	SKIPE T3,OLDSWI		; if it exists.
	MTOPR%
	CFIBF%			;(T1)
	MOVEI T1,-5		;Set the job wide terminal interrupt mask.
	MOVE T2,OLDRTJ		
	STIW%
	MOVX T1,ST%DIM+.FHSLF	;Terminal interrupt mask
	DMOVE T2,OLDRTI
	STIW%
	RET
	SUBTTL UTILITY ROUTINES -- RESTORE CTERM TERMINAL STATE

;Restore the terminal state after reentry
;CALL TRMREE with no arguments
;Returns +1 always
TRMREE:	MOVEI T1,.PRIIN		;CCOC words
	DMOVE T2,CTMCOC		
	SFCOC%
	MOVEI T1,.PRIIN		;JFN mode word
	MOVE T2,CTMRFM
	SFMOD%
	STPAR%
	MOVX T2,.MOXOF		;Pause on end of page
	MOVE T3,CTMMOD
	MTOPR%
	MOVX T2,.MOTCE		;Set two character switch sequence
	MOVE T3,CTMSWI		
	MTOPR%
	MOVE T2,CTMTYP		;Set terminal type
	STTYP%
	MOVX T2,.MOSLW		;Terminal page width
	MOVE T3,CTMWID
	MTOPR%
	MOVX T2,.MOSLL		;Terminal page width
	MOVE T3,CTMLEN
	MTOPR%
	MOVEI T1,-5		;Set the job wide terminal interrupt mask.
	MOVE T2,CTMRTJ		
	STIW%
	MOVX T1,ST%DIM+.FHSLF	;Terminal interrupt mask
	DMOVE T2,CTMRTI
	STIW%
	MOVEI T1,.PRIIN		;Get terminal type
	GTTYP%
	MOVEM T2,TRMTYP
	CAIL T2,0		;Range 
	CAIL T2,TRMTBL		; check
	RET			;Failed.
	MOVE T2,TRMTAB(T2)      ;Get the characteristics
	MOVEM T2,TRMCHA		;Save them.
	RET			;Done.
	SUBTTL UTILITY ROUTINES -- RESTORE TERMINAL STATE FOR TEXTI RESTART
;Restore the terminal state before a TEXTI% JSYS restart after it has been
;interrupted by an out-of-band character.
;CALL TRMRTX with no arguments
;Returns +1 always
TRMRTX:	MOVEI T1,.PRIIN
	DMOVE T2,TXTCOC		;Get original CCOC words
	SFCOC%			;Restore them.
	MOVEI T1,.PRIIN
	MOVE T2,TXTRFM		;Get orginal JFN mode word
	SFMOD%			;Restore it.
	MOVX T2,.MOSFW		;Get the field width
	MOVE T3,TXTFW		;Restore it.
	MTOPR%
	MOVEI T2,4		;Argument block length
	MOVEM T2,TXTMSK
	MOVEI T2,.MOSBM		;Get the original break mask
	MOVEI T3,TXTMSK		;Restore it.
	MTOPR%
	RET			;Done.
	SUBTTL UTILITY ROUTINES -- EXIT WITH REENTRY ALLOWED
;Here when two character escape sequence is typed.
;Returns +1, if at all.
;Preserves all ACs, DEBRK%s always
REENTR:	CALL REENT0		;Do work.
	DEBRK%

REENT0:	SAVET			;Save temporary registers
	MOVEI T1,.FHSLF		;Turn off
        DIR%			; interrupts
	CALL REENT1		;Do work
	MOVEI T1,.FHSLF		;Turn on 
	EIR%			; interrupt
	RET

REENT1:	SKIPE DEBUG		;If not debugging.
	IFSKP.
	  CALL TRMSTP		;Save CTERM terminal state
	  CALL TRMRST		;() Restore original state of terminal 
	  CALL SETPNM		;restore program(node) name
	ENDIF.
	TMSG <
[Connection interrupted, back at node >
	CALL PRTNOD		;Print local node name
	TMSG <,
Type CONTINUE to resume connection]
>
	SKIPN DEBUG		;Is debugger on ?
	IFSKP.
	  CALL BUGENT		;Yes. Go to it instead.
	ELSE.
	  HALTF%		;Exit program.
	  CALL TRMSAV		;() Restart - save current terminal state
	  CALL TRMREE		;() Restore CTERM terminal
	  CALL SETPNM		;restore program(node) name
	  SKIPE DEBUG		;Is debugger on ?
	  CALL BUGENT		;Yes. Go to it.
	ENDIF.
	RET   			;Done.
	SUBTTL UTILITY ROUTINES -- ERROR ROUTINES
;Bomb out of this program
;CALL FATAL with no arguments
;Never returns
FATAL:	CALL TRMRST		;Restore state of terminal 
	RESET%			;Be on the safe side.
	HALTF%			;Exit program
	JRST .-1		;Do not allow reentry

;Print jsys error and die
;CALL ERR with no arguments
;Prints error 
;Returns +1 always
ERR:	TMSG <
?>     
	MOVEI T1,.PRIOU		;Send it to the terminal
	MOVE T2,[XWD .FHSLF,-1] ;Latest error
	SETZ T3,		;No limit
	ERSTR%			;Print out the error.
	 TRN
	 TRN
	JRST FATAL		
	SUBTTL UTILITY ROUTINES -- STRING LENGTH
;Routine to find the difference of two eight bit byte pointers
;CALL CHDIFF with
;	T1/ finishing byte pointer
;	T2/ starting byte pointer
;Returns +1 always with T1/ difference in bytes.
CHDIFF: DMOVE T3,T1
	LSH T3,-^D33		;Get byte offset within word
	LSH T4,-^D33		;Get byte offset within word
	SUB T4,T3		;The byte difference
	HRRZS T2	    	;Now 
	HRRZS T1		; compute 
	SUB T1,T2		; the word difference
	LSH T1,2   		;Convert to bytes.
	ADD T1,T4	    	;Add them up
	RET		    	;Done.
	SUBTTL UTILITY ROUTINES -- GET INTERRUPT SEQUENCE
;Gets the two character interrupt sequence from the user.
;CALL GETINS with no arguments
;Returns +1 always with SWCHR1 and SWCHR2 set up.
GETINS:	SKIPE RESCAN		;Rescan buffer filled in ?
	IFSKP.
	  HRROI T1,[ASCIZ/Two character interrupt sequence (^\,<RET>): /] ;No.
	  PSOUT%		;Prompt user.
	  MOVEI T1,.PRIIN	;Initialize.
	  CFIBF%
	  SETZ T4,		;Initialize string storage.
	  MOVE T1,TCEPTR	;Byte pointer to string (in T4)
	  MOVX T2,<RD%BEL+RD%CRF+TCESIZ> ;Suppress CR, break on LF, max is 5
	  HRROI T3,[ASCIZ/Two character interrupt sequence (^\,<RET>): /] ;Prompt
	  RDTTY%			
	   ERJMP ERR       	;Error. Print message and die
	  TXNE T2,RD%BTM	;Saw terminator ?
	  IFSKP.
	    DO.
	      PBIN%		;No. Eat characters until CR/LF
	      CAIN T1,.CHLFD
	      LOOP.
	    ENDDO.
	  ENDIF.
	  MOVE T1,TCEPTR      	;Get the 
	  ILDB T2,T1		; first character
	  ILDB T3,T1		;Get the second.
	  CAIE T2,.CHLFD	;Is the first character line feed ?
	  IFSKP.
	    MOVEI T3,<<.CHCBS_7> ! .CHCRT> ;Yes. Use the default.
	  ELSE.
	    LSH T2,7       	;No. Use the 
	    IORM T2,T3      	; given sequence.
	  ENDIF.
	ELSE.
	  MOVEI T3,<<.CHCBS_7> ! .CHCRT> ;Yes. Use the default.
	ENDIF.
	LDB T4,[POINT 7,T3,28]	;Get first character
	MOVEM T4,ESCCHR		;Save it
	MOVEI T1,.PRIIN		;Now set up the 
	MOVEI T2,.MOTCE		; two character 
	MTOPR% 			; escape sequence
	 ERJMP ERR         	;Error. Print message and die
	RET			;Done.
	SUBTTL UTILITY ROUTINES -- GET THE RSCAN BUFFER
;If the node name was specified in the RSCAN buffer, pick it up.
;CALL GETRSC with no arguments
;Returns +1 always with RESCAN set accordingly and node name set up if present
GETRSC:	SETZM RESCAN		;Initialize RESCAN flag
	SKIPE DEBUG		;Is debugging on ?
	RET			;Yes. Force user to type in node & escape seq.
	MOVX T1,.RSINI		;Initialize RSCAN% buffer
	RSCAN%
	 RET			;On failure, give up.
	MOVEM T1,RSCCNT		;Save count.
	MOVN T3,T1		;Get RESCAN buffer 
	MOVEI T1,.PRIIN
	MOVE T2,RSCPTR
	SIN%
	HRROI T1,[ASCIZ\CTERM-SERVER\] ;Is first word CTERM-SERVER ?
	MOVE T2,RSCPTR
	STCMP%
	TXNN T1,SC%SUB		;Is it ?
	RET			;No. Done.
	DO.			;Yes. Get past white space.
	  ILDB T3,T2		;Get next byte
	  CAIE T3,.CHSPC	;Is it SPACE 
	  CAIN T3,.CHTAB	; or TAB ?
 	  LOOP.   		;Yes. Continue
	ENDDO.
	CAIE T3,.CHLFD		;Is last char LF or
	CAIN T3,.CHCRT		; CR ?
	RET			;Yes. Done.
	CAIN T3,.CHFFD		;Is last char form feed ?
	RET 			;Yes. Done.
	SETOM RESCAN		;No. There must a node name.
	MOVEI T1,6		;Max node name size
	MOVE T4,NODPTR		;Now fill in the node name
	DO.
	  SOSL T1		;Decrement count and test for done
	  IDPB T3,T4		;Put byte into storage.
	  ILDB T3,T2		;Get next byte
	  CAIE T3,.CHLFD	;Is last char LF or
	  CAIN T3,.CHCRT	; CR ?
	  EXIT.			;Yes. Exit loop.
	  CAIN T3,.CHFFD	;Is last char form feed ?
	  EXIT.			;Yes. Done.
	  CAIN T3,":"		;Is last char a colon?
	  EXIT.			;Yes. Done.
	  LOOP.
	ENDDO.
	SETZ T1,		;Null
	IDPB T1,T4		; terminate

;At this point T3 will probably contain ":".  If so, see if another node
; name follows.  If so, it is a PMR case and we hand over control to NRT.
	CAIE T3,":"		;Is it colon?
	IFSKP.			;Yes
	  ILDB T3,T2		;This should be another colon
	  CAIE T3,":"		;Is it?
	  RET			;No, done
	  ILDB T3,T2		;Get one more byte
	  CAIE T3,.CHLFD	;LF?
	  CAIN T3,.CHCRT	;or CR?
	  RET			;All done then
	  CAIN T3,.CHFFD	;Form feed?
	  RET			;Yes, done
	  HRROI T1,[ASCIZ /
/]
	  PSOUT%		;Give a new line
	  MOVEI T1,.FHSLF	;Set error for fork so that exec can try NRT.
	  MOVEI T2,NSPX20	;This is the error that SET HOST looks for.
	  SETER%		;Set it
	  HALTF%		;Stop
	  JRST .-1		;Yes, stop
	ENDIF.
	RET			;Done.
	SUBTTL UTILITY ROUTINES -- NODE NAMES
;Gets the remote node name from the user.
;CALL GETNOD with no arguments
;Returns +1 always
GETNOD:	SKIPE RESCAN		;Rescan succeeded ?
	RET			;Yes. Node name already set up.
	MOVEI T1,.PRIIN		;Initialize.
	CFIBF%
	PROMPT <Node name: >
	MOVEI T1,[FLDDB.(.CMNOD,<CM%NSF>)]
	CALL CFIELD		;Get field and confirm command.
	MOVE T1,NODPTR		;Move to right place
	HRROI T2,ATMBUF
	SETZ T3,
	SOUT%
	RET			;Done.

;Print out escape sequence
;CALL PRTINS with no arguments
;Preserves all ACs
PRTINS:	SAVEAC <T1,T2,T3>
	MOVEI T1,.PRIIN
	MOVEI T2,.MORTC
	MTOPR%			;(T1,T2/T3)
	LDB T1,[POINT 7,T3,28]	;Get first character.
	CALL PRTIN1		;(T1) Print it
	MOVEI T1,","		;Delimiter.
	PBOUT%
	LDB T1,[POINT 7,T3,35]	;Get second character.
	CAIE T1,.CHCRT		;Is it carriage return ?
	JRST PRTIN1		;No. Print it and done.
	HRROI T1,[ASCIZ\<RET>\] ;Yes. Print this
	PSOUT%
	RET

;Print character visibly
;CALL PRTIN1 with 
;	T1/ character
;Uses T1 and T2 only
PRTIN1:	CAIL T1," "		;Is it a control character ?
	CAIN T1,.CHDEL		;Or DELETE ?
	IFNSK.
	  MOVE T2,T1		;Yes. Save it.
	  MOVEI T1,"^"		;Get a hat.
	  PBOUT%		;Put it out.
	  MOVE T1,T2		;Get back the character
	  XORI T1,100		;Convert it.
	ENDIF.
	PBOUT%			;Put it out.
	RET

;Print local node name
;CALL PRTNOD with no arguments
;Returns +1 always
;Preserves all ACs
PRTNOD:	SAVET 
	STKVAR <<NAME,2>>
	MOVEI T1,.NDGLN		;Function code
	MOVEI T2,T3		;Address of argument block
	HRROI T3,NAME		;Byte pointer to node name
	NODE%
	HRROI T1,NAME		;Point again to node name
	PSOUT%			;Print it out.
	RET

;Set program name - sets the program name displayed via SYSTAT to the
;nodename of the remote node.
;Returns +1 always.

SETPNM:	SETZ T1,
	MOVEI T4,6		;Node name count
	MOVE T3,NODPTR		;Get pointer to nodename
	MOVE T2,[POINT 6,T1];Point to SIXBIT program name
GTNOD:	ILDB CX,T3		;Get a Byte
	JUMPE CX,GTDON		;if null, then done
	CAIL CX,140		;is this a lower case character?
	TRZA CX,100		;yes, make it SIXBIT
	SUBI CX,40		;make it SIXBIT
	IDPB CX,T2		;Save it
	SOJG T4,GTNOD		;get all six characters
GTDON:	SETNM%			;Set program name to NODENAME
	RET

;TRYNRT - Set up correct error msg so that EXEC tries NRT: on return.
;Takes nothing and never returns.

TRYNRT:	    MOVEI T1,.FHSLF	;Set error for fork so that exec can try NRT.
	    MOVEI T2,NSPX20	;This is the error that SET HOST looks for.
	    SETER%		;Set it
	    HRROI T1,[ASCIZ\Trying NRT: ]\]
	    SKIPN QUIET		;Are we printing status msgs?
	    PSOUT%		;Yes, let them know that we'll try NRT
	    JRST FATAL		;No, no more to do.
	SUBTTL DEBUG PROCESS -- ENTRY
;Entry to debug process
;CALL BUGENT with no arguments
;Returns +1 always
;Preserves all ACs
BUGENT:	SAVET			;Save temporary registers
	TXO BUGREG,BG.ENA	;Say debugging enabled.
	CALL TRMSTP		;Save current terminal state
	CALL TRMRST		;Restore original terminal state
	CALL BUGCMD		;Go to command parser.
	CALL TRMREE		;Restore terminal state
	RET   			;Done.

;The debug command parser - top level.
;CALL BUGCMD with no arguments
;Returns +1 always (if at all)
BUGCMD:	PROMPT (DEBUG>)		;Prompt.
	KEYWRD (KEYMAI)		;Main command level dispatch
	JRST (T1)		;Do it.

;Here for parse failure	- T2 contains error code
;Returns +1 always
BUGBAD:	SKIPE T1,BUGJFN		;Extraneous JFN ?
	RLJFN%			;Yes. Get rid of it.
	MOVEI T1,.PRIOU		;Output designator
	HRLI T2,.FHSLF		;Fork handle
	SETZ T3,
	ERSTR%
	 TRN
	 TRN
	JRST BUGCMD

;Here for reparse
BUGRPS:	SKIPE T1,BUGJFN		;Extraneous JFN ?
	RLJFN%			;Yes. Get rid of it.
	JRST BUGCMD

;Debug command - continue the program
BUGCON:	CALL CFMRTN		;Confirm the command
	RET			;Done

;Debug command - go to DDT
BUGDDT:	MOVEI T1,.PRIIN		;Save JFN mode word
	RFMOD%
	MOVEM T2,DDTMOD
	CALL CFMRTN
	MOVEM P,BUGACS+17	;Save registers
	MOVE P,[0,,BUGACS]
	BLT P,BUGACS+16
	TMSG <
The registers are in BUGACS.
Type "JRST DDTRET$X" to return.
>
	JRST 770000		;Go to DDT
DDTRET:	MOVE P,[BUGACS,,0]	;Restore registers
	BLT P,CX
	MOVE P,BUGACS+17
	MOVEI T1,.PRIIN		;Restore JFN mode word
	MOVE T2,DDTMOD
	SFMOD%
	STPAR%
	JRST BUGCMD

;Debug command - exit the program.
BUGEXI:	CALL CFMRTN		;Confirm the command
	HALTF%			;Stop
	CALL TRMSAV		;() Restart - save current terminal state
	JRST BUGCMD		;Continue

;Debug command - set trace flag(s)
BUGTRC:	KEYWRD (KEYTRC,BUGBAD)  ;Get the trace flag id.
	MOVE T4,T1		;Save it
	CALL CFMRTN		;Confirm the command
	IORM T4,BUGREG		;Set the flags
	JRST BUGCMD		;Continue

;Debug command - clear trace flag(s)
BUGUNT:	KEYWRD (KEYTRC,BUGBAD)  ;Get the trace flag id.
	MOVE T4,T1		;Save it
	CALL CFMRTN		;Confirm the command
	ANDCAM T4,BUGREG 	;Clear the flags
	JRST BUGCMD		;Continue
	SUBTTL DEBUG PROCESS -- SET LOGGING FILE
;Debug command - Log trace output to file
BUGLOG:	SKIPE T1,BUGJFN		;Have a temporary JFN ?
	RLJFN%			;Yes. Get rid of it.
	MOVEI T1,[FLDDB.(.CMOFI)] ;Function descriptor block
	CALL RFIELD		;Parse 
	MOVEM T2,BUGJFN		;Save JFN.
	CALL CFMRTN 		;Confirm the command.
	SKIPN T1,BUGFIL		;Have a JFN already ?
	IFSKP.
	  CAME T1,BUGJFN	;Yes. Same as new one ?
	  RLJFN%		;No. Get rid of it.
	  NOP
	ENDIF.
	MOVE T1,BUGJFN		;Make 
	MOVEM T1,BUGFIL		; this the trace file
	SETZM BUGJFN		;No longer temporary
	MOVX T2,<FLD(7,OF%BSZ)+OF%APP> ;Make the file exist
	OPENF%
	 NOP
	TXO T1,<CO%NRJ>		;Keep JFN around
	CLOSF%
	 NOP
	JRST BUGCMD		;Continue
	SUBTTL DEBUG PROCESS -- HELP COMMAND
;Debug command - help
BUGHLP:	CALL CFMRTN		;Confirm the command
	TMSG <
The debugger commands are:

CONTINUE - resume the program.
DDT - go into DDT. Type JRST DDTRET$X to return.
EXIT - exit the program. It is continuable.>

	TMSG <
HELP - print this text.
LOG {file-spec} - send all tracing to this file.
TRACE {identifier} - trace a collection of events:
	ALL, RECEIVED-DECNET-MESSAGES, SENT-DECNET-MESSAGES, CTERM-READ, 
	CTERM-WRITE, OUT-OF-BANDS, TIMER>
	TMSG <
UNTRACE {identifier} - turn off the tracing of a collection of events

The debugger is enabled by depositing a 1 in location "DEBUG", before starting
or continuing this program.
>
	JRST BUGCMD		;Continue
	SUBTTL DEBUG PROCESS -- SHOW COMMAND
;Debug command - show
BUGSHO:	CALL CFMRTN		;Confirm the command
	SKIPE BUGFIL
	IFSKP.
	  TMSG <
No logging file set up.>
	ELSE.
	  TMSG <
Logging file is >
	  MOVEI T1,.PRIOU
	  MOVE T2,BUGFIL
	  SETZ T3,
	  JFNS%
	ENDIF.
	TMSG <
Flags that are on
-----------------
>
	TXNN BUGREG,BG.CTR
	IFSKP.
	  TMSG <RECEIVED-CTERM-MESSAGES
>
	ENDIF.
	TXNN BUGREG,BG.OOB
	IFSKP.
	  TMSG <OUT-OF-BAND
>
	ENDIF.
	TXNN BUGREG,BG.MSI
	IFSKP.
	  TMSG <RECEIVED-DECNET-MESSAGES
>
	ENDIF.
	TXNN BUGREG,BG.MSO
	IFSKP.
	  TMSG <SENT-DECNET-MESSAGES
>
	ENDIF.
	JRST BUGCMD		;Continue
	SUBTTL DEBUG PROCESS -- DISPLAY BUG
;Put message in debug file
;CALL BUGDSP with
;BUGMPT, BUGDPT, BUGCNT set up.
;Returns +1 always
;Uses no ACs
BUGDSP:	SAVEAC <T1,T2,T3,T4,Q1,Q2,Q3>
	SKIPN T1,BUGFIL		;Is there a debug file ?
	RET			;No. Done.
	MOVX T2,<OF%APP+FLD(7,OF%BSZ)>
	OPENF%
	 JRST ERR
	CALL BUGDS0		;Display the data
	MOVE T1,BUGFIL		;Close the file.
	TXO T1,CO%NRJ
	CLOSF%
	 JRST ERR
	RET

BUGDS0:	HRROI T2,[ASCIZ\
*****************
\]
	SETZ T3,
	SOUT%			;Put out delimiter.
	MOVE T2,BUGMPT
	SETZ T3,
	SOUT%			;Put out message
	HRROI T2,[ASCIZ\ at \]
	SOUT%
	HRROI 2,-1		;Output time
	SETZ T3,
	ODTIM%
	HRROI T2,[ASCIZ\
\]
	SOUT%
	SKIPN BUGCNT		;If no additional data, done.
	RET
	MOVE Q1,BUGCNT		;Get count
	MOVE Q2,BUGDPT		;Get pointer to data
	DO.
	  MOVE T3,[NO%LFL+FLD(4,NO%COL)+10] ;Octal format numbers
	  MOVEI Q3,^D18		;per line count
	  DO.			;Output string as numbers.
	    SOJL Q1,BUGDS1
	    ILDB T2,Q2		;Get byte
	    NOUT%
	     TRN
	    SOJG Q3,TOP.
	  ENDDO.
	  HRROI T2,[ASCIZ\
\]
	  SETZ T3,
	  SOUT%
	  LOOP.
	ENDDO.
BUGDS1:	HRROI T2,[ASCIZ\
\]
	SETZ T3,
	SOUT%

       	MOVE Q1,BUGCNT		;Get count
	MOVE Q2,BUGDPT		;Get pointer to data
	DO.
	  MOVEI Q3,^D18		;Line length
	  DO.			;Output string as characters.
	    SOJL Q1,BUGDS2
	    ILDB T2,Q2 		;Get byte
	    ANDI T2,177		;Make it 7 bits
	    CAIL T2,^D32	;Is it a control character ?
	    CAIN T2,.CHDEL	;No. Is it DELETE ?
	    IFNSK.
	      PUSH P,T2  	;Yes to either. Save character
	      MOVEI T2,"^"	;Get hat.
	      BOUT%		;Put it out.
	      POP P,T2   	;Get character back.
	      XORI T2,100 	;Make it visible.
	    ENDIF.
	    BOUT%
	    MOVEI T2," "	;Get a space
	    BOUT%		;Put it out
	    SOJG Q3,TOP.
	  ENDDO.
	  HRROI T2,[ASCIZ\
\]	 
	  SETZ T3,
	  SOUT%
	  LOOP.
	ENDDO.
BUGDS2:	HRROI T2,[ASCIZ\
\]
	SETZ T3,
	SOUT%
	RET
	END <4,,ENTVEC>