Google
 

Trailing-Edge - PDP-10 Archives - BB-F493Z-DD_1986 - 10,7/dteco.mac
There are 4 other files named dteco.mac in the archive. Click here to see a list.
	TITLE	TECO %26(257) TEXT EDITOR AND CORRECTOR
	SUBTTL	RC CLEMENTS/PMH/CAM/EAR/DML/JNG/BGS/DCE/MHK/CGN/RDH

	SEARCH	JOBDAT,MACTEN,UUOSYM	;STANDARD DEFINITIONS
	SEARCH	SWIL			;SWIL DEFINITIONS

	.REQUE	REL:SWIL		;SWIL PACKAGE

	SALL				;PRETTY LISTINGS
	.DIREC	FLBLST			;PRETTIER LISTINGS

	COMMENT	\

TECO  --  "Text Editor and COrrector" for TOPS-10

Copyright (C) 1970, 1971, 1972, 1975, 1976, 1977, 1978, 1980, 1982, 1984, 1986
Digital Equipment Corporation, Maynard, Massachusetts, U.S.A.

This software is furnished under a license and may be used and copied only
in accordance with the terms of such license and with the inclusion of the
above copyright notice.  This software or any other copies thereof may not
be provided or otherwise made available to any other person.   No title to
and ownership of the software is hereby transferred.

The information in this software is subject to change  without  notice and
should not be construed as a commitment by Digital Equipment Corporation.

Digital  assumes  no  responsibility  for  the  use  or reliability of its
software on equipment which is not supplied by Digital.

\


;TECO VERSION IDENTIFICATION

MAJVER==26	;MAJOR VERSION LEVEL
MINVER==0	;MINOR (MAINTENANCE RELEASE) LEVEL
CSTVER==0	;CUSTOMER VERSION (WHO LAST . . .)
EDTVER==257	;EDIT LEVEL

%%TECO==:<BYTE (3)CSTVER(9)MAJVER(6)MINVER(18)EDTVER>

IF2,<	PURGE	CSTVER,MAJVER,MINVER,EDTVER>

	LOC	.JBVER
	EXP	%%TECO		;VERSION #
	SUBTTL	Revision History

;*** CHANGES FROM VERSION 23 TO 23B ***

; EDIT 114- REMOVES CODE WHICH CHANGED BAK FILE PROTECTION TO
;           STANDARD. CHANGES SEARCH COMMAND TO ACCEPT LOWER CASE
;           FS AND FN. PROVIDES FOR $ IN Q REGISTER BY RETURNING
;           TO NEXT LEVEL WHEN $ SEEN RATHER THAN REINITIALIZING.
;           AREAS AFFECTED: GO, RCH2, ALTMOD, MAC, BKCLS2,
;                           FILSP2, FCMD, EQM

; EDIT 115- FIXES PERTAIN TO LINE SEQUENCE NUMBER PROCESSING
;           CHANGES INSERTION OF 5 SPACES TO 5 SPACES AND TAB
;           CHANGES SEQ# CHECK SO THAT 5 SPACES AND TAB ARE
;            ACCEPTED AS LINE SEQ# (THIS ELIMINATES THE INSERTION
;            AFTER THE FIRST TIME AND ALLOWS THEM TO BE REMOVED
;            USING THE /SUPLSN SWITCH)
;           AREAS AFFECTED:PPA06, PPA08,

; EDIT 116- CHANGES GARBAGE COLLECTION ROUTINE TO CHECK FOR
;           ANYTHING TO SAVE PRIOR TO ATTEMPTING A BLT.
;           AREAS AFFEDTED: GCS12


; EDIT 117- CHANGES SEARCH ROUTINE TO PROVIDE PROPER OPERATION
;           OF ^S, TECO'S "WILD DELIMITER", WHEN THE DELIMITER
;           IS THE FIRST BUFFER CHARACTER.
;           AREAS AFFECTED: S1, S4A, BCOUNT

; EDIT 120- CHANGES OPERATION OF ET COMMAND TO CONFORM TO
;           DOCUMENTATION. ET SHOULD SUPPRESS CASE FLAGGING.
;           AREAS AFFECTED: TYO

; EDIT 121- PROVIDES WARNING MESSAGE WHEN TECO
;           DETECTS SEQUENCED FILE WITH NO LSN SWITCHES.
;           ADDS CLEAR OF OUTPUT BUFFER PRIOR TO PACKING
;           TO INSURE AGAINST SPURIOUS BIT35 SETTING.
;           AREAS AFFECTED: YNKSEQ,PPA05

; EDIT 122- FIXES HP COMMAND TO SET BIT 35 FOR FIRST
;           LINE NUMBER IN THE BUFFER.
;           AREAS AFFECTED: HOLE

; EDIT 123- REDEFINES OUTPUT BUFFERS AFTER SECOND OPEN FOR
;           FILES WHICH ARE SUPERSEDED. THIS FIXES THE "ADDRESS
;           CHECK FOR DEVICE DSK" PROBLEM.
;           AREAS AFFECTED: OPNW3

; EDIT 124- REMOVES THE %SUPERSEDING EXISTING FILE MESSAGE
;           FOR NON-DIRECTORY DEVICES AND LIB: FILES.
;           AREAS AFFECTED: OPNW2, OPNW3

; EDIT 125- CORRECTS "ILL MEM REF AT USER PC 403647" BY ADDING
;           A CHECK FOR SHORT ERROR MESSAGES USED PRIOR TO
;           PERFORMING CORE CONTRACTION.
;           AREAS AFFECTED: ERRP7

; EDIT 126- CHANGES RENAME PROCESSING TO CONFORM TO DATE75
;           STANDARD.
;            AREAS AFFECTED: EBAKU1, OPNW33, BKCLS3, BKCLS5

; EDIT 127- CORRECTS EDIT#114 WHICH FAILED TO KEEP PROTECTION
;           OF INPUT FILE AS PROT FOR BAK FILE.
;           AREAS AFFECTED: BKCLS2

; EDIT 130- CORRECTS PROBLEM CAUSED BY EDIT 121. PW COMMAND
;           DID NOT WORK SINCE REGISTER "T" WAS NOT SAVED
;           CAUSING THE COMMAND TO BE INTERPRETED AS A P COMMAND.
;            AREAS AFFECTED: PPA05

; EDIT 131- CORRECTS PORTION OF EDIT 124 WHICH CHECKED WRONG STATUS
;           BIT. AREAS AFFECTED: OPNW3B

; EDIT 132- ADDS CHECK FOR DATA IN Q REGISTER PRIOR TO ALLOWING
;           INCREMENT (% COMMAND) AND GENERATES ERROR MESSAGE IF
;           ATTEMPTED WITH TEXT.  AREAS AFFECTED: PCNT

; EDIT 133- MAKES EB WORK PROPERLY FOR FILES OUTSIDE OF
;           USER'S PPN. SHOULD JUST DO ER/EW UNDER THIS
;           CONDITION INSTEAD OF TRYING TO RENAME FILES.
;           AREAS AFFECTED: EBAKUP

; EDIT 134- CHANGES CALLI AND TTCALL UUO'S TO STANDARD FORMAT

; EDIT 135- REPLACES EDIT 132 TO PUT ERROR MESSAGE IN STANDARD FORM
;           AND PROVIDE FOR CHECK ON Q COMMAND AS WELL AS %
;           ALSO PROVIDES PROPER OPERATION WITH NEGATIVE INTEGER.
;            AREAS AFFECTED: PCNT, QREG

; EDIT 136- GENERAL CLEAN-UP TO MAKE EDIT 123 MORE EFFICIENT,
;           REMOVE ROUTINE NOT NEEDED WITH EDIT 133, AND MAKE
;           DEVICE DTA WORK PROPERLY.
;           AREAS AFFECTED: OPNRD, EBAKUP, OPNWR, BAKCLS, EBS1

; EDIT 137- ELIMINATES THE CONVERSION OF OLD ALTMODES TO CODE 033
;           IN COMMAND STRINGS IF TTY NO ALTMOD IS SET.
;           AREAS AFFECTED: ALTIN, TYI

;EDIT 140- ADDS DEBUG SWITCH WHICH SAVES SYMBOLS, MAKES YANK
;          MORE EFFICIENT FOR NNN<Y> COMMANDS, AND CLEANS UP
;          THE %LINE NUMBER DETECTED MESSAGE
;          AREAS AFFECTED: TECO, LIS03, YANK2, YNKSEQ, CMDBAS

; EDIT 141- REMOVE UNNECESSARY PORTION OF EDIT 121 AND
;           EDIT 130.  WORK ON LINE SEQUENCE NUMBER PROCESSING.
;           AREAS AFFECTED:PPA04,PPA05

; EDIT 142- FIXES COMMAND DISPATCH TABLE ENTRIES FOR CR AND
;           LF TO PRESERVE NUMERIC ARGUMENTS.
;           AREAS AFFECTED: DTB

; EDIT 143- MAKE CODE FOR Q-REG MORE EFFICIENT.
;           AREAS AFFECTED: QREG, QTXTST

; EDIT 144- MAKES EH COMMAND USE STACK PROPERLY.
;           AREAS AFFECTED: ERRSET

; EDIT 145- FIXES EW TO OTHER PPN'S.
;           AREAS AFFECTED: OPNW33

; EDIT 146- MAKES EB WORK PROPERLY FOR ERSATZ DEVICES.  RENAMES
;	    DEVICE TO DSK FOR OUTPUT.  AREAS AFFECTED: EBAKU2

; EDIT 147- CHANGES OPEN FOR EB COMMAND TO PHYSICAL ONLY SINCE
;           PHYS DEVICE NAME IS IN OPEN BLOCK.  THIS IS NECESSARY
;           TO ALLOW PROPER OPERATION OF RENAME SEQUENCE.
;           AREAS AFFECTED: OPNW4, BKCLS4

; EDIT 150- MODIFY LSN PROCESSING TO HANDLE SOS PAGE MARKS.
;           AREAS AFFECTED: PPA08, PPA13, YANK5

; EDIT 151- GENERAL CLEANUP OF COMMENTS, ETC.

; EDIT 152- CORRECTS CCL PROCESSING TO ACCEPT SPACES FROM COMPIL
;           TO MAKE TECO FOO. COMMANDS WORK.
;           AREAS AFFECTED: CCLTM1, CCLIL

; EDIT 153- ADDS SPECIAL CHECK FOR ERSATZ PPN TO INSURE SUPERSEDING
;           MESSAGE WORKS FOR SYS:, NEW:, ETC.
;            AREA AFFECTED: FILSP7

; EDIT 154- MAKE EDIT 147 MORE EFFICIENT
;           AREAS AFFECTED: OPNW44

; EDIT 155- DELAY CLEARING EB AND OUTPUT OPEN FLAGS ON EX
;           COMMAND IN CASE ERROR OCCURS IN PROCESSING.
;            AREAS AFFECTED: CLOSEF

; EDIT 156- ADD ERROR CHECK AND MESSAGE FOR TAG TOO LONG.
;           AREAS AFFECTED: OG1

; EDIT 157- NOT USED (RESERVED)

; EDIT 160- PREVENTS TECO FROM GOING INTO INFINITE LOOP IF
;           ERROR FILE IS NOT FOUND AND USER HAS SET 3EH.
;           AREA AFFECTED: ERRP5

; EDIT 161- CHANGES THE WAY <> USE THE STACK TO INSURE PROPER
;           GARBAGE COLLECTIOM.
;            AREAS AFFECTED: LSSTH, INCMA2

; EDIT 162- FIXES PROBLEM CAUSED BY EDITS 147, 154, AND 160.
;            AREAS AFFECTED: ERRP5, OPNW44, BKCLS4
;*** CHANGES FROM VERSION 23B TO 24 ***

; EDIT 163- CORRECT OPERATION OF EB WHEN USER HAS CHANGED PATH
;           AREAS AFFECTED: EBAKU2

; EDIT 164- CORRECTS ERROR PRINTOUT PROBLEM WHICH CAN CAUSE RANDOM
;           CORE UUO'S TO BE EXECUTED.
;            AREAS AFFECTED: ERRP, ERRP0

; EDIT 165- PROVIDES PRINTING OF LOOKUP ERROR CODE DURING EB
;            AREAS AFFECTED: LKUPER

; EDIT 166- CORRECTS PROBLEMS WITH ?NCS ERROR
;           AREAS AFFECTED: LIS01, ERRTYP

; EDIT 167- CAUSES SPACES IN ARITHMETIC STRINGS TO BE IGNORED
;           EXCEPT AS A + OPERATOR
;           AREAS AFFECTED: CD93

; EDIT 170- CORRECTS TYPEOUT OF Q-REG NAME ON AN IQN ERROR FROM
;           AN * COMMAND
;           AREAS AFFECTED: LIS03

; EDIT 171- CORRECTS OPERATION OF EW COMMAND WHEN PPN IS SPECIFIED
;           PRIOR TO FILE.EXT
;           AREAS AFFECTED: FILSP6

; EDIT 172- CORRECTLY PUTS BOTH ARGUMENTS, IN A TWO ARGUMENT
;	    COMMAND (M,N T; M,N X; M,N K), WITHIN BUFFER BOUNDS
;	     AREA AFFECTED: CHK1

;EDIT 173- FIXES TWO ARGUMENT P COMMAND TO SET BIT 35 WHEN
;	   FIRST ARGUMENT IS BEG OF BUFFER OR BEG OF LINE
;	    AREAS AFFECTED: CHK1, PUNCHR, PUNCH1(DELETED)

;EDIT 174- CORRECTS UIN ERROR CAUSED BY A NULL REPLACEMENT
;	   ALTMODE DELIMITED F SEARCH FOLLOWED BY AN *
;	   COMMAND
;	    AREAS AFFECTED:NOALT; LIS03; LIS02; FND3-1

;EDIT 175- RE-DO ER,EW,EB,EZ,EM,EF,EX,EG COMMANDS TO UNDERSTAND
;	   DEFAULT PATHS, SFD'S, ERSATZ DEVICES, LIBRARIES,
;	   THE /SCAN PATH SETTING, THE FILE DAEMON, ETC. ETC.
;	   TECO WILL NOW EDIT THE FILE SPECIFIED BY AN EB
;	   COMMAND IN PLACE, I.E. BOTH THE BAK FILE AND THE EDITED
;	   SOURCE FILE WILL APPEAR IN THE DIRECTORY THAT THE USER
;	   SPECIFIED IN THE EB COMMAND. EXCEPTION: IF THE FILE TO
;	   BE EDITED IS NOT FOUND IN THE AREA SPECIFIED, BUT RATHER
;	   IN SOME LIBRARY AREA (LIB:, A HIGHER-LEVEL SFD, ON [1,4]
;	   WHEN NEW: WAS SPECIFIED, ETC.), THEN TECO WILL PRINT THE
;	   MESSAGE %FILE WAS FOUND IN [P,PN,SFD,SFD...] AND THEN
;	   TURN THE COMMAND INTO AN ER FROM THE AREA WHERE THE FILE
;	   WAS ACTUALLY FOUND AND AN EW INTO THE AREA THAT THE USER
;	   SPECIFIED. AN EB IN PLACE IS OBVIOUSLY NOT REASONABLE FOR
;	   FILES FOUND IN LIBRARY AREAS, AND THIS ACTION IS THOUGHT TO
;	   BE MORE REASONABLE THAN A ?FNF-0 ERROR. TECO WILL NOW ALSO
;	   RESPECT .RBSPL AND .RBNCA (NOT .RBVER - EDITING CHANGES THE
;	   VERSION) WHEN EDITING A FILE AS A RESULT OF AN EB COMMAND.
;	   THIS EDIT WAS CAREFUL NOT TO BREAK DECTAPES.
;		AREAS: LOTS

;EDIT 176- CORRECTS PROBLEM OF /SUPLSN SWITCH AND NULL CHARACTERS
;	   IN OUTPUT FILES.  CORRECTES PROBLEM OF /GENLSN
;	   WITH THE M,NP COMMAND AND EX COMMAND.  EX PROBLEM CAUSED BY
;	   EDIT 174.
;	     AREAS AFFECTED: PPA02; PPA06; PPA13; CHK1

;EDIT 177- PREVENTS RANDOM CORE UUO CAUSED BY EDIT 164.
;		AREAS AFFECTED: ERRP0

;EDIT 200- CORRECTS SOME MINOR PROBLEMS WITH EDIT 175. TECO.ERR WAS
;	   SOMETIMES BEING PRINTED INCORRECTLY. REMOVES ERDONE FLAG.
;	AREAS AFFECTED: ERDONE,OPNRD,EBAKUP,WTFIL,BAKCLS,EPATH,CCLIL

;EDIT 201- MAKE FS SEARCH FASTER FOR SAME LENGTH ARGUMENTS.
;		AREAS AFFECTED: FND

;EDIT 202- CLEAR THE OCTAL NUMBER FLAG ON ILLEGAL OCTAL DIGITS.
;		AREAS AFFECTED: CDNUM

;[LAST EDIT IN VERSION 24]
;EDIT 203- INITIALIZE LINE SEQUENCE NUMBER FOR EB COMMAND
;		AREA AFFECTED: EBAKUP

;EDIT 204- SAVE/RESTORE REGISTER USED BY TRACE.  THIS CORRECTS
;		FNF ERRORS FROM ER OR EB COMMANDS IF TRACE IS ON.
;		AREA AFFECTED: RCH

;EDIT 205- IMPLEMENT "?AOR ARGUMENT OUT OF RANGE " FOR U COMMAND
;		AREA AFFECTED: USE

;EDIT 206- MOVE "RUBSW==0" UP NEAR THE BEGINNING OF THE PROGRAM SO MACRO
;		VERSION 53 DOSEN'T COMPLAIN THAT RUBSW WAS REFERENCED
;		BEFORE IT WAS DEFINED.
;		AREAS AFFECTED:CNTRLR+3,"MISC PARAMETERS"+25

;EDIT 207- ADD CODE TO CHECK IF THE COMMAND BUFFER NEEDS MEMORY, IN ORDER
;		TO STAY WITHIN BOUNDS, UPON INITIALIZATION.
;		IF NECESSARY MEMORY IS EXPANDED.
;		AREAS AFFECTED:INITG+2

; EDIT 210- ADD CODE TO MAKE WINNING SEARCHES WITHIN ITERATIONS
;		RETURN -1.
;		AREAS AFFECTED:FND2+1

; EDIT 211- FOR THE X COMMAND USE FULL WORDS TO REPRESENT THE BUFFER
;		POINTER SO WHEN GREATER THAN 2**18 WE WON'T LOSE.
;		AREA AFFECTED: X+4

; EDIT 212- WHEN DOING A *I COMMAND DON'T GET FOOLED INTO THINKING THAT
;		THE COMMAND BUFFER HAS MOVED WHEN A GARBAGE COLLECTION HAS
;		OCCURED.
;		AREA AFFECTED:X3+6.5

; EDIT 213- WHEN SEARCHING, LEARN THAT WE ARE DONE WHEN WE EXAMINE
;		AND DON'T MATCH A CHARACTER OUTSIDE OF THE
;		BUFFER.  THIS MAKES ^EL WORK BECAUSE THE BIT MASK
;		ISN'T MESSED UP BY ADDITIONAL SEARCH ATTEMPTS.
;		AREAS AFFECTED: S3, S4A+4.5

; EDIT 214- FIX FILE STUFF IN EDIT [175] THAT DOESN'T SUPPORT NON-SFD
;		MONITORS.

; EDIT 215- REMEMBER X-MATCH FOR ADDITIONAL SEARCHES.
;		AREAS AFFECTED: CD93+8L, SERCHT

; EDIT 216- DON'T OVERFLOW THE SEARCH STRING STORAGE AREA
;		WHEN THE 81ST CHARACTER IS ^R OR ^Q.
;		AREA AFFECTED: SERCHG

; EDIT 217- GENERATE SOS PAGE MARKS WHEN USING LINE SEQUENCE
;		NUMBERS.
;		AREAS AFFECTED: PPA06, PPA14

; EDIT 220- STOP TIMESHARING THE SEQUIN FLAG FOR INPUT AND OUTPUT
;		OF SEQUENCED FILES.  THIS ELIMINATES THE LOSS OF
;		THE FIRST CHARACTER IN A /GENLSN'ED OUTPUT FILE
;		IF IT IS A TAB OR A CR.
;		AREAS AFFECTED: YANK1, YANK5, YNKSEZ

; EDIT 221- ACCOUNT FOR COMPIL FEATURE WHICH THROWS IN A NULL
;		AFTER THE FILE SPEC IN COMMAND LINE.
;		AREAS AFFECTED:CCLIL,CCLNUL

; EDIT 222- PREVENT SEARCHES FROM MATCHING A NULL WHEN THE ^^
;		COMMAND IS NOT GIVEN A CHARACTER TO OPERATE ON.
;		ADD THE MCO ERROR (MISSING CHARACTER OPERAND).
;		AREAS AFFECTED:CNTRU, THE ERR FILE

; EDIT 223- PREVENT SPACE/TAB SEARCHING FROM GOING TO FURTHER BUFFER
;		POSITIONS WHEN A CHARACTER HAS ALREADY BEEN FOUND.
;		AREAS AFFECTED:SPTB, S4D

; EDIT 224- CLEAN UP SOME COMMENTS AND ADD NEW ONES.

; EDIT 225 - FIX THE MAKE AND TECO COMMANDS BROKEN BY EDIT 221.
;	       AREAS AFFECTED: CCLDUN
;
; EDIT 226 - MAKE TECO SAVE SYMBOLS IN THE HIGH SEGMENT ONLY
;		IF DEBUGGING.

; EDIT 227- REWRITE *I LOGIC BECAUSE IT EXHIBITED A VARIETY
;		OF OBSCURE BUGS.
;		AREAS AFFECTED: LIS01, LIS03, TIMES, ERRTYP

;230	GIVE A WARNING MESSAGE IF OUTPUT IS TO DEVICE NUL:
;		AREA AFFECTED: OPNWR0

;231	IMPLEMENT "EC" COMMAND TO PREVENT TECO FROM MAKING
;		ALL SEARCHES WITHIN ITERATIONS INTO
;		COLON-SEARCHES.
;		0EC	MAKES ITERATION-SEARCHES COLON-SEARCHES.
;		NEC	FOR ANY NON-ZERO N, MAKES ITERATION-SEARCHES
;			NON-COLON SEARCHES.
;		EC	RETURNS CURRENT SETTING.
;
;		AREAS AFFECTED: ECTABL, FND2, COLOIT.
;				(COLOIT IS A NEW ROUTINE)

;232	DON'T SUPERCEDE OUTPUT FILE WHEN ?FNF ERROR OCCURS AFTER
;		"MAKE OUTFIL=INFILE" COMMAND.
;		AREA AFFECTED: ERRP6
;VERSION 24 (DISPLAY TECO... JUD LEONARD)
; EDIT 162- SCREEN FEATURES FROM ERIC OSMAN'S TV
; EDIT 163- FIX TTYSET TO TURN OFF FREE CRLF, NOT ON.
; EDIT 164- FIX VT05 FILL SEQUENCE TO USE RUBOUT RATHER THAN NULL
;	    AS FILLER.  DAS87 DISCARDS NULLS.
;	    AREA AFFECTED: CNFILL+2

;Version 25(233) RDH 19-Sep-79
;
;233	Use 700 series monitor terminal types, don't enquire
;	directly of terminal; add "EA" = Edit All command, read in
;	entire file (with <FF>s etc.); don't set "." to "B" on a search
;	failure - rather preserve "." across the failure; write crash
;	recovery file nnnTEB.TMP; add "E@" = Edit At (indirect) to
;	read commands from file (such as nnnTEB.TMP); support ANSI
;	terminals (VT100); add space (as first char typed) to scroll
;	through text, <LF> to do a "1L$$"; add "\\" as octal mode "\".
;
;234	RDH	24-Dec-79
;	Implement dump mode I/O for disk (read/write entire file in one
;	giant I/O operation). Initial load with SCAN/WILD (only to read
;	SWITCH.INI at the moment, but . . .). Add SWITCH.INI switchs:
;		/EAMODE:[ON/OFF] Default dump in entire file
;		/OKLSN		Don't worry about LSN's in EAMODE
;		/OKNULL		Don't worry about null's in EAMODE
;		/INITFILE:file	Process "file" as command file on startup
;	Add "EP" to write out (using dump mode if possible) file and then
;	"EF" it (like "EX" but without THE EXIT). Add ^H (backspace) to
;	scroll backwards (a backwards space). Rename crash recovery file
;	to be nnnTEC.CMD (so LOGOUT doesn't delete it!). Add <CR> to put
;	cursor on current screen (if not already there a la back/space).
;
;235	RDH	5-Feb-80
;	Obscure bug in memory management on ?Core cap exceeded errors.
;	Revise [205] to allow Q-reg text anywhere in addressable memory
;	Q-reg numerical values can range to approx +- 25 billion.
;
;236	RDH	18-Feb-80
;	Implement "arrow" keys. Various and sundry minor bugs.
;
;237	RDH	28-Feb-80
;	Don't allow 0-length inserts. Make <TAB> command part of normal
;	insert command (saves call to NROOM to expand buffer by 1).
;
;240	RDH	4-Mar-80
;	More junky little bugs: Q-reg relocation bug; If core expansion
;	fails acs get trounced (F2 in particular, which causes all
;	further SFD references to fail - this is also regular TECO bug).
;	Modernize command editing - ^R to retype, ^W to rubout a word,
;	^V to quote next character, ^A/^B to do lower/upper case (it's
;	what TV does, and seems as good as any other idea); TECO'S EO
;	value is now 3, setting EO=2 reverts to old editing characters.
;
;241	RDH	26-Apr-80
;	Trash left on screen in obscure situations (due to CNTLF being
;	called for character that wasn't echoed - either from command
;	file or first char typed in command string). Add crash recovery
;	file control - /CRFILE:file names the file, /CRPROT:nnn gives
;	the protection, /CRDISP:NEVER!TEMPORARY!DELETE!PRESERVE to [not]
;	delete the crash file, /CRSAVE:n to update the recovery file
;	every "n" characters, modulo line breaks.
;
;242	RDH	20-May-80
;	Assorted buggies.
;
;243	MHK	2-Jun-80
;	Implement University of Texas search algorithm which includes the
;	following features:
;		1) 10 times faster searching (forward direction)
;		2) backwards searches (using old TECO method)
;		3) bounded searches
;		4) FK searches (Find and Kill specified string)
;
;244	DPM	13-Jun-80
;	With all the various flavors of TECO floating around, finding the
;	correct TECO.ERR file is nearly impossible. Solution: don't depend
;	on an error file for messages. Implement $INFO, $WARN, and $FATAL
;	macros to generate verbosity controlled messages.
;	RDH	15-Jul-80
;	"FD<str>$" to find and delete matched string, "FK<str>$" to find
;	string, then delete from previous "." inclusively through to new
;	"."; "FR<str>$" to delete last string and replace with <str>;
;	"FV" to return last string value (size of string); and "F_" as
;	similar to "FS" on general principles. Allow user to specify /RUN
;	in SWITCH.INI (if he does, he deserves whatever he gets). Change
;	"EP" to "EC" for compatibility with "-11/etc." TECO's, and always
;	zero the buffer on exit. Add "EK" to kill current output file.
;	Make "1+:Sblah$" type expressions work (":" commands imply a
;	free "()" sequence, which includes PUSHing SARG). Ill mem ref
;	from "FS" search (day one bug) - must call NROOM after setting new
;	COMCNT/COMPTR. Don't do TEBJ sequence if nested into a command file
;	(<CR>'s from command file cause nnnJ$$ to appear in nnnTEB file,
;	which are not re-executed until after the entire command file
;	is completed).
;
;245	RDH	24-Sep-80
;	Minor bug(s).
;
;246	RDH	24-Feb-81
;	Use TERMINAL LENGTH/STOP if available.
;
;247	RDH	21-Apr-82
;	Add VK100/VT101/VT102/VT125 terminal types (equivalent to VT100).
;
;250	RDH	22-Jul-82
;	Edit 217 will lead to I/O Address Check for certain bizarre
;	files (e.g., a TOPS-20 DUMPER tape) - if a break character
;	appears within a few characters of end of I/O buffer and input
;	file LSNs exist. Note: an unexpected side "aspect" of this edit
;	is that the "cleaned-up" code now generates LSNed files that
;	are approximately .2% smaller than before (re standard TECO -
;	which liked to leave random nulls sprinkled in the output file).
;	In particular, while the files will FILCOM, they will not match
;	using DIRECT/CHECKSUM!
;
;251	RDH	22-Aug-82
;	i,jP commands appended <FF> characters to output stream (this
;	was caused by an earlier edit to clean up some code - not a problem
;	with standard TECO sources).
;
;252	RDH	28-OCT-82
;	Preserve file version (.RBVER) for EB files. This applies even
;	to faked ER/EW files, but does not apply to explicit user ER/EW
;	sequences (i.e., if the user types "EB" the version is preserved,
;	if the user types "ER" and/or "EW" the version is zero).

;DTECO %25(252) Released with 7.02 (as a tool) Spring, 1984
;253	RDH	22-Jun-84
;	Add VT103/VT180/VT185/VT220/VT240 as more ANSI klones.
;
;254	RDH
;	Version 26
;	Change over to SWIL (replace SCAN/WILD); first pass at running in
;	extended addressing. (Also note the /SFT switch added, but forgotten
;	in the edit history...); add "EP" command to PUSH to a new context;
;
;255	RDH	16-Feb-85
;	Don't do moby dump I/O except for disk devices (LPTs for example
;	get annoyed); other assorted little buggies of little import.
;	Some source cleanup (remove ancient edit numbers).
;
;256	RDH	22-Feb-85
;	Make n%<Q> add value "n" to q-register <Q>; Make n^T type out
;	ASCII character of value "n". Both are under control of EO=3.
;
;257	LEO	20-SEP-85
;	Copyrights.
;
;[END OF REVISION HISTORY]
;DEFAULT DEFINITIONS FOR ASSEMBLY SWITCHES & PARAMETERS:

ND	ERRMSG,2		;MEDIUM LENGTH ERROR MESSAGES
ND	AUTOFS,0		;DEFAULT IS NON-AUTOTYPE AFTER SEARCHES
ND	TYCASW,0		;DEFAULT TYPE-OUT MODE CAUSES FLAGGING OF
				;CHARACTERS IN THE LOWER CASE RANGE WITH '
ND	SRCHSW,0		;DEFAULT PREVAILING SEARCH MODE IS ACCEPT
				;EITHER LC OR UC ALPHABETICS AS A MATCH
ND	SRCHMX,^D200		;MAXIMUM CHARACTERS IN A SEARCH STRING
ND	EOVAL,3			;THE STANDARD SETTING OF THE EO FLAG FOR
				;THIS VERSION IS 3 (^R/^W/^U EDITING)
ND	BUGSW,1			;STANDARD IS SAVE SYMBOLS

ND	TEBPRT,077		;DEFAULT CRASH FILE PROTECTION
ND	TEBSAV,^D128		;UPDATE CRASH RECOVERY FILE EVERY TEBSAV CHARS
				; (CAN BE OVERRIDDEN VIA /CRSAVE:NNN)

ND	HIORGP,600		;HIGH SEG ORIGIN PAGE
ND	CSECTN,1		;CODE SECTION FOR EXTENDED ADDRESSING
ND	DSECTN,3		;DATA SECTION FOR EXTENDED ADDRESSING
ND	LSECTN,6		;LAST SECTION FOR EXTENDED ADDRESSING
				;  (LSECTN+1 = FIRST FREE SECTION)

ND	PDLEN,^D200		;LENGTH OF PROGRAM STACK
ND	LPF,40			;32 WORD Q-REGISTER PDL
ND	QRGMAX,44		;NUMBER OF Q-REGISTERS (A-Z; 0-9)

ND	CMFMAX,4		;LEVELS COMMAND FILES MAY NEST.

ND	XSPGMX,4		;MAXIMUM "IDLE" PAGES TO CARRY AROUND
				;ANY IN EXCESS WILL BE DEALLOCATED

ND	RMWAIW,1000		;RANDOM MEMORY ALLOCATION INCREMENT (WORDS)
ND	COMAIW,200		;COMMAND BUFFER ALLOCATION INCREMENT (WORDS)
ND	TMPBSZ,200		;SIZE OF TMPCOR BUFFER

ND	DSKBFN,3		;NUMBER OF INPUT BUFFERS
ND	DSKBSZ,^D128		;SIZE OF DISK INPUT BUFFERS
				;  THIS UTILIZES ONE PAGE OF BUFFER SPACE.
				;  TECO IS SUFFICIENTLY COMPUTE BOUND THAT
				;  USING MANY/LARGE BUFFERS DOES NOT RUN
				;  ANY FASTER.

ND	TTIBFN,1		;NUMBER OF TERMINAL INPUT BUFFERS
ND	TTIBSZ,30		;SIZE OF TERMINAL INPUT BUFFER(S)
ND	TTOBFN,2		;NUMBER OF TERMINAL OUTPUT BUFFERS
ND	TTOBSZ,100		;SIZE OF TERMINAL OUTPUT BUFFERS

ND	TTLMAX,^D36		;MAXIMUM SCREEN LENGTH WE CAN HANDLE
ND	TTWMAX,^D132		;MAXIMUM SCREEN WIDTH WE CAN HANDLE
	WINDEX==<<TTWMAX+2>/5>+1;INTERNAL LINE STORAGE ALLOCATION SIZE
	WINTOP==TTLMAX*WINDEX	;INTERNAL SCREEN STORAGE ALLOCATION SIZE

ND	RUN603,0		;ALLOW TO RUN UNDER 6.03 MONITORS
ND	TTY603,'VT52  '		;TERMINAL TYPE TO USE FOR 6.03
;ACCUMULATOR ASSIGNMENTS

FF=	0	;CONTROL FLAGS
T=	1
TT=	2	;*** TT AND TT1 MUST BE ADJACENT ***
TT1=	3
A=	4	;*** A, AA AND B MUST BE CONTIGUOUS AND IN THAT ORDER ***
AA=	5	;TYPE-IN POINTER TO COMMAND BUFFER & SEARCH TABLE INDEX
B=	6	;*** B AND E MUST BE ADJACENT ***
E=	7
C=	10
D=	11
F2=	12	;MORE CONTROL FLAGS
I=	13	;"INPUT" CHARACTER ADDRESS
OU=	14	;"OUTPUT" CHARACTER ADDRESS (MUST BE I+1)
CH=	15	;CHARACTER AC
PF=	16	;Q-REGISTER PDL PTR
P=	17	;PROGRAM STACK

;DIFFERENT AC DEFINITIONS FOR INTERFACING WITH SCAN/WILD
;THESE WILL HAVE TO BE RECONCILED WITH TECO'S CONVENTIONS SOMEDAY

T1=1		;TEMP ACS
T2=T1+1
T3=T2+1
T4=T3+1
P1=5		;PERM ACS
P2=P1+1
P3=P2+1
P4=P3+1
;CONTROL FLAGS
;RIGHT HALF - AC FF

ALTF==	1B35		;ALT-MODE SEEN
ARG2==	1B34		;THERE IS A SECOND ARGUMENT
ARG==	1B33		;THERE IS AN ARGUMENT
SLSL==	1B32		;@ SEEN
PCHFLG==1B31		;N SEARCH
COLONF==1B30		;COLON SEEN
COLONP==1B29		;FREE "()" DUE TO COLON MODIFIER IN EFFECT
SYLF==	1B28		;SYLLABLE FLAG
XPLNFL==1B27		;HAVE TYPED EXTENSION OF ERROR MESSAGE ALREADY
EMFLAG==1B26		;HAVE TYPED 1ST LINE OF ERROR MESSAGE
FINDR==	1B25		;LEFT ARROW SEARCH
QMFLG==	1B24		;PROCESSING ERROR MESSAGE
SEQUIN==1B23		;OUTPUT: AFTER EOL NEXT 5 CHARS ARE SEQ #
TRACEF==1B22		;? SEEN
SEQF==	1B21		;SEQUENCE NUMBER SEEN ON INPUT
BELLF==	1B20		;^G SEEN
;	1B19		;FREE
FORM==	1B18		;A FORM FEED TERMINATED THE LAST YANK OR APPEND COMMAND

;LEFT HALF - AC FF

F.NNUL==1B17		;NON-NULL INSERT STRING (MIGHT BE ONLY ^V, SAY)
PMATCH==1B16		;PREVAILING MATCH MODE
TABSRT==1B15		;TABBED INSERT (<TAB> COMMAND)
TIBKA== 1B14		;INPUT IN [BREAK ON ALL] CHARACTER MODE
TINEC== 1B13		;DON'T ECHO INPUT CHARACTERS
TMPFLG==1B12		;TMPCOR UUO ALLOWED
FINF==	1B11		;INPUT CLOSED BY EOF
UREAD==	1B10		;INPUT FILE IS OPEN
UWRITE==1B09		;OUTPUT FILE IS OPEN
CFOF==	1B08		;COMMAND FILE OPEN, USE IT RATHER THAN TTY
EZTMP== 1B07		;THIS COMMAND IS EZ, NOT EW
FEXTF==	1B06		;FILE EXT EXPECTED (.TYPED).
UBAK==	1B05		;EB IN EFFECT
;	1B04		;FREE
TYOF==	1B03		;NEED TO OUTPUT A BUFFER
TYOCTF==1B02		;ALLOW CONTROL CHARS TYPED WITHOUT "^"
CCLFLG==1B01		;TECO COMMAND REQUESTS Y AFTER EB
;CONTROL FLAGS
;RIGHT HALF - AC F2

CTLVA==	1B35		;^V/A SEEN INSIDE TEXT
CTLVVA==1B34		;DOUBLE ^V/A SEEN INSIDE TEXT
CTLWB==	1B33		;^W/^B SEEN INSIDE TEXT
CTLWWB==1B32		;DOUBLE ^W/^B SEEN INSIDE TEXT
XMATCH==1B31		;EXACT MATCH SEARCH MODE
EMATCH==1B30		;TEMPORARILY ACCEPT EITHER UPPER OR LOWER CASE
LINCHR==1B29		;TTY LINE HAS LC BIT ON
TYMSGF==1B28		;TYPE MESSAGE WITH NO CASE FLAGGING
OCTALF==1B27		;OCTAL RADIX
CQUOTE==1B26		;QUOTE THE NEXT COMMAND CHARACTER
SKIMRF==1B25		;WATCH FOR ^R WHEN SKIMMING
SKIMQF==1B24		;WATCH FOR ^Q WHEN SKIMMING
NOTRAC==1B23		;DISABLE TRACING
TYSPCL==1B22		;TYPE <CR>, ETC INSTEAD OF PRINTER CONTROLS
SKANFS==1B21		;SKANNING FS OR FN
TXTCTL==1B20		;NO CONTROL COMMANDS IN TEXT EXCEPT ^T, ^R
LCASE==	1B19		;CONVERT UPPER CASE TO LOWER CASE BY DEFAULT
UCASE==	1B18		;CONVERT LOWER CASE TO UPPER CASE BY DEFAULT

XCASE==UCASE!LCASE!CTLVA!CTLVVA!CTLWB!CTLWWB	;ANY CASE CONTROL

;LEFT HALF - AC F2

GOING== 1B17		;A COMMAND STRING HAS BEEN SEEN
DOING==	1B16		;AND IS BEING EXECUTED NOW
CTXN==	1B15		;^N IN SEARCH ARGUMENT
NOALT== 1B14		;DON'T CONVERT OLD ALTMODES TO 033
NALTFS==1B13		;NULL REPLACEMENT ALTMODE DELIMITED F SEARCH

SFDS==  1B12		;SUB FILE DIRECTORIES ARE IN EFFECT
LSNINF==1B11		;IGNORE CHAR AFTER SEQ# IF IT'S A TAB OR CR
			;REPLACES USE OF SEQUIN
LSNF==  1B10		;A LSN WAS SEEN SOMETIME IN THE TEXT BUFFER
CBTMF== 1B09		;CLEAR TO EOS IN GO BEFORE CLIS
S.MINS==1B08		;MINUS SEARCH
S.REPL==1B07		;FIND AND REPLACE SEARCH
S.DELE==1B06		;FD COMMAND
S.KILL==1B05		;FK COMMAND
S.FRCM==1B04		;FR COMMAND
;CHARACTER ECHO CONTROL FLAGS

EC$UPA==1B0	;ECHO AS ^X
EC$SLF==1B1	;ECHO AS SELF
EC$DLR==1B2	;ECHO AS "$"
EC$CRL==1B3	;ECHO WITH <CR><LF> APPENDED


;I/O CHANNELS

INCHN==	2
OUTCHN==3
TTYCHN==4	;CHANNEL FOR TTY IO
  TTYIOS==IO.FCS+.IOASC	;BASIC TTY I/O MODE
CCLCHN==5	;CHANNEL FOR THE CCL TMP FILE
ERRCHN==6	;CHANNEL FOR ERROR MESSAGE FILE
TEBCHN==7	;CRASH RECOVERY FILE I/O CHANNEL
CMFCHN==10	;COMMAND ("E@") FILE I/O CHANNEL
;MISC PARAMETERS

BEGPAG==200	;FAKE ASCII CHAR = BEGINNING OF BUFFER
ENDPAG==201	;FAKE ASCII CHAR = END OF BUFFER IF NO EOL AT END
SPCTAB==202	;FAKE ASCII CHAR = SIGNAL TO SEARCH FOR A STRING OF SPACE/TABS
SMATXN==^D131	;Number of characters in the search matricies
BITMLN==SMATXN/^D36+1 ;Number of words needed to hold SMATXN bits


STABLN==^D131	;LENGTH OF SEARCH TABLE
GCTBLN==100	;GARBAGE COLLECTION TABLE(S) SIZE

EO21==1		;TECO %22+ FEATURES
EO25==2		;TECO %25+ NEW HANDLING OF ^R, ^W, ^V, ^G; ^T AND % COMMANDS

FXVRSN==<12,,%%FXVE>	;SCAN/WILD PROTOCOL VERSION

BLKSIZ==200	;SIZE OF DISK BLOCK IN WORDS

PAGSIZ==1000	;SIZE OF MEMORY PAGE IN WORDS
  PG2WRD==^D9	;LSH OF PAGE ADDRESS TO WORD ADDRESS
  WRD2PG==-^D9	;LSH OF WORD ADDRESS TO PAGE ADDRESS
;OPERATORS

;TEMP (HA!)

	OPDEF	IFIW	[1B0]
		.NODDT	IFIW		;KEEP SETZ OPCODE

	IFX2EF==^D17-^D05		;LSH FOR IFIW INDEX TO EFIW INDEX


;CHECK EO FLAG: CHKEO	EO#,ADDR
;IF EOFLAG GREATER THAN EO#, RETURN AT CALL+1
;OTHERWISE GO TO ADDR

; OPDEF Local UUOS
;
	OPDEF	MSG.	[1B8]		;Verbosity controlled message processor
	OPDEF	CHKEO	[20B8]		;EO flag checking

; Macro to generate a comment message
;
DEFINE	$INFO	(PFX,ADR,TXT),<
	MSG.	0,[''PFX'',,[ASCIZ |TXT|]
		   IFB	<ADR>,<EXP .+1>
		   IFNB	<ADR>,<EXP ADR>
		  ]
>


; Macro to generate a warning message
;
DEFINE	$WARN	(PFX,ADR,TXT),<
	MSG.	1,[''PFX'',,[ASCIZ |TXT|]
		   IFB	<ADR>,<EXP .+1>
		   IFNB	<ADR>,<EXP ADR>
		  ]
>


; Macro to generate a fatal message
;
DEFINE	$FATAL	(PFX,ADR,TXT),<
	MSG.	2,[''PFX'',,[ASCIZ |TXT|]
		   IFB	<ADR>,<EXP GO>
		   IFNB	<ADR>,<EXP ADR>
		  ]
>
;MACRO TO DEFINE DATA LOCATIONS

DEFINE U(A,B)<
RELOC
A:	BLOCK	B
RELOC
>
SUBTTL	Program entry and initialization

	TWOSEG	<HIORGP_PG2WRD>

U LOCORE,0			;START OF DATA AREA

COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1984,1986. ALL RIGHTS RESERVED.
\ ;END COPYRIGHT\

TECO:	TDZA	B,B		;NORMAL PROGRAM ENTRY
	MOVNI	B,1		;THE CCL ENTRY
	RESET			;INITIALIZE ALL IO
	MOVE	P,[IOWD PDLEN,PDLST]  ;INITIALIZE STACK
	SKIPN	CH,SECTN	;WERE WE RUNNING EXTENDED (^C, START)?
	JRST	TECO01		;NO
	HRRI	CH,TECO05	;YES
	XJRST	CH		;SO GET BACK TO DESIGNATED PC SECTION

;SELECT A SECTION IF FEASIBLE

TECO01:	XMOVEI	CH,777		;GET CURRENT PC SECTION
	HLRZ	CH,CH		;REDUCE TO JUST SECTION NUMBER
	JUMPE	CH,TECO02	;IF IN SECTION 0 (NORMAL) JUST INITIALIZE
	CAIN	CH,CSECTN	;WERE WE MAGICALLY STARTED IN CODE SECTION?
	JRST	TECO05		;YES, ALL SET HERE, NO FINAGALING NEEDED
	OUTSTR	[ASCIZ\? DTECO knows better than you in which section to run!\]
	EXIT			;PISS ON MEDDLING USER

;RUNNING IN SECTION 0, TRY FOR DESIGNATED EXTENDED PC SECTION (CSECTN)

TECO02:	MOVE	TT1,[PA.GMS!<0,,CSECTN>]  ;MAP SECTION 0 INTO SECTION CSECTN
	MOVEI	TT,1		;ONLY MAP ONE SECTION
	MOVE	T,[.PAGSC,,TT]	;PAGE. ARG POINTER TO
	PAGE.	T,		;TRY FOR EXTENDED PC SECTION
	 JRST	TECO05		;NOPE, OH WELL, NO BIG DEAL
	XJRST	[CSECTN,,TECO05];GOT IT
;RESET MEMORY (IN CASE ^C, START)

TECO05:	SETZB	FF,F2		;INITIALIZE FLAGS
	SETZM	LOCORE		;CLEAR DATA IN CASE OF ^C,ST
	MOVE	A,[XWD LOCORE,LOCORE+1]  ;BLT POINTER TO
	BLT	A,LOWEND-1	;CLEAR IMPURE STORAGE
	MOVEM	B,CCLSW		;REMEMBER HOW WE WERE STARTED

;FLAG RUNNING EXTENDED OR SECTION-0 (E.G., 7.02, KS10, ETC.)

	XMOVEI	A,777		;CURRENT PC SECTION
	HLLZM	A,SECTN		;REMEMBER CURRENT PC SECTION
	LSH	A,WRD2PG	;MAKE "PAGE NUMBER" OFFSET
;***				;MUST USE SECTION 0 PAGE ADDRESSES!!!
;***	MOVEM	A,SECTNP	;REMEMBER PC SECTION PAGE OFFSET

;GET RID OF DANGLING I/O BUFFER PAGES AND THE LIKE

	MOVE	TT,.JBREL	;HIGHEST LOCATION IN LOW SEGMENT
	ADDI	TT,PAGSIZ-1	;ROUND UP AND
	LSH	TT,WRD2PG	;TRUNCATE TO PAGE ADDRESS
	MOVEI	T,HIORGP-1	;FIRST PAGE IN HIGH SEGMENT
	SUB	T,TT		;MAKE COUNT OF PAGES THAT SHOULDN'T EXIST
	JUMPE	T,TECO07	;NO PAGES TO DELETE
	ADD	TT,A		;RELOCATE TO PAGES IN CURRENT SECTION
	PUSHJ	P,PGZAP		;MAKE SURE PAGES DON'T EXIST
	 HALT	.		;BLETCH

;GET RID OF DANGLING DATA SECTIONS

TECO07:	SKIPN	SECTN		;RUNNING EXTENDED
	JRST	TECO10		;NO
	MOVEI	T,<LSECTN-DSECTN+1>  ;MAX DATA SECTIONS POSSIBLE
	MOVEI	TT,DSECTN	;FIRST POSSIBLE DATA SECTION
	PUSHJ	P,PSZAP		;MAKE SURE THEY DON'T EXIST
	 HALT	.		;EXTENDED BLETCH

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

TECO10:	PUSHJ	P,TTOPEN	;GO OPEN TTY
	PUSHJ	P,GETTYP	;FIGURE OUT WHAT KIND OF SCREEN
	PUSHJ	P,TTYGET	;GET AND REMEMBER INITIAL TTY MODES
	MOVEI	A,1		;SET TABS
	MOVEM	A,OURTAB	;SET NO TAB CONVERSION
	MOVEM	A,OURFCR	;SET NO FREE CRLF
	MOVEM	A,OURDEM	;SET DEFERRED ECHO MODE
	SETZM	OURBLN		;SET NO BLANK SUPPRESSION
	SETZM	OURPSZ		;SET PAGE 0
	SETZM	OURSTO		;SET NO STOP
	PUSHJ	P,TTYSET	;SETUP TECO TERMINAL CHARACTERISTICS
	SKIPE	SCTYPE		;IF VIDEO SCREENING
	PUSHJ	P,CLRSCN	;THEN CLEAR SCREEN
	MOVSI	A,(ASCII */\*)
	MOVEM	A,PTRCHR	;WHAT POINTER LOOKS LIKE ON SCREEN
	SETOM	SCH		;SO FIRST CHARACTER IS TTYED

	PUSHJ	P,UUOINI	;INITIALIZE UUO HANDLER
	 HALT	.		;CAN'T RECOVER FROM THIS
	PUSHJ	P,PSIINI	;INITIALIZE PSI SERVICE (^C TRAP IN PARTICULAR)
	 HALT	.+1		;CAN'T INIT PSI????

;*** THIS IS A KROCK, BUT WHAT CAN I SAY?

	MOVE	A,[BOSWT,,BOSWT+1]  ;START OF SWITCHES BLOCK
	SETOM	BOSWT		;INITIALIZE SWITCHES
	BLT	A,EOSWT		;TO NO VALUE SEEN FLAG
	JSP	OU,CALLSW	;CALL SCAN/WILD
		ISLEN,,ISBLK		;MOVE	T1,[ISLEN,,ISBLK]
		IFIW	.ISCAN##	;PUSHJ	P,.ISCAN##
	JSP	OU,CALLSW	;CALL SCAN/WILD
		OSLEN,,OSBLK		;MOVE	T1,[OSLEN,,OSBLK]
		IFIW	.OSCAN##	;PUSHJ	P,.OSCAN##

;*** END OF THE KROCK

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

TECO20:	MOVE	TT,.JBFF	;FIRST FREE LOSEG LOCATION
	MOVEM	TT,RMWBAS	;BECOMES BASE FOR RANDOM MEMORY ALLOCATION
	MOVEM	TT,RMWEND	;SET END ADDRESS FOR RANDOM MEMORY

	SKIPE	SECTN		;RUNNING EXTENDED?
	MOVSI	TT,DSECTN	;YES, SELECT FIRST DATA SECTION AS BASE ADDRESS
	MOVEM	TT,CMDBAS	;SET BASE ADDRESS FOR COMMAND BUFFER
	MOVEM	TT,CMDEND	;ALSO END ADDRESS FOR COMMAND BUFFER SO FAR
	MOVSI	T,(POINT 7,0,-1);PROTOTYPE BYTE POINTER
	SKIPE	SECTN		;PC IN EXTENDED SECTION?
	TLOA	T,(1B12)	;YES, USE DOUBLE-WORD BYTE POINTER
	HRR	T,TT		;NO, USE SINGLE-WORD BYTE POINTER
	DMOVEM	T,CMDPTR	;SET MASTER COMMAND BUFFER BYTE POINTER
	IMULI	TT,5		;CONVERT TO TEXT ADDRESS
	MOVEM	TT,QRBUF	;SET Q-REG/ETC BASE ADDRESS
	MOVEM	TT,BEG		;SET BEGIN ("B") ADDRESS OF EDITING TEXT
	MOVEM	TT,PT		;SET CURSOR (".") ADDRESS WITHIN EDITING TEXT
	MOVEM	TT,Z		;SET END ("Z") ADDRESS FOR EDITING TEXT
	SKIPN	SECTN		;RUNNING EXTENDED?
	SKIPA	TT,.JBREL	;NO, LOCAL CURRENT MEMORY LIMIT (WORDS)
	HRLOI	TT,DSECTN-1	;YES, GLOBAL CURRENT MEMORY LIMIT (WORDS)
	IMULI	TT,5		;CURRENT MEMORY LIMIT (CHARACTERS)
	MOVEM	TT,MEMSIZ	;SET END ADDRESS FOR Q-REG/TEXT MEMORY
	SETOM	MESFLG		;ON STARTUP THE SCREEN IS ALL MESSED UP!
				; THIS WILL FORCE INITIALIZATION OF SCRN??
				; VARIABLES

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

TECO30:	MOVE	A,[F%FDAE&<-1,,0>!.GTFET]	;GETTAB FTFDAE
	GETTAB	A,		;NEED TO KNOW IF FILE DAEMON
	  SETZ	A,		;MONITOR FOR EB STUFF
	SETZM	FDAEM		;ASSUME NOT
	TXNE	A,F%FDAE&<0,,-1>;FILE DAEMON MONITOR?
	SETOM	FDAEM		;YES, SIGN BIT OF .RBPRV CHANGED
	MOVE	C,[%FTSTR]	;FIND OUT IF SFDS ARE USED
	GETTAB	C,		;...
	JRST	.+2		;ASSUME SO
	TXNE	C,F%SFD &<0,,-1>;SFDS HERE?
	TXO	F2,SFDS		;YES, SET THE FLAG

	MOVE	A,.MYJOB##	;GET OUR JOB NUMBER
	MOVEI	C,3		;WANT THREE DIGITS' WORTH
TECO40:	IDIVI	A,12		;CONVERT JOB NUMBER TO SIXBIT
	ADDI	AA,20
	LSHC	AA,-6
	SOJG	C,TECO40
	HRRI	B,'TEC'		;FORM NAME ###TEC
	MOVEM	B,TMPTEC	;SAVE
	HRREI	A,TYCASW	;GET DEFAULT TYPE-OUT CASE FLAGGING MODE
	MOVEM	A,TYCASF	;AND MAKE IT CURRENT
	HRROI	A,.GTLIM	;THE "BATCH" JOB TABLE
	GETTAB	A,		;READ MONITOR INFORMATION
	 SETZ	A,		;DUH?
	TXNE	A,JB.LBT	;ARE WE A BATCH JOB?
	SKIPGE	A,S.EOBA	;YES, GET BATCH EO VALUE
	MOVE	A,S.EOMO	;NO (OR NO /EOBATCH), GET TIMESHARING EO
	CAIG	A,EOVAL		;USER GIVE AN EOVAL WITHIN REASON?
	CAIGE	A,0		;DID USER SPECIFY EITHER /EOMODE OR /EOBATCH?
	MOVEI	A,EOVAL		;NO, PICKUP SYSTEM DEFAULT
	MOVEM	A,EOFLAG	;AND SET OUR EO RUNTIME VALUE
	MOVEM	A,EOFLAG
	HRREI	A,ERRMSG-2	;SET ERROR MESSAGE TYPE INDICATOR
	MOVEM	A,ERRLEN	;-1=SHORT, 0=MEDIUM, +1=LONG
	HRREI	A,AUTOFS	;INIT AUTOTYPE-AFTER-SEARCHES FLAG
	MOVEM	A,AUTOF

;FALL THROUGH TO NEXT PAGE
;COMPUTE A VALUE WHICH IS 2/3 THE SIZE OF THE CHARACTER BUFFER.IF
;1/3 IS LESS THAN 128 CHARACTERS, THE BUFFER WILL BE 2/3 FILLED ON
;A "Y" OR "A" COMMAND,OTHERWISE, THE BUFFER WILL BE FILLED TO THE
;TOTAL AVAILABLE BUFFER - 128 CHARACTERS. PAYING ATTENTION TO THE
;FORM FEED AND LF OPERATORS.

;IT SHOULD BE NOTED THAT IN THE CASE OF AUTOMATIC
;MEMORY EXPANSION, THESE INSTRUCTIONS MUST BE RE-EXECUTED
;TO INSURE PROPER MEMORY BOUNDS.

TECO50:	MOVEI	A,SYL
	MOVEM	A,DLIM		;DLIM:=SYL
	MOVEI	FF,0		;CLEAR FLAG REGISTER
IFN SRCHSW,<TXO	FF,PMATCH>	;MAKE EXACT MODE CURRENT
	XMOVEI	T,RENTR		;OUR "REENTER" ADDRESS
	MOVEM	T,.JBREN	;SET IT UP TOO
	JRST	GO		;START TECO'ING
	SUBTTL	REENTER COMMAND RECOVERY

RENTR:	MOVE	P,[IOWD PDLEN,PDLST]  ;[RE]INITIALIZE PUSHDOWN STACK
	SKIPN	CH,SECTN	;RUNNING EXTENDED ADDRESSING?
	JRST	RENTR1		;NO
	HRRI	CH,RENTR1	;YES
	XJRST	CH		;[RE]ENTER SELECTED PC SECTION

RENTR1:	PUSHJ	P,TTOPEN	;GO [RE]OPEN TERMINAL CHANNEL
	PUSHJ	P,GETTYP	;FIND OUT WHAT TYPE OF TERMINAL WE NOW HAVE
	PUSHJ	P,TTYGET	;GET AND REMEMBER TTY MODES BECAUSE USER
				;MAY HAVE CHANGED THEM WHILE AT MONITOR LEVEL
	PUSHJ	P,TTYSEC	;RESTORE OUR OWN MODES

;FAKE OUT THE CRASH FILE

	MOVEI	CH,.CHBEL	;A ^G CHARACTER
	PUSHJ	P,TEBCHR	;STUFF IN FIRST ^G
	PUSHJ	P,TEBCHR	;A SECOND ^G IN CASE THE FIRST GETS CAUGHT
				; BY A "DANGLING" ^V IN THE CRASH FILE
	MOVEI	CH,.CHCNU	;A ^U CHARACTER
	PUSHJ	P,TEBCHR	;ABORT LAST POSSIBLE PARTIAL COMMAND
	PUSHJ	P,TEBJ		;ISSUE NNNJ$$ COMMAND SO WE KNOW WHERE WE ARE

;OTHER RANDOM CLEANUP

	PUSHJ	P,TYICNR	;ZAP COMMAND FILE (IF ANY)
	SETOM	SCH		;SO CHARACTER COMES FROM TTY
	SETOM	MESFLG		;ASSUME DISPLAY IS AMUCK
	SETZM	WINFLG		;SO DISPLAY HAPPENS
	SETZM	VFREEZ		; . . .

;RESUME TECO'ING

	XMOVEI	T,GO		;ADDRESS FROM WHENCE TO RESUME
	MOVEM	T,PSICCV+.PSVOP	;SET FOR DEBRK. TO SEE
	DEBRK.			;ALLOW FURTHER CONTROL-C'S
	 JRST	GO		;MUST HAVE BEEN ?ILL MEM REF OR SUCH
	 JRST	GO		; WHICH TOOK US TO MONITOR LEVEL
;SCAN/WILD INTERFACE STUFF

;CALLSW -- CALL A SCAN/WILD ROUTINE
;CALL IS:
;
;	JSP	OU,CALLSW
;		<ARG>
;		<RTN>
;	 NON-SKIP RETURN
;	SKIP RETURN
;
;WHERE <ARG> IS THE ARGUMENT TO BE PASSED IN SCAN'S T1; AND <RTN> IS
;THE ROUTINE TO BE CALLED.
;
;SKIP OR NON-SKIP RETURN IS PRESERVED.
;
;PRESERVES ALL ACS.

CALLSW:	PUSH	P,T1		;SAVE
	PUSH	P,T2		; SCAN'S
	PUSH	P,T3		;  VOLATILE
	PUSH	P,T4		;   ACS
	MOVE	T1,(OU)		;FETCH T1 ARGUMENT
	PUSHJ	P,@1(OU)	;CALL SCAN/WILD ROUTINE
	 HRRI	OU,-1(OU)	;NON-SKIP RETURN
	DMOVEM	T1,SCNT1	;SAVE WHAT SCAN RETURNED US
	DMOVEM	T3,SCNT3	; . . .
	POP	P,T4		;   RESTORE
	POP	P,T3		;  SCAN'S
	POP	P,T2		; VOLATILE
	POP	P,T1		;ACS
	JRST	3(OU)		;RETURN TO CALLER


U SCNT1,1			;SCAN'S RETURNED T1
U SCNT2,1			; AND T2
U SCNT3,1			;  AND T3
U SCNT4,1			;   AND T4
;TECO/SCAN CHARACTER I/O

;SCNTYI  --  RETURN ONE COMMAND INPUT CHARACTER

SCNTYI:	MOVEI	P4,.CHLFD	;HMMM
	POPJ	P,		;GO AWAY AGAIN


;SCNTYO  --  TYPE ONE COMMAND TERMINAL CHARACTER

SCNTYO:	PUSHJ	P,TECCTX	;SWITCH TO TECO ACS
	PUSH	P,CH		;SAVE A REG
	PUSH	P,A		; AND ANOTHER REG
	PUSH	P,AA		;  AND YET ANOTHER REG
	MOVE	CH,SCNACS+T1	;THE CHARACTER SCAN WANTS TO OUTPUT
	PUSHJ	P,TYOM		;TYPE A CHARACTER
	POP	P,AA		;  RESTORE A REG
	POP	P,A		; AND ANOTHER REG
	POP	P,CH		;AND YET ANOTHER REG
	PJRST	SCNCTX		;SWITCH BACK TO SCAN


;SCNTYS  --  TYPE ONE SPECIAL CHARACTER (E.G., "<ESC>")

SCNTYS:	PUSHJ	P,TECCTX	;SWITCH TO TECO ACS
	PUSH	P,CH		;SAVE A REG
	PUSH	P,A		; AND ANOTHER REG
	PUSH	P,AA		;  AND YET ANOTHER REG
	MOVE	CH,SCNACS+T1	;THE CHARACTER SCAN WANTS TO OUTPUT
	PUSHJ	P,TYOS		;TYPE A SPECIAL CHARACTER
	POP	P,AA		;  RESTORE A REG
	POP	P,A		; AND ANOTHER REG
	POP	P,CH		;AND YET ANOTHER REG
	PJRST	SCNCTX		;SWITCH BACK TO SCAN
;SCNCTX  --  SWITCH TO SCAN/WILD CONTEXT

SCNCTX:	MOVEM	10,TECACS+10	;Save AC 10
	MOVEI	10,TECACS	;Set up BLT
	BLT	10,TECACS+10-1	;Save TECO's ACs
	MOVSI	10,SCNACS	;SCAN'S ACS
	BLT	10,10		;SET THEM UP
	POPJ	P,		;Return in SCAN's context


;TECCTX  --  SWITCH TO TECO CONTEXT

TECCTX:	MOVEM	10,SCNACS+10	;Save AC 10
	MOVEI	10,SCNACS	;Set up BLT
	BLT	10,SCNACS+10-1	;Save SCAN's ACs
	MOVSI	10,TECACS	;Address of TECO context acs
	BLT	10,10		;Back to TECO mode
	POPJ	P,		;Return in TECO's context


U	TECACS,10		;TECO's ACs
U	SCNACS,10		;SCAN's ACs
;SWITCH DEFINITIONS

DM	CRF,.FXLEN,0,0
DM	INI,.FXLEN,0,0

DEFINE	SWTCHS,<
SL	CRDISP,S.CRDI,$TB,$TBDEL,FS.NFS!FS.VRQ
SP	CRFILE,S.CRFI,.SWFIL##,CRF,FS.NFS!FS.VRQ
SP	CRPROT,S.CRPR,.SWOCT##,,FS.NFS!FS.VRQ
SP	CRSAVE,S.CRSA,.SWDEC##,,FS.NFS!FS.VRQ
SN	EAMODE,S.EAMO,FS.NFS
SP	EOBATC,S.EOBA,.SWDEC##,,FS.NFS!FS.VRQ
SP	EOMODE,S.EOMO,.SWDEC##,,FS.NFS!FS.VRQ
SP	INITFI,S.INIT,.SWFIL##,INI,FS.NFS!FS.VRQ
SN	OKLSN,S.OKLS,FS.NFS
SN	OKNULL,S.OKNU,FS.NFS
SN	SFT,S.SFT,FS.NFS
>

KEYS	($TB,<NEVER,TEMPORARY,DELETE,PRESERVE>)

DOSCAN(TECSW)
;DATA BLOCKS

;FOR SCAN

;MONITOR COMMAND TABLE

CCMDT:	'MAKE  '		;CREATE A NEW FILE
	'TECO  '		;EDIT AN EXISTING FILE

	CCMDL==.-CCMDT

;ISCAN PARAMETER BLOCK

ISBLK:	EXP	FXVRSN		;SCAN/WILD PROTOCOL VERSION WORD
	IOWD	CCMDL,CCMDT	;IOWD OF LEGAL MONITOR COMMANDS
	CCLSW,,'TEC'		;ADR OF STARTING OFFSET,,CCL NAME
	0,,SCNTYO		;CHAR INPUT RTN,,CHAR OUTPUT RTN
	Z			;INDIRECT FILE BLOCK POINTER (XWD)
	Z			;PROMPT RTN,,MONRET RTN
	Z			;FLAGS,,<FUTURE>
	Z			;ERROR INTERCEPT RTN

	ISLEN==.-ISBLK

;TSCAN PARAMETER BLOCK

;TSBLK:	EXP	FXVRSN		;SCAN/WILD PROTOCOL VERSION WORD
;	IOWD	TECSWL,TECSWN	;IOWD POINTER FOR SWITCH NAMES
;	XWD	TECSWD,TECSWM	;DEFAULT TABLE,,PROCESSOR TABLE
;	XWD	0,TECSWP	;<FUTURE>,,STORAGE POINTERS
;	SIXBIT	/TECO/		;HELP
;	XWD	CLRALL,0	;CLEAR ALL,,CLEAR FILE
;	XWD	INX,OUX		;ALLOC INPUT AREA,,ALLOC OUTPUT AREA
;	Z			;MEMORIZE STICKY,,APPLY STICKY
;	Z			;CLEAR STICKY,,FLAGS
;	Z			;<FUTURE>,,SWITCH VALUE STORAGE RTN
;
;	TSLEN==.-TSBLK

;OSCAN BLOCK

OSBLK:	EXP	FXVRSN		;SCAN/WILD PROTOCOL VERSION WORD
	IOWD	TECSWL,TECSWN	;IOWD POINTER FOR SWITCH NAMES
	XWD	TECSWD,TECSWM	;DEFAULT TABLE,,PROCESSOR TABLE
	XWD	0,TECSWP	;<FUTURE>,,STORAGE POINTERS
	SIXBIT	/TECO/		;HELP
	SIXBIT	/TECO/		;OPTIONS NAME

	OSLEN==.-OSBLK
;FOR WILD

;LKBLK:	EXP	FXVRSN		;SCAN/WILD PROTOCOL VERSION WORD
;	WIFIR,,WILAS		;<FIRST,,LAST> SCAN BLOCK POINTER ADR
;	INOPN,,INFIL		;<OPEN,,LOOKUP> BLOCK ADDRESS
;	.FXLEN,,FILLEN		;SCAN BLOCK LENGTH,,LOOKUP LENGTH
;	0,,WICUR		;FLAGS!CHANNEL,,CUR SCNBLK PTR ADR
;	Z			;END OF DIRECTORY RTN
;
;	LKLEN==.-LKBLK


;SCBLK:	EXP	FXVRSN		;SCAN/WILD PROTOCOL VERSION WORD
;	WICUR,,[OUSCN]		;<CUR INPUT,,OUTPUT> SCNBLK PTR ADR
;	INOPN,,OUOPN		;<INPUT,,OUTPUT> OPEN BLK ADR
;	INFIL,,OUFIL		;<INPUT,,OUTPUT> FILE BLK ADR
;	[0,,-1],,FILLEN		;DEFAULT EXT ADR,,FILE BLK LEN
;	0,,SCFLG		;<FUTURE>,,SCWILD PROCESSING FLAGS
;
;	SCLEN==.-SCBLK
;THIS PAGE CONTAINS THE COMMAND READER FOR THE CCL SYSTEM

CCLDSK:	.IOASC			;ASCII I/O
	'DSK   '		;TO A DISK DEVICE
	0,,CCLB			;INPUT BUFFER RING HEADER

U CCLB,3			;THE HEADER FOR CCL FILE I/O

CCLIN:	HRRZ	TT,.JBFF	;GET FIRST FREE
	ADDI	TT,TMPBSZ	;LAST LOC USED IN TMPCOR
	CAMG	TT,.JBREL	;ENOUGH ROOM?
	JRST	CCLIN2		;YES, JUST READ IN BUFFER
	LSH	TT,WRD2PG	;NO, MAKE PAGE ADDRESS
	ADD	TT,SECTNP	;OFFSET TO PC SECTION
	PUSHJ	P,P1CRE		;ALLOCATE ANOTHER MEMORY PAGE
	 HALT	.		;BAD NEWS
CCLIN2:	HRLI	T,'EDT'		;SET UP READ BLOCK FOR TMPCOR UUO
	HRLOI	TT,-TMPBSZ-1	;SIZE OF TMPCOR READ
	ADD	TT,.JBFF	;MAKE IOWD POINTER TO TMPCOR BUFFER
	MOVE	TT1,[.TCRDF,,T]	;TMPCOR UUO ARG POINTER TO
	TMPCOR	TT1,		;READ AND DELETE FILE EDT
	  JRST	CCLTMP		;NO FILE EDT OR NO TMPCOR UUO
	HRRZ	AA,.JBFF	;GET START OF BUFFER AREA
	HRLI	AA,350700	;PICK UP EDT CHARACTERS, SKIP LINED "S"
	TXO	FF,TMPFLG	;SET TMPCOR FLAG
	JRST	CCLTM1		;FINISH PROCESSING COMMAND
;HERE IF TMPCOR FAILED. READ NNNEDT.TMP FROM DSK:

CCLTMP:	HLLZ	B,TMPTEC	;GET SIXBIT JOB #
	HRRI	B,'EDT'		;REST OF NAME
	MOVE	T,[-XFILEN,,XFILNM-1]	;PDL INTO LOOKUP BLOCK
	PUSH	T,[XFILEN]	;FIRST WORD IS CNT OF ARGS
	PUSH	T,[0]		;LOOK ON DEFAULT PATH
	PUSH	T,B		;STORE FILENAME
	PUSH	T,['TMP   ']	;EXTENSION
	MOVE	T,.JBFF		;USE BUFFER SPACE BRIEFLY
	OPEN	CCLCHN,CCLDSK	;OPEN DSK CHANNEL
	  JRST	TECO		;IF NO DSK, SAY "*"
	INBUF	CCLCHN,1	;DONT ADR CHECK
	LOOKUP	CCLCHN,XFILNM	;OPEN THE FILE
	  JRST	TECO		;IT WASN'T THERE?
	INPUT	CCLCHN,0
	MOVEM	T,.JBFF		;GIVE BACK SPACE
	IBP	CCLB+1		;SKIP THE LINED S
	MOVE	AA,CCLB+1	;SETUP BYTE POINTER TO INPUT
CCLTM1:	MOVE	T,TTYPT2	;OUTPUT CHARS
	MOVEI	C,2		;INIT CHAR CTR
	MOVEI	A,"="		;FLAG NO EQUALS SIGN SEEN


;FALL INTO LOOP ON NEXT PAGE
;LOOP BACK HERE ON EACH NEW CHARACTER IN THE TMP FILE
CCLIL:	ILDB	B,AA		;INPUT THE FILE NAME & EXT
	CAMN	B,A		;FIRST EQUALS SIGN SEEN?
	JRST	CCLEQL		;YES
	CAIE	B,.CHCRT	;CR?
	CAIN	B,"}"		;OLD ALT?
	AOJA	C,CCLNUL	;THEN PROCESS
	JUMPE	B,CCLIL		;THROW AWAY NULLS
	IDPB	B,T		;ELSE STORE CHAR
	AOJA	C,CCLIL		;AND LOOP FOR ALL CHARS

;HERE ON THE FIRST "=" IN THE COMMAND STRING
CCLEQL:	MOVE	D,T		;SAVE C & T
	MOVE	E,C		;INCASE .TE A=B
	MOVEI	B,.CHESC	;REPLACE FIRST EQUALS SIGN
	IDPB	B,T		;  WITH <ALT>ER
	MOVEI	B,"E"		;  SINCE WE EXPECT
	IDPB	B,T		;  AN INPUT FILE
	MOVEI	B,"R"		;  SPEC TO FOLLOW
	IDPB	B,T		;  THE FIRST ONE
	ADDI	C,3		;COUNT THE CHARS STORED
	SETO	A,		;PREVENT FINDING LATER EQUALS
	TXO	FF,CCLFLG	;DO A Y IN ANY CASE
	JRST	CCLIL		;AND LOOP BACK FOR NEXT CHAR
;HERE ON A NUL (END OF COMMAND). SEE IF IT WAS MAKE OR TECO

CCLNUL:	MOVEI	TT,"W"		;PREPARE FOR EW COMMAND
	CAILE	B,.CHCRT	;WAS BREAK A CRLF?
	JRST	CCLDUN		;NO. ALTMODE ASSUMED
	TXO	FF,CCLFLG	;REQUEST Y AFTER EB
	MOVEI	TT,"B"		;NOW PREPARE FOR EB
	AOJN	A,CCLDUN	;CONTINUE UNLESS EB & "=" WAS SEEN
	MOVE	T,D		;IF .TE A=B,  WE NEVER SAW THE "="
	AOS	C,E		;IN CASE .MA A=B, THEN .TE<CRLF>
				; SINCE TYI USES SOSG, THE COUNT MUST BE
				; ONE TOO LARGE (YECH).
CCLDUN:	MOVEI	B,.CHESC	;AN <ESC> TO TERMINATE THE FILE SPEC
	IDPB	B,T		;TERMINATE THE FILE SPEC
	SKIPL	S.EAMO		;EAMODE SET?
	TXZ	FF,CCLFLG	;YES, NO FREE YANKS THEN
	TXZN	FF,CCLFLG	;WANT TO YANK IN THE FIRST PAGE?
	JRST	CCLDU1		;NO
	MOVEI	B,"E"		;YES, A YANK COMMAND
	IDPB	B,T		;STUFF IT INTO THE BUFFER
	MOVEI	B,"Y"		;YANK COMMAND, PART TWO
	IDPB	B,T		;STUFF IT INTO THE BUFFER TOO
	MOVEI	B,.CHESC	;ANOTHER <ESC> CHARACTER
	IDPB	B,T		;TERMINATE THE YANK COMMAND
	ADDI	C,3		;COUNT THE "EY$" CHARACTERS
CCLDU1:	IDPB	B,T		;SECOND ALT TO TERMINATE COMMAND
	ADDI	C,2		;COUNT TERMINATING "$$" CHARACTERS
	MOVEI	B,"E"		;NOW FILL IN THE EB OR EW
	MOVE	T,TTYPT		;AT THE BEGINNING OF STRING
	MOVEM	T,TIB+.BFPTR	;ALSO INITIALIZE TO READ THIS
	IDPB	B,T		;STORE "E"
	IDPB	TT,T		;AND EITHER W OR B
	MOVEM	C,TIB+.BFCTR	;SET BUFR CTR
	TXZE	FF,TMPFLG	;TMPCOR UUO IN PROGRESS?
	JRST	CCLDU2		;YES, DON'T CLOSE DSK
	SETZM	XNAM		;NOW FLUSH FILE
	RENAME	CCLCHN,XFILNM	;BY RENAME TO ZERO
	  JFCL			;PROTECTED?
CCLDU2:	RELEAS	CCLCHN,
	POPJ	P,
;FIGURE OUT WHAT KIND OF TERMINAL THIS IS, AND SET THE SCTYPE CODE

GETTYP:	MOVEI	A,.TOTRM	;TRMOP. TERMINAL TYPE FUNCTION
	MOVE	AA,TTYUDX	;GET TERMINAL UDX
	MOVE	B,[2,,A]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;READ MONITOR'S TERMINAL TYPE
	 SETO	B,		;MONITOR DOESN'T KNOW (PRE-7.00)

IFN	RUN603,<MOVE B,[TTY603]>;IF 6.03, SET ASSEMBLED TERMINAL

;HERE WITH TERMINAL TYPE IN B (SIXBIT NAME), SEE IF WE LIKE IT

	MOVSI	A,-TYPTLN	;LENGTH OF OUR TYPE TABLE
GETTY2:	CAME	B,TYPTBL(A)	;TERMINAL WE KNOW ABOUT?
	AOBJN	A,GETTY2	;NO, CHECK REST OF TABLE
	MOVE	B,TYPVTX(A)	;GET INTERNAL TERMINAL TYPE
				; (0 IF UNKNOWN)
	MOVEM	B,SCTYPE	;REMEMBER FOR SCREEN CHECKING
	HRLZ	A,TYPCTL(B)	;ADDRESS OF CONTROL CODES TABLE
	HRRI	A,TTYESC	;ADDRESS OF CONTROL CODES TABLE
	BLT	A,TTYESZ	;COPY WORKING TABLE
	MOVEI	A,8
	MOVEM	A,TABSIZ	;TABS EVERY 8 COLUMNS
	POPJ	P,
;TTY CONTROL STUFF

;INTERNAL TERMINAL TYPES

VXTTY==0			;NO SCREEN CONTROL (UNKNOWN/HARDCOPY)
VX05==1				;VT05
VXD50==2			;VT50-CLASS
VXDEC==3			;VT52-CLASS
VXANSI==4			;VT100 (ANSI) CLASS

TYPCTL:	VCTTY			;(00) NONE (E.G., HARDCOPY TERMINAL)
	VC05			;(01) VT05 CONTROL
	VCD50			;(02) DEC-STANDARD SANS CURSOR ADDRESSING
	VCDEC			;(03) DEC-STANDARD ESCAPE CONTROL
	VCANSI			;(04) ANSI-STANDARD ESCAPE CONTROL



;TERMINAL TYPES DEFINITIONS

DEFINE	TRMTYP,<
X	VT05,	VX05		;GOOD OLE VT05
X	VT50,	VXD50		;DINKY VT50
X	VT52,	VXDEC		;STANDARD VT52
X	VT55,	VXDEC		;VT52 WITH GRAPHICS
X	VT61,	VXDEC		;FANCY EDITING TERMINAL
X	DAS21,	VXDEC		;FUNNY LOOKING VT52
X	VT100,	VXANSI		;NOT-SO-NEW-ANYMORE NEWEST LATEST GREATEST
X	VT101,	VXANSI		;EL CHEAPO VT100
X	VT102,	VXANSI		;FANCY VERSION OF EL CHEAPO VT100
X	VT103,	VXANSI		;EGADS, THEY'RE PROLIFERATING LIKE RABBITS
X	VT125,	VXANSI		;VT100 WITH GRAPHICS
X	VT180,	VXANSI		;ROBIN
X	VT185,	VXANSI		;ROBIN RED BREST?
X	VT220,	VXANSI		;NEWEST LATEST GREATEST WITH SUCKY KEYBOARD
X	VT240,	VXANSI		;FANCIER VERSION OF NEWEST ETC.
X	VK100,	VXANSI		;VT100 WITH EVEN MORE GRAPHICS ("GIGI")
> ;END TRMTYP MACRO



;THE TTY TYPES TABLE

DEFINE	X(NAM,DSP),<SIXBIT\NAM\>

TYPTBL:	TRMTYP			;DEFINE TERMINAL NAMES TABLE
	TYPTLN==.-TYPTBL	;LENGTH OF TYPE TABLE



;THE TTY TYPE DISPATCH TABLE

DEFINE	X(NAM,DSP),<EXP DSP>

TYPVTX:	TRMTYP			;DEFINE TYPE DISPATCH TABLE
	VXTTY			;(--) UNKNOWN TERMINAL (NO CONTROL)
;OUR WORKING TABLE OF TTY CONTROL

U THOME,1			;(00) HOME
U TEREOL,1			;(01) ERASE TO END OF LINE
U TEREOS,1			;(02) ERASE TO END OF SCREEN
U TCUP,1			;(03) CURSOR UP
U TDOWN,1			;(04) CURSOR DOWN
U TRIGHT,1			;(05) CURSOR RIGHT
U TLEFT,1			;(06) CURSOR LEFT
U TDCAD,1			;(07) DIRECT CURSOR ADDRESS PROCESSOR
U TKESC,1			;(10) START OF ESCAPE SEQUENCE
U TKCUP,1			;(11) CURSOR UP "KEY"
U TKDWN,1			;(12) CURSOR DOWN "KEY"
U TKRGT,1			;(13) CURSOR RIGHT "KEY"
U TKLFT,1			;(14) CURSOR LEFT "KEY"
U TCOCH,1			;(15) CONTINUATION CHARACTER

	TTYESC==THOME		;START OF CONTROL TABLE
	TTYESZ==TCOCH		;END OF CONTROL TABLE
;PROTOTYPE CONTROL TABLE FOR HARDCOPY TERMINALS

VCTTY:	BLOCK	1			;(00) HOME
	BLOCK	1			;(01) ERASE TO END OF LINE
	BLOCK	1			;(02) ERASE TO END OF SCREEN
	BLOCK	1			;(03) CURSOR UP
	BLOCK	1			;(04) CURSOR DOWN
	BLOCK	1			;(05) CURSOR RIGHT
	BLOCK	1			;(06) CURSOR LEFT
	BLOCK	1			;(07) DIRECT CURSOR ADDRESS PROCESSOR
	BLOCK	1			;(10) START OF ESCAPE SEQUENCE
	BLOCK	1			;(11) CURSOR UP "KEY"
	BLOCK	1			;(12) CURSOR DOWN "KEY"
	BLOCK	1			;(13) CURSOR RIGHT "KEY"
	BLOCK	1			;(14) CURSOR LEFT "KEY"
	EXP	"!"			;(15) LINE CONTINUATION CHARACTER

;PROTOTYPE CONTROL TABLE FOR VT05'S

VC05:	BYTE(7)	035,177,177,177,177	;(00) HOME
	BYTE(7)	036,177,177,177,177	;(01) ERASE TO END OF LINE
	BYTE(7)	037,177,177,177,177	;(02) ERASE TO END OF SCREEN
	BYTE(7)	032,177,177,177,177	;(03) CURSOR UP
	BYTE(7)	012,000,000,000,000	;(04) CURSOR DOWN
	BYTE(7)	030,000,000,000,000	;(05) CURSOR RIGHT
	BYTE(7)	010,000,000,000,000	;(06) CURSOR LEFT
	IFIW	VT05LN			;(07) DIRECT CURSOR ADDRESS PROCESSOR
	EXP	0			;(10) START OF ESCAPE SEQUENCE
	EXP	032			;(11) CURSOR UP "KEY"
	EXP	013			;(12) CURSOR DOWN "KEY"
	EXP	030			;(13) CURSOR RIGHT "KEY"
	EXP	010			;(14) CURSOR LEFT "KEY"
	EXP	"!"			;(15) CONTINUATION CHARACTER

;PROTOTYPE CONTROL TABLE FOR DEC-STANDARD TERMINALS SANS CURSOR CONTROL (VT50'S)

VCD50:	BYTE(7)	033,"H",000,000,000	;(00) HOME
	BYTE(7)	033,"K",000,000,000	;(01) ERASE TO EOL
	BYTE(7)	033,"J",000,000,000	;(02) ERASE TO EOS
	BYTE(7)	033,"A",000,000,000	;(03) CURSOR UP
	BYTE(7)	033,"B",000,000,000	;(04) CURSOR DOWN
	BYTE(7) 033,"C",000,000,000	;(05) CURSOR RIGHT
	BYTE(7)	033,"D",000,000,000	;(06) CURSOR LEFT
	IFIW	VT50LN			;(07) DCA PROCESSOR
	EXP	.CHESC			;(10) START OF ESCAPE SEQUENCE
	EXP	"A"			;(11) CURSOR UP "KEY"
	EXP	"B"			;(12) CURSOR DOWN "KEY"
	EXP	"C"			;(13) CURSOR RIGHT "KEY"
	EXP	"D"			;(14) CURSOR LEFT "KEY"
	EXP	"!"			;(15) CONTINUATION CHARACTER
;PROTOTYPE CONTROL TABLE FOR DEC-STANDARD TERMINALS (VT52'S)

VCDEC:	BYTE(7)	033,"H",000,000,000	;(00) HOME
	BYTE(7)	033,"K",000,000,000	;(01) ERASE TO EOL
	BYTE(7)	033,"J",000,000,000	;(02) ERASE TO EOS
	BYTE(7)	033,"A",000,000,000	;(03) CURSOR UP
	BYTE(7)	033,"B",000,000,000	;(04) CURSOR DOWN
	BYTE(7) 033,"C",000,000,000	;(05) CURSOR RIGHT
	BYTE(7)	033,"D",000,000,000	;(06) CURSOR LEFT
	IFIW	VT52LN			;(07) DCA PROCESSOR
	EXP	.CHESC			;(10) START OF ESCAPE SEQUENCE
	EXP	"A"			;(11) CURSOR UP "KEY"
	EXP	"B"			;(12) CURSOR DOWN "KEY"
	EXP	"C"			;(13) CURSOR RIGHT "KEY"
	EXP	"D"			;(14) CURSOR LEFT "KEY"
	EXP	"|"			;(15) CONTINUATION CHARACTER

;PROTOTYPE CONTROL TABLE FOR ANSI-STANDARD TERMINALS (VT100)

VCANSI:	BYTE(7)	033,"[","H",000,000	;(00) HOME
	BYTE(7)	033,"[","0","K",000	;(01) ERASE TO EOL
	BYTE(7)	033,"[","0","J",000	;(02) ERASE TO EOS
	BYTE(7)	033,"[","1","A",000	;(03) CURSOR UP
	BYTE(7) 033,"[","1","B",000	;(04) CURSOR DOWN
	BYTE(7) 033,"[","1","C",000	;(05) CURSOR RIGHT
	BYTE(7) 033,"[","1","D",000	;(06) CURSOR LEFT
	IFIW	VTANLN			;(07) DCA PROCESSOR
	EXP	.CHESC			;(10) START OF ESCAPE SEQUENCE
	EXP	"A"			;(11) CURSOR UP "KEY"
	EXP	"B"			;(12) CURSOR DOWN "KEY"
	EXP	"C"			;(13) CURSOR RIGHT "KEY"
	EXP	"D"			;(14) CURSOR LEFT "KEY"
	EXP	"|"			;(15) CONTINUATION CHARACTER
;PSI SERVICE INITIALIZATION

;SETUP PSI SYSTEM

PSIINI:	XMOVEI	T,PSIVEC	;BASE PSI VECTOR
	SKIPE	SECTN		;RUNNING EXTENDED?
	TXO	T,PS.IEA	;YES, WANT "EXTENDED" FORMAT THEN
	PIINI.	T,		;INITIALIZE PSI SYSTEM
	 POPJ	P,		;BLETCH

;BY DEFAULT, ALWAYS GET ^C TRAPPING, SO INCLUDE IT AS PART OF THE
;"GENERIC" PSI SETUP CODE

	XMOVEI	T,CCINT		;CONTROL-C TRAP ROUTINE
	MOVEM	T,PSICCV+.PSVNP	;SET TRAP PC
	MOVX	T,PS.VTO!PS.VDS	;CONTROL-FLAGS: IGNORE FURTHER ^C'S
	MOVEM	T,PSICCV+.PSVFL	;SET FLAGS WORD
	MOVE	T,[PS.FON!PS.FAC+[.PCSTP  ;ENABLE ARG BLOCK FOR ^C TRAP
			XWD	PSICCV-PSIVEC,0	;VECTOR OFFSET
			EXP	0]]		;JUNK WORD
	PISYS.	T,		;ENABLE CONTROL-C TRAPPING
	 POPJ	P,		;JUNK
	JRST	CPOPJ1		;PSI (AND ^C TRAP) SETUP
;CONTROL-C TRAP SERVICE ROUTINE

CCINT:	PUSH	P,A		;SAVE ACCUMULATORS A, AA,  AND B
	PUSH	P,AA		; . . .
	PUSH	P,B		; . . .
	PUSH	P,T		;SAVE
	PUSH	P,TT		; EVEN
	PUSH	P,TT1		;  MORE
	PUSH	P,CH		;   ACS
	PUSHJ	P,TEBURB	;FORCE COMMAND BACKUP UPDATE NOW
	PUSHJ	P,CLREOS	;CLEAR OUT JUNK AT BOTTOM OF SCREEN
	PUSHJ	P,TTYRST	;RESTORE ORIGINAL USER TTY MODES
	PUSHJ	P,ZAPTT		;CLEAR OUT THE TTY
	EXIT	1,		;LET MONITOR HAVE USER

;BACK HERE WHEN USER TYPES CONTINUE

CCONT:	PUSHJ	P,TTOPEN	;RE-OPEN DEVICE TTY:
	PUSHJ	P,GETTYP	;CHECK ON TERMINAL TYPE JUST IN CASE . . .
	PUSHJ	P,TTYGET	;GET TTY MODES (USER MAY HAVE CHANGED THEM)
	PUSHJ	P,TTYSEC	;SETUP OUR TTY MODES
	TXNN	F2,DOING	;EXECUTING A COMMAND?
	SKIPE	COMCNT		;NO, ANY COMMAND CHARACTERS IN YET?
	JRST	CCONT5		;YES TO ONE OF THE ABOVE, JUST RESUME

;HERE WHEN USER ^C'ED FROM COMMAND INPUT WAIT, NO CHARACTERS IN YET

	PUSHJ	P,CLRSCN	;FORCIBLY CLEAR THE WHOLE SCREEN
	XMOVEI	CH,GO		;ADDRESS FROM WHENCE TO RESUME
	MOVEM	CH,PSICCV+.PSVOP;SET FOR DEBRK. TO SEE
	JRST	CCONT8		;AND GO RESTART

;HERE WHEN USER ^C'ED FROM SOMETHING HAPPENING, JUST RESUME

CCONT5:	SETOM	MESFLG		;NOTE THAT SCREEN IS [PROBABLY] TRASHED
	SETZM	WINFLG		;WE WANT IT UPDATED NOW!
	SETZM	VFREEZ		; . . .
CCONT8:	POP	P,CH		;RESTORE
	POP	P,TT1		; SOME
	POP	P,TT		;  MORE
	POP	P,T		;   ACS
	POP	P,B		;RESTORE A, AA, AND B
	POP	P,AA		; . . .
	POP	P,A		; . . .
	DEBRK.			;BACK TO THE OLD GRIND....
	 HALT	GO		;DUH?
	 HALT	GO		;DOUBLE DUH?
	SUBTTL	TERMINAL HANDLING AND I/O ROUTINES

;TTOPEN - OPEN AND INITIALIZE THE TERMINAL I/O CHANNEL

TTOPEN:	OPEN	TTYCHN,TTYBLK	;OPEN DEVICE TTY:
	  JRST	TTOPF1		;OPEN FAILURE? OFF TO A BAD START!
	SETOM	TTSTS		;INITIALLY JUNK STATUS
	MOVEI	T,TTYCHN	;TTY I/O CHANNEL
	DEVTYP	T,		;GET DEVICE TYPE INFORMATION
	  JRST	TTOPF2		;CAN'T FAIL
	LDB	TT,[POINTR T,TY.DEV]  ;GET DEVICE CODE
	CAIE	TT,.TYTTY	;IS TTY: A TRUE TERMINAL?
	  JRST	TTOPF3		;NO, BARF ON USER
	MOVEI	T,TTYCHN	;TTY I/O CHANNEL AGAIN
	IONDX.	T,		;GET OFFICIAL TTY UDX
	  JRST	TTOPF4		;CAN'T FAIL
	MOVEM	T,TTYUDX	;SAVE FOR ASSORTED AND SUNDRY TRMOP.S

;NOW SET UP INPUT BUFFER RING STRUCTURE

	MOVE	A,[TTIBFN,,TTIBSZ+3]  ;TERMINAL INPUT BUFARG
	MOVEI	AA,TTIBF1	;FIRST INPUT BUFFER
	MOVEI	B,TIB		;TERMINAL INPUT BUFFER RING
	PUSHJ	P,SETBF		;INITIALIZE INPUT BUFFER RING
	 HALT	.		;CAN'T HAPPEN

;NOW SET UP OUTPUT BUFFER RING STRUCTURE

	MOVE	A,[TTOBFN,,TTOBSZ+3]  ;TERMINAL OUTPUT BUFARG
	MOVEI	AA,TTOBF1	;FIRST OUTPUT BUFFER
	MOVEI	B,TOB		;OUTPUT RING HEADER
	PUSHJ	P,SETBF		;INITIALIZE OUTPUT BUFFER RING
	 HALT	.		;CAN'T HAPPEN

	POPJ	P,		;TERMINAL CHANNEL ALL SET
;TTOPEN ERRORS

TTOPF1:	OUTSTR	[ASCIZ\? Can't OPEN device TTY:\]
	JRST	TTOPFX		;COMMON ERROR EXIT

TTOPF2:	OUTSTR	[ASCIZ\? DEVTYP failure for TTY channel\]
	JRST	TTOPFX		;COMMON ERROR EXIT

TTOPF3:	OUTSTR	[ASCIZ\? Device TTY: is not a real terminal\]
	JRST	TTOPFX		;COMMON ERROR EXIT

TTOPF4:	OUTSTR	[ASCIZ\? IONDX. failure for TTY channel\]
	JRST	TTOPFX		;COMMON ERROR EXIT

TTOPFX:	OUTSTR	[ASCIZ\
\]				;BLANK LINE BEFORE THE "."
	EXIT	1,		;RETURN TO MONITOR LEVEL
	JRST	TTOPEN		;USER .CONTINUED, SO TRY AGAIN
;ROUTINE TO GET AND REMEMBER VARIOUS TTY SETTINGS, SO IF WE CHANGE THEM,
;WE CAN RESTORE THEM CORRECTLY WHEN TECO EXITS TO THE MONITOR FOR ANY
;REASON

TTYGET:	MOVE	TT,TTYUDX	;GET OUR TTY UDX FOR SUBSEQUENT TRMOP.'S

	MOVEI	T,.TOLCT	;LOWER CASE CONVERSION
	MOVE	B,[2,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;READ LC SETTING
	  SETZ	B,		;ASSUME LOWER CASE TTY
	SKIPN	B		;LOWER CASE CAPABILITY?
	TXOA	F2,LINCHR	;YES, SET FLAG
	TXZ	F2,LINCHR	;NO, CLEAR IT

	MOVEI	T,.TOALT	;READY TO CHECK FOR ALTMODE CONVERSION
	MOVE	B,[2,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;READ ALTMODE CONVERSION SETTING
	  MOVEI	B,0		;ASSUME NOT
	SKIPE	B		;COPY ALTMODE CONVERSION SWITCH TO F2
	TXOA	F2,NOALT
	TXZ	F2,NOALT

	MOVEI	T,.TOTAB	;PREPARE TO READ TAB-SPACES SWITCH
	MOVE	B,[2,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;READ TAB-SPACES SWITCH
	  SETZ	B,		;ASSUME NOT
	MOVEM	B,TTYTAB	;REMEMBER TAB SWITCH SETTING

	MOVEI	T,.TONFC	;PREPARE TO READ FREE CRLF SWITCH
	MOVE	B,[2,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;READ CRLF SWITCH
	  SETZ	B,		;ASSUME FREE CRLF
	MOVEM	B,TTYFCR	;SAVE CURRENT FREE CRLF SETTING

	MOVEI	T,.TOBLK	;PREPARE TO READ TTY BLANK
	MOVE	B,[2,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;READ CRLF SWITCH
	 SETZ	B,		;ASSUME TTY NO BLANK SUPPRESS
	MOVEM	B,TTYBLN	;SAVE CURRENT TTY BLANK

	MOVEI	T,.TODEM	;PREPARE TO READ DEFERRED ECHO MODE
	MOVE	B,[2,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;READ DEFERRED ECHO SETTING
	  SETZ	B,		;ASSUME IMMEDIATE ECHO
	MOVEM	B,TTYDEM	;SAVE CURRENT DEFERRED ECHO MODE

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

	MOVEI	T,.TOWID	;PREPARE TO READ TTY WIDTH
	MOVE	B,[2,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;READ TTY WIDTH
	  MOVEI	B,^D80		;ASSUME VT52-CLASS WIDTH
	CAILE	B,TTWMAX	;CAN WE HANDLE IT?
	MOVEI	B,TTWMAX	;NO, USE MOST WE SUPPORT
	SUBI	B,1		;(WE START AT 0)
	MOVEM	B,SWIDTH	;SET SCREEN WIDTH

	MOVEI	T,.TOSTO	;PREPARE TO READ TERMINAL STOP
	MOVE	B,[2,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;READ TERMINAL [NO] STOP
	  JRST	TTYGE5		;FALL BACK TO TERMINAL PAGE
	MOVEM	B,TTYSTO	;REMEMBER USER'S TERMINAL [NO] STOP SETTING

	MOVEI	T,.TOLNB	;PREPARE TO READ TERMINAL LENGTH
	MOVE	B,[2,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;READ TERMINAL "FORMS" LENGTH
	  JRST	TTYGE5		;ASSUME NOT YET IMPLEMENTED
	JUMPN	B,TTYGE7	;USE LENGTH IF ANY IS SET
	MOVEI	T,.TOSSZ	;PREPARE TO READ STOP SIZE
	MOVE	B,[2,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;READ STOP SIZE
	  JRST	TTYGE5		;ASSUME NOT YET IMPLEMENTED
	JUMPN	B,TTYGE7	;USE STOP SIZE IF ANY IS SET

TTYGE5:	MOVEI	T,.TOPSZ	;PREPARE TO READ PAGE SIZE
	MOVE	B,[2,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;READ PAGE SIZE
	  SETZ	B,		;ASSUME PAGE 0
	MOVEM	B,TTYPSZ	;SAVE CURRENT USER'S PAGE SIZE
TTYGE6:	JUMPN	B,TTYGE7	;USE KNOWN PAGE SIZE
	MOVE	B,SCTYPE	;GET TTY TYPE
	MOVE	B,[DEC 63,20,12,24,24](B)  ;HYPOTHESIZE A LENGTH
TTYGE7:	CAILE	B,TTLMAX	;CAN WE HANDLE IT?
	MOVEI	B,TTLMAX	;NO, THE MOST WE CAN HANDLE
	MOVEM	B,SSIZE		;SAVE SCREEN "SIZE"
	MOVE	T,B		;NEED TWO CONTIGUOUS REGISTERS
	IMULI	T,^D100		;TO CALCULATE PERCENTAGE OF SCREEN
	IDIVI	T,^D120		;TO USE FOR TEXT (20 OUT OF 24 LINES)
	MOVEM	T,DLENTH	;SET LENGTH OF TEXT AREA
	MOVEM	T,SLENTH	; . . .
	IDIVI	T,3		;PREFERRED OFFSET FOR CURSOR
	MOVEM	T,CLENTH	;SET FOR OTHERS

	POPJ	P,		;WE HAVE READ ALL PERTINENT TTY INFO
;ROUTINE TO SET VARIOUS TTY MODES FROM OURTAB, OURFCR ETC.
;
;ENTER AT TTYSEC TO CLEAR THE TERMINAL INPUT STREAM COMMAND WHICH
;STARTED US UP (E.G., REENTER COMMAND) AND WHICH WOULD OTHERWISE PREVENT
;THE DISPLA ROUTINE FROM UPDATING THE SCREEN (IT WOULD THINK IT HAD
;TYPEAHEAD (THE MONITOR COMMAND) AND TERMINATE).

TTYSEC:	MOVEI	T,.TOSIP	;SKIP-IF-INPUT FUNCTION
	MOVE	TT,TTYUDX	;FOR OUR COMMAND TERMINAL
	MOVE	B,[2,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;NUDGE TERMINAL AND CLEAR COUNTERS
	 JFCL			;DON'T CARE, AS LONG AS DISPLA DOES OUTPUT

TTYSET:	TDZA	A,A		;SETUP FROM OUR MODES
TTYRST:	MOVEI	A,1		;RESET OLD TERMINAL MODES
	SKIPN	SCTYPE		;ONLY MUCK WITH USER TTY IF VIDEO SCREENING
	POPJ	P,		;HARDCOPY, LEAVE IT ALONE
	MOVE	TT,TTYUDX	;SET TTY UDX FOR TRMOP.S BELOW

	MOVEI	T,.TOTAB+.TOSET	;PREPARE TO SET TAB CONVERSION
	MOVE	TT1,OURTAB(A)	;GET TAB SETTING
	MOVE	B,[3,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;SET UP TTY TAB-SPACES SWITCH
	  JFCL			;IGNORE FAILURE

	MOVEI	T,.TONFC+.TOSET	;PREPARE TO SET FREE CRLF SETTING
	MOVE	TT1,OURFCR(A)	;GET STATE TO SET
	MOVE	B,[3,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;SET UP FREE CRLF SWITCH
	  JFCL			;ERROR IS OK

	MOVEI	T,.TOBLK+.TOSET	;PREPARE TO SET TTY NO BLANK SUPPRESSION
	MOVE	TT1,OURBLN(A)	;GET STATE TO SET
	MOVE	B,[3,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;SET TTY NO BLANK SUPPRESSION
	  JFCL			;ERROR IS OK

	MOVEI	T,.TODEM+.TOSET	;PREPARE TO SET DEFERRED ECHO MODE
	MOVE	TT1,OURDEM(A)	;GET STATE TO SET
	MOVE	B,[3,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;SET UP DEFERRED ECHO MODE
	  JFCL			;ERROR IS OK

	MOVEI	T,.TOSTO+.TOSET	;PREPARE TO SET STOP
	MOVE	TT1,OURSTO(A)	;GET STATE TO SET
	MOVE	B,[3,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;SET TERMINAL [NO] STOP
	  JRST	TTYSE5		;FAILED, USE TERMINAL PAGE INSTEAD
	JRST	TTYSE7		;DO NOT USE PAGE TRMOP.!

TTYSE5:	MOVEI	T,.TOPSZ+.TOSET	;PREPARE TO SET PAGE SIZE 0
	MOVE	TT1,OURPSZ(A)	;GET STATE TO SET
	MOVE	B,[3,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;SET UP PAGE SIZE 0
	  JFCL			;ERROR IS OK

TTYSE7:	POPJ	P,		;USER'S TERMINAL HAS BEEN [RE]SET
;*** DO NOT SEPARATE OURFCR FROM TTYFCR, NOR OURTAB FROM TTYTAB ***
U OURFCR,1			;WHAT TECO'S CRLF BIT IS
U TTYFCR,1			;HOLDS CRLF BIT AS EXISTING THE LAST
				;TIME WE WENT FROM MONITOR TO TECO
U OURTAB,1			;WHAT TECO'S TAB-SPACE BIT IS
U TTYTAB,1			;SAME FOR TAB-SPACES BIT

U OURBLN,1			;WHAT TECO'S BLANK SUPRESSION IS
U TTYBLN,1			;AND USER'S SELECTION

U OURDEM,1			;WHAT TECO'S DEFERRED ECHO MODE IS
U TTYDEM,1			;AND USER'S SELECTION

U OURPSZ,1			;TECO'S PAGE SIZE
U TTYPSZ,1			;ORIGINAL PAGE SIZE

U OURSTO,1			;TECO'S [NO] STOP
U TTYSTO,1			;ORIGINAL [NO] STOP
;ROUTINE TO RETURN NON-NULL TTY CHARACTER IN CH.
;CALL	PUSHJ PDP,TYI
;	RETURN

TYI:	TXZE	FF,TYOF		;NEED A TYO?
	PUSHJ	P,TYOOUT	;YES. DO SO.
TYI0:	SKIPL	CH,SCH		;IF SAVED CHARACTER IN SCH
	JRST	TYIB4		;USE IT INSTEAD OF INPUTTING ONE FROM TTY
	TXNE	FF,CFOF		;READING FROM COMMAND FILE?
	JRST	TYICF		;YES, DIFFERENT BUFFER(S)
	SOSG	TIB+.BFCTR	;CHARS IN NORMAL MODE?
	PUSHJ	P,TYIIN		;NONE LEFT, GET ANOTHER BUFFERFUL
	ILDB	CH,TIB+.BFPTR	;YES. GET ONE
	JUMPE	CH,TYI0		;FLUSH NULLS
TYI3:	PUSHJ	P,TEBCHR	;SAVE COMMAND CHARACTER IN CRASH RECOVERY FILE
TYI4:	TXZ	FF,TIBKA	;CLEAR CHARACTER MODE
	TXZN	FF,TINEC	;NO ECHO?
	SKIPE	CMFECH		;OR SUPPRESSING COMMAND FILE ECHO?
	PJRST	ALTLIN		;YES, DON'T DO ANY SPECIAL CHARACTER STUFF
				; 1) ECHO <BEL> AS ^G
				; 2) COUNT SCREEN SCROLLING
	CAIE	CH,.CHBEL	;NO, USER TYPE A <BEL>?
	JRST	TYI4NG		;NO, NO ECHO WORRIES THEN
	MOVE	CH,CHTBL(CH)	;YES, GET <BEL> ECHO CONTROL
	TXZ	CH,EC$SLF	;THE MONITOR ALREADY ECHOED THIS WAY
	PJRST	TYIEC0		;SO JUST ECHO IT FOR HIM AS ^G

TYI4NG:	CAIL	CH," "		;CONTROL CHARACTER?
	JRST	ALTLIN		;NO (BUT WATCH FOR OLDE ALTMODES)
	CAIL	CH,.CHLFD	;VERTICAL MOTION CHARACTER?
	CAILE	CH,.CHFFD	; . . .
	SKIPA	CH,CHTBL(CH)	;NO, GET ECHO CONTROL BITS
	JRST	CNTLF		;YES, COUNT ANY EFFECTS ON SCREEN
	TXNE	CH,EC$CRL	;THIS CHARACTER ECHO WITH <CR><LF>?
	JRST	TYI5C		;YES, ACCOUNT FOR POSSIBLE SCROLLING
	ANDI	CH,177		;NO, REDUCE TO JUST ASCII CHARACTER
	POPJ	P,		;AND GIVE IT TO CALLER

TYI5C:	PUSH	P,CH		;SAVE THE BITS/CHARACTER
	MOVEI	CH,.CHLFD	;PRETEND A LINE FEED
	PUSHJ	P,CNTLF		;NOTE SCREEN MAY HAVE SCROLLED
	POP	P,CH		;RESTORE THE BITS/CHARACTER
	ANDI	CH,177		;AND REDUCE TO JUST CHARACTER
	POPJ	P,		;AND GIVE IT TO CALLER
TYIINZ:	CLOSE	TTYCHN,		;CLEAR EOF (^Z)
TYIIN:	MOVEI	CH,TTYIOS	;BASIC TTY STATUS
	TXNE	FF,TIBKA	;WANT SINGLE CHARACTER?
	IORI	CH,IO.BKA	;YEAH
	TXNE	FF,TINEC	;WANT TO SUPPRESS ECHO?
	IORI	CH,IO.SUP	;YEAH
	CAME	CH,TTSTS	;SAME IOS AS LAST PASS THROUGH HERE?
	SETSTS	TTYCHN,(CH)	;NO, CHANGE TO NEW TERMINAL MODE
	MOVEM	CH,TTSTS	;SAVE NEW LAST STATUS

IFN	RUN603,<
	TXNE	CH,IO.BKA	;WANT CHARACTER MODE HERE?
	JRST	[INCHRW	CH		;YES, PICK UP SINGLE CHARACTER
		JRST	CPOPJ1]		;AND SKIP TYI0'S "ILDB"
> ;END IFN RUN603

	IN	TTYCHN,		;ASK FOR INPUT
	POPJ	P,		;GOT IT, RETURN TO READ IT
	STATZ	TTYCHN,IO.EOF	;END OF FILE?
	JRST	TYIINZ		;GO CLEAR EOF
	OUTSTR	[ASCIZ\? I/O error reading from command terminal\]
	EXIT			;AND THAT IS THE END OF THAT
TYIB4:	SETOM	SCH		;SO CHARACTER IS INPUT NEXT TIME
	POPJ	P,

;CONVERT 175 & 176 TO ALTMODE (033) UNLESS TTY NOALT IS ON

ALTLIN:	CAIL	CH,175		;OLD ALTMODE?
	CAILE	CH,176
	POPJ	P,		;NO
	TXNN	F2,NOALT	;TEST TTY NOALT BIT
ALTX:	MOVEI	CH,.CHESC	; CONVERT TO 033
	POPJ	P,

;CONVERT 175 & 176 TO ALTMODE (033) IF EO = 1

ALTEO:	CAIE	CH,175		;OLD ALTMODE?
	CAIN	CH,176
	CHKEO	EO21,ALTX	;RUNNING OLD MACRO? IF SO, CONVERT
	POPJ	P,		;NO, 175=RIGHT BRACE, 176=TILDE
;HERE TO READ CHARACTER FROM COMMAND FILE RATHER THAN TTY:

TYICF:	SOSL	CMFIBH+.BFCTR	;ANY CHARACTERS LEFT?
	JRST	TYICF3		;YES, KEEP READING THEM
	PUSHJ	P,TYICN		;NO, READ ANOTHER BUFFER
	  SKIPA	CH,COMCNT	;EOF, GET COMMAND CHARACTER COUNT
	JRST	TYICF		;GOT MORE CHARACTERS, COUNT EM DOWN
	SKIPE	EQM		;IF REQUEST FROM A MACRO, OK
	JRST	TYI		; (MUST BE FROM CMCCT)
	JUMPE	CH,GO		;NO, IF NO OUTSTANDING COMMANDS, RESTART
				; AND REFRESH SCREEN AS NEEDED
	$WARN	(EOC,,<End of command file with unterminated commands pending>)
	JRST	TYI		;AND GET REGULAR TTY COMMANDS

TYICF3:	ILDB	CH,CMFIBH+.BFPTR;YES, READ NEXT COMMAND FILE CHARACTER
	AOS	CMFCTR		;BUMP CHARACTER COUNTER
	JUMPE	CH,TYICF	;DISCARD NULLS
	SKIPN	CMFECH		;USER REQUEST ECHOING OF THE COMMAND FILE?
	CAIN	CH,.CHDEL	;YES, BUT DON'T ECHO RUBOUTS
	JRST	TYI4		;RETURN COMMAND CHARACTER (BUT DON'T WRITE
				; IT IN CRASH RECOVERY FILE!)
	TXNE	FF,TINEC	;SUPPRESSING INPUT ECHO?
	JRST	TYI4		;YES, IF IT NEEDS ECHOING, IT WILL BE ECHOED LATER
	PUSH	P,A		;SAVE SOME ACS
	PUSH	P,AA		; THAT TYOM KRUMPS UPON
	CAIN	CH,.CHLFD	;A <LF>???
	SOS	CURLIN		;YES, CNTLF GETS CALLED BY TYI AND TYO . . .
	PUSHJ	P,TYOM		;"ECHO" THE COMMAND FILE CHARACTER
	POP	P,AA		;RESTORE POSSIBLE TROUNCED ACS
	POP	P,A		; . . .
	JRST	TYI4		;PROCESS COMMAND CHARACTER NORMALLY
;READ ANOTHER BUFFER, POPPING UP TO PREVIOUS FILE ON EOF

TYICN:	IN	CMFCHN,		;READ NEXT BUFFER
	JRST	CPOPJ1		;RETURN WITH CHARACTERS
	STATO	CMFCHN,IO.EOF	;END OF FILE?
	JRST	TYICE2		;NO, I/O ERROR, GO COMPLAIN
	TXZ	FF,CFOF		;NO MORE COMMAND FILE (PROBABLY)
	RELEAS	CMFCHN,		;LET GO OF USED-UP FILE
	SOSG	CMFLVL		;DECREMENT NESTING COUNT
	JRST	TYICNZ		;ALL FILES USED UP, BACK TO TTY:

;HERE ON EOF FROM COMMAND FILE NESTED WITHIN ANOTHER COMMAND FILE,
;"POP" BACK TO PREVIOUS COMMAND FILE AND CONTINUE PROCESSING

	PUSH	P,A		;NEED A COUPLA ACS HERE
	PUSH	P,AA		; . . .
	MOVE	A,CMFPDP	;COMMAND FILE STACK POINTER
	SUBI	A,CMFLEN	;"POP" THE POINTER
	MOVEM	A,CMFPDP	;SAVE NEW POINTER FOR NEXT TIME
	HRLZ	A,A		;LEFT HALF OF BLT POINTER
	HRRI	A,CMFBLK	;POINT TO "ACTIVE" COMMAND FILE AREA
	BLT	A,CMFBLK+CMFLEN-1  ;"POP" PREVIOUS COMMAND FILE SPECS
	MOVE	A,[CMFBLK,,COMBLK]  ;BLT POINTER TO
	BLT	A,COMBLK+COMBLN-1  ;SET UP SPEC IN FILE SPEC AREA
	PUSHJ	P,FILALT	;GO SETUP OPEN AND LOOKUP BLOCKS
	PUSHJ	P,CMFOPN	;OPEN AND SET UP FOR I/O
	MOVE	A,CMFCTR	;CHAR POSITION IN FILE WE WERE LAST AT
	IDIVI	A,<BLKSIZ*5>	;A:=BLOCK NUMBER IN FILE
	USETI	CMFCHN,1(A)	;SET TO READ THAT PARTICULAR BLOCK
	IN	CMFCHN,		;AND BRING IT IN
	CAIA			;GOOD
	  JRST	TYICE2		;CAN'T GET EOF SO MUST BE ERROR
	MOVN	AA,AA		;DON'T HAVE SUB AC FROM MEM
	ADDM	AA,CMFIBH+.BFCTR;SO DO ADD NEGATIVE INSTEAD
	IBP	CMFIBH+.BFPTR	;BUMP BYTE POINTER PAST ALREADY READ CHARS
	AOJL	AA,.-1		;LOOP FOR ALL OF THEM
				; (CAN'T DO ADJBP SINCE IT DOESN'T DO THE
				;  RIGHT THING IN THIS CASE)
	TXO	FF,CFOF		;COMMAND FILE OPEN AGAIN
	POP	P,AA		;RESTORE ACS USED UP
	POP	P,A		; . . .
	JRST	CPOPJ1		;BACK TO TYICF TO READ A CHARACTER
;COMMAND FILE I/O ERROR ROUTINE(S)

TYICE2:	GETSTS	CMFCHN,B	;I/O STATUS IN B FOR ERRP
	PUSHJ	P,TYICNR	;ABORT AND CLEAR COMMAND FILE
	$FATAL (INP,,<Input error 11 on file 09>)

;CLEAR COMMAND FILE PROCESSING

TYICNR:	RELEAS	CMFCHN,		;TOSS OUT FILE
TYICNZ:	SETZM	CMFLVL		;NO COMMAND FILES NESTED
	SETZM	CMFECH		;NO LONGER SUPPRESSING TYI ECHO
	SETZM	CMFTYO		;NOR GENERAL PROGRAM OUTPUT
	SETZM	CMFPDP		;NO MORE SPECS ON THE STACK
	TXZ	FF,CFOF		;COMMAND FILE PROCESSING IS DEAD
;RDH	SETOM	MESFLG		;SCREEN NEEDS REFRESHING
	POPJ	P,		;ET C'EST CA.
;TYIEC  --  "ECHO" A COMMAND CHARACTER
;CALL IS:
;
;	MOVX	CH,<CHAR>
;	PUSHJ	P,TYIEC
;	RETURN
;
;WHERE <CHAR> IS THE 7-BIT ASCII COMMAND CHARACTER TO BE ECHOED JUST AS
;WOULD THE MONITOR.
;
;PRESERVES ALL ACS.

TYIEC:	CAIN	CH,.CHDEL	;A <DEL>
	IORI	CH,1000		;YES
	CAIGE	CH," "		;NORMAL PRINTING ASCII?
	SKIPA	CH,CHTBL(CH)	;NO, CONTROL, FETCH ECHO BITS
	TXO	CH,EC$SLF	;YES, JUST ECHO AS SELF
	TRZE	CH,1000		;WAS IT A <DEL>?
	ANDI	CH,177		;YES, RUBOUTS DON'T ECHO AT ALL

;NOW ECHO THE CHARACTER TO THE TERMINAL AS WOULD THE MONITOR

TYIEC0:	PUSH	P,CH		;SAVE THEM
	TXNN	CH,EC$UPA	;ECHO IN ^X FORM?
	JRST	TYIEC2		;NO
	MOVEI	CH,"^"		;YES, FIRST THE UP-ARROW
	PUSHJ	P,TYOM		;OUTPUT IT
	HRRZ	CH,0(P)		;THE CHARACTER AGAIN
	TRO	CH,100		;ASCIIIZE IT
	PUSHJ	P,TYOM		;AND OUTPUT IT TOO
	MOVE	CH,0(P)		;CHARACTER AND FLAGS AGAIN
TYIEC2:	TXNN	CH,EC$SLF	;ECHO LITERALLY
	JRST	TYIEC3		;NO
	ANDI	CH,177		;YES
	PUSHJ	P,TYOM		;OUTPUT CHARACTER
	MOVE	CH,0(P)		;RESTORE FLAGS AND CHARACTER
TYIEC3:	TXNN	CH,EC$DLR	;ECHO AS "$" (I.E., ALTMODE)
	JRST	TYIEC4		;NO
	MOVEI	CH,"$"		;YES
	PUSHJ	P,TYOM		;SO OUTPUT THE DOLLAR SIGN
	MOVE	CH,0(P)		;RESTORE FLAGS AND CHARACTER
TYIEC4:	TXNN	CH,EC$CRL	;CHARACTER GET <CR><LF> APPENDED?
	JRST	TYIEC5		;NO
	MOVEI	CH,.CHCRT	;YES, FIRST THE <CR>
	PUSHJ	P,TYOM		;OUTPUT IT
	MOVEI	CH,.CHLFD	;THEN THE <LF>
	PUSHJ	P,TYOM		;OUTPUT IT TOO
TYIEC5:	POP	P,CH		;RESTORE STACK AND CHARACTER
	ANDI	CH,177		;AND NOTHING BUT THE CHARACTER
	POPJ	P,		;RETURN
;THE CHARACTER TABLE

CHTBL:	EC$UPA+.CHNUL			;000  NUL
	EC$UPA+.CHCNA			;001  ^A
	EC$UPA+.CHCNB			;002  ^B
	EC$UPA+.CHCNC			;003  ^C
	EC$UPA+.CHCND			;004  ^D
	EC$UPA+.CHCNE			;005  ^E
	EC$UPA+.CHCNF			;006  ^F
	EC$UPA+EC$SLF+.CHBEL		;007  ^G (BELL)
	EC$UPA+.CHCNH			;010  ^H (BACKSPACE)
	EC$SLF+.CHTAB			;011  ^I (TAB)
	EC$SLF+.CHLFD			;012  ^J (LINE FEED)
	EC$SLF+.CHVTB			;013  ^K (VERTICAL TAB)
	EC$SLF+.CHFFD			;014  ^L (FORM FEED)
	EC$SLF+.CHCRT			;015  ^M (CARRIAGE RETURN)
	EC$UPA+.CHCNN			;016  ^N
	EC$UPA!EC$CRL+.CHCNO		;017  ^O
	EC$UPA+.CHCNP			;020  ^P
	.CHCNQ				;021  ^Q (XON)
	EC$UPA+.CHCNR			;022  ^R
	.CHCNS				;023  ^S (XOFF)
	.CHCNT				;024  ^T
	EC$UPA+.CHCNU			;025  ^U
	EC$UPA+.CHCNV			;026  ^V
	EC$UPA+.CHCNW			;027  ^W
	EC$UPA+.CHCNX			;030  ^X
	EC$UPA+.CHCNY			;031  ^Y
	EC$UPA!EC$CRL+.CHCNZ		;032  ^Z (EOF)
	EC$DLR+.CHESC			;033  ^[ (ESCAPE)
	EC$UPA+.CHCBS			;034  ^\
	EC$UPA+.CHCRB			;035  ^]
	EC$UPA+.CHCCF			;036  ^^
	EC$UPA+.CHCUN			;037  ^_
;HERE WHEN A LINE FEED PASSES THE SCREEN, TO NOTE WHEN SCROLLING OCCURS

CNTLF:	CAIL	CH,.CHLFD	;VERTICAL CHARACTER MOTION?
	CAILE	CH,.CHFFD	; . . .
	POPJ	P,		;NO
	PUSH	P,CH		;YES, SAVE IT
	CAIN	CH,.CHLFD	;<LF>?
	MOVEI	CH,1		;YES
	CAIN	CH,.CHVTB	;<VT>?
	MOVEI	CH,4		;YES
	CAIN	CH,.CHFFD	;<FF>?
	MOVEI	CH,10		;YES
	PUSH	P,CH		;SAVE COUNT OF LINES THIS CHARACTER IS WORTH
CNTLF2:	AOS	CH,CURLIN	;COUNT CURSOR MOVEMENT DOWNWARDS
	SUB	CH,SSIZE	;FORCED SCREEN TO SCROLL YET?
	JUMPL	CH,CNTLF8	;NO
	SETOM	SCRLED		;NOTE THE SCREEN HAS ACTUALLY SCROLLED
	MOVE	CH,[WINDOW+WINDEX,,WINDOW]  ;YES, SCREEN SCROLLED A LINE
	BLT	CH,WINDOW+WINTOP-WINDEX-1  ;SO SCROLL OUR COPY TOO
	SETOM	WINDOW+WINTOP-WINDEX  ;LAST LINE NOW BLANK
	MOVE	CH,[WINDOW+WINTOP-WINDEX,,WINDOW+WINTOP-WINDEX+1]
	BLT	CH,WINDOW+WINTOP-1  ;SO BLANK OUR COPY TOO
	PUSH	P,A		;NEED
	PUSH	P,AA		; TO
	PUSH	P,B		;  SAVE
	PUSH	P,C		;   LOTS
	PUSH	P,D		;    OF
	PUSH	P,E		;     ACS
	PUSH	P,T		;      .
	PUSH	P,TT		;       .
	PUSH	P,TT1		;        .
	PUSH	P,I		;         .
	PUSH	P,OU		;          .
	DMOVE	A,SCRNA		;SCREEN BASE
	MOVEI	D,1		;WANT TO MOVE DOWN A LINE
	PUSHJ	P,DISMV		;CALL THE MAGIC ROUTINE
	DMOVEM	A,SCRNA		;SET FOR NEXT CALL TO WINFIL
	POP	P,OU		;          .
	POP	P,I		;         .
	POP	P,TT1		;        .
	POP	P,TT		;       .
	POP	P,T		;      .
	POP	P,E		;     NEED
	POP	P,D		;    TO
	POP	P,C		;   RESTORE
	POP	P,B		;  LOTS
	POP	P,AA		; OF
	POP	P,A		;ACS
	SOS	CURLIN		;BACKUP CURSOR TO LAST LINE AGAIN
CNTLF8:	SOSLE	(P)		;NEED TO ACCOUNT FOR MORE LINES?
	JRST	CNTLF2		;YES, GO BACK AND DO IT AGAIN
	POP	P,CH		;NO, JUNK COUNT WORD
	POP	P,CH		;RESTORE CALLER'S CHARACTER
	POPJ	P,		;AND RETURN TO WHOMEVER
U SCH,1				;HOLDS SAVED CHARACTER TO BE "INPUT" NEXT
				; INSTEAD OF TYPED IN ONE
U SCRLED,1			;.LT. 0 IF SCREEN SCROLLED DUE TO TYPEIN
U COLUMN,1			;PRINTING COLUMN
U CURLIN,1			;DISPLAY CURSOR IS CURRENTLY ON THIS LINE #
;ROUTINE TO TYPE A CHARACTER.
;CALL AS FOLLOWS:
;FOR TYPING TEXT:		FOR TYPING MESSAGES:
;	MOVE CH,CHARACTER		MOVE CH,CHARACTER
;	PUSHJ P,TYO			PUSHJ P,TYOM
;	RETURN				RETURN
;UNLESS TYOCTF IS TRUE, CONTROL CHARACTERS ARE TYPED WITH "^"
;FOLLOWED BY THE CORRESPONDING PRINTING CHARACTER.
;
;USES ACS A AND AA

TYOS:	TXOA	F2,TYSPCL	;TYPE <CR>, ETC INSTEAD OF PRINTER CONTROLS
TYOM:	TXZ	F2,TYSPCL	;CLR SPECIAL TYPEOUT FLAG
	TXOA	F2,TYMSGF	;SET NO-CASE-FLAGGING FLAG
TYO:	TXZ	F2,TYMSGF+TYSPCL;CLR NO-CASE-FLAGGING FLAG & SPECIAL FLAG
	PUSHJ	P,ALTEO		;CHECK FOR FUNNY ALTMODES
	TXNE	F2,TYSPCL	;ARE WE TYPING <ALT>, <CR> ETC. ??
	JRST	TYOSP		;YES, LOOK FOR SPECIAL CASES
TYO2:	CAIN	CH,.CHTAB	;IS IT A TAB ??
	JRST	TYOTAB		;YES
	CAIN	CH,.CHLFD	;LINEFEED??
	JRST	TYOLF		;YES
	CAIN	CH,.CHCRT	;CARRIAGE RETURN ??
	JRST	TYOCR		;YES
	CAIN	CH,.CHESC	;ESCAPE??
	JRST	TYOESC		;YES
	CAIE	CH,.CHFFD	;<FF>?
	CAIN	CH,.CHBEL	;A <BEL>?
	JRST	TYOBEL		;YES, JUST OUTPUT IT
	CAIN	CH,.CHCNH	;<BS>?
	JRST	TYOBS		;YES
	CAIG	CH,37		;SKIP IF NON-CONTROL
	JRST	TYOCT		;HANDLE NON-FORMATTING CONTROLS
	PUSHJ	P,SFLAGC	;SKIP IF CHARACTER WRONG CASE
	CAIA			;IT'S THE CORRECT CASE
	JRST	TYOFLG		;FLAG WRONG CASE CHARACTERS
TYOCH:	AOS	COLUMN		;YES, SO REMEMBER TO INCREMENT IT FOR CHARACTER
	JRST	TYOA		;FINALLY....GO TYPE THE BLASTED CHARACTER !!!
TYOBEL:	TXNN	F2,TYMSGF	;MESSAGE OR TEXT?
TYOCT:	TXNE	FF,TYOCTF	;WANT TO OUTPUT CONTROL LITERALLY?
	JRST	TYOA		;TYPE CONTROL CHARACTER LITERALLY
	PUSH	P,CH		;SAVE CONTROL-CHARACTER TO BE TYPED
	MOVEI	CH,"^"		;GET UPARROW
	PUSHJ	P,TYO		;TYPE IT
	MOVE	CH,(P)		;GET CONTROL CHARACTER, BUT LEAVE IT ON THE STACK
	ADDI	CH,100		;MAKE IT CORRESPONDING NON-CONTROL
	JRST	TYOFL5		;TYPE X OF ^X


TYOFLG:	PUSH	P,CH		;SAVE CHARACTER
	MOVEI	CH,CFLAG	;GET WRONG CASE SYMBOL
	PUSHJ	P,TYO		;TYPE WRONG CASE FLAG
	MOVE	CH,(P)		;GET CHARACTER ORIGINALLY TO BE PRINTED
TYOFL5:	PUSH	P,TYCASF	;SAVE CURRENT CASE SWITCH
	SETOM	TYCASF		;SET CASE TO 0 SO NO FLAGGING
	PUSHJ	P,TYO		;OF X PART OF ^X
	POP	P,TYCASF	;RESTORE CASE SWITCH
	POP	P,CH		;AND ORIGINAL CONTROL CHARACTER
	POPJ	P,		;AND RETURN


TYOBS:	SKIPN	SCTYPE		;ON VIDEO SCREEN?
	JRST	TYOCT		;NO, RANDOM CONTROL CHARACTER
	SOSGE	COLUMN		;BACKSPACE MOVES CURSOR BACKWARDS
	SETZM	COLUMN		;***KROCK
	JRST	TYOA		;OUTPUT THE CHARACTER WITHOUT FURTHER ADO

TYOTAB:	MOVE	CH,COLUMN	;GET CURRENT COLUMN COUNT
;RDH	CAML	CH,SWIDTH	;ARE WE AT RIGHT MARGIN?
;RDH	PUSHJ	P,CRR		;YES, SO GO TO NEXT LINE
;RDH	MOVE	CH,COLUMN	;GET CURRENT COLUMN COUNT
	ADDI	CH,8		;ADD 8 TO IT FOR TAB COUNT
	TRZ	CH,7		;BUT JUST GO TO NEXT MULTIPLE OF 8
	SUB	CH,COLUMN	;CH:=COUNT OF POSITIONS TO NEXT TAB STOP
	ADDM	CH,COLUMN	;UPDATE COLUMN POSITION COUNTER NOW
	PUSH	P,CH		;SAVE COUNT
	MOVEI	CH," "		;GET TAB SIMULATOR CHARACTER (SPACE)
	PUSHJ	P,TYOA		;OUTPUT A SPACE (ERASING SCREEN SLOT)
	SOSLE	(P)		;COUNT IT DOWN
	JRST	.-2		;FILL ENTIRE TAB SLOT
	POP	P,CH		;RESTORE STACK
	MOVEI	CH,.CHTAB	;RETURN WHAT WE WERE CALLED WITH
	POPJ	P,		;RETURN TO CALLER

TYOCR:	SETZM	COLUMN		;SET COLUMN TO 0 BECAUSE CR GOES TO LEFT MARGIN
	MOVEI	CH,.CHCRT	;REMEMBER WE STARTED WITH CR
	JRST	TYOA		;TYPE CARRIAGE RETURN
TYOESC:	MOVEI	CH,"$"		;ALTMODE PRINTS AS DOLLAR SIGN
	PUSHJ	P,TYO		;TYPE DOLLAR SIGN
	MOVEI	CH,.CHESC	;RESTORE CH AS ESCAPE
	POPJ	P,

;HERE TO TYPE OUT CHARACTERS IN THE FORM <ESC>, ETC.

TYOSP:	PUSH	P,A		;SAVE A
	PUSH	P,CH		;AND CH TOO
	MOVEI	A,TSPTBL	;SPECIAL CHARACTER-NAMES TABLE
TYOSP2:	LDB	CH,[POINT 7,(A),35]  ;LOOK AT TABLE ENTRY
	JUMPE	CH,TYOSP9	;NOT A SPECIAL CHARACTER
	CAME	CH,(P)		;SPECIAL CASE CHARACTER?
	AOJA	A,TYOSP2	;NOT THIS ONE, LOOK AT REST OF THE TABLE
	MOVEI	CH,"<"		;YES, START OF SPECIAL TYPEOUT
	PUSHJ	P,TYOCH		;OUTPUT CHARACTER
	TLOA	A,(POINT 7,)	;MAKE BYTE POINTER TO SPECIAL TYPEOUT
TYOSP5:	PUSHJ	P,TYOCH		;OUTPUT ANOTHER CHARACTER
	ILDB	CH,A		;FETCH NEXT FUNNY CHARACTER
	JUMPN	CH,TYOSP5	;AND TYPE IT OUT
	MOVEI	CH,">"		;END OF SPECIAL CASE NAME
	PUSHJ	P,TYOCH		;TYPE IT OUT
	POP	P,CH		;RESTORE REAL CHARACTER
	POP	P,A		;AND SCRATCH AC USED
	POPJ	P,		;RETURN TO TYOS CALLER

TYOSP9:	POP	P,CH		;RESTORE CHARACTER
	POP	P,A		;AND SCRATCH AC TROUNCED
	JRST	TYO2		;TYPE OUT NORMALLY

;THE SPECIAL NAME TABLE FOR CHARACTERS

TSPTBL:	<ASCII	"BEL"> + .CHBEL	;^G = <BEL>
	<ASCII	"TAB"> + .CHTAB	;^I = <TAB>
	<ASCII	"LF">  + .CHLFD	;^J = <LF>
	<ASCII	"VT">  + .CHVTB	;^K = <VT>
	<ASCII	"FF">  + .CHFFD	;^L = <FF>
	<ASCII	"CR">  + .CHCRT	;^M = <CR>
	<ASCII	"ESC"> + .CHESC	;^[ = <ESC>
	EXP	0		;END OF TABLE

TYOLF:	PUSHJ	P,CNTLF		;GO NOTE LINE WENT OUT
				;AND OUTPUT IT
TYOA:	SOSG	TOB+.BFCTR	;OUTPUT SPACE AVAILABLE?
	PUSHJ	P,TYOOUT	;NO, DO OUTPUT
	IDPB	CH,TOB+.BFPTR	;STUFF CHARACTER IN OUTPUT BUFFER
	TXO	FF,TYOF		;MARK OUTPUT PENDING IN BUFFER
	AOS	TYOTCT		;COUNT TOTAL ACTIVITY
	POPJ	P,		;RETURN

TYOOUT:	TXZ	FF,TYOF		;NOTE NO NEED FOR OUTPUT ANYMORE
	OUT	TTYCHN,		;GIVE CURRENT BUFFER TO MONITOR
	POPJ	P,		;RETURN WITH NEW BUFFER
	POPJ	P,		;IGNORE ERROR FOR NOW
;TTY OPEN BLOCK

TTYBLK:	TTYIOS			;INITIAL I/O STATUS
	'TTY   '		;AIM FOR TTY DEVICE
	TOB,,TIB		;RING HEADERS FOR I/O

TTYPT:	POINT	7,TTIBF1+3	;CCL COMMAND BUFFER POINTER
TTYPT2:	POINT	7,TTIBF1+3,13	;TO INSERT FILE NAME AFTER EW OR EB


U TYIPT,1			;
U TIB,3				;BUFFER HEADER
U TTIBF1,<TTIBFN*<TTIBSZ+3>>	;TERMINAL INPUT BUFFER RING
U TOB,3				;DITTO
U TTOBF1,<TTOBFN*<TTOBSZ+3>>	;TERMINAL OUTPUT BUFFER RING
U TTSTS,1			;CURRENT TERMINAL I/O MODE
U TTYUDX,1			;UDX OF TTY ON TTY CHANNEL
U TYOTCT,1			;COUNT OF TERMINAL OUTPUT SINCE START OF CMD

U IBUF,3			;INPUT TEXT FILE BUFFER RING HEADER
U OBUF,3			;OUTPUT TEXT FILE BUFFER RING HEADER
U BICNT,1			;.EQ. 0 THEN INPUT BUFFER RING NOT SETUP
				;.GT. 0 THEN COUNT OF BUFFERED INPUTS (+1)
U BOCNT,1			;.EQ. 0 THEN OUTPUT BUFFER RING NOT SETUP
				;.GT. 0 THEN COUNT OF BUFFERED OUTPUTS (+1)
U IOFIR,1			;FIRST PAGE IN USE FOR I/O
U IOLIST,4			;DUMP-MODE I/O COMMAND LIST
;INBMES  --  TYPE OUT A MESSAGE, INSURING A FRESH LINE
;CALL IS:
;
;	PUSHJ	P,INBMES
;	  ASCIZ\TEXT\
;	RETURN
;
;USES CH

INBMES:	SKIPE	COLUMN		;IN COLUMN 0 (LEFT MARGIN)
	PUSHJ	P,CRR		;NO, ISSUE A CRLF
INLMES:	PUSH	P,A		;PRESERVE AC "A"
	HRRZ	A,-1(P)		;GET LOCAL ADDRESS OF ASCIZ STRING
	TLOA	A,(POINT 7,)	;MAKE INTO A BYTE POINTER AND SKIP INTO LOOP
INLME2:	PUSHJ	P,TYOM		;OUTPUT THIS CHARACTER
	ILDB	CH,A		;GET THE NEXT CHARACTER
	JUMPN	CH,INLME2	;AND OUTPUT IT
	HRRI	A,1(A)		;ADVANCE PAST JUNK
	HRRM	A,-1(P)		;AND SET RETURN ADDRESS
	POP	P,A		;RESTORE AC "A"
	PJRST	CRR		;CAP OFF THE MESSAGE WITH A <CR><LF>
;ROUTINE TO OUTPUT DECIMAL (OCTAL IF OCTALF IS ON) INTEGER
;CALL	MOVE B,INTEGER
;	MOVEI A,ADDRESS OF OUTPUT ROUTINE
;	PUSHJ P,DPT
;	RETURN

DPT:	MOVEM	A,LISTF5
	JUMPGE	B,DPT1		;NUMBER GREATER THAN 0?
	MOVEI	CH,"-"		;NO. OUTPUT -
	PUSHJ	P,@LISTF5
	MOVMS	B		;B:=ABSOLUTE VALUE OF B
DPT1:	MOVEI	A,12		;RADIX 10
	TXNE	F2,OCTALF	;OCTAL RADIX?
	MOVEI	A,10		;YES, CHANGE TO RADIX 8
DPT3:	IDIVI	B,(A)		;E:=DIGIT
	PUSH	P,E		;PUT DIGIT ON TOP OF PUSH DOWN LIST
	CAIE	B,0		;DONE?
	PUSHJ	P,DPT3		;NO. PUSH THIS DIGIT AND PRINT RETURN ADDRESS.
	POP	P,CH		;YES. CH:=DIGIT
	ADDI	CH,"0"		;CONVERT IT TO ASCII.
	JRST	@LISTF5		;PRINT IT

;ROUTINE TO TYPE CARRIAGE RETURN LINE FEED
;CALL	PUSHJ P,CRR
;	RETURN

CRR:	MOVEI	CH,.CHCRT	;A <CR>
	PUSHJ	P,TYOM		;OUTPUT IT
	MOVEI	CH,.CHLFD	;AND A <LF>
	PJRST	TYOM		;OUTPUT IT AND RETURN
	SUBTTL	CRASH RECOVERY FILE ROUTINES

;THE TEB??? ROUTINES (AND ASSOCIATED VARIABLES) WRITE THE CRASH RECOVERY
;FILE WHICH CONTAINS VERBATIM EVERY CHARACTER TYPED IN BY THE USER (YES,
;EVEN RUBOUTS!). CCL CHARACTERS ARE INCLUDED, BUT ALL OTHER COMMAND FILE
;CHARACTERS (E@ FILES) ARE EXCLUDED.
;
;THE CRASH RECOVERY FILE IS CONTROLLED BY THE /CRDISP SWITCH, WHICH
;TAKES "NEVER", "TEMPORARY", "DELETE", OR "PRESERVE" AS ARGUMENTS.
;"NEVER" TURNS OFF CRASH RECOVERY. "TEMPORARY" WRITES THE RECOVERY FILE
;AS NNNTEB.TMP AND DELETES IT ON EXIT. "DELETE" WRITES THE RECOVERY FILE
;AS NNNTEB.TEB (SO LOGOUT WON'T GET IT) AND DELETES IT ON EXIT. "PRESERVE"
;WRITES THE RECOVERY FILE AS NNNTEB.TEB AND DOESN'T DELETE IT.
;
;FURTHER, THE USER CAN SPECIFY THE CRASH RECOVERY FILE EXPLICITLY
;VIA /CRFILE:FILESPEC.
;
;THE CRASH RECOVERY FILE IS AUTOMATICALLY UPDATED EVERY TEBSAV CHARACTERS
;(ACTUALLY THE FIRST BREAK CHARACTER AFTER TEBSAV CHARACTERS) AND IN ANY
;CASE EVERY BLOCK'S WORTH (640 DECIMAL).


;CRASH RECOVERY IMPURE DATA

U TEBINF,1			;.NE. 0 THEN TEBINI HAS BEEN CALLED
U TEBING,1			;.NE. 0 THEN CRASH FILE BEING WRITTEN
U TEBCNT,1			;COUNT OF CHARACTERS TILL NEXT CHECKPOINT
U TEBOBH,3			;OUTPUT BUFFER RING HEADER BLOCK
U TEBOBF,BLKSIZ+3		;OUTPUT BUFFER RING (1 BUFFER ONLY)
;TEBINI  --  INITIALIZE CRASH RECOVERY FILE FOR WRITTING

TEBINI:	SETOM	TEBINF		;TEBINI HAS BEEN CALLED
	SETZM	TEBING		;BUT WE'RE NOT WRITING THE FILE (YET)
	MOVE	TT,S.CRDI	;/CRDISP SETTING
	CAIN	TT,$TBNEV	;/CRDISP:NEVER?
	POPJ	P,		;YES, THEN NO CRASH RECOVERY FILE

;SUPPLY DEFAULT CRASH FILE IF USER DIDN'T GIVE ONE

	MOVSI	A,'DSK'		;DEFAULT CRASH FILE DEVICE
	SKIPN	S.CRFI+.FXDEV	;/CRFILE GIVE A DEVICE?
	MOVEM	A,S.CRFI+.FXDEV	;NO, USE OUR DEFAULT
	SKIPGE	TT,S.CRDI	;/CRDISP SETTING
	MOVEI	TT,$TBTEM	;NONE, DEFAULT IS /CRDISP:TEMPORARY
	MOVE	A,TMPTEC	;SIXBIT/NNNTEC/
	SUBI	A,1		;SIXBIT/NNNTEB/ (IN CASE .TMP EXTENSION)
	SETO	AA,		; -1 = NO WILDCARDS
	SKIPN	S.CRFI+.FXNAM	;/CRFILE GIVE A FILENAME?
	DMOVEM	A,S.CRFI+.FXNAM	;NO, USE NNNTEB AS A DEFAULT
	MOVSI	A,'TEB'		;TEB EXTENSION
	CAIN	TT,$TBTEM	;/CRDISP:TEMPORARY?
	MOVSI	A,'TMP'		;YES, LET LOGOUT DELETE IT FOR US
	SKIPN	S.CRFI+.FXEXT	;/CRFILE GIVE AN EXTENSION?
	HLLOM	A,S.CRFI+.FXEXT	;NO, USE DEFAULT (,,-1 = NO WILDCARDS)
	MOVX	B,FX.DIR	;THE DIRECTORY-TYPED FLAG
	TDNE	B,S.CRFI+.FXMOM	;/CRFILE GIVE A DIRECTORY?
	JRST	TEBIN1		;YES
	IORM	B,S.CRFI+.FXMOM	;NO, WE ARE SUPPLYING ONE THEN
	IORM	B,S.CRFI+.FXMOD	;AND IT IS TO BE [,]
	SETZM	S.CRFI+.FXDIR	; . . .
	SETOM	S.CRFI+.FXDIM	; -1 = NO WILDCARDS
TEBIN1:	MOVEI	A,TEBPRT	;DEFAULT CRASH FILE PROTECTION
	SKIPE	FDAEM		;IS THIS A FILE-DAEMON SYSTEM?
	TRO	A,400		;YES
	SKIPL	S.CRPR		;USER SPECIFY /CRSPRO?
	MOVE	A,S.CRPR	;YES, USE HIS EXPLICIT PROTECTION THEN
	DPB	A,[POINTR S.CRFI+.FXMOD,FX.PRO]  ;SUPPLY PROTECTION
	MOVEI	A,FX.PRO	;THE PROTECTION MASK
	DPB	A,[POINTR S.CRFI+.FXMOM,FX.PRO]  ;SET MASK TOO

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;NOW SETUP THE OPEN AND LOOKUP BLOCKS FROM THE SCAN BLOCK

	SETZM	XFIBLK		;INITIALIZE FIRST WORD OF FILE BLOCK
	MOVE	A,[XFIBLK,,XFIBLK+1]  ;BLT POINTER TO
	BLT	A,XFIBLK+XFILEN-1  ;INITIALIZE ENTIRE FILE BLOCK
	MOVEI	A,XFILEN	;LENGTH OF ENTER BLOCK
	MOVEM	A,XCNT		;SET IN ENTER BLOCK
	JSP	OU,CALLSW	;THIS IS A TOTALLY DISGUSTING KROCK!
		.FXLEN,,S.CRFI		;T1/SCAN BLOCK
		IFIW	TEBIX		;ADDRESS OF ROUTINE TO GO TO .STOPB
	 JRST	TEBIF5		;WILDCARDS?
	MOVX	A,UU.RRC	;ASCII, AUTO UPDATE OF RIB

IFN	RUN603,<SETZ A,>	;6.03 WILL GIVE ?ILL DATA MODE . . .

	IORM	A,OPNSTS	;SET INITIAL I/O STATUS
	MOVSI	A,TEBOBH	;ADDRESS OF OUTPUT BUFFER RING HEADER
	MOVEM	A,OPNBUF	;SET IN OPEN BLOCK
	OPEN	TEBCHN,OPNBLK	;INITIALIZE I/O CHANNEL
	 JRST	TEBIF1		;CAN'T OPEN DSK:?????????

;WE HAVE OUTPUT DEVICE, VERIFY IT'S USEFULLNESS

	MOVEI	A,OPNBLK	;I/O CHANNEL
	DEVSIZ	A,		;SEE HOW BIG BUFFERS SHOULD BE
	 MOVEI	A,BLKSIZ+3	;ASSUME OK
	ANDI	A,-1		;JUST BUFFER SIZE (INC OVERHEAD)
	SUBI	A,2		;JUST BUFFER SIZE
	CAIE	A,BLKSIZ+1	;RIGHT SIZE?
	JRST	TEBIF3		;NO, FORGET IT
	HRLI	A,TEBOBF+.BFHDR	;ADDRESS OF BUFFER IN RING
	MOVSM	A,TEBOBF+.BFHDR	;SETUP BUFFER RING
	HRRI	A,(BF.VBR)	;VIRGIN BUFFER RING BIT
	MOVSM	A,TEBOBH+.BFADR	;LINK RING TO HEADER BLOCK
	SETZM	TEBOBH+.BFCTR	;FORCE INITIAL OUT

;NOW CREATE OUTPUT FILE

	ENTER	TEBCHN,XFIBLK	;CREATE THE RECOVERY FILE
	 JRST	TEBIF4		;CREATE ERROR

;ALL SET FOR CRASH RECOVERY FILE WRITING

	SETOM	TEBING		;WE ARE NOW LOGGING ALL INPUT
	POPJ	P,		;RETURN ALL SET


;JUNK KROCK ROUTINE FOR CALLING .STOPB

TEBIX:	MOVEI	T2,OPNBLK	;ADDRESS OF OPEN BLOCK
	MOVE	T3,[XFILEN,,XFIBLK]  ;LENGTH,,ADDRESS OF ENTER BLOCK
	MOVEI	T4,PTHBLK	;AND A PATH BLOCK WE CAN USE
	PJRST	.STOPB##	;NOW LET SCAN DO ITS THING
;INITIALIZATION FAILURES

;THESE ROUTINES ARE JUNK, BUT UNTIL TECO HAS A BETTER ERROR-HANDLING
;FACILITY THEY WILL JUST HAVE TO DO . . .

TEBIF1:	$WARN	(COC,TEBIFX,<Cannot OPEN crash recovery file>)

TEBIF3:	$WARN	(CRB,TEBIFX,<Crash recovery file blocksize not 200>)

TEBIF4:	$WARN	(CEC,TEBIFX,<Cannot ENTER crash recovery file>)

TEBIF5:	$WARN	(WIC,TEBIFX,<Wildcards illegal in /CRFILE switch>)

TEBIFX:	$WARN	(RWC,,<Running without crash recovery>)
	SETZM	TEBING		;MAKE PREDICTION COME TRUE
	SETOM	WINFLG		;DON'T MUNGE ON THE SCREEN
	PJRST	CRR		;ISSUE <CR><LF>
;TEBCHR  --  ADD COMMAND CHARACTER TO CRASH RECOVERY FILE.
;CALL IS:
;
;	MOVX	CH,<CHAR>
;	PUSHJ	P,TEBCHR
;	RETURN
;
;WHERE <CHAR> IS THE 7-BIT ASCII COMMAND CHARACTER AS TYPED BY THE USER.
;
;ON AN I/O ERROR A WARNING MESSAGE IS ISSUED, BUT ANY REAL ERRORS ARE
;JUST IGNORED.
;
;PRESERVES ALL ACS.

TEBCHR:	SKIPN	TEBING		;DOING COMMAND BACKUP?
	POPJ	P,		;NO, THEN DON'T DO IT
	SOSG	TEBOBH+.BFCTR	;ANY ROOM IN OUTPUT BUFFER?
	PUSHJ	P,TEBOUT	;NO, OUTPUT CURRENT BUFFER
	IDPB	CH,TEBOBH+.BFPTR;PUT CHARACTER IN BUFFER
	SOSLE	TEBCNT		;TIME TO FORCE A CHECKPOINT YET?
	POPJ	P,		;NO
	CAIL	CH,.CHLFD	;YES, A BREAK CHARACTER ENCOUNTERED?
	CAILE	CH,.CHFFD	; (I.E., A <LF>, <VT>, OR <FF>)
	CAIN	CH,.CHESC	;OR AN <ESC>?
	CAIA			;YES
	POPJ	P,		;NO, THEN STILL MORE TO COME

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;TIME TO CHECKPOINT THE OUTPUT FILE

TEBURB:	SKIPN	TEBING		;DOING COMMAND CRASH RECOVERY?
	POPJ	P,		;NO, THEN DON'T DO IT
	PUSH	P,A		;NEED A COUPLA ACS
	PUSH	P,AA		; . . .
	MOVE	AA,[TEBCHN,,.FOURB]  ;FILOP. FUNCTION WORD
	MOVE	A,[1,,AA]	;FILOP. ARG POINTER TO
	PUSH	P,TEBOBH+.BFPTR	;MONITOR BUG - LEAVES POINTER MUNGED
	PUSH	P,TEBOBH+.BFCTR	;MONITOR BUG - THE COUNTER TOO
	FILOP.	A,		;CHECKPOINT THE CRASH RECOVERY FILE
	 OUTSTR	[ASCIZ\% Error checkpointing crash recovery file, proceeding
\]				;COMPLAIN TO USER
	POP	P,A		;SAVED BYTE COUNTER
	SKIPE	TEBOBH+.BFCTR	;DID WE JUST CROSS A BLOCK BOUNDRY?
	MOVEM	A,TEBOBH+.BFCTR	;NO, STILL HAVE OLD BLOCK, SUPPRESS NULLS
	POP	P,TEBOBH+.BFPTR	;END OF MONITOR BUG
	SKIPGE	A,S.CRSA	;/CRSAVE:NNN GIVEN?
	MOVEI	A,TEBSAV	;NO, COUNT OF CHARACTERS TILL NEXT CHECKPOINT
	CAIG	A,0		;IF 0 (E.G., /CRSAVE:0)
	MOVEI	A,-1		;THEN WAIT FOR A BLOCK BOUNDRY
	MOVEM	A,TEBCNT	;RESET CHARACTER COUNTER
	POP	P,AA		;RESTORE THE CRUNCHED ACS
	POP	P,A		; . . .
	POPJ	P,		;AND RETURN IN ANY CASE

;OUTPUT CURRENT BUFFER, GET NEW ONE

TEBOUT:	OUT	TEBCHN,		;GIVE BUFFER TO MONITOR
	CAIA			;ALL WELL AND GOOD
	 OUTSTR	[ASCIZ\% Error writing crash recovery file, proceeding
\]				;COMPLAIN TO USER
	MOVEM	A,TEBCNT	;NEED AN AC
	SKIPGE	A,S.CRSA	;GET USER-SPECIFIED SAVE COUNT
	MOVEI	A,TEBSAV	;COUNT OF CHARACTERS TO NEXT CHECKPOINT
	CAIG	A,0		;IF 0 (E.G., /CRSAVE:0)
	MOVEI	A,-1		;THEN WAIT FOR A BLOCK BOUNDRY
	EXCH	A,TEBCNT	;RESET SINCE OUT IS AN IMPLICIT CHECKPOINT
	POPJ	P,		;AND RETURN IN ANY CASE
;TEBFIN  --  TIME TO EXIT, TOSS OUT CRASH RECOVERY FILE NOW.

TEBFIN:	SKIPGE	A,S.CRDI	;GET /CRDISP SETTING
	MOVEI	A,$TBDEL	;NONE, ASSUME /CRDISP:DELETE
	JUMPE	A,TEBFI6	;IF NO FILE DON'T BOTHER
	CAIN	A,$TBPRE	;/CRDISP:PRESERVE?
	JRST	TEBFI3		;YES
	SETZB	A,AA		;NULL FILENAM = DELETE
	SKIPE	TEBING		;I/O CHANNEL OPEN?
	RENAME	TEBCHN,A	;YES, DELETE CRASH RECOVERY FILE
	 JFCL			;HO HUM
TEBFI3:	CLOSE	TEBCHN,		;LET GO OF FILE IN ANY CASE
	RELEAS	TEBCHN		;AND DEVICE/CHANNEL AS WELL
TEBFI6:	SETZM	TEBING		;FILE NO LONGER OPEN
	POPJ	P,		;AND THAT'S THAT.



;TEBJ  --  WRITE OUT A <NNN>J COMMAND TO THE BACKUP COMMAND FILE TO
;ENSURE THAT, IN THE EVENT OF A CRASH RECOVERY STINT ON A DIFFERENT
;TERMINAL TYPE, THE CURSOR (".") WILL BE IN THE RIGHT PLACE.

TEBJ:	PUSH	P,A		;SAVE A
	PUSH	P,B		;SAVE B
	PUSH	P,B+1		;AND "IDIVI B,"
	PUSH	P,CH		;SAVE CHARACTER
	XMOVEI	A,TEBCHR	;CHARACTER OUTPUT ROUTINE
	MOVE	B,I		;THE CURRENT CURSOR POSITION
	SUB	B,BEG		;MAKE INTO RELATIVE TEXT POSITION
	PUSHJ	P,DPT		;"TYPE" THE CURSOR POSITION
	MOVEI	CH,"J"		;A "J" COMMAND
	PUSHJ	P,TEBCHR	;PUT IT IN BACKUP FILE
	MOVEI	CH,.CHESC	;AND TERMINATING <ESC>
	PUSHJ	P,TEBCHR	;PUT IT IN BACKUP FILE
	PUSHJ	P,TEBCHR	;TERMINATE REGULAR COMMAND
	POP	P,CH		;RESTORE CH
	POP	P,B+1		;RESTORE "IDIVI B,"
	POP	P,B		;RESTORE B
	POP	P,A		;RESTORE A
	POPJ	P,		;RETURN
	SUBTTL	COMMAND CHARACTER ROUTINES

;RETURN NEXT COMMAND CHAR AT CURRENT LEVEL
;CALL:	PUSHJ	P,SKRCH
;	ERROR RETURN IF NO MORE CHARS AT THIS LEVEL
;	NORMAL RETURN WITH CHAR IN CH

SKRCH:	SKIPG	COMCNT		;ANY CHARS LEFT?
	POPJ	P,		;NO, TAKE ERROR RETURN
	PUSHJ	P,RCH		;YES, GET NEXT
CPOPJ1:	AOS	(P)		;SKIP RETURN
	POPJ	P,



;PEEK AT NEXT COMMAND CHAR AT CURRENT LEVEL
;CALL:	PUSHJ	P,PKRCH
;	ERROR RETURN IF NO MORE CHARS AT THIS LEVEL
;	NORMAL RETURN WITH CHAR IN CH

PKRCH:	SKIPG	COMCNT		;ANY CHARS LEFT?
	POPJ	P,		;NO, TAKE ERROR RETURN
	PUSH	P,COMPTR	;SAVE CURRENT COMMAND POINTER
	PUSH	P,COMPTX	; (DOUBLE-WORD POINTER ADDRESS)
	PUSH	P,COMCNT	;SAVE CURRENT COMMAND COUNTER
	PUSHJ	P,GCH		;YES, GET NEXT CHAR SANS TRACING
	POP	P,COMCNT	;RESTORE COMMAND COUNTER
	POP	P,COMPTX	; (DOUBLE-WORD POINTER ADDRESS)
	POP	P,COMPTR	;RESTORE COMMAND POINTER
	JRST	CPOPJ1		;TAKE SUCCESSFUL RETURN WITH CHAR IN CH
;GET NEXT CHAR FROM CURRENT COMMAND LEVEL WHERE A CHAR IS
;KNOWN TO BE THERE, AND NO TRACING IS WANTED

GCH:	SOS	COMCNT		;REDUCE CHAR COUNT
	ILDB	CH,COMPTR	;GET CHAR.
	JRST	ALTEO		;CONVERT OLD ALTMODES AND RETURN



;ROUTINE TO RETURN NEXT CHARACTER FROM COMMAND BUFFER.
;CALL	PUSHJ P,RCH
;	RETURN ALWAYS WITH CHARACTER IN CH

RCH:	SOSGE	COMCNT		;DECREMENT COMMAND BUFFER CHARACTER COUNT
				;IS COMMAND BUFFER EMPTY?
	JRST	RCH2		;YES. POP UP TO HIGHER MACRO LEVEL.
	ILDB	CH,COMPTR	;NO. GET COMMAND CHARACTER IN CH
	PUSHJ	P,ALTEO		;CONVERT OLD ALTMODES IF EO = 1
	TXNE	FF,TRACEF	;IN TRACE MODE?
	TXNE	F2,NOTRAC	;TRACE ENABLED?
	POPJ	P,		;NO, RETURN
	PUSH	P,A		;YES, SAVE A FOR CALLING ROUTINE
	PUSHJ	P,TYO		;TYPE THE COMMAND
	POP 	P,A		;RESTORE THE STATE
	POPJ	P,		;AND RETURN

RCH2:	POP	P,CH		;SAVE RETURN FOR POPJ IN CH
	POP	P,COMCNT	;GET RID OF FLAG
	SKIPE	EQM		;DON'T ALLOW NEG MACRO COUNT
	SOS	EQM		;DECREMENT THE MACRO LEVEL
	SOSG	COMCNT		;IF ANG BRAK ON PDL, ITS A INCOMPLETE MACRO
	$FATAL	(IAB,,<Incomplete <...> or (...) in macro>)
	POP	P,COMCNT	;GET COUNT FROM NEXT MACRO LEVEL
	POP	P,COMPTX	;RESTORE DOUBLE-WORD POINTER ADDRESS (IF ANY)
	POP	P,COMPTR	;CURRENT POINTER TOO
	POP	P,COMMAX	;NUMBER OF COMMAND CHARACTERS
	PUSH	P,CH		;PUT RETURN BACK ON PDL.
	JRST	RCH		;TRY AGAIN.
;SCAN COMMAND STRING FOR CHARACTER IN TT
;IGNORING PAIRS STARTING WITH CHAR. IN TT1 AND ENDING WITH (TT)
;ASSUMED THAT COMPTR IS SET
;NON-SKIP RETURN IF (TT) CAN'T BE FOUND
;SKIP RETURN IF FOUND
;COMPTR LEFT SET FOR NEXT CHAR. IN COMMAND STRING

SKAN:	TXO	F2,NOTRAC	;INHIBIT TRACE ACTION WHILE SKANNING
	MOVEI	C,0		;CTR FOR <> AND "...' PAIRS
SKAN0:	TXZ	F2,SKIMQF+SKIMRF+SKANFS	;CLR SKIM FLAGS
	PUSHJ	P,SKIMCH	;GET COMMAND CHAR.
	CAIN	CH,(TT1)	;SECONDARY CHARACTER?
	AOJA	C,SKAN1		;YES, COUNT IT
	CAIN	CH,(TT)		;PRIMARY CHAR?
	JRST	SKAN99		;YES!
SKAN1:	CHKEO	EO21,SKAN0	;OLD STYLE SKAN IF EO = 1
	MOVEI	T,SKNTAB	;NO, WATCH OUT FOR TEXT STRINGS
SKAN00:	PUSHJ	P,DISPAT
	JRST	SKAN0		;NOT A TEXT-ARG COMMAND, IGNORE IT
SKAN2:	PUSHJ	P,SKIMCH	;GET CHAR AFTER "^"
	CAIN	CH,"A"
	JRST	SKAN7		;^A COMMAND
	CAIN	CH,"^"
	JRST	SKAN11		;^^ COMMAND
	JRST	SKAN0		;ORDINARY CONTROL-COMMAND, FORGET IT


;EB; EP; ER; EW; EZ; E@.

SKAN3:	PUSHJ	P,SKIMCH
	MOVEI	T,SK3TAB	;WHICH E COMMAND?
	JRST	SKAN00


;@I; @N; @S; @_; @FN; @FS; @F_

SKAN4:	PUSHJ	P,SKIMCH	;WHAT FOLLOWS @?
	MOVEI	T,SK4TAB
	PUSHJ	P,DISPAT
	JRST	SKAN4		;MUST BE 1 OF THESE 4


;O; EB; EP; ER; EW; E@ - EAT NORMAL STRING DELIMITED BY <ESC>

SKAN9:	PUSHJ	P,SKIM		;IGNORE TO $
	JRST	SKAN0
;HERE TO EAT ^AMESSAGE^A

SKAN7:	MOVEI	T,.CHCNA	;IGNORE TO ^A
	JRST	SKAN5


;HERE TO EAT !TAG!

SKAN8:	MOVEI	T,"!"		;IGNORE TO !
SKAN5:	PUSHJ	P,SKIM1		;IGNORE TO CHAR IN T
	JRST	SKAN0


;EAT TEXT STRING DELIMITED BY @/TEXT/ CLASS CONSTRUCTION

SKAN6:	PUSHJ	P,SKIMCH	;GET SEARCH DELIMITER
	SKIPA	T,CH		;IGNORE TO NEXT OCCURRENCE


;EAT TEXT DELIMITED BY NORMAL <ESC> CONSTRUCTION

SKAN12:	MOVEI	T,.CHESC	;DELIMITER IS ALTMODE
	PUSHJ	P,SKIMRQ	;SKIP TO DELIMITER & WATCH OUT FOR ^Q,^R
	JRST	SKAN0


;@I - GET EXPLICIT TERMINATOR AND EAT STRING

SKAN13:	PUSHJ	P,SKIMCH	;GET INSERT DELIMITER
	SKIPA	T,CH		;IGNORE TO NEXT OCCURRENCE


;I; <TAB> - EAT STRING UP TO NORMAL <ESC> DELIMITER

SKAN14:	MOVEI	T,.CHESC	;DELIMITER IS ALTMODE
	PUSHJ	P,SKIM.R	;SKIP TO DELIMITER & WATCH OUT FOR ^R
	JRST	SKAN0


;Q-REGISTER COMMAND, EAT Q-REGISTER NAME

SKAN11:	PUSHJ	P,SKIMCH	;IGNORE NEXT CHAR.
	JRST	SKAN0
;@FN; @FS; @F_ - EAT TWO TEXT STRINGS WITH EXPLICIT DELIMITERS

SKAN16:	MOVEI	T,SK5TAB	;TABLE FOR @F
	JRST	SKAN17


;FN; FS; F_ - EAT TWO TEXT STRINGS WITH NORMAL <ESC> DELIMITER

SKAN15:	MOVEI	T,SK1TAB	;TABLE FOR F COMMANDS
SKAN17:	TXO	F2,SKANFS	;SIGNAL FS OR FN IN PROGRESS
	PUSHJ	P,SKIMCH	;GET CHAR AFTER F
	JRST	SKAN00


;D/FD; K/FK; R/FR

SKAN20:	TXZN	F2,SKANFS	;CLEAR F-COMMAND (2 STRING ARGS) FLAG
	JRST	SKAN0		;OOPS - WASN'T AN F COMMAND
	JRST	SKAN12		;GO EAT SINGLE STRING


;@D/@FD; @K/@FK; @R/@FR

SKAN21:	TXZN	F2,SKANFS	;CLEAR F-COMMAND (2 STRING ARGS) FLAG
	JRST	SKAN0		;OOPS - WASN'T AN F COMMAND
	JRST	SKAN6		;GO EAT SINGLE STRING


;HERE ON END OF "PAIRED" STRING, RETURN UNLESS NESTED

SKAN99:	SOJGE	C,SKAN0		;IF MATCH JUST ENDS A PAIR, LOOP BACK
	TXZ	F2,NOTRAC	;ENABLE TRACING
	JRST	CPOPJ1		;OTHERWISE, WE HAVE WHAT WE WANT
;SKIM OVER TEXT
;
;SKIM	SKIP TO NEXT ALTMODE, GIVING ^R & ^Q NO SPECIAL TREATMENT
;SKIM1	SKIP OVER ARBITRARY CHAR IN T, GIVING ^R & ^Q NO SPECIAL TREATMENT
;SKIM.R	SKIP TO ARBITRARY CHAR IN T, UNLESS IT IS AFTER ^R
;SKIMRQ	SKIP TO ARBITRARY CHAR IN T, UNLESS IT IS AFTER EITHER ^R OR ^Q

SKIMRQ:	TXO	F2,SKIMQF	;CK FOR ^Q AND ^R
SKIM.R:	TXOA	F2,SKIMRF	;CK FOR ^R
SKIM:	MOVEI	T,.CHESC	;SKIP TO NEXT ALTMODE
SKIM0:	CHKEO	EO25,SKIM1	;IF EO=1,2 THEN USE OLD QUOTING CHARACTERS

SKIM1V:	PUSHJ	P,SKIMCH	;SKIM ANOTHER COMMAND CHARACTER
	CAIN	CH,(T)		;DELIMITER CHARACTER WE WANT?
	JRST	SKIM3		;YES
	TXNE	F2,SKIMRF	;NO, ALLOWING QUOTING?
	CAIE	CH,.CHCNV	;YES, IS THIS THE QUOTE CHARACTER?
	JRST	SKIM1V		;NO, KEEP LOOKING FOR DELIMITER
	PUSHJ	P,SKIMCH	;YES, EAT IT AND THE CHARACTER QUOTED
	JRST	SKIM1V		;KEEP LOOKING FOR DELIMITER

SKIM1:	PUSHJ	P,SKIMCH	;GET NEXT TEXT CHAR.
	CAIN	CH,(T)		;CHARACTER WE WANT?
	JRST	SKIM3		;YES
	CAIN	CH,.CHCNQ	;^Q?
	TXNN	F2,SKIMQF	;YES, CK FLAG ON?
	JRST	.+2		;NO
	JRST	SKIM2		;YES
	CAIN	CH,.CHCNR	;^R?
	TXNN	F2,SKIMRF	;YES, CK FLAG ON?
	JRST	SKIM1		;NO, KEEP LOOKING
SKIM2:	PUSHJ	P,SKIMCH	;GOBBLE UP NEXT CHARACTER
	JRST	SKIM1		;CONTINUE SKIMMING
SKIM3:	TXZE	F2,SKANFS	;SKIMMING OVER FS OR FN?
	JRST	SKIM0		;YES, IGNORE 1ST DELIMITER
	POPJ	P,

;GET A SINGLE CHARACTER FROM COMMAND STRING
;TAKE ERROR RETURN FROM SKAN IF THERE ARE NO MORE

SKIMCH:	PUSHJ	P,SKRCH		;GET A COMMAND CHAR.
APOPJ:	POP	P,A		;ERROR RETURN FROM SKAN IF NO MORE CHARS.
	POPJ	P,
;SKAN ROUTINE DISPATCH TABLES

SKNTAB:	XWD	SKAN15,"F"
	XWD	SKAN14,"I"
	XWD	SKAN14,.CHTAB	;TAB
	XWD	SKAN9,"O"
	XWD	SKAN8,"!"
	XWD	SKAN7,1		;^A
	XWD	SKAN11,36	;^^
	XWD	SKAN2,"^"
	XWD	SKAN3,"E"
	XWD	SKAN11,"U"
	XWD	SKAN11,"Q"
	XWD	SKAN11,"X"
	XWD	SKAN11,"G"
	XWD	SKAN11,"M"
	XWD	SKAN11,"%"
	XWD	SKAN11,"["
	XWD	SKAN11,"]"
	XWD	SKAN4,"@"
	XWD	SKAN11,42	;"
SK1TAB:	XWD	SKAN12,"S"	;S OR FS
	XWD	SKAN12,"N"	;N OR FN
	XWD	SKAN12,"_"	;_ OR F_
	XWD	SKAN20,"D"	;D (IGNORED) OR FD
	XWD	SKAN20,"K"	;K (IGNORED) OR FK
	XWD	SKAN20,"R"	;R (IGNORED) OR FR
	XWD	0,0		;LIST TERMINATOR

SK3TAB:	XWD	SKAN9,"B"	;EB
	XWD	SKAN9,"P"	;EP
	XWD	SKAN9,"R"	;ER
	XWD	SKAN9,"W"	;EW
	XWD	SKAN9,"Z"	;EZ
	XWD	SKAN9,"@"	;E@
	XWD	0,0

SK4TAB:	XWD	SKAN16,"F"	;@F
	XWD	SKAN13,"I"	;@I
SK5TAB:	XWD	SKAN6,"S"	;@S OR @FS
	XWD	SKAN6,"N"	;@N OR @FN
	XWD	SKAN6,"_"	;@_ OR @F_
	XWD	SKAN21,"D"	;@D (IGNORED) OR @FD
	XWD	SKAN21,"K"	;@K (IGNORED) OR @FK
	XWD	SKAN21,"R"	;@R (IGNORED) OR @FR
	XWD	0,0
	SUBTTL	START TECO'ING

;HERE FROM ERROR

GOE:	TRZA	FF,777777-TRACEF-QMFLG-FORM-SEQF

;HERE TO START UP A NEW COMMAND

GO:	TRZ	FF,777777-TRACEF-FORM-SEQF
	PUSHJ	P,PCSEC		;VERIFY PC IN PROPER SECTION
;RDH	TXZ	FF,CCLFLG	;CLEAR "Y" REQUESTED FLAG
	TXZ	F2,DOING	;NOT IN A COMMAND YET
	TXZ	F2,NOTRAC
	MOVE	P,[IOWD PDLEN,PDLST]	;INITIALIZE PUSHDOWN LIST
	SETZM	PDLST0		;FLAG PDL TOP - NOTE: PDL FLAGS ARE
				;0    =	TOP OF PDL
				;-1   =	LAST ITEM IS AN ITERATION
				;+1   =	LAST ITEM IS A PARENTHESIS
				;GT 1 =	LAST ITEM IS A MACRO
	PUSH	P,CH		;SAVE POSSIBLE ALREADY INPUT CHARACTER
	AOSN	TOOBIG		;MAYBE TIME TO TRY TO SHRINK DOWN?
	PUSHJ	P,SHRINK	;YES, SEE IF ANY MEMORY CAN BE RECLAIMED
;	MOVE	A,BEG		;GET POSITION BUFFER FLOATED AWAY TO
;	SUB	A,OLDBEG	;CALCULATE DISTANCE IT MOVED
;	ADDM	A,SCRNA		;MARK NEW START OF SCREEN BASE
;	ADDM	A,SCRNB		;AND FIRST CHARACTER ON SCREEN
;	ADDM	A,SCRNZ		;AND END OF SCREEN TOO
;	ADDM	A,OLDBEG	;MARK FOR NEXT DRIFT
	SKIPE	SCTYPE		;MAYBE DON'T DISPLAY
	SKIPE	CMFTYO		;SUPPRESSING OUTPUT DUE TO COMMAND FILE?
	JRST	GO2		;DO NOT DISPLAY
	SKIPE	VFREEZ		;SCREEN FROZEN BY "V" COMMAND?
	JRST	GO2		;YES, DO NOT REDISPLAY!
	SKIPN	WINFLG		;SCREEN HAVE IMPORTANT INFO?
	JRST	GOSC		;NO, OK TO REDISPLAY
	SKIPN	SCRLED		;YES, DID IT CAUSE A SCROLL?
	JRST	GOSB		;NO, THEN WE CAN STILL SAFELY REDISPLAY
	SKIPE	S.SFT		;USER TIRED OF JUNK MESSAGE?
	$INFO	(SFT,,<Screen "frozen" due to program typeout, ^L to refresh>)
	JRST	GO2		;JUST TYPE "*"

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

GOSB:	TXZ	F2,CBTMF	;DON'T ERASE TO END OF SCREEN
GOSC:	MOVE	I,Z		;GET POINTER TO END OF BUFFER
	MOVEM	I,SCRNVZ	;TELL DISPLAY TO GO ALL THE WAY
;	MOVE	B,SCRNB		;START OF SCREEN
;	MOVE	C,SCRNZ		;END OF SCREEN
;	CAML	B,BEG		;SCREEN START IN IN TEXT BUFFER?
;	CAMLE	C,Z		;AND END STILL IN TEXT BUFFER?
;	SETOM	MESFLG		;NO - SOMETHING MESSED UP
	SKIPE	MESFLG		;RECONFIGURE DISPLAY IF REFRESH NECESSARY
	PUSHJ	P,WINIT		;RECALCULATE DISPLAY START
	PUSHJ	P,WINFIL	;FILL UP NEW SCREENFUL
	SKIPGE	DISPTF		;SEE IF POINTER IS ON SCREEN
	JRST	GOSC2		;IT WAS, WE'RE OK
	PUSHJ	P,WINIT		;WASN'T, SO RECALCULATE SCREEN START
	PUSHJ	P,WINFIL	;AND REBUILD A SCREEN IMAGE
	SKIPL	DISPTF		;CURSOR ON SCREEN NOW?
	 HALT	.+1		;BLETCH
GOSC2:	SKIPE	MESFLG		;IF WINDOW OUT OF SYNC WITH SCREEN,
	PUSHJ	P,ZAPSCN	;MAKE THEM BOTH EMPTY
	PUSHJ	P,DISPLX	;OUTPUT THE SCREEN IMAGE
	MOVE	CH,SLENTH	;LENGTH OF SCREEN DISPLAY AREA
	PUSHJ	P,LINECH	;POSITION CURSOR TO COMMAND AREA
	TXZE	F2,CBTMF	;WANT A CLREOS HERE?
	PUSHJ	P,CLREOS	;YES
	SETZM	SCRLED		;CLEAR SCREEN-HAS-SCROLLED FLAG
GO2:	POP	P,CH		;RESTORE POSSIBLE FIRST COMMAND CHARACTER
	SETZM	EQM		;CLEAR MACRO LEVEL COUNT
	MOVE	PF,[XWD -LPF-1,PFL-1]
	SKIPN	CMFINF		;HAVE WE PROCESSED INIT FILE YET?
	PUSHJ	P,CMFINI	;NO, PROCESS IT IF REQUESTED
	SKIPN	TEBINF		;HAVE WE CALLED TEBINI YET?
	PUSHJ	P,TEBINI	;NO, INITIALIZE CRASH RECOVERY FILE
	JRST	CLIS
CLIS:	SETZM	WINFLG		;SO DISPLAY WILL HAPPEN NEXT TIME
	SETZM	VFREEZ		; . . .
CLIS4:	SETZM	COMCNT		;AT THIS POINT WE HAVE NO COMMAND CHARACTERS
	SETZM	COLUMN		;AND ARE AGAINST THE LEFT MARGIN
	SKIPN	CCLSW		;NEED CCL COMMAND?
	JRST	LIS0		;NO
	PUSHJ	P,CCLIN		;GET THE CCL COMMAND TO TYI BUFFER
	JRST	LI0		;AND DON'T PROMPT "*"

LIS0:	SKIPN	CMFECH		;NOECHOING OF COMMAND FILE INPUT?
	TXNE	FF,QMFLG	;1ST CHARACTER IN ALREADY?
	JRST	LIS1A		;YES
	MOVEI	CH,"*"
	PUSHJ	P,TYOM		;TYPE *
LIS1:	TXO	FF,TIBKA!TINEC	;CATCH FIRST CHARACTER TYPED
LIS1A:	TXOE	FF,QMFLG	;UNLESS ONE ALREADY IN
	JRST	LIS1C		;WE ALREADY HAVE FIRST CHAR
	PUSHJ	P,TYI
	SKIPN	CMFECH		;NOECHOING COMMAND FILE INPUT?
	SKIPN	SCTYPE		;IF USING A SCREEN,
	JRST	LIS1C		;NOT, JUST PROCESS COMMAND
	PUSH	P,CH		;WE ARE, SAVE TYPED CHARACTER A MOMENT
	PUSHJ	P,CLREOS	;CLEAR OLD COMMAND FROM SCREEN
	POP	P,CH		;GET USER'S CHARACTER BACK
LIS1C:	CAIE	CH,.CHDEL	;IS CHARACTER A <DEL>
	CAIN	CH,.CHCNU	;OR A ^U?
LIS1E:	TXZA	FF,QMFLG	;FORCE TYI CALL
	CAIA			;(SKIP)
	JRST	LIS1		;JUST EAT THE CHARACTER SANS ECHO
LIS1F:	SKIPE	TKESC		;DOES THIS TERMINAL SEND ESCAPE SEQUENCES?
	JRST	LIS2		;YES, GO CHECK FOR ESCAPE SEQUENCE
	CAMN	CH,TKCUP	;CURSOR UP KEY?
	JRST	LIS4A		;YES
	CAMN	CH,TKDWN	;CURSOR DOWN KEY?
	JRST	LIS4B		;YES
	CAMN	CH,TKRGT	;CURSOR RIGHT KEY?
	JRST	LIS4C		;YES
	CAMN	CH,TKLFT	;CURSOR LEFT KEY?
	JRST	LIS4D		;YES
LIS1N:	CAIN	CH,.CHCNH	;^H (BACKSPACE) TYPED?
	JRST	LIS4P		;YES, DISPLAY PREVIOUS SCREEN
	CAIN	CH," "		;SPACE TYPED?
	JRST	LIS4S		;YES, DISPLAY MORE OF SCREEN
	CAIN	CH,.CHCRT	;<CR>?
	JRST	LIS4V		;YES, PUT CURSOR ON SCREEN
	CAIN	CH,.CHLFD	;<LF>?
	JRST	LIS4L		;YES, 1L$$
	CAIN	CH,.CHFFD	;<FF>?
	JRST	LIS4R		;YES, REFRESH SCREEN
	SKIPN	CMFECH		;NO, SUPPRESSING COMMAND FILE ECHO?
	PUSHJ	P,TYIEC		;NO, ECHO THE CHARACTER
	CAIN	CH,.CHCNZ	;^Z?
	JRST	LIS4Z		;YES, RETURN TO MONITOR LEVEL
	CAIN	CH,"*"		;1ST CHAR AN ASTERISK?
	JRST	LIS4X		;YES, SAVE AWAY PREVIOUS COMMAND STRING
	JRST	LI0		;NO, REGULAR COMMAND - CONTINUE NORMALLY
;HERE TO INTERPRET POSSIBLE USER-INDUCED ESCAPE SEQUENCE (E.G., THE
;VARIOUS "ARROW" KEYS).

LIS2:	CAMN	CH,TKESC	;START OF AN ESCAPE SEQUENCE?
	SKIPN	TT,SCTYPE	;ON A VIDEO TERMINAL?
	JRST	LIS1N		;NO, FORGET THIS STUFF
	CAIE	TT,VXANSI	;ANSI ESCAPE SEQUENCES?
	JRST	LIS2E		;NO
	TXO	FF,TIBKA!TINEC	;YES, QUIETLY
	PUSHJ	P,TYI		; READ SECOND CHARACTER OF SEQUENCE
	CAIE	CH,"["		;REALLY ANSI SEQUENCE?
	JRST	LIS2U		;NO, QUEER CHARACTERS
LIS2E:	TXO	FF,TIBKA!TINEC	;QUIETLY
	PUSHJ	P,TYI		; SNARF NEXT NEXT INPUT CHARACTER
	CAMN	CH,TKCUP	;CURSOR UP KEY?
	JRST	LIS4A		;YES
	CAMN	CH,TKDWN	;CURSOR DOWN KEY?
	JRST	LIS4B		;YES
	CAMN	CH,TKRGT	;CURSOR RIGHT KEY?
	JRST	LIS4C		;YES
	CAMN	CH,TKLFT	;CURSOR LEFT KEY?
	JRST	LIS4D		;YES

;UNKNOWN ESCAPE SEQUENCE, JUST TREAT IT AS A REGULAR COMMAND SEQUENCE
;IF ANSI, THEN WE LOSE THE "[", BUT THINGS ARE TOUGH ALL OVER.

LIS2U:	MOVEM	CH,SCH		;SAVE SECOND CHARACTER
	SKIPE	CMFECH		;SUPPRESSING COMMAND FILE ECHO?
	JRST	LIS2X		;YES, DON'T ECHO STUFF THEN
	MOVE	CH,TKESC	;NO, "ESCAPE" CHARACTER
	PUSHJ	P,TYIEC		;"ECHO" IT
	MOVE	CH,SCH		;AND THE OTHER CHARACTER TYPED
	PUSHJ	P,TYIEC		;"ECHO" IT TOO
LIS2X:	MOVE	CH,TKESC	;FIRST CHARACTER TYPED
	JRST	LI0		;TREAT AS A REGULAR COMMAND
;MOVE CURSOR UP ONE SCREEN LINE

LIS4A:	SKIPA	D,[-1]		;MOVE "UP" ONE LINE

;MOVE CURSOR DOWN ONE SCREEN LINE

LIS4B:	MOVEI	D,1		;MOVE "DOWN" ONE LINE
	SKIPN	SCTYPE		;ON A VIDEO TERMINAL?
	JRST	LI0		;NO, TREAT AS NORMAL CHARACTER THEN
	PUSH	P,D		;SAVE COUNT
	MOVE	A,DIPTI		;GET LAST REMEMBERED "." IN DISPLAY IMAGE
	CAMN	A,PT		;HAS "." CHANGED (E.G., "BJ.=$$" COMMAND)
	SKIPL	DISPTF		;NO, IS "." ON THE CURRENT SCREEN?
	CAIA			;SOMETHING SMELLS, RE-BUILD THE BLOODY SCREEN
	JRST	LIS4B1		;NO, PROCEEDING NORMALLY

;HERE WHEN SOMETHING FUNNY IS HAPPENING - FOR SOME REASON THE CURSOR
;(I.E., ".") IS NOT ON THE CURRENT SCREEN IMAGE (E.G., ^H COMMAND) OR
;"." IS NOT CORRECTLY REPRESENTED BY THE CURRENT SCREEN IMAGE WHICH
;DISPLAYS "." (E.G., "BJ.=$$" COMMAND WHICH LEAVES THE SCREEN FROZEN,
;"." DISPLAYED ON FROZEN SCREEN, BUT "." IS REALLY AT 0).

	MOVE	TT,Z		;GET END OF TEXT BUFFER
	MOVEM	TT,SCRNVZ	;ENSURE THAT DISPLAY GOES ALL THE WAY
	PUSHJ	P,WINIT		;INITIALIZE A VIRGIN SCREEN
	PUSHJ	P,WINFIL	;AND RE-BUILD IT FROM FIRST PRINCIPLES
	MOVE	D,(P)		;RESTORE D
LIS4B1:	CAIN	D,1		;MOVING DOWN?
	SETOM	PT		;YES, DON'T GET CONFUSED BY THE "/\"
	DMOVE	A,DIPTA		;BASE/COUNT PAIR FOR SCREEN LINE WITH "."
	PUSHJ	P,DISMV		;MOVE POINTER AROUND
	POP	P,D		;RESTORE COUNT (DIRECTION FLAG ALSO)
	JUMPGE	D,LIS4B3	;IF MOVING FORWARD ALL SET
	CAMN	A,DIPTA		;HAS ANYTHING HAPPENED
	CAME	AA,DIPTAA	; (DITTO)
	CAIA			;YES
	JRST	[MOVEM	A,PT	;NO, AT TOP OF TEXT
		JRST	GO]	;SO CAN'T GO ANY FURTHER
	SETZ	D,		;CHANGE THE POINTER NOT AT ALL
	PUSHJ	P,DISMV		;BUT SET I TO START OF SCREEN LINE
LIS4B3:	SETZB	C,CH		;INITIALIZE COUNTER AND CHARACTER
	CAMGE	I,Z		;AGAINST BOTTOM OF TEXT?
	SKIPN	DIPTC		;OR CURSOR AGAINST MARGIN?
	JRST	LIS4B8		;YES
LIS4B5:	PUSHJ	P,DISCHR	;GET A DISPLAY CHARACTER
	CAIE	CH,.CHCRT	;IF END OF DISPLAY LINE
	CAMN	C,DIPTC		;OR REACHED OLD CURSOR'S "POSITION"
	SOSA	I		;YES, TOSS OUT "CURRENT" CHARACTER
	AOJA	C,LIS4B5	;NOT YET
LIS4B8:	MOVEM	I,PT		;MOVE THE CURSOR (".")

;NOW WRITE AN NNNJ COMMAND INTO COMMAND FILE (IN CASE LATER EXECUTED ON
;A DIFFERENT SCREEN SIZE)

	TXNN	FF,CFOF		;IF TOP-LEVEL COMMAND TERMINAL TYPEIN
	PUSHJ	P,TEBJ		;THEN WRITE THE NNNJ COMMAND
	JRST	GO		;NOW UPDATE SCREEN
;CURSOR RIGHT

LIS4C:	AOS	A,PT		;MOVE RIGHT ONE PLACE
	CAMLE	A,Z		;STILL IN THE TEXT BUFFER?
	SOS	PT		;NO, BACK TO WHERE WE WERE
	JRST	GO		;NEXT COMMAND


;CURSOR LEFT

LIS4D:	SOS	A,PT		;MOVE LEFT ONE PLACE
	CAMGE	A,BEG		;STILL IN THE TEXT BUFFER?
	AOS	PT		;NO, BACK TO WHERE WE WERE
	JRST	GO		;NEXT COMMAND
;HERE TO FORCE A SCREEN REFRESH

LIS4R:	SETZM	WINFLG		;CLEAR STICKY SCREEN FLAG
	SETZM	VFREEZ		; . . .
	SETOM	MESFLG		;AND ANNOUNCE THE TRASHED SCREEN EFFECT
	TXO	F2,CBTMF	;ALSO CLEAR OUT BOTTOM OF SCREEN
LIS4RG:	TXZ	FF,QMFLG	;GOBBLE UP THE CHARACTER
	JRST	GO		;AND LET GOSC REFRESH THE SCREEN


;HERE TO DO A "1L$$" COMMAND WHEN USER TYPES A <LF>. IN ADDITION,
;IF NOT VIDEO SCREEN MODE DO A "1T$$" AS WELL.

LIS4L:	MOVEI	B,1		;EXPLICIT "1" LINE
	TXO	FF,ARG		;MAKE IT TOTALLY EXPLICIT
	PUSHJ	P,LINE		;ADVANCE ONE LINE
	SKIPE	SCTYPE		;VIDEO SCREEN HANDLING?
	JRST	GO		;YES, DO SCREEN UPDATE
	PUSHJ	P,CRR		;NO, START UP A NEW LINE
	MOVEI	B,1		;WANT ONE LINE ONLY
	TXO	FF,ARG		;EXPLICITLY ONE LINE
	PUSHJ	P,TYPE		;TYPE ONE LINE
	JRST	GO		;GO FOR NEXT COMMAND


;HERE TO "SCROLL" BACKWARDS THROUGH THE TEXT WITHOUT CHANGING "."

LIS4P:	SKIPN	SCTYPE		;DOING VIDEO SCREEN HANDLING?
	JRST	LI0		;NO, TREAT BACKSPACE AS A CHARACTER
	PUSHJ	P,VUPRV		;VIEW PREVIOUS WINDOW'S WORTH
	PUSHJ	P,CLREOS	;CLEAR ANY JUNK LEFT LYING AROUND
	JRST	LIS4RG		;RESTART COMMAND SCANNING


;HERE TO "SCROLL" FOREWARDS THROUGH THE TEXT WITHOUT CHANGING "."

LIS4S:	SKIPN	SCTYPE		;DOING VIDEO SCREEN HANDLING?
	JRST	LI0		;NO, TREAT SPACE AS A SPACE
	PUSHJ	P,VUNXT		;VIEW NEXT WINDOW'S WORTH
	PUSHJ	P,CLREOS	;CLEAR ANY JUNK LEFT LYING AROUND
	JRST	LIS4RG		;RESTART COMMAND SCANNING
;HERE TO PUT CURSOR ON CURRENT SCREEN

LIS4V:	PUSHJ	P,TYI		;GET THE FOLLOWING <LF>
	CAIE	CH,.CHLFD	;IT IS A <LF>, ISN'T IT?
	HALT	.+1		;BLETCH
	SKIPN	SCTYPE		;OR NON-SCREEN-MODE TERMINAL?
	JRST	LIS1E		;YES, EAT THE <CR><LF>
	SKIPL	DISPTF		;CURSOR ALREADY ON SCREEN?
	JRST	LIS4V2		;NO
	DMOVE	A,DIPTA		;YES, GET CURSOR BASE
	SETZ	D,		;MOVE 0 LINES
	JRST	LIS4V4		;FIND START OF LINE

LIS4V2:	DMOVE	A,SCRNA		;CURRENT SCREEN BASE
	MOVE	D,CLENTH	;HOW FAR DOWN WE PREFER THE CURSOR
LIS4V4:	PUSHJ	P,DISMV		;GET APPROPRIATE TEXT ADDRESS
	MOVEM	I,PT		;SET NEW "."

;NOW WRITE AN NNNJ COMMAND INTO COMMAND FILE (IN CASE LATER EXECUTED ON
;A DIFFERENT SCREEN SIZE)

	TXNN	FF,CFOF		;IF TOP-LEVEL COMMAND TERMINAL TYPEIN
	PUSHJ	P,TEBJ		;THEN WRITE THE NNNJ COMMAND
	JRST	GO		;NOW UPDATE SCREEN



;RETURN TO MONITOR LEVEL. NO ATTEMPT IS MADE TO PROTECT AGAINST
;PSYCHOPATHIC USERS ISSUING ".FINISH" COMMANDS . . .

LIS4Z:	TXZE	FF,TYOF		;NEED A TYO?
	PUSHJ	P,TYOOUT	;YES. DO SO.
	PJRST	FINISZ		;NOTHING SPECIAL HERE


;SAVE PREVIOUS COMMAND STRING IN NAMED Q-REGISTER

LIS4X:	MOVE	C,COMLEN	;LENGTH OF STRING
	TXNN	F2,NALTFS	;FS<STRING>$$ COMMAND LAST THING?
	SUBI	C,1		;NO, TOSS OUT SECOND $ OF $$
				; NOTE THAT IF COMMAND WAS ABORTED BY ^G^U
				; THEN DELLIN LEFT COMLEN COUNTING THE ^G
				; CHARACTER SO WE CAN DO THE SUBI HERE.
	MOVE	B,CMDBAS	;POSITION OF FIRST CHAR. IN BYTES
	IMULI	B,5
	TXNN	F2,GOING	;ANY CMD SEEN BEFORE?
	TDZA	B,B		;NO - FLAG NCS ERROR FOR LATER.
	PUSHJ	P,XQREG		;YES - SAVE CMD IN Q-REG BUFFER
	MOVEM	B,COMSAV	;SAVE FOR LATER
	HRRZI	CH,"*"		;RESTORE CH (GARBAGED BY XQREG)
	JRST	LI0		;START UP COMMAND PROCESSING
	SUBTTL	TECO COMMAND INPUT AND EDITING

LI0:;	SETZM	COMCNT		;COMCNT:=0
	TXZ	F2,NALTFS	;CLEAR FLAG
	SETZM	TAGSYM		;INITIALIZE "O" COMMAND TAG "SYMBOL TABLE"
	MOVE	T,[XWD TAGSYM,TAGSYM+1]  ;BLT POINTER TO
	BLT	T,SYMEND-1	;ZERO TAG SYMBOL TABLE
	DMOVE	A,CMDPTR	;MASTER COMMAND BUFFER STUFFER
	DMOVEM	A,COMPTR	;RESET DYNAMIC COMMAND POINTER

LI10:	TXZ	FF,ALTF+BELLF+XPLNFL+EMFLAG
LI11:	MOVEI	A,1		;ONE CHARACTER
	ADJBP	A,COMPTR	;ADVANCE COMMAND BUFFER BYTE POINTER
	SKIPN	SECTN		;PC IN EXTENDED SECTION?
	HRRZ	AA,A		;NO, HALF WORD ADDRESS
	CAMGE	AA,CMDEND	;ROOM IN COMMAND BUFFER?
	JRST	LI30		;YES

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;EXPAND COMMAND BUFFER, ALLOCATING CORE IF NEEDED

LI20:	MOVE	T,Z		;GET THE NUMBER OF CHARACTERS NOW
	ADDI	T,COMAIW*5	;PLUS INCREMENTAL TEXT GROWTH SIZE
	CAMG	T,MEMSIZ	;WILL THIS OVERFLOW?
	JRST	LI23		;NO, JUST EXPAND THE COMMAND BUFFER
	PUSHJ	P,GRABAK	;GET THE NECESSARY CORE
	 JRST	CORERR		;BUMMER! COMMAND GOT TOO BIG

;OK, EXPAND THE COMMAND BUFFER CONFIDENTLY

LI23:	MOVEI	B,COMAIW	;EXPAND COMMAND BUFFER
	ADDB	B,CMDEND	;EXTEND COMMAND BUFFER END ADDRESS
	MOVE	A,QRBUF		;BASE TEXT ADDRESS FOR Q-REGS/ETC.
	IDIVI	A,5		;A:=Q-REG/ETC. BASE WORD ADDRESS.
	MOVE	AA,A		;BASE TEXT ADDRESS (WORDS)
	ADDI	AA,COMAIW	;OFFSET BY "EXPANSION" SIZE
	MOVE	B,Z		;EDITING BUFFER END TEXT ADDRESS
	IDIVI	B,5		;B:=EDITING BUFFER END WORD ADDRESS.
	SUB	B,A		;B:=TOTAL Q-REG AND TEXT WORDS
	MOVSI	T,((B))		;ASSUME IFIW INDEXING OFF OF AC "B"
	SKIPE	SECTN		;PC IN EXTENDED SECTION?
	LSH	T,IFX2EF	;YES, SELECT EFIW INDEXING THEN
	IOR	A,T		;INDEX "SOURCE" POINTER
	IOR	AA,T		;INDEX "DESTINATION" POINTER

;LOOP MOVING TEXT AREA DOWN IN MEMORY

LI25:	MOVE	T,@A		;GET A Q-REG/DATA BUFFER WORD
	MOVEM	T,@AA		;AND MOVE IT DOWN
	SOJGE	B,LI25		;LOOP FOR ENTIRE TEXT AREA

;NOW RELOCATE ALL THE WORLD'S POINTERS (MUCH SIMPLER THAN GC'S WORRIES)

	MOVEI	B,COMAIW*5	;HOW FAR TEXT MOVED
	ADDM	B,QRBUF		;RELOCATE Q-REG BASE ADDRESS
	ADDM	B,BEG		;RELOCATE EDITING BUFFER "B" ADDRESS
	ADDM	B,PT		;RELOCATE EDITING BUFFER "." ADDRESS
	ADDM	B,Z		;RELOCATE EDITING BUFFER "Z" ADDRESS
	MOVSI	AA,-SCRNRL	;LENGTH OF SCREEN RELOCATION TABLE
	ADDM	B,@SCRNRP	;RELOCATE SCREEN POINTER
	AOBJN	AA,.-1		;RELOCATE THE REST OF 'EM

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;HERE ON EACH COMMAND INPUT CHARACTER

LI30:	TXZN	FF,QMFLG	;1ST CHAR IN ALREADY?
	PUSHJ	P,TYI		;GET A NON-NULL CHARACTER IN CH
	CAIN	CH,.CHDEL	;<DEL>?
	JRST	CTRDL		;YES, UNCONDITIONALLY RUBOUT ONE CHARACTER
	TXZE	F2,CQUOTE	;IS QUOTE-THE-NEXT-CHARACTER SET?
	JRST	LI3QT		;YES, THEN WE HAVE A COMMAND CHARACTER
	CAIN	CH,.CHBEL	;CONTROL-G?
	JRST	CTRLG		;YES
	CAIN	CH,.CHCNR	;CONTROL-R?
	JRST	CTRLR		;YES
	CAIN	CH,.CHCNU	;CONTROL-U?
	JRST	CTRLU		;YES
	CAIN	CH,.CHCNV	;CONTROL-V?
	JRST	CTRLV		;YES
	CAIN	CH,.CHCNW	;CONTROL-W?
	JRST	CTRLW		;YES

;WE HAVE A COMMAND CHARACTER IN CH. STASH IT AWAY AND READ MORE

	AOS	COMCNT		;COUNT ANOTHER COMMAND CHARACTER
	IDPB	CH,COMPTR	;AND STASH IT IN THE COMMAND BUFFER
	CAIN	CH,.CHESC	;<ESC>?
	JRST	LI70		;YES, MAYBE TIME TO EXECUTE THE COMMAND
	JRST	LI10		;BACK FOR THE NEXT COMMAND CHARACTER

LI3QN:	TXO	F2,CQUOTE	;WANT TO QUOTE THE NEXT CHARACTER
LI3QQ:	TXZ	FF,ALTF!BELLF	;AND DO NOTHING ELSE WITH IT
LI3QT:	AOS	COMCNT		;COUNT THIS CHARACTER AS A COMMAND CHARACTER
	IDPB	CH,COMPTR	;AND PUT IT IN THE COMMAND BUFFER
	JRST	LI11		;BACK FOR THE NEXT COMMAND CHARACTER
LI70:	TXZ	FF,BELLF	;$ CLEARS ^G FLAG
	TXON	FF,ALTF		;SET ALT-MODE FLAG. WAS IT ON?
	JRST	LI11		;NO, KEEP ACCEPTING COMMAND INPUT
	MOVE	A,COMCNT	;COUNT OF COMMAND CHARACTERS
	MOVEM	A,COMMAX	;SET COMMAND CHARACTER ADDRESS UPPER BOUND
	MOVEM	A,COMLEN	;SAVE IN CASE OF * COMMAND NEXT
	CAIG	A,2		;JUST $$?
	PUSHJ	P,TEBURB	;YES, FORCE OUT BACKUP FILE CHARACTERS
	DMOVE	A,CMDPTR	;MASTER COMMAND BUFFER BYTE POINTER
	DMOVEM	A,COMPTR	;RESET COMMAND BUFFER BYTE POINTER
	SETZM	CCLSW		;FINISHED WITH CCL READ
	SKIPE	CMFECH		;SUPPRESSING ECHO DUE TO COMMAND FILE?
	JRST	LI74		;YES, THEN NO <CR><LF>
	SKIPN	SCTYPE		;UNLESS DISPLAYING,
	PUSHJ	P,CRR		;TYPE CRLF
LI74:	TXZE	FF,TYOF		;ANY OUTPUT HANGING AROUND?
	PUSHJ	P,TYOOUT	;YEAH, NOW IS A REASONABLE TIME TO FORCE IT OUT
	SETZM	TYOTCT		;CLEAR OUTPUT ACTIVITY COUNTER
				; (SO "<SBLAH$;0TT>" DOES NICE THINGS)
	JRST	CD		;DECODE COMMAND
;HERE ON <DEL>

CTRDL:	PUSHJ	P,RUBCHR	;RUBOUT ONE COMMAND CHARACTER
	 JRST	LIS1E		;EMPTY, WATCH FIRST CHARACTER SPECIAL
	JRST	LI10		;RESUME COMMAND TYPEIN


;HERE ON CONTROL-G

CTRLG:	TXO	FF,BELLF	;SET BELL FLAG
	TXZ	FF,ALTF		;AND CLEAR ESC SEEN FLAG
	JRST	LI3QT		;AND STUFF ^G INTO COMMAND BUFFER


;HERE ON CONTROL-R

CTRLR:	CHKEO	EO21,LI3QQ	;IF EO=1 THEN ^R IS RANDOM CHARACTER
	CHKEO	EO25,LI3QN	;IF EO=2 THEN ^R IS QUOTING CHARACTER
	PUSHJ	P,RETYPR	;OTHERWISE ^R RETYPES THE CURRENT LINE
	SKIPG	COMCNT		;HAVE ANY COMMANDS?
	JRST	LIS1E		;NO, WATCH FIRST CHARACTER SPECIAL
	JRST	LI11		;AND SIMPLY DISAPPEARS

;HERE ON CONTROL-U

CTRLU:	PUSHJ	P,DELLIN	;DELETE ONE "PHYSICAL" COMMAND LINE
	 JRST	CLIS4		;EMPTY, RE-PROMPT
	JRST	LI10		;RESUME COMMAND TYPEIN


;HERE ON CONTROL-V

CTRLV:	CHKEO	EO25,LI3QQ	;IF EO=1 OR 2 THEN ^V IS RANDOM CHARACTER
	JRST	LI3QN		;OTHERWISE ^V IS QUOTING CHARACTER



;HERE ON CONTROL-W

CTRLW:	CHKEO	EO25,LI3QQ	;IF EO=1 OR 2 THEN ^W IS RANDOM CHARACTER
	PUSHJ	P,RUBWRD	;OTHERWISE ^W RUBS-OUT A COMMAND WORD
	 JRST	LIS1E		;EMPTY, WATCH FIRST CHARACTER SPECIAL
	JRST	LI10		;RESUME COMMAND TYPEIN
;RETYPE THE CURRENT COMMAND LINE

RETYPR:	TXNE	FF,BELLF	;^G^R (RETYPE ENTIRE COMMAND)?
	PUSHJ	P,BACKUP	;YES, DELETE THE ^G FROM THE COMMAND BUFFER
	MOVE	D,COMCNT	;MARK CURRENT POSITION
	PUSHJ	P,BACKLN	;BACK UP TO BEG OF LINE
	 JRST	RETYP2		;HIT BEG OF COMMAND STRING
	IBP	COMPTR		;SKIP THE <CR>
	AOS	C,COMCNT	; (AND COUNTER TOO)

;AT THIS POINT, COMCNT IS ONE TOO SMALL AND COMPTR POINTS ONE BYTE IN FRONT
;OF THE FIRST TEXT COMMAND CHARACTER TO BE REPRINTED (E.G., ON THE <LF>
;OR IMMEDIATELY IN FRONT OF THE COMMAND BUFFER IF NO FULL LINES YET).

RETYP2:	SKIPE	CMFECH		;COMMAND FILE NO ECHO?
	JRST	RETYP4		;YES, NO OUTPUT HERE THEN
	MOVEI	CH,.CHCRT	;<CR>
	PUSHJ	P,TYOM		;BACK TO START OF LINE
	MOVEI	CH,.CHLFD	;<LF>
	SKIPN	SCTYPE		;ON VIDEO TERMINAL?
	PUSHJ	P,TYOM		;NO, THEN NEED NEW LINE AS WELL
	CAILE	E,0		;NICE NORMAL <CR><LF> SETUP?
	PUSHJ	P,RETYUP	;NO, EMBEDDED LINE MOVEMENTS, WORK HARDER
	MOVEI	CH,"*"		;OUR PROMPT
	SKIPG	COMCNT		;HAVE WE BACKED UP TO THE START?
	PUSHJ	P,TYOM		;YES, THEN RE-PROMPT FOR NEATNESS TOO
	MOVEM	D,COMCNT	;RESET COMCNT TO CORRECTNESS
	JRST	RETYP5		;ENTER RETYPE LOOP

;LOOP OUTPUTTING THE COMMAND LINE AS PRESENT IN THE BUFFER

RETYP4:	ILDB	CH,COMPTR	;GET NEXT [POSSIBLE] COMMAND CHAR
	JUMPLE	C,RETYP5	;(BACKLN CAN RETURN US -1)
	SKIPN	CMFECH		;SUPPRESSING ECHO DUE TO COMMAND FILE?
	PUSHJ	P,TYIEC		;ECHO (TYPE) COMMAND CHARACTER
RETYP5:	CAMGE	C,D		;CAUGHT UP YET?
	AOJA	C,RETYP4	;NO, DO MORE

RETYP8:	SKIPE	SCTYPE		;ON VIDEO SCREEN?
	PUSHJ	P,CLREOS	;YES, ERASE POSSIBLE GARBAGE
	LDB	CH,COMPTR	;RELOAD CURRENT [LAST] CHARACTER
	CAIN	CH,.CHESC	;LOOKING AT AN ALTMODE?
	TXO	FF,ALTF		;YES, BETTER SET FLAG
	POPJ	P,		;RETURN
RETYUP:	SKIPN	SCTYPE		;ON VIDEO SCREEN?
	POPJ	P,		;HARDCOPY - WE CAN DO NOTHING USEFUL HERE
	PUSH	P,CH		;SAVE CHARACTER
	CAML	E,SLENTH	;MOVEMENT GREATER THAN SCREEN SIZE?
	JRST	RETYU8		;YES, JUST CLEAR SCREEN
	PUSHJ	P,CUP		;MOVE CURSOR UP ONE LINE
	SOJG	E,.-1		;MOVE UP AS MANY LINES AS NEEDED
	PUSHJ	P,CLREOS	;CLEAR REST OF SCREEN
	POP	P,CH		;RESTORE CHARACTER
	POPJ	P,		;AND RETURN

RETYU8:	PUSHJ	P,CLRSCN	;ERASE AND HOME UP
	SETZ	E,		;WE DID ALL THE LINES NEEDED
	POP	P,CH		;RESTORE CHARACTER
	POPJ	P,		;BACK TO WHOMEVER
;HERE TO RUBOUT ONE COMMAND CHARACTER

RUBCHR:	PUSHJ	P,RUBOUT	;RUBOUT ONE COMMAND CHARACTER
	 POPJ	P,		;ALL USED UP, WATCH FIRST CHAR SPECIAL
	JRST	CPOPJ1		;BACK FOR MORE COMMAND INPUT


;HERE TO RUBOUT ONE COMMAND "WORD"

RUBWRD:	SKIPN	SCTYPE		;ON VIDEO TERMINAL?
	JRST	RUBWR1		;NO, THE "^W" STAYS
	PUSHJ	P,RUB2P		;YES, ERASE THE "^W" FROM THE SCREEN
	TXNN	FF,BELLF	;^G^W (RUBOUT "SENTENCE")?
	JRST	RUBWR1		;NO
	PUSHJ	P,RUB2P		;YES, ERASE THE "^G" FROM THE SCREEN
	PUSHJ	P,BACKUP	; AND FROM THE COMMAND BUFFER TOO!

;NOW EAT ANY AND ALL PRECEDING SPACES (ASSUME <CR><LF> = SPACE)

RUBWR1:	LDB	CH,COMPTR	;FETCH CURRENT LAST COMMAND CHARACTER
	CAIE	CH,.CHVTB	;IF A <VT>
	CAIN	CH,.CHFFD	;OR A <FF>
	JRST	RUBWR4		;EAT IT, AND PRECEDING <CR>, IF PRESENT
RUBWR2:	CAIE	CH,.CHTAB	;IF A <TAB>
	CAIN	CH," "		;OR A SPACE
	JRST	RUBWR3		;JUST ABSORB IT
	CAIE	CH,.CHLFD	;A <LF>?
	JRST	RUBWR7		;RANDOM CHARACTER, EAT IT
	PUSHJ	P,RUBOUT	;RUBOUT THE <LF>
	 POPJ	P,		;ALL USED UP, WATCH FIRST CHAR SPECIAL
	CAIE	CH,.CHCRT	;PRECEDED BY A <CR>?
	JRST	RUBWR5		;NO, TREAT AS A POSSIBLE WORD BREAK

RUBWR3:	PUSHJ	P,RUBOUT	;RUBOUT THE CHARACTER
	 POPJ	P,		;ALL USED UP, WATCH FIRST CHAR SPECIAL
	JRST	RUBWR2		;LOOK FOR MORE SPACES
RUBWR4:	PUSHJ	P,RUBOUT	;EAT THE <VT> OR <FF>
	 POPJ	P,		;ALL USED UP, WATCH FIRST CHAR SPECIAL
	CAIN	CH,.CHCRT	;PRECEDED BY A <CR>?
	JRST	RUBWR7		;YES, EAT THE <CR> TOO

RUBWR5:	CAIL	CH,"0"		;NUMERIC?
	CAILE	CH,"9"		; . . .
	CAIL	CH,"A"		;ALPHAMERIC (UPPER CASE)?
	CAILE	CH,"Z"		; . . .
	CAIL	CH,"a"		;ALPHAMERIC (LOWER CASE)?
	CAILE	CH,"z"		; . . .
	CAIN	CH,"-"		;OR RANDOM HYPHEN?
	JRST	RUBWR7		;YES TO ONE OF ABOVE, PART OF WORD, EAT IT
	TXNN	FF,BELLF	;^G^W (RUBOUT "SENTENCE")?
	JRST	CPOPJ1		;NO, ONLY ONE WORD, ALL DONE
	CAIE	CH," "		;YES, ON A SPACE?
	CAIN	CH,.CHCRT	;OR A TAB?
	JRST	RUBWR7		;YES, THEN NOT A "SENTENCE" BREAK
	CAIE	CH,.CHLFD	;<LF>?
	JRST	RUBWR6		;NO, END OF "SENTENCE"
	PUSHJ	P,BACKUP	;PEEK AT CHARACTER PRECEDING <LF>
	AOS	COMCNT		;RESTORE COMMAND CHARACTER COUNT
	IBP	COMPTR		;AND COMMAND CHARACTER POINTER
	CAIN	CH,.CHCRT	;<CR><LF> PAIR?
	JRST	RUBWR4		;YES, THEN NOT A "SENTENCE" BREAK
	LDB	CH,COMPTR	;NO, RESTORE CHARACTER
RUBWR6:	TXZ	FF,BELLF	;CLEAR ^G FLAG
	JRST	CPOPJ1		;AND RESUME COMMAND TYPEIN

RUBWR7:	PUSHJ	P,RUBOUT	;RUBOUT ANOTHER COMMAND CHARACTER
	 POPJ	P,		;ALL USED UP, WATCH FIRST CHAR SPECIAL
	JRST	RUBWR5		;SEE IF END OF "WORD" YET
;DELETE ONE "PHYSICAL" (TERMINATED BY <CR><EOL>) COMMAND LINE

DELLIN:	TXNN	FF,BELLF	;^G^U (DELETE ENTIRE COMMAND)?
	JRST	DELLI2		;NO, JUST ^U, EAT THIS PHYSICAL LINE
	PUSHJ	P,BACKUP	;YES, EAT THE ^G
	ADDI	C,1		;(SIGH) SO LIS4X CAN SUBI IT OUT AGAIN
	MOVEM	C,COMLEN	;IN CASE OF "*" COMMAND IMMEDIATELY FOLLOWING
	TXO	F2,GOING	;FLAG THAT WE HAVE SOMETHING GOING ON
DELLI2:	PUSHJ	P,BACKLU	;BACKUP A LINE, GUARANTEEING MOVEMENT
	SETOM	COMCNT		;NOTE NO COMMANDS LEFT
	SKIPE	CMFECH		;COMMAND FILE NO ECHO?
	JRST	DELLI6		;YES
	SKIPE	SCTYPE		;NO, USER TYPEIN, ON VIDEO TERMINAL?
	JRST	DELLI4		;YES, ERASE THE LINE
	PUSHJ	P,INLMES	;"ECHO" THE ^U
	ASCIZ	\^U\
	PUSHJ	P,CRR		;GO TO A NEW LINE
	JRST	DELLI6		;AND FINISH UP

DELLI4:	MOVEI	CH,.CHCRT	;A <CR>
	PUSHJ	P,TYOM		;BACK TO MARGIN
	CAIE	E,0		;BAD CASE (EMBEDDED "LINES")?
	PUSHJ	P,RETYUP	;YES, MOVE CURSOR BACK THEN
	PUSHJ	P,CLREOL	;YES, ERASE ABOUT-TO-BE ERASED LINE FROM SCREEN
DELLI6:	SKIPGE	COMCNT		;ANYTHING LEFT IN BUFFER?
	POPJ	P,		;NO
	AOS	COMCNT		;KEEP CRLF
	IBP	COMPTR
	JRST	CPOPJ1		;CONTINUE TYPE-IN
;RUBOUT ONE COMMAND CHARACTER, CLEARING THE SCREEN AS NEEDED

RUBOUT:	SKIPG	COMCNT		;ANYTHING TYPED IN?
	POPJ	P,		;NO, RETURN ALL USED UP
	LDB	CH,COMPTR	;RELOAD THE CHAR.
	SKIPE	COMCNT		;AT BEGINNING OF COMMAND STRING?
	SKIPE	CMFECH		;COMMAND FILE NO ECHO?
	JRST	RUBOU8		;YES TO ONE OF ABOVE

;RUBOUT ONE LOGICAL CHARACTER FROM THE SCREEN

	SKIPN	SCTYPE		;ON VIDEO TERMINAL?
	JRST	RUBOU6		;NO
	CAIN	CH,.CHDEL	;A RUBOUT?
	JRST	RUBOU8		;YES (?)
	CAIE	CH,.CHCRT	;A <CR>?
	CAIN	CH,.CHTAB	;A <TAB>?
	JRST	RUBTAB		;YES, HAIRY CASE
	CAIN	CH,.CHLFD	;<LF>?
	JRST	RUBLF		;YES
	CAIN	CH,.CHVTB	;<VT>?
	JRST	RUBVT		;YES
	CAIN	CH,.CHFFD	;<FF>?
	JRST	RUBFF		;YES
	CAIGE	CH," "		;RANDOM CONTROL CHARACTER?
	SKIPA	CH,CHTBL(CH)	;YES
	HRLI	CH,(EC$SLF)	;NO, PRINTING ASCII
	TXNE	CH,EC$CRL	;ECHO WITH <CR><LF>?
	JRST	RUBCRL		;YES, ICK
	PUSH	P,C		;SAVE AN AC
	SETZ	C,		;INITIAL COUNTER
	TXNN	CH,EC$SLF	;ECHO LITERALLY?
	TXNE	CH,EC$DLR	;OR AS "$"?
	MOVEI	C,1		;YES, ONE SCREEN POSITION TAKEN UP
	TXNE	CH,EC$UPA	;ECHO AS ^X?
	MOVEI	C,2		;YES, THEN TAKES UP TWO POSITIONS
RUBOU3:	PUSHJ	P,RUB1P		;WIPE OUT ONE SCREEN CHARACTER
	SOJG	C,RUBOU3	;LOOP FOR ALL SCREEN POSITIONS
	POP	P,C		;RESTORE AC
	JRST	RUBOU8		;FINALLY GO DELETE CHARACTER
RUBOU6:	PUSHJ	P,TYOM		;JUST ECHO THE CHARACTER BEING RUBBED-OUT

RUBOU8:	PUSHJ	P,BACKUP	;BACK OVER THE CHAR.
RUBOU9:	JUMPG	C,CPOPJ1	;RESUME TYPE-IN IF ANYTHING LEFT
	SKIPE	SCTYPE		;ON SCREEN-MODE TERMINAL?
	POPJ	P,		;YES, JUST WAIT
	PUSHJ	P,CRR		;NO, SO GO TO NEW LINE,
	MOVEI	CH,"*"		;RE-PROMPT,
	PJRST	TYOM		;AND WAIT FOR NEW COMMAND

RUBCRL:	PUSHJ	P,CUP		;BACKUP A LINE FIRST, THEN
RUBTAB:	PUSHJ	P,BACKUP	;RUBOUT THE LAST CHARACTER
	JUMPLE	C,RETYPR	;IF NONE LEFT, RE-PROMPT
	TXZE	FF,BELLF	;^G SEEN RECENTLY (E.G., ^G^W)?
	JRST	RUBTA2		;YES, DON'T DELETE IT IN RETYPE CODE
	PUSHJ	P,RETYPR	;OTHERWISE REBUILD THE SCREEN LINE
	JRST	CPOPJ1		;AND RETURN FOR MORE INPUT

RUBTA2:	PUSHJ	P,RETYPR	;REBUILD THE SCREEN LINE
	TXO	FF,BELLF	;TURN ^G FLAG BACK ON
	JRST	CPOPJ1		;RETURN HAPPILY

RUBVT:	SKIPA	E,[4]		;<VT> IS 4 <LF>S
RUBFF:	MOVEI	E,^D8		;<FF> IS 8 <LF>S
	PUSHJ	P,CUP		;MOVE UP THE SCREEN
	SOJG	E,.-1		; FOR REQUISITE NUMBER OF LINES
	JRST	RUBOU8		;AND DELETE THE CHARACTER

RUBLF:	PUSHJ	P,CUP		;MOVE CURSOR UP ONE LINE
	JRST	RUBOU8		;DELETE THE <LF>

RUB2P:	PUSHJ	P,RUB1P		;BLANK FIRST (OF TWO) SCREEN POSITIONS
RUB1P:	SKIPE	CMFECH		;NO-ECHOING OF COMMAND FILE?
	POPJ	P,		;YES, THEN NO OUTPUT
	MOVEI	CH,.CHCNH	;BACKSPACE CHARACTER
	PUSHJ	P,TYOM		;OUTPUT IT
	MOVEI	CH," "		;SPACE CHARACTER
	PUSHJ	P,TYOM		;OUTPUT IT
	MOVEI	CH,.CHCNH	;ANOTHER BACKSPACE CHARACTER
	PJRST	TYOM		;OUTPUT IT
;BACKUP TO BEGINNING OF CURRENT LINE
;CALL:	PUSHJ	P,BACKLN
;	RETURN IF BACKUP WENT TO BEGINNING OF COMMAND STRING
;	RETURN IF CR-EOL COMBINATION FOUND
;
;RETURNS IN E THE COUNT OF "LOGICAL" LINES PASSED - I.E., THE COUNT OF
;<LF>'S, <VT>'S, OR <FF>'S NOT IMMEDIATELY PRECEDED BY A <CR>. NOTE THAT
;A <VT> IS 4 <LF>S, AND A <FF> IS 8 <LF>S.
;
;BACKLU IS LIKE BACKLN ONLY IT WILL GO BACK A LINE EVEN IF POINTER
;IS ONLY JUST PAST A <CR><LF>. THIS ALLOWS MULTIPLE ^U'S TO EAT MULTIPLE
;LINES.

BACKLU:	SETZ	E,		;COUNT OF LINES PASSED
	LDB	CH,COMPTR	;GET CURRENT COMMAND CHARACTER
	CAIN	CH,.CHLFD	;<LF>
	MOVEI	E,1		;YES, ONE LINE
	CAIN	CH,.CHVTB	;<VT>?
	MOVEI	E,4		;YES, FOUR LINES
	CAIN	CH,.CHFFD	;<FF>?
	MOVEI	E,^D8		;YES, EIGHT LINES
	JRST	BACKL0		;NOW SEARCH FOR THE PRECEDING LINE

BACKLN:	SETZ	E,		;COUNT OF LINES PASSED LOOKING FOR <CR>
	LDB	CH,COMPTR	;COPY OF CURRENT LAST CHARACTER
	SKIPA	C,COMCNT	;AND COUNT OF CHARACTERS
BACKL0:	PUSHJ	P,BACKUP	;BACK UP ONE CHAR
BACKL1:	JUMPG	C,BACKL5	;KEEP GOING IF MORE TO DO
BACKL2:	HLRZ	C,E		;GET LAST "LINES" COUNT
	ADD	E,C		;ADD TO TOTAL SO FAR
	ANDI	E,-1		;RETURN "LINES" SKIPPED
	MOVE	C,COMCNT	;RESTORE C
	TXZ	FF,BELLF	;CLEAR FLAG
	POPJ	P,		;SINCE WE JUST HIT THE START OF THE BUFFER
BACKL5:	PUSHJ	P,CKEOL		;IS THIS AN EOL CHAR?
	JRST	BACKL8		;NO, LOOP FOR OTHER FUNNY CHARACTERS
	HLRZ	C,E		;GET LAST "LINES" COUNT
	ADD	E,C		;ADD TO TOTAL SO FAR
	CAIN	CH,.CHLFD	;<LF>?
	HRLI	E,1		;YES
	CAIN	CH,.CHVTB	;<VT>?
	HRLI	E,4		;YES, = 4 <LF>S
	CAIN	CH,.CHFFD	;<FF>?
	HRLI	E,^D8		;YES, = 8 <LF>S
	PUSHJ	P,BACKUP	;YES, BACK UP ONE MORE
	JUMPLE	C,BACKL2	;IF AT BEGINING, THEN STOP IN ANY CASE
	TXNN	FF,BELLF	;DOING ^G BACKUP (E.G., ^G^R OR ^G^U)?
	CAIE	CH,.CHCRT	;NO, AT OTHER THAN A <CR><EOL>?
	JRST	BACKL1		;YES (TO EITHER), DON'T STOP HERE
	ANDI	E,-1		;RETURN COUNT OF "EXCESS" LINES SKIPPED
	JRST	CPOPJ1		;TAKE SKIP RETURN

BACKL8:	CAIGE	CH," "		;CONTROL CHARACTER?
	MOVE	CH,CHTBL(CH)	;YES, GET ECHO CONTROL BITS
	TXNE	CH,EC$CRL	;THIS CHARACTER ECHO WITH <CR><LF>?
	ADDI	E,1		;YES, COUNT IT IN LINES COUNTER
	JRST	BACKL0		;AND LOOK AT NEXT (PREVIOUS) CHARACTER



;BACK UP BYTE POINTER IN COMPTR, LOAD APPROPRIATE CHARACTER IN CH,
;AND ADJUST COMCNT

BACKUP:	MOVNI	T,1		;NEGATIVE ONE POSITIONS
	ADJBP	T,COMPTR	;BACK UP COMPTR ONE POSITION
	DMOVEM	T,COMPTR	;AND LEAVE RESULTS IN COMPTR
	SOSLE	C,COMCNT	;DECREMENT COMMAND COUNT
	LDB	CH,COMPTR	;LOAD CHAR IF ANY LEFT
	POPJ	P,
	SUBTTL	TECO COMMAND EXECUTION

CD:	TXO	F2,GOING!DOING	;A COMMAND STRING IS IN
RET:	PUSHJ	P,PCSEC		;CHECK FOR WRONG PC SECTION
	TXZ	FF,ARG!ARG2!FINDR!PCHFLG!SEQUIN
	TXZ	F2,S.MINS!S.REPL!S.DELE!S.KILL!S.FRCM  ;CLEAR SEARCH FLAGS
	TXZE	FF,COLONP	;COLON-MODIFIED COMMAND FORGET TO RETURN VALUE?
	$FATAL	(NVR,,<Colon-modified command didn't return a value>)
CD1:	SETZM	SYL		;NO ARGUMENT ELEMENT (OR ATOM) SEEN
CD2:	SETZM	NUM		;NO ARGUMENT STRING SEEN
	MOVE	A,BEG		;STARTING CHARACTER ADDRESS
	CAML	A,Z		;ANY TEXT IN TEXT BUFFER
	TXZ	F2,LSNF		;NO, THEN NO LSN'S LEFT EITHER
	MOVSI	A,(MOVE B,)	;STANDARD ARG OPERATOR IS MOVE B,SYL
CD3:	HLLM	A,DLIM
CD5:	PUSHJ	P,RCH
CD9:	MOVE	A,CH		;GET COMMAND CHARACTER
	CAIL	CH,"0"		;IS IT A DIGIT?
	CAILE	CH,"9"
	TXZ	F2,OCTALF	;NO, CLEAR OCTAL RADIX FLAG
	CAIE	A,"`"		;ACCENT GRAVE IS ILLEGAL
	CAILE	A,"z"		;ALSO 173-177 ARE ILLEGAL
	MOVEI	A,0
	CAILE	A,"_"		;REDUCE LOWER CASE TO UPPER
	SUBI	A,40
	ROT	A,-1		;DIV BY 2
	JUMPL	A,CD92		;ODD CHARACTER
	HLRZ	A,DTB(A)	;GET CODE & ADDR FOR EVEN CHAR.
	JRST	CD93
CD92:	HRRZ	A,DTB(A)	;GET CODE & ADDR FOR ODD CHAR.
CD93:	TRNN	A,300000	;IS IT A JRST DISPATCH WITH NO ARG PROCESSING?
	JRST	<HIORGP_PG2WRD>(A)  ;YES, DO IT
	MOVE	B,NUM		;NO, TAKE CARE OF ARGUMENTS
	XCT	DLIM		;NUM:=NUM (DLIM OPERATOR) SYL
	MOVEM	B,NUM
	SETZM	SYL		;CLEAR OLD OPERAND
	MOVE	C,SARG		;SAVE SECOND ARGUMENT IN C.
	TXZ	FF,SYLF		;CLR DIGIT STRING BIT
	TXZ	F2,CTLVA+CTLVVA+CTLWB+CTLWWB+EMATCH+TXTCTL
	TRZ	A,100000	;CLR PUSHJ DISPATCH BIT
	TRZE	A,200000	;JRST OR PUSHJ DISPATCH?
	JRST	<HIORGP_PG2WRD>(A)
	PUSHJ	P,<HIORGP_PG2WRD>(A)
	JRST	RET


U DLIM,1			;
U NUM,1				;
U SYL,1				;
U SARG,1			;
;CHECK FOR PC SECTION GOODNESS

PCSEC:	PUSH	P,TT		;SAVE AN AC
	XMOVEI	TT,777		;GET CURRENT PC SECTION
	ANDCMI	TT,777		;REDUCE TO JUST SECTION COUNT
	CAMN	TT,SECTN	;PC STILL IN RIGHT SECTION?
	JRST	PCSEC8		;YES, OK
	$FATAL	(WPS,PCSEC3,<Wrong PC section, returning to proper PC section>)

PCSEC3:	MOVE	TT,SECTN	;THE CORRECT PC SECTION
	HLLM	TT,-1(P)	;FORCE POPJ TO RIGHT SECTION TOO
	HRRI	TT,PCSEC8	;AND A LOCAL PC
	XJRST	TT		;RESTORE SECTION GOODNESS

PCSEC8:	POP	P,TT		;RESTORE TRASHED AC
	POPJ	P,		;RETURN IN PROPER SECTION



;DIGITS FORM DECIMAL INTEGERS.

CDNUM:	TXON	FF,SYLF		;DIGIT STRING ALREADY STARTED?
	SETZM	SYL		;NO, INIT TO ZERO
	MOVEI	A,12		;RADIX 10
	TXNN	F2,OCTALF	;OCTAL FLAG ON?
	JRST	CDNUM1		;NO
	MOVEI	A,10		;YES, RADIX 8
	CAIG	CH,"7"		;8 OR 9 IN OCTAL STRING?
	JRST	CDNUM1		;NO, PROCEED
	TXZ	F2,OCTALF	;YES, CLEAR OCTAL FLAG
	$FATAL	(OCT,,<	"00" in octal digit string>)
CDNUM1:	IMUL	A,SYL		;SCALE PREVIOUS VALUE
	ADDI	A,-60(CH)	;ADD IN NEW DIGIT

;SOME COMMANDS HAVE A NUMERIC VALUE

VALRET:	MOVEM	A,SYL
CD7:	TXO	FF,ARG
	JRST	CD5
;$ (<ESC>) COMMAND

ALTMOD:	PUSHJ	P,PKRCH		;PEEK AHEAD ONE CHARACTER
	 JRST	ALTM2		;NO COMMAND CHARACTERS LEFT AT THIS LEVEL
	CAIE	CH,.CHESC
	JRST	CD
ALTM1:	TXNE	FF,TRACEF	;TRACING?
	PUSHJ	P,CRR		;YES, TYPE CR/LF BEFORE *
	JRST	GO

ALTM2:	SKIPN	EQM		;WITHIN A MACRO?
	JRST	GO		;NO
	JRST	CD		;MACRO RETURN



;^ MEANS THAT THE NEXT CHARACTER IS A CONTROL CHARACTER.

UAR:	PUSHJ	P,SKRCH		;GET NEXT COMMAND CHARACTER.
	$FATAL	(MEU,,<Macro ending with ^>)
	TRZ	CH,140		;CHANGE IT TO CONTROL CHARACTER
	JRST	CD9		;DISPATCH



;^O SETS FLAG FOR OCTAL RADIX INPUT

OCTIN:	TXO	F2,OCTALF
	JRST	CD5		;RETURN WITHOUT MESSING UP ARGUMENTS
;IF A COMMAND TAKES TWO NUMERIC ARGUMENTS, COMMA IS USED TO SEPARATE THEM

COMMA:	MOVEM	B,SARG		;SAVE CURRENT ARGUMENT IN SARG.
	TXZE	FF,ARG		;WAS THERE A CURRENT ARGUMENT?
	TXOE	FF,ARG2		;YES. WAS THERE ALREADY A SECOND ARGUMENT?
	$FATAL	(ARG,,<Improper arguments>)
	JRST	CD1		;YES. CLEAR CURRENT ARGUMENT.


;@ COMMAND MODIFIER

ATSIGN:	TXO	FF,SLSL		;SET @ SEEN FLAG
	JRST	RET		;AND CONTINUE WITH COMMAND SCAN
				; NOTE THAT "@" MUST PRECEDE ANY ":" MODIFIER
;COLON COMMAND MODIFIER

;GENERATE A FREE "()" SEQUENCE. THIS IS SO COMMANDS SUCH AS THE EXPRESSION
;"1+:.,.+9SFOO$" DOES NOT LOSE THE LEADING "1+" ATOM. THIS IS SORT OF A
;KROCK. THE PROBLEM ARISES FROM THE NECESSITY TO NEST EXPRESSIONS WITHIN
;THE VALUE-RETURNING COMMAND (IN THIS CASE, ".+9"). FURTHER, THE SECOND
;ARG MUST ALSO BE PRESERVED (E.G., "100,150+:1,.+(2*2)SBLAH$T").

COLON:	PUSH	P,SARG		;PRESERVE SECOND ARG
	PUSH	P,NUM		;PRESERVE CURRENT EXPRESSION VALUE
	PUSH	P,DLIM		;PRESERVE CURRENT OPERATOR
	PUSH	P,FF		;PRESERVE CURRENT ARG AND ARG2 VALUE
	PUSH	P,[1]		;SET PAREN FLAG ON PDL
	TXZ	FF,ARG!ARG2	;START WITH A FRESH SLATE
	TXO	FF,COLONF!COLONP;SET : SEEN FLAG
	JRST	CD1		;CONTINUE WITH COLON-MODIFIED COMMAND


;(	USED TO OVERRIDE LEFT TO RIGHT OPERATOR SCAN FOR +,-,*,/,& AND #.

OPENP:	PUSH	P,SARG		;PRESERVE SECOND ARG
	PUSH	P,NUM		;PUSH CURRENT ARGUMENT.
	PUSH	P,DLIM		;CURRENT OPERATOR
	PUSH	P,FF		;SAVE ARG AND ARG2
	PUSH	P,[1]		;SET PAREN FLAG ON PDL
	JRST	CD1
;HERE TO STORE THE VALUE FROM A COLON-MODIFIED COMMAND

CLOSEC:	TXZN	FF,COLONP	;CLOSE THE "()" GENERATED BY THE COLON-
				; MODIFIED COMMAND (E.G., "1+:.,.+9SBLAH$=")
	JRST	VALRET		;OOPS, WASN'T REALLY COLON-MODIFIED
	MOVE	T,-1(P)		;GET OLD FLAGS (ARG AND ARG2)
	TXNN	T,ARG2		;WAS ARG2 SET?
	TXZA	FF,ARG2		;NO, ENSURE IT IS NOW CLEAR
	TXO	FF,ARG2		;YES, ENSURE IT IS NOW SET
	TXNN	T,COLONF	;IN A COLON-MODIFIED NESTED EXPRESSION?
	TXZA	FF,COLONF	;NO
	TXO	FF,COLONF	;YES (E.G., "100,200+:B,Z+:.,.+10SY$SX$T$$")
	TXNN	T,COLONP	;IN A FREE "()" DUE TO COLON-MODIFIER?
	TXZA	FF,COLONP	;NO
	TXO	FF,COLONP	;YES

;)	END OF PARENTHESIS OPERATOR PRECEDENCE CONTROL

CLOSEP:	POP	P,T		;LAST THING ON PDL A LEFT PAREN?
	JUMPL	T,CLOSE1	;SOMETHING LIKE "(...<...)"   (MATCH ANGLE>)
	SOJN	T,CLOSE2	;MISSING (
	MOVEM	B,SYL		;YES. SAVE CURRENT ARGUMENT.
	POP	P,T		;TOSS OFF OLD FLAGS
	POP	P,DLIM		;RESTORE OPERATOR
	POP	P,NUM		;RESTORE ARGUMENT.
	POP	P,SARG		;RESTORE SECOND ARGUMENT
	JRST	CD7

CLOSE1:	$FATAL	(PAR,,<Confused use of parenthesis>)
CLOSE2:	$FATAL	(MLP,,<Missing left parenthesis>)
;LOGICAL AND

CAND:	MOVSI	A,(AND B,)	;DLIM = AND B,SYL
	JRST	CD3

;LOGICAL OR

COR:	MOVSI	A,(OR B,)	;DLIM = OR B,SYL
	JRST	CD3

;ADD TAKES ONE OR TWO ARGUMENTS

PLUS:	MOVSI	A,(ADD B,)	;DLIM = ADD B,SYL
	JRST 	CD3

;SUBTRACT TAKES ONE OR TWO ARGUMENTS

MINUS:	MOVSI	A,(SUB B,)	;DLIM = SUB B,SYL
	JRST	CD3

;MULTIPLY TAKES TWO ARGUMENTS

TIMES:	MOVE	B,COMMAX	;CALCULATE WHICH CHARACTER
	SUB	B,COMCNT	;* WAS.
	CAIN	B,1		;WAS * THE FIRST CHAR?
	JRST	STARQ		;YES, LOAD Q-REGISTER
	MOVSI	A,(IMUL B,)	;DLIM = IMUL B,SYL
	JRST	CD3

STARQ:	SKIPE	B,COMSAV	;IS THERE A SAVED COMMAND BUFFER?
	JRST	STARQ2		;YES, PUT IT IN A Q REGISTER
	PUSHJ	P,GCH		;NO - EAT Q-REG NAME
	$FATAL	(NCS,,<No command string seen prior to *00>)

STARQ2:	TLNN	B,300000	;THIS REALLY IS A Q-REGISTER STYLE POINTER?
	TLNN	B,400000	;ISN'T IT?
	HALT	.+1		;NO - I WONDER WHAT HAPPENED TO IT?
	PUSHJ	P,QREGVI	;REG NAME WITH IQL CHECK
	MOVEM	B,QTAB-"0"(CH)	;AND SAVE PTR IN THE Q-REG.
	SETZM	COMSAV		;NO LONGER NEED THIS POINTER
	JRST	CD		;NEXT COMMAND

;DIVIDE (TRUNCATES) TAKES TWO ARGUMENTS

SLASH:	MOVSI	A,(IDIV B,)	;DLIM = IDIV B,SYL
	JRST	CD3
;RETURNS THE VALUE OF THE FORM FEED FLAG

FFEED:	TXNE	FF,FORM		;IS IT SET?
	JRST	FFOK		;YES, RETURN A -1
				;NO, DO BEGIN ROUTINE
;RETURNS THE NUMERIC VALUE 0.

BEGIN:	MOVEI	A,0
	JRST	VALRET

;^N RETURNS VALUE OF EOF FLAG

EOF:	TXNN	FF,FINF		;EOF SEEN?
	JRST	BEGIN		;NO, RETURN 0
	JRST	FFOK		;YES, RETURN -1

;AN ABBREVIATION FOR B,Z

HOLE:	SETZM	SARG		;SET SECOND ARGUMENT TO 0.
	TXO	FF,SEQUIN	;INITIALIZE AS NEW LINE
	TXNE	FF,ARG2		;FLAG ANY ARGS BEFORE H
	$FATAL	(ARG,,<Improper arguments>)
	TXOA	FF,ARG2

;.=NUMBER OF CHARACTERS TO THE LEFT OF THE POINTER

PNT:	SKIPA	A,PT

;Z=NUMBER OF CHARACTERS IN THE BUFFER

END1:	MOVE	A,Z
	SUB	A,BEG
	JRST	VALRET

;RETURN LENGTH OF LAST TEXT STRING PROCESSED

LSVCMD:	MOVE	A,VVAL		;LENGTH OF LAST TEXT
	JRST	VALRET

U VVAL,1			;LENGTH OF LAST TEXT STRING PROCESSED
U VVALFR,1			;VVAL USED IN FR COMMAND
;N=	CAUSES THE VALUE OF N TO BE TYPED OUT.

PRNT:	TXNN	FF,ARG		;INSIST ON ARG BEFORE =
	$FATAL	(NAE,,<No argument before =>)
	SETOM	WINFLG		;SO DISPLAY DOESN'T ERASE WHAT = TYPES
	PUSHJ	P,PKRCH		;PEEK AT NEXT COMMAND CHARACTER
	 JRST	PRNT9		;NONE LEFT
	CAIE	CH,"="		;ANOTHER = SIGN?
	JRST	PRNT9		;NO
	TXO	F2,OCTALF	;YES, THAT MEANS OCTAL RADIX TYPE-OUT
	PUSHJ	P,SKRCH		;SWALLOW THE EXTRA =
	TXZ	F2,OCTALF	;AT END OF MACRO
PRNT9:	SKIPE	CMFTYO		;SUPPRESSING OUTPUT WHILE IN COMMAND FILE?
	POPJ	P,		;YES, DON'T ACTUALLY TYPE ANYTHING
	PUSHJ	P,PRNT9S	;PRINT NUMBER
	JRST	CRR		;CRLF AND RETURN TO CALLER

;TYPE C(B) IN OCTAL

OCTMS:	TXOA	F2,OCTALF	;SET OCTAL RADIX

;TYPE C(B) IN DECIMAL

DECMS:	TXZ	F2,OCTALF	;DECIMAL RADIX
PRNT9S:	XMOVEI	A,TYO		;OUTPUT ON TTY
	PUSHJ	P,DPT		;TYPE NUMBER
	TXZ	F2,OCTALF	;CLR RADIX FLAG
	POPJ	P,
;N^T	OUTPUT ASCII CHARACTER "N" (E.G., "A" FOR N=^O101, ETC) TO
;	COMMAND STREAM; IF "N" OMITTED, THEN ACCEPT AND RETURN VALUE
;	OF NEXT COMMAND INPUT CHARACTER. IF EO .LE. 2 THEN "N" IGNORED
;	AND COMMAND INPUT ALWAYS PERFORMED.
;
;NOTE WELL THAT THIS ROUTINE WILL READ FROM THE COMMAND FILE IF ONE
;IS IN EFFECT. THIS IS SO THAT A CRASH RECOVERY PROCEDURE SUCH AS
;"[email protected]" WILL WORK - I.E., GET YOU BACK TO WHEREVER YOU LEFT
;OFF.

CMCCT:	CHKEO	EO25,CMCCTI	;OLD VERSIONS ALL FORMS ^T ARE TYPEIN
	TXNN	FF,ARG		;^T OR N^T FORM?
	JRST	CMCCTI		;^T, ACCEPT CHARACTER FROM COMMAND INPUT
	SKIPE	CMFTYO		;SUPPRESSING OUTPUT WHILE IN COMMAND FILE?
	POPJ	P,		;YES, DON'T ACTUALLY TYPE ANYTHING
	MOVE	CH,B		;POSITION CHARACTER
	PUSHJ	P,TYO		;TYPE OUT COMMAND'S CHARACTER
	PUSHJ	P,TYOOUT	;AND FORCE IT OUT NOW!
	JRST	RET		;NEXT COMMAND

CMCCTI:	TXO	FF,TIBKA	;ONE CHARACTER AT A TIME
	PUSHJ	P,TYI		;GET A SINGLE CHAR.
	PJRST	VCHRET		;RETURN VALUE IN "CH"

;HAS THE VALUE OF ELAPSED TIME, IN 60THS OF A SECOND, SINCE MIDNITE.

GTIME:	TIMER	A,
	JRST	VALRET

;HAS THE VALUE OF THE CONSOLE DATA SWITCHES.

LAT:	SWITCH	A,
	JRST	VALRET

;HAS THE VALUE OF THE NEXT CHARACTER IN THE COMMAND STRING.

CNTRUP:	PUSHJ	P,SKRCH		;^^ HAS VALUE OF CHAR FOLLOWING IT
	$FATAL	(MUU,,<Macro ending with ^^>)
VCHRET:	MOVE	A,CH
	JRST	VALRET
;HAS THE VALUE OF THE NUMBER REPRESENTED BY THE DIGITS (OR MINUS SIGN)
;FOLLOWING THE POINTER IN THE BUFFER.  THE SCAN TERMINATES ON ANY OTHER
;CHARACTER.  THE POINTER IS MOVED OVER THE NUMBER FOUND (IF ANY).

BAKSL:	PUSHJ	P,PKRCH		;PEEK AT NEXT COMMAND CHARACTER
	 JRST	BAKSL0		;NONE LEFT
	CAIE	CH,"\"		;ANOTHER BACKSLASH?
	JRST	BAKSL0		;NO
	TXO	F2,OCTALF	;YES, SWITCH TO OCTAL RADIX THEN
	PUSHJ	P,SKRCH		;EAT THE SECOND BACKSLASH
	  TXZ	F2,OCTALF	;END OF MACRO, NOT "\\" AFTER ALL
BAKSL0:	TXZE	FF,ARG		;WHICH KIND OF BACKSLASH?
	JRST	NBAKSL		;ARG TO MEMORY
	MOVE	I,PT		;MEMORY TO VALRET
	CAML	I,Z		;CAN WE READ ANOTHER?
	JRST	BAKSL3		;NO
	PUSHJ	P,GETINC	;CHECK FOR + OR - SIGN
	CAIN	CH,"+"
	JRST	BAKSLA		;IGNORE +
	CAIE	CH,"-"
	JRST	BAKSL1		;NO SIGN
	TXO	FF,ARG		;NEGATION FLAG
BAKSLA:	CAML	I,Z		;OVERDID IT ?
	JRST	BAKSL3		;YES. EXIT
	PUSHJ	P,GETINC	;NO. GET A CHAR
BAKSL1:	CAIG	CH,"9"		;DIGIT?
	CAIGE	CH,"0"		;DIGIT?
	SOJA	I,BAKSL2	;NOT A DIGIT. BACKUP AND LEAVE LOOP
	TXNE	F2,OCTALF	;OCTAL MODE?
	CAIG	CH,"7"		;YES, MORE STRINGENT REQUIREMENTS
	CAIA			;VALID OCTAL/DECIMAL DIGIT
	SOJA	I,BAKSL2	;NOT A VALID OCTAL DIGIT
	SUBI	CH,"0"		;CONVERT TO NUMBER
	EXCH	CH,SYL
	TXNE	F2,OCTALF	;OCTAL MODE?
	IMULI	CH,^D8		;YES
	TXNN	F2,OCTALF	;DECIMAL MODE?
	IMULI	CH,^D10		;YES
	ADDM	CH,SYL		;SYL:= 10.*SYL+CH
	JRST	BAKSLA		;LOOP

BAKSL3:	MOVE	I,Z		;HERE ON OVERFLOW
BAKSL2:	TXZE	FF,ARG		;MINUS SIGN SEEN?
	MOVNS	SYL		;YES. NEGATE
	MOVEM	I,PT		;MOVE POINTER PAST #
	TXZ	F2,OCTALF	;CLEAR USED-UP RADIX FLAG
	JRST	CD7		;DONE
;NA (WHERE N IS A NUMERIC ARGUMENT) = VALUE IN 7-BIT ASCII OF THE
;CHARACTER TO THE RIGHT OF THE POINTER.

ACMD:	TXNN	FF,ARG		;DOES AN ARGUMENT PRECEED A?
	JRST	APPEND		;NO. THIS IN AN APPEND COMMAND.
	MOVE	A,Z		;IF POINTER IS AT END OF
	SUB	A,PT		; BUFFER OR IF BUFFER EMPTY,
	JUMPE	A,VALRET	; MUST GIVE 1A=0
	MOVE	I,PT		;YES.
	PUSHJ	P,GET		;CH:=CHARACTER TO THE RIGHT OF PT.
	PJRST	VCHRET		;RETURN CH AS VALUE
;NUI	PUTS THE NUMERIC VALUE N IN Q-REGISTER I.

USE:	TXNN	FF,ARG		;INSIST ON ARG BEFORE U
	$FATAL	(NAU,,<No argument before U>)
	PUSHJ	P,QREGVI	;CH:=Q-REGISTER INDEX.
	PUSHJ	P,USEQV		;STUFF B INTO NUMERIC Q-REG
	JRST	RET		;DONE


;HELPER TO STORE AC B AS NEW NUMERIC Q-REG VALUE

USEQV:	TLNE	B,400000	;DOES THE ARG LOOK LIKE A TEXT POINTER?
	TLNE	B,300000	;(IE., IS IT OUT OF RANGE?)
	JRST	USEQV2		;NO, GO STORE IT
	 $FATAL	(AOR,,<Argument out of range>)

USEQV2:	MOVEM	B,QTAB-"0"(CH)	;STORE ARGUMENT IN SELECTED Q-REG.
	POPJ	P,		;SUCCESSFUL RETURN

;QI	HAS THE VALUE OF THE LATEST QUANTITY PUT INTO Q-REGISTER I.

QREG:	PUSHJ	P,QTXTST	;GET Q-REG & CHECK FOR TEXT
	JRST	VALRET

;ROUTINE TO RETURN Q-REGISTER INDEX IN CH AND CONTENT IN A.

QREGVI:	PUSHJ	P,SKRCH		;CH:=NEXT COMMAND STRING CHARACTER.
	$FATAL	(MIQ,,<Macro ending with 00>)
QREGV2:	CAIL	CH,"a"		;LC LETTER?
	CAILE	CH,"z"		; . . .
	CAIA			;NO.
	TXZ	CH,40		;YES, SHIFT TO UPPER CASE SET
	CAIL	CH,"0"		;DIGIT?
	CAILE	CH,"9"		; . . .
	CAIL	CH,"A"		;LETTER?
	CAILE	CH,"Z"		; . . .
	$FATAL	(IQN,,<Illegal Q-register name "00">)
	CAILE	CH,"9"		;ALPHANUMERIC, IS DIGIT?
	SUBI	CH,"A"-"9"-1	;NO, TRANSLATE LETTERS DOWN BY NUMBER OF
	POPJ	P,		;CHARACTERS BETWEEN 9 AND A. ONLY 36 Q-REG'S


;N%I	ADDS "N" TO THE QUANTITY IN Q-REGISTER I AND STANDS FOR THE
;	NEW VALUE; IF "N" OMITTED, THEN "1" IS DEFAULT. IF EO .LT. 2
;	THEN "1" ALWAYS, "N" IGNORED.

PCNT:	CHKEO	EO25,PCNT2	;OLD FORMS ALWAYS ADD JUST 1
	TXNN	FF,ARG		;USER SPECIFY AN ARGUMENT?
PCNT2:	MOVEI	B,1		;NO, DEFAULT VALUE OF "1"
	PUSHJ	P,QTXTST	;GET Q-REG & CHECK FOR TEXT
	ADD	B,A		;B:=NEW Q-REG NUMERIC VALUE
	PUSHJ	P,USEQV		;STORE NEW NUMERIC VALUE
	MOVE	A,B		;VALRET WANTS "A" TO HOLD VALUE
	JRST	VALRET		;RETURN NEW VALUE.


QTXTST:	PUSHJ	P,QREGVI	;GET Q-REG INDEX
	MOVE	A,QTAB-"0"(CH)	;GET Q-REG CONTENTS
	TLNE	A,400000	;DOES IT CONTAIN TEXT?
	TLNE	A,300000	;..
	POPJ	P,		;NO,RETURN
	$FATAL	(NNQ,,<No numeric in Q-register 00>)
;M,NXI	COPIES A PORTION OF THE BUFFER INTO Q-REGISTER I.
;	IT SETS Q-REGISTER I TO A DUPLICATE OF THE (M+1)TH
;	THROUGH NTH CHARACTERS IN THE BUFFER.  THE BUFFER IS UNCHANGED.
;NXI	INTO Q-REGISTER I IS COPIED THE STRING OF CHARACTERS STARTING
;	IMMEDIATELY TO THE RIGHT OF THE POINTER AND PROCEEDING THROUGH
;	THE NTH LINE FEED.

XCMD:	PUSHJ	P,GETARG	;C:=FIRST STRING ARGUMENT ADDRESS
				;B:=SECOND STRING ARGUMENT ADDRESS.
	PUSHJ	P,CHK1		;IS SECOND ARG. ADDR. GT FIRST ARG. ADDR.?
	EXCH	B,C		;YES.
	SUB	C,B		;C:=LENGTH OF STRING.
	MOVNM	C,VVAL		;SAVE LENGTH OF STRING
				; (NEGATIVE SINCE PT NOT AFFECTED)
	PUSHJ	P,XQREG		;MOVE DATA TO Q-REG BUFR
	PUSHJ	P,QREGVI	;GET INDEX TO Q-REG
	MOVEM	B,QTAB-"0"(CH)	;STORE NEW Q-REG TEXT POINTER
	JRST	RET		;END OF COMMAND
;TRANSFER DATA TO Q-REGISTER BUFFER
;CALL IS:
;
;	MOVX	B,<ADR>
;	MOVX	C,<LEN>
;	PUSHJ	P,XQREG
;	RETURN
;
;WHERE <ADR> IS THE STARTING CHARACTER ADDRESS OF THE TEXT STRING; AND
;<LEN> IS THE LENGTH OF THE STRING TO BE LOADING INTO A Q-REGISTER BUFFER.
;
;ON RETURN AC B HAS THE Q-REGISTER POINTER. IT IS THE CALLER'S RESPONSIBILITY
;TO SAVE THE POINTER.
;
;RDH	ONE SUGGESTION THAT HAS BEEN MADE IS TO DELETE THE CURRENT Q-REG
;	CONTENTS BEFORE TRYING TO LOAD IT IN ORDER TO MAXIMIZE THE CHANCES
;	OF HAVING ENOUGH MEMORY TO HOLD THE NEW TEXT . . .

XQREG:	PUSH	P,PT		;PRESERVE USER'S "."
	ADDI	C,3		;C:=LENGTH OF STRING + 3 (FOR BYTE COUNT)
	MOVE	T,BEG		;GET START CHARACTER ADDRESS OF TEXT BUFFER
	MOVEM	T,PT		;PT:=BEG
	ADD	T,C		;PROPOSED NEW BEG
	IDIVI	T,5		;TT:=OFFSET FROM WORD-ALIGNEDNESS
	CAIE	TT,0		;IF NOT WORD ALIGNED, THEN
	SUBI	TT,5		;CALCULATE [NEGATIVE] FILL REQUIRED
	SUB	C,TT		;ADD IN NULL-FILL TO SPACE REQUEST
	ADDM	C,(P)		;(P):=PT + LENGTH OF STRING + 3 + NULL-FILL.
	PUSHJ	P,NROOMQ	;INSERT STRING AT BEG, RELOCATING SCREEN
	SKIPE	OU,RREL		;RELOCATION IF GARBAGE COLLECTION OCCURRED.
	ADDM	OU,(P)		;RELOCATE NEW TRUE "." IF NECESSARY
	CAMGE	B,BEG		;DON'T NEED TO RELOCATE IF *I
	JRST	XQREG3		;STRING ADDRESS IS ALL SET
	ADD	B,C		;STRING IS FROM TEXT BUFFER, SHIFT IT UP
	ADD	B,OU		;B:=FIRST ADDR + LENGTH + 3 + NULL-FILL + RREL
XQREG3:	MOVE	OU,BEG		;OU:=ADDRESS OF Q-REG BUFFER
	ADDM	C,BEG		;BEG:=C(BEG)+LENGTH OF STRING + 3 + NULL-FILL
	ADD	C,TT		;C:=LENGTH OF STRING + 3
	PUSHJ	P,PTQCNT	;WRITE THE Q-REG LENGTH FIRST
	MOVE	I,B		;SOURCE TEXT ADDRESS FOR COPY
	JRST	XQREG7		;START UP TEXT STRING COPY LOOP

XQREG5:	PUSHJ	P,GETINC	;PICK UP NEXT TEXT CHARACTER
	PUSHJ	P,PUTINC	;AND STUFF IT AWAY INTO Q-REG
XQREG7:	SOJGE	C,XQREG5	;LOOP UNTIL ALL CHARACTERS COPIED
	MOVE	B,PT		;QTAB ENTRY := 4B2 + Q-REG BUFFER
	SUB	B,QRBUF		;ADDRESS RELATIVE TO C(QRBUF)
	TLO	B,400000
	POP	P,PT		;MOVE PT PAST STRING.
	POPJ	P,
;GI	THE TEXT IN Q-REGISTER I IS INSERTED INTO THE BUFFER AT THE
;	CURRENT LOCATION OF THE POINTER.  THE POINTER IS THEN PUT JUST
;	TO THE RIGHT OF THE INSERTION.  THE Q-REGISTER IS NOT CHANGED.

QGET:
	SETZM	VVAL		;CLR STRING LENGTH HOLD
	PUSHJ	P,QTEXT		;INIT Q-REG ACCESS
	MOVE	B,CH		;SAVE INDEX
	PUSHJ	P,GTQCNT	;C:=LENGTH OF STRING
	JUMPE	C,RET		;IF NO TEXT, ALL DONE
	PUSHJ	P,NROOMC	;MOVE FROM PT THROUGH Z UP C POSITIONS
	MOVE	CH,B		;RE-SET Q-REG NAME
	PUSHJ	P,QTEXTC	;FIND NEW [POSSIBLY GARBAGE-COLLECTED] Q-REG
	PUSHJ	P,GTQCNT	;SKIP COUNT FIELD
	MOVE	OU,PT
QGET1:	PUSHJ	P,GETINC	;GET NEXT Q-REG TEXT CHARACTER
	PUSHJ	P,PUT		;AND PUT IT INTO THE TEXT BUFFER
	ADDI	OU,1		;ADVANCE OUTPUT POINTER
	SOJG	C,QGET1		;LOOP FOR ENTIRE Q-REG'S WORTH OF TEXT
	MOVEM	OU,PT		;PUT "." JUST PAST THE "INSERT"
	JRST	RET		;ALL DONE


;INITIALIZE ACCESS OF TEXT FROM A Q-REGISTER

QTEXT:	PUSHJ	P,QREGVI	;A=QTAB ENTRY, CH=Q-REG INDEX
QTEXTC:	MOVE	A,QTAB-"0"(CH)	;GET Q-REGISTER POINTER
	TLZE	A,400000	;MAKE SURE IT CONTAINS TEXT
	TLZE	A,300000
	$FATAL	(NTQ,,<No text in Q-register 00>)
	ADD	A,QRBUF
	MOVE	I,A		;I=Q-REG BUFFER ADDRESS
	POPJ	P,
;GET 21 BIT Q-REGISTER CHARACTER COUNT

GTQCNT:	PUSHJ	P,GETINC	;LOW ORDER 7 BITS
	MOVEM	CH,C
	PUSHJ	P,GETINC	;MIDDLE 7 BITS
	LSH	CH,7
	IORM	CH,C
	PUSHJ	P,GETINC	;HIGH 7 BITS
	LSH	CH,^D14
	IORM	CH,C
	SUBI	C,3		;LESS 3 BYTES USED TO STORE THIS COUNT
	POPJ	P,



;SET 21-BIT Q-REGISTER CHARACTER COUNT

PTQCNT:	MOVE	CH,C		;FIRST CHAR OF BUFFER :=LEAST SIGNIFICANT 7 BITS
	PUSHJ	P,PUTINC	;OF LENGTH OF STRING + 3
	LSH	CH,-7		;SECOND CHARACTER = MIDDLE 7 BITS
	PUSHJ	P,PUTINC
	LSH	CH,-7
	SUBI	C,3		;C:=LENGTH OF TEXT STRING
	PJRST	PUTINC		;STUFF LAST CHARACTER OF COUNT, RETURN
;MI	PERFORM NOW THE TEXT IN Q-REGISTER I AS A SERIES OF COMMANDS.

MAC:	PUSHJ	P,QTEXT		;INIT Q-REG ACCESS
	PUSH	P,COMMAX	;SAVE CURRENT COMMAND STATE
	PUSH	P,COMPTR	;SAVE CURRENT COMMAND BYTE POINTER
	PUSH	P,COMPTX	; (DOUBLE-WORD POINTER ADDRESS)
	PUSH	P,COMCNT	;SAVE CURRENT COMMAND CHARACTER COUNT
	PUSH	P,.		;FLAG MACRO ON PDL (LARGE POS. NO.)
	PUSHJ	P,GTQCNT	;GET NUMBER OF CHARACTERS IN MACRO
	MOVEM	C,COMCNT	;THAT MANY COMMANDS TO COUNT
	MOVEM	C,COMMAX	;AND MAX.
	SUBI	I,1		;ADJUST TO SUIT BTAB
	IDIVI	I,5
	HLLZ	OU,BTAB(OU)	;MAKE A BYTE POINTER
	TLZ	OU,77		;CLEAR OUT INDEXING/ETC.
	SKIPE	SECTN		;PC IN EXTENDED SECTION?
	TLOA	OU,(1B12)	;YES, USE DOUBLE-WORD POINTER
	HRR	OU,I		;NO, USE SINGLE-WORD LOCAL POINTER
	MOVEM	OU,COMPTR	;SET NEW COMMAND BYTE POINTER
	MOVEM	I,COMPTX	; (DOUBLE-WORD POINTER ADDRESS)
	AOS	EQM		;INCREMENT THE MACRO LEVEL
	JRST	CD5		;DON'T FLUSH ANY ARGUMENTS


;]I	POPS Q-REGISTER I OFF THE Q-REGISTER PUSHDOWN LIST.
;	THE Q-REGISTER PUSHDOWN LIST IS CLEARED EACH TIME $$ IS TYPED.

CLOSEB:	SKIPA	C,[POP PF,]

;[I	PUSHES Q-REGISTER I ONTO THE Q-REGISTER PUSHDOWN LIST.

OPENB:	MOVSI	C,261000+PF*40
	PUSHJ	P,QREGVI
	HRRI	C,QTAB-"0"(CH)	;C:=Q-REGISTER INDEX.
	XCT	C		;PUSH OR POP Q-REGISTER.
	JRST	RET
;E COMMANDS SELECT AND CONTROL FILE INPUT-OUTPUT MEDIA

ECMD:	PUSHJ	P,SKRCH		;GET CHAR AFTER E
	$FATAL	(MEE,,<Macro ending with E>)
	MOVEI	T,ECTABL	;INDEX DISPATCH TABLE
	PUSHJ	P,DISPAT
	$FATAL	(IEC,,<Illegal character "00" after E>)

;E-COMMAND DISPATCH TABLE

ECTABL:	XWD	EA,	"A"	;EDIT ALL (READ IN WHOLE FILE)
	XWD	EB,	"B"	;EDIT AND MAKE A BACKUP COPY OF A FILE
	XWD	EC,	"C"	;FINISH FILE I/O AND CLOSE OUTPUT
	XWD	EF,	"F"	;CLOSE OUTPUT FILE AS IS (NO MORE I/O)
	XWD	EG,	"G"	;EXIT AND RE-EXECUTE LAST COMPIL-CLASS COMMAND
	XWD	EH,	"H"	;(OBSOLETE) SET ERROR LEVEL TYPEOUT
	XWD	EK,	"K"	;KILL (ABORT) THE OUTPUT FILE
	XWD	EM,	"M"	;PERFORM MAGTAPE OPERATION
	XWD	EO,	"O"	;SET OLD VERSION COMPATIBILITY
	XWD	EP,	"P"	;PUSH TO A NEW CONTEXT
	XWD	ER,	"R"	;SELECT FILE FOR READ ONLY
	XWD	ES,	"S"	;SET AUTO-TYPEOUT ON SEARCH MATCH
	XWD	ET,	"T"	;TERMINAL CONTROL
	XWD	EU,	"U"	;SET UPPER VS LOWER CASE CONTROL
	XWD	EW,	"W"	;SELECT FILE TO WRITE ONLY
	XWD	EX,	"X"	;OUTPUT AND CLOSE OUTPUT FILE, EXIT
	XWD	EY,	"Y"	;YANK COMMAND
	XWD	EZ,	"Z"	;ZERO DECTAPE DIRECTORY
	XWD	CMFCMD,	"@"	;READ COMMAND FILE
	XWD	0,0		;MARKS END OF LIST
;MISCELLANEOUS CHARACTER DISPATCHER
;CALL:	MOVE	CH,CHARCATER
;	MOVEI	T,TABLE ADDR
;	PUSHJ	P,DISPAT
;	NOT FOUND RETURN
;ENTER AT DISP1 TO AVOID CONVERTING LC TO UC

DISPAT:	CAIL	CH,"a"		;LOWER CASE?
	CAILE	CH,"z"		; . . .
	CAIA			;NO
	TRZ	CH,40		;YES, CONVERT TO UPPER CASE
DISP1:	PUSH	P,A		;SAVE AC A WHILE WE USE IT
DISP2:	HRRZ	A,(T)		;GET TABLE ENTRY
	JUMPE	A,APOPJ		;"ERROR" RETURN IF NO MATCH
	CAME	A,CH		;TABLE ENTRY MATCH?
	AOJA	T,DISP2		;NOT A MATCH
	HLRZ	A,(T)		;MATCH, GET DISPATCH ADDRESS
	HRRM	A,-1(P)		;SET DISPATCH ADDRESS (AS IF PJRST)
	PJRST	APOPJ		;RESTORE AC A & DISPATCH
;EA -- READ IN ENTIRE FILE INCLUDING <FF>'S
;EAFIL  --  EA ENTRY POINT FROM RDFIL

EAFIL:	TXZA	FF,ARG		;CLEAR ARG FLAG
EA:	TXNN	FF,ARG		;USER TYPE NEA?
	HRLOI	B,377777	;NO, ASSUME LARGE REPEAT COUNT
	JUMPLE	B,EASET		;IF 0 OR -1 SET EA MODE FLAG
	TXNN	FF,UREAD	;GOT AN INPUT FILE?
	$FATAL	(NFI,,<No file for input>)
	PUSH	P,B		;SAVE REPEAT COUNT
	PUSHJ	P,TRLFF		;CHECK FOR ANY TRAILING <FF> NEEDED

;ALLOCATE ROOM FOR THE WHOLE FILE

EA2:	SKIPLE	C,INSIZ		;BYTES REMAINING IN INPUT FILE
	TXNE	FF,ARG		;IF USER SPECIFIED REPEAT COUNT FOR APPEND
	JRST	EA6		;JUST DO IT, GRABBING CORE AS NEEDED
;RDH	SKIPE	SECTN		;*** MONITOR HASN'T IMPLEMENTED EXTENDED DUMP
;RDH	JRST	EA6		;*** MODE I/O YET, SO DO IT THE HARD WAY FOR NOW
	DMOVE	A,PT		;GET "." AND "Z"
	MOVEM	AA,PT		;TELL NROOM IT IS A DATA EXPANSION
	ADDI	C,^D3000	;TECO'S ELBOW ROOM
	PUSHJ	P,NROOMC	;MAKE ROOM FOR REST OF INPUT FILE
	ADD	A,RREL		;RELOCATE "."
	ADD	AA,RREL		;AND Z IN CASE GARBAGE COLLECTION WAS DONE
	DMOVEM	A,PT		;RESTORE "." AND "Z" TO RIGHTFUL PLACES
	IDIVI	AA,5		;AA:=WORD ADDRESS IN WHICH "." RESIDES
	MOVEM	B,EAXDEL	;CLEAR (OR PREPARE TO SET) FLAG
	JUMPE	B,EA2E		;IF NOT WORD ALIGNED DO IT THE HARD WAY
	MOVNI	B,5		;CALCULATE
	ADDM	B,EAXDEL	;NUMBER OF BYTES OFFSET
	ADDI	AA,1		;ROUND UP "Z" TO NEXT WORD BOUNDRY
EA2E:	MOVE	T,INSWT		;INPUT FILE SWITCHES
;RDH	TXNN	T,GENLSN!SUPLSN	;ANYTHING FUNNY HAPPENING?
	SKIPLE	BICNT		;OR HAVE WE STARTED BUFFERED INPUT?
	JRST	EA6		;YUP, DO IT THE HARD WAY
	MOVE	T,INCHR		;GET INPUT DEVICE CHARACTERISTICS
	TXNN	T,DV.DSK	;NON-DISK?
	JRST	EA6		;YUP, DO IT THE HARD WAY

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;HERE TO DUMP IN THE WHOLE FILE IN ONE SWELL FOOP

EA3:	POP	P,B		;ADJUST STACK
	MOVE	T,INSIZ		;FILE SIZE IN BYTES
	ADDI	T,4		;ROUND UP AND
	IDIVI	T,5		;TRUNCATE TO NUMBER OF WORDS
	MOVE	C,T		;SAVE TOTAL WORD COUNT
	SKIPE	SECTN		;RUNNING EXTENDED?
	JRST	EA3E		;YES, DIFFERENT I/O THEN

;HERE TO DO OLDE-FASHIONED (NON-EXTENDED) DUMP-MODE I/O

	IDIVI	T,400000	;TAKE MOD 128K
	CAILE	T,1		;.GT. 256K?
	 HALT	.		;CAN'T GET HERE
	CAIE	T,0		;.LE. 128K?
	SKIPA	T,[400000]	;NO, .GT. 128K
	EXCH	T,TT		;YES, ONLY ONE IOWD NEEDED
	MOVNS	T		;NEGATIVE WORD COUNT
	HRLZS	T		; IN LEFT HALF
	MOVNS	TT		;NEGATIVE (OR ZERO) WORD COUNT
	HRLZS	TT		; IN LEFT HALF
	HRRI	T,-1(AA)	;FIRST WORD ADDRESS DUMP STYLE
	CAIE	TT,0		;NEED TWO IOWDS?
	HRRI	TT,400000-1(AA)	;YES, SECOND PART OF COMMAND LIST
	JRST	EA3I		;GO DO DUMP-MODE INPUT

;HERE FOR NEW-FANGLED (EXTENDED) DUMP-MODE I/O

EA3E:	MOVE	TT,AA		;I/O ADDRESS IN 'BI-WORD' FORMAT

;HERE TO ACTUALLY PERFORM THE I/O

EA3I:	DMOVEM	T,IOLIST	;POSITION DUMP-MODE COMMAND LIST
	SETZB	T,TT		;A '0' TO
	DMOVEM	T,IOLIST+2	;TO TERMINATE THE COMMAND LIST
	MOVSI	T,INCHN		;I/O CHANNEL
	HRRI	T,.FOSET	;FUNCTION: SETSTS
	MOVEI	TT,.IODMP	;TO SELECT DUMP-MODE I/O
	MOVE	CH,[2,,T]	;FILOP. ARG POINTER TO
	FILOP.	CH,		;SWITCH TO DUMP-MODE INPUT
	 JRST	INERR		;DUH???
	HRRI	T,.FOINP	;FUNCTION: INPUT
	SKIPE	SECTN		;RUNNING EXTENDED?
	HRRI	T,.FOFXI	;YES, SELECT EXTENDED DUMP I/O
;***	XMOVEI	TT,IOLIST	;ADDRESS OF DUMP-MODE COMMAND LIST
	MOVEI	TT,IOLIST	;*** ADDRESS OF DUMP-MODE COMMAND LIST
	MOVE	CH,[2,,T]	;FILOP. ARG POINTER TO
	FILOP.	CH,		;DUMP THE WHOLE FILE
	 JRST	INERR		;I/O ERROR, FORGET IT
	HRRI	T,.FOSET	;FUNCTION: SETSTS (AGAIN)
	MOVEI	TT,IO.EOF+.IOASC;TO SWITCH BACK TO STANDARD ASCII
	MOVE	CH,[2,,T]	;FILOP. ARG POINTER TO
	FILOP.	CH,		;RESELECT ASCII I/O
	 JRST	INERR		;DUH???
	TXO	FF,FINF		;GOT IT, TELL YANK3 ABOUT IT

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIUOS PAGE

;FILE IS READ IN, CHECK FOR EMBEDDED NULLS AND/OR LINE SEQUENCE NUMBERS

EA4:	MOVN	T,C		;COUNT OF WORDS TO CHECK
	MOVE	TT,AA		;START OF JUST-READ TEXT
	ADD	TT,C		;END (+1) OF JUST READ TEXT
	MOVSI	TT1,((T))	;PREPARE TO INDEX VIA AC "T"
	SKIPE	SECTN		;RUNNING EXTENDED?
	LSH	TT1,IFX2EF	;YES, REPOSITION INDEX REGISTER
	IOR	TT,TT1		;SET INDEXING FROM AC "T"
	SKIPG	S.OKNU		;OKNULLS? (USER WANTS SPEED)
	JRST	EA4L		;NO, CHECK FOR NULLS TOO
	SKIPLE	S.OKLS		;OKLSN?
	JRST	EA4OK		;YES, USER REALLY WANTS SPEED!

;JUST CHECK FOR LINE SEQUENCE NUMBERS, USER IS WILLING TO LIVE WITH NULLS

	MOVEI	TT1,1B35	;THE LSN BIT
	TDNN	TT1,@TT		;GOT AN LSN HERE?
	AOJL	T,.-1		;NO, CHECK NEXT WORD
	JUMPGE	T,EA4OK		;IF NO LSNS THEN ALL SET
	JRST	EA4N		;OOPS - SAW AN LSN!

;CHECK FOR BOTH NULLS AND LINE SEQUENCE NUMBERS

EA4L:	MOVX	CH,177B20	;CENTER NULL CHECK MASK
EA4L0:	SKIPN	TT1,@TT		;GET A WORD FROM THE BUFFER
	JRST	EA4N		;FULL OF NULLS
	TLNE	TT1,(177B6)	;GOT A NULL?
	TLNN	TT1,(177B13)	;GOT A NULL?
	JRST	EA4N		;YEP
	TDNE	TT1,CH		;GOT A NULL?
	TRNN	TT1,177B27	;GOT A NULL?
	JRST	EA4N		;YEP
	TRNE	TT1,177B34	;GOT A NULL?
	TRNE	TT1,1B35	;GOT A LSN?
	JRST	EA4N		;YEP
	AOJL	T,EA4L0		;NO, CHECK NEXT WORD
	JRST	EA4OK		;IF NO LSN, BUFFER IS OK
;EITHER A LINE SEQUENCE NUMBER OR AN EMBEDDED NULL HAS BEEN DETECTED.

EA4N:	XMOVEI	TT1,@TT		;FROM WHENCE TO START RE-WRITING
	SETZB	A,AA		;INITIALIZE FOR LOOP
	SUBI	T,1		;BACKUP FOR LOOP BELOW
	MOVE	I,INSWT		;COPY OF /GENLSN FOR LOOP TEST
	TXO	I,1B17		;TEMP FIRST-TIME FLAG

;A := WORD BEING BUILT; AA := WORD BEING CHECKED
;T := NEGATIVE COUNT; @TT := ADDRESS OF NEXT AA; TT1 := ADDRESS FOR THIS A

EA4N1:	LSH	AA,7		;DISCARD THIS NULL
	JUMPN	AA,EA4N6	;AND CHECK REST OF WORD
	AOJGE	T,EA4N8		;EXIT IF DONE
	MOVE	AA,@TT		;NEXT FRESHLY-READ FILE WORD
	TXZE	AA,1B35		;IS THIS WORD AN LSN?
	TXNN	I,SUPLSN!1B17	;YES, SUPPRESS UNLESS USER WANTS 'EM
	JRST	EA4N6		;REGULAR TEXT OR DESIRED LSN
	TXZ	I,1B17		;NOTE WE'VE SEEN AN LSN
	TXNN	I,SUPLSN	;NOW, DO WE REALLY CARE?
	JRST	EA4N6		;NO
EA4N3:	AOJGE	T,EA4N8		;AN UNDESIRED LSN
	MOVE	AA,@TT		;GET WORD FOLLOWING
	TXNE	AA,1B35		;ANOTHER LSN?
	JRST	EA4N3		;YES (??)
	TLNE	AA,(177B6-11B6)	;A TAB CHARACTER
	JRST	EA4N6		;NO WAY, NOT SOS-STYLE
	TLC	AA,(11B6)	;MAYBE
	TLCN	AA,(11B6)	;TRAILING SOS-STYLE TAB?
	LSH	AA,7		;YES, STRIP IT TOO
	JRST	EA4N6		;GO HANDLE REST OF TEXT WORD

EA4N6:	TLNN	AA,(177B6)	;A NULL?
	JRST	EA4N1		;YES, DISCARD IT
	LSHC	A,7		;NO, CONCATENATE CHAR TO PREVIOUS
	TLNN	A,(177B7)	;GOT 5 MORE CHARACTERS YET?
	JRST	EA4N6		;NO
	LSH	A,1		;YES, LEFT-JUSTIFY THE CHARACTERS
	MOVEM	A,(TT1)		;AND WRITE THEM BACK TO THE BUFFER
	SETZ	A,		;RESET CHARACTER ACCUMULATOR
	AOJA	TT1,EA4N6	;AND GET MORE CHARACTERS
EA4N8:	LSH	A,7		;LEFT-JUSTIFY THE TEXT
	TLNN	A,(177B7)	;DONE YET?
	JUMPN	A,EA4N8		;NO, FINISH WORD
	LSH	A,1		;LEFT-JUSTIFY THE WORD
	MOVEM	A,(TT1)		;YES, CAP OFF TEXT BUFFER
	TXNE	I,1B17		;DID WE SEE ANY LSNS?
	JRST	EA4N9		;NO
	MOVE	OU,TT1		;SAVE END ADDRESS
	PUSHJ	P,INBMES	;TELL HAPLESS USER
	  ASCIZ	\% Line Sequence Number detected in input file\
	TXO	FF,SEQF		;NOTE WE'VE SEEN LSN'S
	AOSA	I,OU		;PUT ADDRESS IN I
EA4N9:	AOS	I,TT1		;POSITION AND
	IMULI	I,5		; CALCULATE POTENTIAL NEW "Z"
	JRST	EA4OK2		;FINISH OFF THE BUFFER

;HERE TO RE-READ THE FILE THE HARD WAY
;
;EA4N:	SETSTS	INCHN,.IOASC	;SET ASCII MODE, CLEAR EOF
;	USETI	INCHN,1		;POSITION TO FIRST BLOCK
;	TXZ	FF,FINF		;CLEAR OUR EOF FLAG
;	HRLOI	B,377777	;SET LARGE REPEAT COUNT
;	JRST	EA7		;AND READ THE FILE THE HARD WAY
;FILE HAS NO LINE SEQUENCE NUMBERS NOR EMBEDDED NULLS, SUPPRESS ANY
;TRAILING NULLS

EA4OK:	MOVE	I,Z		;WHERE WE STARTED READING
	ADD	I,INSIZ		;NEW "Z"
	SUB	I,EAXDEL	;ALLOW FOR ANY EXTRA NULLS PUT IN ABOVE
EA4OK2:	SETZM	INSIZ		;NOTE NO MORE TEXT LEFT IN INPUT FILE
	MOVE	B,Z		;SAVE OLD Z
	SUBI	I,1		;BACKUP TO LAST CHARACTER
	PUSHJ	P,GET		;AND GET IT
	JUMPE	CH,.-2		;IF NULL, CHUCK IT
	ADDI	I,1		;THIS CHARACTER IS VALID
	CAMGE	I,PT		;SOME JOKER FEED US A FILE OF NULLS?
	MOVE	I,PT		;YEAH, WELL FOO ON HIM
	MOVEM	I,Z		;SET "Z", SUPPRESSING TRAILING NULLS
	SKIPE	C,EAXDEL	;GOT SOME EXCESS NULLS NEEDING DELETION?
	CAML	B,I		;YEAH, DO THEY STILL EXIST?
	JRST	EA4XT		;NO, TIME TO GET OUT
	EXCH	B,PT		;YES, SET "." TO START OF NULL FILL
	PUSHJ	P,NROOMC	;ABUT NEW FILE TEXT TO PREVIOUS TEXT
	ADD	B,RREL		;JUST IN CASE  . . .
	MOVEM	B,PT		;RESTORE TRUE USER'S "."
EA4XT:	POPJ	P,		;RETURN HAVING READ ENTIRE FILE
				;SHOULD ALSO DELETE INPUT BUFFERS!

;LOOP YANKING (APPENDING ACTUALLY) FROM INPUT FILE

EA6:	POP	P,B		;GET LOOP COUNT
EA7:	MOVE	OU,Z		;END OF EDITING BUFFER
	PUSHJ	P,YANK2		;APPEND ANOTHER CHUNK OF INPUT TEXT
	TXZE	FF,FORM		;TERMINATED BY A <FF>?
	AOS	Z		;YES, ACCOUNT FOR THE <FF> TOO!
				; THIS CODE DEPENDS ON YANK51'S ACTUALLY
				; HAVING READ IN THE <FF> BUT NOT COUNTING
				; IT IN Z.
	TXNN	FF,FINF		;MORE INPUT FILE LEFT?
	SOJG	B,EA7		;YES, READ (APPEND) N TIMES
	POPJ	P,		;AND RETURN


U EAXDEL,1			;NULL-FILL COUNT (NEGATIVE) FOR DUMP I/O


;HERE TO SET EA MODE DEFAULT

EASET:	CAIE	B,0		;EA MODE OFF?
	MOVEI	B,1		;NO, EA MODE ON
	MOVEM	B,S.EAMO	;SET FOR RDFIL TO SEE
	POPJ	P,		;ALL DONE
;EX -- FINISH OUTPUT AND RETURN TO THE TIME-SHARING EXEC.
;^Z -- FINISH OUTPUT (IF ANY) AND EXIT

FINISZ:	TXNN	FF,UWRITE	;HAVE WE GOT AN OUTPUT FILE?
	JRST	FINIZ3		;NO
	PUSHJ	P,.RUNCK##	;YES, /RUN (ETC.) PENDING?
	  CAIA			;NO, NOT A SERIOUS PROBLEM
	$FATAL	(OFZ,,<Output file still OPEN, type "EX$$" to exit>)
	$WARN	(OFO,,<Output file still OPEN, type CONTINUE then "EX$$" to write it>)
	JRST	FINISM		;GO EXIT ANYWAY

FINIZ3:	MOVE	B,BEG		;START OF TEXT BUFFER
	CAMN	B,Z		;ANY TEXT IN BUFFER?
	JRST	FINISM		;NO, ALL CLEAR TO EXIT (EVEN /RUN)
	PUSHJ	P,.RUNCK##	;GOT A /RUN PENDING?
	  CAIA			;NO, NOT A SERIOUS PROBLEM
	$FATAL	(NFZ,,<No file for output>)
	$INFO	(NFO,,<No file for output>)
	JRST	FINISM		;GO EXIT ANYWAY

EX:	PUSHJ	P,EC		;FINISH UP.
FINISK:	PUSHJ	P,ZAPIN		;ZAP INPUT CHANNEL IF ANY
	PUSHJ	P,ZAPOU		;ZAP OUTPUT CHANNEL IF ANY
	TXZ	FF,UREAD+UWRITE+FINF+UBAK	;IN CASE OF A CONTINUE
FINISM:	PUSHJ	P,TEBFIN	;GET RID OF CRASH RECOVERY FILE
	PUSHJ	P,ZAPTT		;FLUSH OUT ANY LAST TERMINAL I/O
	PUSHJ	P,.RUNCM##	;CHECK FOR /RUN AND FRIENDS
FINISO:	EXIT	1,

;GET TO HERE IF USER CONTINUES AFTER EX COMMAND

	SETOM	MESFLG		;SCREEN IS TRASH NOW
	PUSHJ	P,TTOPEN	;RE-OPEN THE COMMAND TERMINAL
	PUSHJ	P,GETTYP	;GET TERMINAL TYPE AGAIN
	PUSHJ	P,TTYGET	;GET CURRENT TTY MODES
	PUSHJ	P,TTYSEC	;SET UP OUR MODES AGAIN
	SETZM	TEBINF		;CALL TEBINI AGAIN
	JRST	GO
;EG -- "EX" AND RE-RUN COMPIL FOR LAST COMPIL-CLASS COMMAND

EG:	PUSHJ	P,EC		;FINISH FILE IO
	PUSHJ	P,TEBFIN	;DELETE CRASH RECOVERY FILE
	SKIPE	SCTYPE		;DOING FANCY VIDEO STUFF?
	PUSHJ	P,CRR		;YES, TIME TO GIVE A <CR><LF>
	PUSHJ	P,ZAPTT		;FLUSH OUT ANY LAST TERMINAL I/O
	PUSHJ	P,ZAPIN		;ZAP INPUT CHANNEL IF ANY
	PUSHJ	P,ZAPOU		;ZAP OUTPUT CHANNEL IF ANY
	TXZ	FF,UREAD+UWRITE+FINF+UBAK	;IN CASE OF A CONTINUE
	MOVEI	A,CCLBLK	;RUN COMPIL
	HRLI	A,1		;AT START ADR PLUS ONE
	RUN	A,		;TRANSFER CONTROL BACK TO COMPIL
	JRST	FINISO		;JUST EXIT IF NO RUN.

CCLBLK:	SIXBIT	/SYS/
	SIXBIT	/COMPIL/	;RUN SYS:COMPIL
	REPEAT	4,<0>
;EC  --  WRITE OUT BUFFER, REST OF INPUT FILE, AND CLOSE OUTPUT FILE

EC:	TXNN	FF,UWRITE	;DO WE HAVE AN OUTPUT FILE
	$FATAL	(NFO,,<No file for output>)
;RDH	SKIPN	SECTN		;*** MONITOR NOT YET READY FOR DUMP I/O
	SKIPLE	BOCNT		;HAVE WE ALREADY STARTED BUFFERED OUTPUT
	JRST	EC2		;YES
	MOVE	T,OUTSWT	;GET OUTPUT SWITCHS
	TXNN	T,GENLSN	;USER EXPLICTLY WANT LSN'S?
	TXNE	F2,LSNF		;OR ARE LSN'S EMBEDDED IN TEXT BUFFER
	JRST	EC2		;YES, DO IT THE HARD WAY
	MOVE	T,OUCHR		;GET OUTPUT DEVICE CHARACTERISTICS
	TXNN	T,DV.DSK	;NON-DISK DEVICE?
	JRST	EC2		;YES, DO IT THE HARD WAY
	TXNE	FF,UREAD	;DO WE HAVE AN INPUT FILE?
	TXNE	FF,FINF		;AND HAVE WE READ IT ALL?
	JRST	EC4		;YES, WE CAN DUMP THE TEXT BUFFER DIRECTLY

;THE SLOW HARD WAY OF COPYING THE FILE

EC2:	TXO	FF,PCHFLG	;KEEP <FF>'S
	HRLOI	E,377777	;A LARGE COUNT
	PUSHJ	P,PUN1		;COPY TEXT PAGES
	JRST	EC7		;CLOSE OFF OUTPUT FILE

;SETUP FOR FAST DUMP I/O

EC4:	MOVE	A,BEG		;START CHARACTER ADDRESS
	IDIVI	A,5		;A:=START WORD ADDRESS
	JUMPE	AA,EC4DO	;ALL SET IF WORD ALIGNED
	MOVNS	AA		;BOATS. CALCULATE
	MOVEI	C,5(AA)		;NULL-FILL REQUIRED
	MOVE	A,BEG		;GET START ADDRESS AGAIN
	MOVE	B,PT		;ALSO COPY OF "."
	MOVEM	A,PT		;TELL NROOMC TO FILL AT START
	PUSHJ	P,NROOMC	;PUT NULL-FILL AT START OF TEXT
	ADDM	C,BEG		;RELOCATE BEG PAST NULL-FILL
	ADD	B,C		;RELOCATE "." PAST NULL-FILL
	ADD	B,RREL		;RELOCATE "." IF NECESSARY
	MOVEM	B,PT		;RESTORE PROPER USER'S "."
	MOVE	A,BEG		;START CHARACTER ADDRESS
	IDIVI	A,5		;START WORD ADDRESS
	JUMPN	AA,EC2		;IF STILL NOT WORD ALIGNED JUST GIVE UP

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;HERE TO DUMP THE TEXT BUFFER DIRECTLY (AND QUICKLY)

EC4DO:	PUSHJ	P,TRLFF		;CHECK FOR A TRAILING <FF>
	MOVE	I,Z		;END CHARACTER ADDRESS
	PUSHJ	P,TRAIL0	;ZERO TRAILING BITS IN LAST WORD
	MOVE	T,Z		;END CHARACTER ADDRESS
	CAMG	T,BEG		;ANY CHARACTERS AT ALL?
	JRST	EC7		;NO, JUST CLOSE OFF FILE THEN
	SUBI	T,1		;POINT BACK AT LAST REAL CHARACTER
	IDIVI	T,5		;WORD ADDRESS OF END
	SUB	T,A		;WORD COUNT OF TEXT BUFFER (ALMOST)
	ADDI	T,1		;WORD COUNT OF TEXT BUFFER
	PUSH	P,T		;SAVE WORD COUNT FOR A MOMENT
	SKIPE	SECTN		;RUNNING EXTENDED?
	JRST	EC4E		;YES, NEW-FANGLED WAY THEN

;DUMP THE BUFFER THE OLDE-FASHIONED WAY

	IDIVI	T,400000	;MOD 128K
	CAIE	T,0		;.LE. 128K?
	SKIPA	T,[400000]	;NO, .GT. 128K - NEED TWO IOWDS
	EXCH	T,TT		;YES, ONLY ONE IOWD NEEDED
	MOVNS	T		;NEGATIVE COUNT
	HRLZS	T		;POSITION COUNT FOR IOWD
	MOVNS	TT		;GET SECOND PART
	HRLZS	TT		;POSITION IT TOO
	HRRI	T,-1(A)		;DUMP MODE IOWD
	CAIE	TT,0		;NEED A SECOND HALF?
	HRRI	TT,400000-1(A)	;YES, MAKE SECOND IOWD COMMAND
	JRST	EC4O		;GO DO THE OUTPUT

;HERE TO FORMAT FOR EXTENDED 'BI-WORD' DUMP I/O

EC4E:	MOVE	TT,A		;POSITION I/O ADDRESS FOR BI-WORD FORMAT

;HERE TO DUMP OUT THE EDITING BUFFER

EC4O:	DMOVEM	T,IOLIST	;SET THE DUMP-MODE COMMAND LIST
	SETZB	T,TT		;AND SOME 0'S
	DMOVEM	T,IOLIST+2	;TO TERMINATE THE COMMAND LIST
	POP	P,T		;RETRIEVE TOTAL WORD COUNT
	MOVSI	TT,((T))	;SETUP TO INDEX OFF OF AC "T"
	SKIPE	SECTN		;RUNNING EXTENDED?
	LSH	TT,IFX2EF	;YUP, DIFFERENT INDEXING THEN
	IOR	TT,A		;BASE ADDRESS OF TEXT BUFFER
	MOVEI	TT1,1B35	;ANNOYING BIT
	TDNE	TT1,@TT		;IS THE BIT SET IN THIS DATA WORD?
	ANDCAM	TT1,@TT		;YES, BLAST IT AWAY
	SOJGE	T,.-2		;FINISH THE REST OF THE BUFFER

	MOVSI	T,OUTCHN	;I/O CHANNEL
	HRRI	T,.FOSET	;FUNCTION: SETSTS
	MOVEI	TT,.IODMP	;TO SELECT DUMP-MODE I/O
	MOVE	CH,[2,,T]	;FILOP. ARG POINTER TO
	FILOP.	CH,		;SWITCH TO DUMP-MODE OUTPUT
	 JRST	OUTERR		;DUH???
	HRRI	T,.FOOUT	;FUNCTION: OUTPUT
	SKIPE	SECTN		;RUNNING EXTENDED?
	HRRI	T,.FOFXO	;YES, SELECT EXTENDED DUMP I/O
;***	XMOVEI	TT,IOLIST	;ADDRESS OF DUMP-MODE COMMAND LIST
	MOVEI	TT,IOLIST	;*** ADDRESS OF DUMP-MODE COMMAND LIST
	MOVE	CH,[2,,T]	;FILOP. ARG POINTER TO
	FILOP.	CH,		;DUMP THE WHOLE BUFFER
	 JRST	OUTERR		;I/O ERROR, FORGET IT
	HRRI	T,.FOSET	;FUNCTION: SETSTS (AGAIN)
	MOVEI	TT,.IOASC	;TO SWITCH BACK TO STANDARD ASCII
	MOVE	CH,[2,,T]	;FILOP. ARG POINTER TO
	FILOP.	CH,		;RESELECT ASCII I/O
	 JRST	OUTERR		;DUH???

;FINISH OFF THE OUTPUT FILE

EC7:	PUSHJ	P,EF		;CLOSE OFF THE OUTPUT FILE
	PUSHJ	P,ZAPIN		;[252] CLEAN OUT THE NOW-USED-UP INPUT FILE
	PJRST	HK		;AND ZERO THE BUFFER
;ET COMMAND

ET:	POP	P,CH		;CLR RET. ADDR. FROM PDL
	TXNE	FF,ARG		;ARGUMENT?
	JRST	ET1		;YES.
	TXNE	FF,TYOCTF	;NO, FLAG ON?
	JRST	FFOK		;YES, RETURN -1
	JRST	BEGIN		;NO, RETURN 0

ET1:	TXZ	FF,TYOCTF	;CLEAR ET FLAG
	JUMPE	B,RET		;ARGUMENT NON-ZERO?
	TXO	FF,TYOCTF	;YES. SET ET FLAG
	JRST	RET		;RETURN

;EO COMMAND

EO:	POP	P,CH		;CLR RET. ADDR. FROM PDL
	TXNE	FF,ARG		;ARGUMENT?
	JRST	EO1		;YES, SET FLAG
	MOVE	A,EOFLAG	;NO, RETURN VALUE OF EOFLAG
	JRST	VALRET

EO1:	CAIG	B,0		;N LE 0?
	MOVEI	B,EOVAL		;YES, SET TO STANDARD
	CAILE	B,EOVAL		;N GT STANDARD FOR THIS VERSION?
	$FATAL	(EOA,,<06EO agument too large>)
	MOVEM	B,EOFLAG	;SET EOFLAG
	JRST	RET

U EOFLAG,1			;EDIT OLD FLAG

;EU COMMAND

EU:	POP	P,CH		;CLR RET. ADDR. FROM PDL
	TXNE	FF,ARG		;ARGUMENT?
	JRST	EU1		;YES
	MOVE	A,TYCASF	;NO, RETURN VALUE OF TYPE-OUT CASE FLAG
	JRST	VALRET

EU1:	MOVEM	B,TYCASF	;SET TYPE-OUT CASE FLAG
	JRST	RET

U TYCASF,1			;TYPE-OUT CASE FLAG: 0 = TYPE ' BEFORE LC
				;+ = TYPE ' BEFORE UC; - = DON'T TYPE FLAGS
;EP COMMAND - PUSH TO A NEW CONTEXT
;Command is:
;
;	EPstr$
;
;Where str is any string ("@" construction not legal), not currently
;used but reserved for future expansion . . .

EP:	PUSHJ	P,SKRCH		;GRAP ANOTHER CHARACTER
	 $FATAL	(UMP,,<Macro ending with unterminated PUSH ("EP") command>)
	CAIE	CH,.CHESC	;TERMINATING <ESC>?
	JRST	EP		;NO, KEEP SCANNING

;GO THE WHOLE COMMAND, DO THE PUSH

EP7:	XMOVEI	T,EPCTXB	;ADDRESS OF CTX. ARG BLOCK TO
	CTX.	T,		;PUSH TO A FRESH CONTEXT
	 $FATAL	(EPF,,<Can't PUSH to a new context>)
	SETOM	MESFLG		;THE SCREEN IS UNDOUBTEDLY TOTALLY TRASHED
	POPJ	P,		;RETURN TO COMMAND PARSER


EPCTXB:	EPCTXL,,.CTSVH		;FIRE UP A FRESH CONTEXT

	EPCTXL==.-EPCTXB	;LENGTH OF CONTEXT UUO ARG BLOCK



;ES COMMAND

ES:	POP	P,CH		;CLR RET ADDR FROM PDL
	TXNE	FF,ARG		;ARG?
	JRST	ES1		;YES
	MOVE	A,AUTOF		;NO, RETURN VALUE OF FLAG
	JRST	VALRET

ES1:	MOVEI	A,.CHLFD	;USE LF FOR FLAG IF ARG = 1 TO 37
	CAIL	B,1
	CAILE	B,37
	MOVE	A,B		;OTHERWISE USE WHAT HE GAVE
	MOVEM	A,AUTOF		;SET NEW VALUE IN FLAG
	JRST	RET

U AUTOF,1			;NON-ZERO IMPLIES AUTOTYPE AFTER SEARCHES
				;POSITIVE IMPLIES TYPE AUTOF AS A PTR MARKER
;^V COMMAND

LOWCAS:	TXNE	FF,ARG		;ARG SEEN?
	JUMPE	B,CLRCAS	;YES, IF 0 CLEAR ALL PREVAILING CASE FLAGS
	TXZ	F2,UCASE	;CLEAR ^W FLAG
	TXO	F2,LCASE	;& SET ^V FLAG
	JRST	RET

;^W COMMAND

STDCAS:	TXNE	FF,ARG		;ARG SEEN?
	JUMPE	B,CLRCAS	;YES, IF 0 CLEAR ALL PREVAILING CASE FLAGS
	TXZ	F2,LCASE	;CLEAR ^V FLAG
	TXOA	F2,UCASE	;& SET ^W FLAG

CLRCAS:	TXZ	F2,LCASE+UCASE	;0^V OR 0^W CLEARS BOTH FLAGS
	JRST	RET

;^X COMMAND

SETMCH:	TXNE	FF,ARG		;ANY ARGUMENT?
	JRST	SETMC1		;YES
	TXNE	FF,PMATCH	;NO, FORCED EXACT MATCH FLAG ON?
	JRST	FFOK		;YES, RETURN -1
	JRST	BEGIN		;NO, RETURN 0

SETMC1:	TXZ	FF,PMATCH	;CLR ^X FLAG
	JUMPE	B,RET		;IF ARG = 0, FLAG = 0
	TXO	FF,PMATCH	;OTHERWISE, SET FLAG
	JRST	RET

;EH COMMAND -- CHANGE ERROR MESSAGE DEFAULT

EH:	$INFO	(EHO,,<"EH" command is obsolete>)
	JRST	RET		;AND THAT IS THE END OF THAT
;E@	READ COMMAND FILE

CMFCMD:	SKIPN	A,CMFLVL	;ALREADY IN A COMMAND FILE?
	JRST	CMFCM3		;NO, FIRST LEVEL
	CAIL	A,CMFMAX	;YES, CAN WE NEST DOWN STILL FURTHER?
	JRST	CMFER1		;NO, ERROR, NESTING LEVEL EXCEEDED
	MOVEI	A,CMFCHN	;YES, CURRENT COMMAND FILE I/O CHANNEL
	DEVCHR	A,		;SEE WHAT IS OUT THERE NOW
	TXNN	A,DV.DSK	;IS IT A DISK?
	JRST	CMFER2		;NO, THEN WE CAN'T DO A LATER USETI
	SKIPN	A,CMFPDP	;GET COMMAND FILE STACK POINTER
	MOVEI	A,CMFPDL	;NONE YET, START AT BEGINING
	HRLI	A,CMFBLK	;BLT POINTER TO "PUSH" CURRENT FILE SPECS
	MOVEI	AA,CMFLEN(A)	;HOW FAR TO COPY TO
	BLT	A,-1(AA)	;"PUSH" CURRENT COMMAND FILE SPECS
	MOVEM	AA,CMFPDP	;SAVE STACK POINTER
	RELEAS	CMFCHN,		;TOSS OUT CURRENT COMMAND FILE

CMFCM3:	MOVEI	B,CMFSWT	;COMMAND FILE SWITCHES
	PUSHJ	P,FILSPC	;GO PARSE COMMAND FILE SPECIFICATION
CMFCM4:	SKIPE	COMEXT		;WAS NON-BLANK EXTENSION TYPED?
	JRST	CMFCM7		;YES
	MOVSI	A,'TEC'		;NO, USE OUR DEFAULT
	MOVEM	A,COMEXT	;SET IN COMXXX BLOCK
	MOVEM	A,XEXT		;AND IN LOOKUP BLOCK TOO
				; THIS DOES PRECLUDE NUL EXTENSIONS ON
				; COMMAND FILES (WHICH IS A BUG) BUT
				; YOU CAN'T WIN EM ALL!
CMFCM7:	MOVE	A,[COMBLK,,CMFBLK]  ;BLT POINTER TO
	BLT	A,CMFBLK+COMBLN-1  ;SAVE COMMAND FILE SPECS
	PUSHJ	P,CMFOPN	;OPEN AND INITIALIZE COMMAND FILE I/O
	AOS	CMFLVL		;NOTE WE ARE NESTED DOWN ANOTHER LEVEL
	SETZM	CMFCTR		;START WITH CHARACTER 0
	SKIPE	A,CMFPDP	;POINTER TO PREVIOUS LEVEL SPECS
	MOVE	A,-<CMFLEN-<CMFSWC-CMFBLK>>(A)  ;GET HIGHER LEVELS' SWITCHES
	IORB	A,CMFSWC	;COMBINE WITH THIS LEVEL'S /ECHO AND /TYO
	TXNE	A,1B0		;/ECHO?
	TDZA	B,B		;YES, ECHO INPUT
	SETO	B,		;NO, DO NOT ECHO INPUT
	MOVEM	B,CMFECH	;SET ECHO CONTROL
	TXNN	A,1B0		;FORCE /TYO IF /ECHO
	TXNE	A,1B1		;/TYO?
	TDZA	B,B		;YES, ALLOW REGULAR PROGRAM OUTPUT
	SETO	B,		;NO, SUPPRESS NORMAL PROGRAM OUTPUT
	MOVEM	B,CMFTYO	;SET OUTPUT CONTROL
	TXO	FF,CFOF		;MARK READING FROM COMMAND FILE
	POPJ	P,		;ALL DONE HERE
;HERE TO SETUP COMMAND FILE I/O

CMFOPN:	MOVEI	A,.IOASC	;ASCII I/O MODE
	DPB	A,[POINTR OPNSTS,IO.MOD]  ;SET IN OPEN BLOCK
	MOVEI	A,CMFIBH	;BUFFER RING HEADER BLOCK
	MOVEM	A,OPNBUF	;SET IN OPEN BLOCK
	OPEN	CMFCHN,OPNBLK	;GET COMMAND FILE DEVICE
	  JRST	CMFER4		;OPEN FAILURE
	MOVEI	A,OPNBLK	;DEVICE BLOCK
	DEVSIZ	A,		;SEE HOW BIG THE BUFFERS ARE
	  MOVEI	A,BLKSIZ+3	;DEFAULT SIZE
	ANDI	A,-1		;JUST THE BLOCK SIZE
	CAILE	A,BLKSIZ+3	;WITHIN TOLERANCES?
	JRST	CMFER5		;NO, BUFFER TOO BIG
	LOOKUP	CMFCHN,XFIBLK	;FIND THE ACTUAL COMMAND FILE
	  JRST	CMFER6		;LOOKUP FAILURE

;GOT THE FILE, SET UP BUFFER RING TO READ IT

	MOVE	A,[BF.VBR+CMFBF1+.BFHDR]  ;INITIAL BUFFER RING POINTER
	MOVEM	A,CMFIBH+.BFADR	;SET UP HEADER BLOCK
	HRLI	A,BLKSIZ+1	;OUR BUFFER SIZE
	MOVEM	A,CMFBF1+.BFHDR	;ONE-BUFFER RING LINKED TO ITSELF
	SETZM	CMFIBH+.BFCTR	;JUST TO MAKE SURE
	POPJ	P,		;ALL SET UP, READY TO READ



;HERE TO SETUP INIT FILE AS A COMMAND FILE

CMFINI:	SETOM	CMFINF		;NOTE CMFINI HAS BEEN CALLED
	SKIPN	A,S.INIT+.FXDEV	;AN INIT FILE SPECIFIED?
	POPJ	P,		;NO, JUST RETURN
	MOVEM	A,COMDEV	;YES, INIT FILE DEVICE
	MOVEI	T,S.INIT+.FXDIR	;DIRECTORY SPEC IN SCAN BLOCK
	MOVE	TT,[-6,,COMPPN]	;COM??? DIRECTORY SPEC
CMFIN2:	MOVE	A,(T)		;GET FIRST/NEXT DIRECTORY WORD
	MOVEM	A,(TT)		;SET IN COM??? BLOCK
	ADDI	T,2		;NEXT ENTRY IN SCAN BLOCK
	AOBJN	TT,CMFIN2	;NEXT ENTRY IN COM??? BLOCK
	MOVE	A,S.INIT+.FXNAM	;INIT FILE NAME
	MOVEM	A,COMNAM	;SET IN COM??? BLOCK
	HLLZ	A,S.INIT+.FXEXT	;INIT FILE EXTENSION
	MOVEM	A,COMEXT	;SET IN COM??? BLOCK
	SETZM	SWITC		;NO ECHO, NO TYPEOUT OF INIT FILE
	PUSHJ	P,FILALT	;SETUP OPEN/LOOKUP/ETC
	PJRST	CMFCM4		;PROCESS COMMAND FILE NORMALLY HEREAFTER
;COMMAND FILE ERROR ROUTINES

;NESTING LEVEL TOO DEEP

CMFER1:	PUSHJ	P,TYICNR	;CLEAR OUT COMMAND FILE STUFF
	$FATAL	(CND,,<Command file nested too deep>)


;TRYING TO NEST AWAY FROM A NON-DISK DEVICE

CMFER2:	PUSHJ	P,TYICNR	;CLEAR OUT COMMAND FILE STUFF
	$FATAL	(PCD,,<Previous command file not a disk>)


;CAN'T OPEN COMMAND FILE DEVICE

CMFER4:	PUSHJ	P,TYICNZ	;CLEAR OUT COMMAND FILE STUFF
	$FATAL	(IDV,,<Input device 04 not available>)


;COMMAND FILE BLOCKSIZE TOO BIG

CMFER5:	PUSHJ	P,TYICNR	;CLEAR OUT COMMAND FILE STUFF
	$FATAL	(CBB,,<Command file block size too big>)


;LOOKUP FAILURE FOR COMMAND FILE

CMFER6:	PUSHJ	P,TYICNR	;CLEAR OUT COMMAND FILE STUFF
	$FATAL (LKP,,<LOOKUP error 03 for 09>)
;COMMAND FILE STORAGE VARIABLES

U CMFBLK,0		;START OF COMMAND FILE BLOCK
U CMFDEV,1		;COMMAND FILE DEVICE,
U CMFNAM,1		; FILE NAME,
U CMFEXT,1		;  EXTENSION,
U CMFPPN,1		;   PROJECT/PROGRAMMER NUMBER,
U CMFSFD,5		;    AND SFD'S.
U CMFSWC,2		;COMMAND FILE SWITCH JUNK

U CMFCTR,1		;CHARACTER POSITION WITHIN FILE
U CMFECH,1		;.NE. 0 THEN DON'T ECHO COMMAND FILE INPUT
U CMFTYO,1		;.NE. 0 THEN SUPPRESS GENERAL PROGRAM OUTPUT.
			; THIS DOES NOT APPLY TO ERROR MESSAGE OUTPUT
			; NOR TO ^ATEXT^A OUTPUT.

	CMFLEN==CMFTYO-CMFBLK+1	;LENGTH OF COMMAND FILE AREA SAVED

U CMFINF,1		;.NE. 0 IF INIT FILE HAS BEEN PROCESSED
U CMFLVL,1		;NESTING LEVEL OF COMMAND FILES
U CMFPDP,1		;PUSHDOWN STACK POINTER TO NESTED COMMAND FILES
U CMFPDL,<CMFLEN*CMFMAX>;STACK AREA FOR NESTED COMMAND FILE SPECS

U CMFIBH,3		;COMMAND FILE BUFFER RING HEADER
U CMFBF1,<BLKSIZ+3>	;COMMAND FILE BUFFER RING
;ER	PREPARE TO READ FILE

ER:	TXZ	FF,FINF+UREAD	;NOT EOF & CLOSE PREVIOUS INPUT
	PUSHJ	P,ZAPIN		;ZAP ANY INPUT FILE
	SETZM	SWITC		;NO FILE SWITCHES TYPED YET
	MOVEI	B,TXTSWT	;TEXT FILE SWITCHES
	PUSHJ	P,FILSPC	;GET FILE SPEC
	PUSHJ	P,RDFIL		;LOOKUP FILE, IF POSSIBLE
	  PUSHJ	P,TYPFFI	;FOUND ON LIBRARY
	TXZ	FF,SEQF		;CLR SEQUENCE NUMBER FLAG
;RDH	TXZE	FF,CCLFLG	;YANK REQUESTED?
;RDH	PUSHJ	P,YANK		;YES, DO IT
	POPJ	P,

U	INDEV,1
U	INBUF,1
U	INCHR,1
U	INPTH,2
U	INPPN,1
U	INSFD,6
U	INNAM,1
U	INEXT,1
U	INSIZ,1			;SIZE OF INPUT FILE (BYTES)
U	INVER,1			;[252] INPUT FILE VERSION
U	INDSZ,2			;INPUT BUFARG AND ADDRESS
;SUBROUTINE TO OPEN THE INPUT DEVICE, SET UP BUFFERS, AND LOOKUP
;THE INPUT FILE. DOES NOT RETURN IF AN OPEN OR LOOKUP FAILURE OCCURS.
;NON-SKIP RETURN IF FILE FOUND IN LIB:, SKIP IF FILE IS OK.

RDFIL:	SETZM	OPNSTS		;ASCII MODE
	MOVEI	E,IBUF
	MOVEM	E,OPNBUF
	MOVE	E,OPNDEV	;PICKUP INPUT DEVICE
	MOVEM	E,INDEV		;SAVE FOR ERRORS
	MOVE	E,OPNCHR	;DEVCHR WORD, TOO
	MOVEM	E,INCHR		;ERROR PROCESSOR NEEDS IT
	OPEN	INCHN,OPNBLK	;OPEN INPUT FILE
	 $FATAL	(IDV,,<Input device 04 not available>)
	SETZM	BICNT		;NO BUFFERED INPUTS YET
	MOVEI	A,OPNBLK	;ADDRESS OF OPEN BLOCK
	DEVSIZ	A,		;ASK MONITOR ABOUT BLOCKSIZE
	 CAIA			;DUH?
	TXNE	E,DV.DSK	;INPUT A DISK?
	MOVE	A,[DSKBFN,,DSKBSZ+3]  ;YES, USE LARGE BUFFERS THEN
	MOVEI	B,IBUF		;INPUT BUFFER RING HEADER
	PUSHJ	P,GETBF		;ALLOCATE AND LINK BUFFER RING
	 $FATAL	(NSI,,<No space for input buffers>)
	DMOVEM	A,INDSZ		;SAVE FOR LATER RECLAIMATION
	MOVE	A,[XNAM,,INNAM]	;COPY INPUT FILE NAME
	BLT	A,INEXT		;FOR ERROR MESSAGES
	MOVE	A,SWITC		;PICKUP USER'S SWITCHES
	TXC	A,GENLSN!SUPLSN	;SEE IF BOTH ARE SET
	TXCN	A,GENLSN!SUPLSN	;ARE THEY?
	 $FATAL	(COS,,<Contradictory switches>)
	MOVEM	A,INSWT		;STORE SETTING FOR INPUT
	TXNN	E,DV.DIR	;LOOKUP UUO NEEDED?
	JRST	RDFIL8		;NO, DON'T DO ONE
	TXNE	E,DV.DTA	;IS IT DECTAPE?
	JRST	RDFIL6		;YES, DO SHORT LOOKUP
	LOOKUP	INCHN,XFILNM	;EXTENDED LOOKUP
	  JRST	LKUPER		;ERROR
	MOVE	A,XSIZ		;SIZE OF FILE IN WORDS
	IMULI	A,5		;A:=SIZE OF FILE IN BYTES
	MOVEM	A,INSIZ		;SAVE FOR EA COMMAND
	MOVE	A,XVER		;[252] INPUT FILE VERSION
	MOVEM	A,INVER		;[252] SAVE IN CASE FAKERW NEEDS IT
	TXO	FF,UREAD	;INPUT FILE NOW OPEN
	SKIPE	XSIZ		;ANYTHING IN THE FILE?
	SKIPG	S.EAMO		;USER WANT WHOLE FILE DUMPED IN?
	JRST	RDFIL3		;NO TO EITHER, NORMAL YANK-IT-IN MODE
	PUSHJ	P,EAFIL		;YES

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

RDFIL3:	MOVEI	E,INCHN		;INPUT CHANNEL
	MOVEM	E,PTHBLK	;PUT INTO PATH BLOCK
	MOVE	E,[PTHLEN,,PTHBLK]  ;DO PATH UUO
	PATH.	E,		;TO DETERMINE WHERE FILE WAS FOUND
	  JRST	CPOPJ1		;PROBABLY A TTY: OR TSK:
	MOVE	E,[PTHPPN,,INPPN]  ;COPY PATH TO FILE
	BLT	E,INSFD+5	;FOR ERROR MESSAGE PROCESSOR
	PUSHJ	P,CHKPTH	;WAS IT FOUND WHERE SAID IT WAS?
	  POPJ	P,		;NO, NON-SKIP RETURN
	JRST	CPOPJ1		;YES, ALL IS WELL
RDFIL6:	LOOKUP	INCHN,SFILNM	;SHORT LOOKUP
	  JRST	LKUPER		;LOOKUP FAILURE
RDFIL8:	TXO	FF,UREAD	;INPUT FILE NOW OPEN
	AOS	(P)		;DECTAPES DON'T HAVE LIB'S
	POPJ	P,		;RETURN
EBAKUP:
EB:	TXNE	FF,UBAK		;IS EB ALREADY IN PROGRESS?
	$FATAL	(EBO,,<E00 Before Current EB Job Closed>)
	TXZ	FF,UBAK!UREAD!FINF  ;INPUT FILE CLOSED
	PUSHJ	P,ZAPIN		;ZAP ANY INPUT FILE
	PUSHJ	P,EF		;CLOSE OUTPUT FILE IF ANY
	SETZM	SWITC		;NO I/O SWITCHES TYPED YET
	MOVEI	B,TXTSWT	;TEXT FILE SWITCHES
	PUSHJ	P,FILSPC	;PARSE USER'S FILE SPEC
	MOVE	E,SWITC		;GET SWITCHES USER TYPED
	TXC	E,GENLSN!SUPLSN	;CHECK FOR CONFLICTING SWITCHES
	TXCN	E,GENLSN!SUPLSN	;DID HE GIVE BOTH?
	 $FATAL	(COS,,<Contradictory switches>)
	MOVEM	E,INSWT		;NO, STORE BOTH AS INPUT...
	MOVEM	E,OUTSWT	;AND AS OUTPUT SWITCHES
	MOVE	E,[<"00000">B34+1] ;SETUP INITIAL LSN
	MOVEM	E,LSNCTR	;FOR OUTPUT FILE
	SKIPE	E,OPNCHR	;GET CHARACTERISTICS OF HIS DEVICE
	TXNE	E,DV.DSK!DV.DTA	;IF DEVICE EXISTS BUT ISN'T RIGHT
	CAIA			;DOESN'T EXIST (GET BETTER MESSAGE
				;WHEN OPEN FAILS) OR IS OK
	$FATAL	(EBD,,<EB with device 04 is illegal>)
	HLRZ	A,XEXT		;GET PROPOSED EXTENSION
	TLC	E,-1-<(DV.TTA)>	;CONTRARY TO POPULAR BELIEF,
	TLCE	E,-1-<(DV.TTA)>	;NUL: DOESN'T PROHIBIT UFD/SFD!
	TXNN	E,DV.DSK	;IS EB DEVICE A DISK?
	JRST	EBAKU0		;NO, DIRECTORY NAMES LEGAL
	CAIE	A,'SFD'		;CAN'T DO EB TO DIRECTORIES,
	CAIN	A,'UFD'		;  SINCE RENAMES WOULD FAIL AT EF
	$FATAL	(EBF,,<EB with illegal file 02>)
EBAKU0:	CAIN	A,'BAK'		;IS IT BAK?
	$FATAL	(EBF,,<EB with illegal file 02>)
	CAIE	A,'TMP'		;USER'S EXTENSION .TMP?
	JRST	EBAKU1		;NO, FILENAME IS OK TO USE
	MOVE	A,XNAM		;CAN'T ALLOW NNNTEC.TMP,
	CAMN	A,TMPTEC	;SINCE THAT'S OUR TEMP OUTPUT FILE
	$FATAL	(EBF,,<EB with illegal file 02>)
EBAKU1:	PUSHJ	P,RDFIL		;OPEN DEVICE & LOOKUP FILE
	  JRST	FAKERW		;ON LIB:, CAN'T DO EB, DO ER/EW
	SETZM	PTHBLK		;CLEAR RETURNED JUNK
	SETZM	PTHFLG		; IN CASE MONITOR LOOKS AT IT
	MOVE	E,OPNCHR	;GET DEVCHR OF EB DEVICE
	MOVEM	E,EBCHR		;STORE FOR BAKCLS
	SETZM	OPNSTS		;ASCII MODE FOR OPNOU
	MOVE	E,[XNAM,,EBNAM]	;SAVE EB FILE & EXT FOR BAKCLS
	BLT	E,EBEXT		;..
	MOVE	E,[PTHPPN,,EBPPN]  ;SAVE EB PATH TOO
	BLT	E,EBSFD+4	;..
	MOVE	E,OPNCHR	;GET EB DEVICE
	TXNN	E,DV.DSK	;IS IT A DSK: ?
	JRST	EBAKU4		;NO, DON'T BOTHER WITH PROTECTIONS

;FALL THROUGH TO NEXT PAGE
;HERE IF EB TO A DISK. CHECK THAT THE INPUT FILE ISN'T TOO PROTECTED TO
;ALLOW ALL THE RENAMES TO HAPPEN AT END OF EDITING. NOTE THAT OTHER
;PROTECTION FAILURES CAN OCCUR (.BAK FILE PROTECTED ETC.), BUT WE ARE
;ONLY CHECKING THIS CASE BECAUSE IT IS BY FAR THE MOST COMMON ERROR.
;WE WILL ALLOW AN EB IF 1) WE ARE THE OWNER OF THE FILE (HAVE CHANGE
;PROTECTION RIGHTS) AND CAN WRITE THE FILE (PROTECTION 0,1, OR 2 IN
;5.07) (NOTE THAT WE COULD ALWAYS EDIT A <777> FILE IN THE USER'S AREA
;WITH ENOUGH RENAMES TO CHANGE THE PROTECTION, BUT WE WILL ARBITRARILY
;DISALLOW EDITING IF THE USER CAN'T EVEN WRITE THE FILE WITHOUT CHANGING
;ITS PROTECTION) OR 2) WE HAVE RENAME ACCESS TO THE FILE (PROTECTED 0
;OR 1 IN 5.07).

	LDB	A,[POINT 9,XPRV,8]  ;PICKUP FILE PROTECTION
	MOVEM	A,EBPROT	;SAVE FOR BAKCLS
	HRLI	A,.ACREN	;CHECK NEEDED RENAME ACCESS
	MOVE	AA,PTHPPN	;FILE'S PPN IN LOC + 1
	MOVE	B,.MYPPN##	;USER'S IN LOC + 2
	MOVEI	E,A		;POINT TO 3 CONTIGUOUS ACS
	CHKACC	E,		;SEE IF WE CAN RENAME IT
	  SETZ	E,		;DON'T KNOW, ASSUME OK
	JUMPE	E,EBAKU3	;IF CHKACC WON, GO EDIT FILE

;HERE IF WE CAN'T RENAME THE FILE. CAN STILL EDIT IT IF WE CAN BOTH
;CHANGE THE PROTECTION & WRITE THE FILE. OTHERWISE, GIVE AN ERROR.

	HRROS	EBPROT		;SET LH=-1 AS FLAG FOR BAKCLS
				;THAT 2 RENAMES WILL BE NEEDED
	HRLI	A,.ACCPR	;CHECK .ACCPR TO SEE IF WE OWN IT
	MOVEI	E,A		;POINT TO THE ARG BLOCK
	CHKACC	E,		;CHECK IF WE CAN CHANGE PROTECTION
	  SETZ	E,		;PATH UUO BUT NO CHKACC?
	JUMPE	E,EBAKU2	;OK, NOW CHECK WRITE ACCESS
	$FATAL	(EBP,,<EB illegal because of file 02 protection>)

EBAKU2:	HRLI	A,.ACWRI	;WE OWN IT, BUT CAN WE WRITE IT?
	MOVEI	E,A		;(MIGHT BE <555>)
	CHKACC	E,		;ASK FILSER
	  SETZ	E,		;NEVER BOMB USER HERE
	JUMPE	E,EBAKU3	;OK, GO EDIT IT
	$FATAL	(EBP,,<EB illegal because of file 02 protection>)
;HERE IF OK TO EDIT A DISK FILE. SETUP THE PROPER STRUCTURE FROM
;THE INPUT CHANNEL SO THAT THE NEW FILE WILL BE ON THE SAME STR.

EBAKU3:	MOVE	E,XDEV		;GET REAL INPUT FILE UNIT
	MOVEM	E,DCBLK		;STORE FOR DSKCHR
	MOVE	E,[DCLEN,,DCBLK];DO DSKCHR TO GET STR
	DSKCHR	E,		; THAT FILE WAS FOUND ON
	  JRST	EBAKU4		;FAILED, USE WHAT WE HAVE
	MOVE	E,DCSNM		;OK, PICKUP STR NAME
	MOVEM	E,OPNDEV	;STORE IN NEW OPEN BLOCK
	MOVX	E,UU.PHS	;USE PHYSICAL ONLY OPEN
	MOVEM	E,OPNSTS	;SINCE WE HAVE PHYSICAL STR NAME

;ENTER HERE IF GOING TO A DECTAPE.

EBAKU4:	MOVE	E,[OPNBLK,,EBSTS]  ;SAVE STS & DEV FOR BAKCLS
	BLT	E,EBDEV		;..
	PUSHJ	P,OPNOU		;OPEN EB DEVICE
	MOVE	E,[-XFILEN+1,,XFILNM]  ;PDL TO LOOKUP BLOCK
	PUSHJ	P,STOMP		;PUT THE RIGHT THING IN .RBPPN
	PUSH	E,TMPTEC	;FILE NAME IS NNNTEC
	PUSH	E,['TMP   ']	;EXTENSION IS TMP (WIPE DATES)
	MOVX	E,<777>B8	;CLEAR ALL DATES FOR ENTER
	ANDM	E,XPRV		; BUT KEEP ORIGINAL PROTECTION
	MOVX	E,<100>B8	;GET LOWEST NON-ZERO PROTECTION
	SKIPN	XPRV		;IF EDITING A <000> FILE,
	MOVEM	E,XPRV		;  DO ENTER WITH <100> SO WON'T
				;  GET SYSTEM DEFAULT PROTECTION
;[252]	SETZM	XVER		;EDITING CHANGES FILE VERSIONS!
	MOVE	E,XSIZ		;NOW SETUP OUTPUT ESTIMATE
	ADDI	E,777		;ROUND UP INPUT + 2 RIBS + 1
	LSH	E,-7		;CONVERT TO BLOCKS
	MOVEM	E,XEST		;STORE FOR OUTPUT ENTER
	SETZM	XALC		;NO NEED FOR CONTIGUITY
	SETZM	XPOS		;CERTAINLY NO SPECIFIC PLACE!
	PUSHJ	P,WTFIL		;DO ENTER ON .TMP FILE
	TXO	FF,UWRITE+UBAK	;IT ALL WORKED! TURN ON FLAGS
EBAKU5:
;RDH	TXZE	FF,CCLFLG	;CALLED FROM TECO COMMAND?
;RDH	PUSHJ	P,YANK		;YES, DO A Y
	POPJ	P,		;DONE
;HERE IF THE EB FILE WAS FOUND ON SOME LIBRARY AREA. TURN THE EB
;INTO AN ER/EW, SO THAT THE FILE ON THE LIBRARY WON'T BE MODIFIED.

FAKERW:	PUSHJ	P,TYPFFI	;TELL WHAT WE'RE DOING
	PUSHJ	P,FILALT	;PUT OUTPUT FILE EXACTLY WHERE
	SETZM	OPNSTS		; THE USER SPECIFIED. ITS KNOWN
				; NOT TO EXIST, SINCE A LOOKUP
				; FOUND IT ONLY ON LIB
	MOVE	A,INVER		;[252] GET INPUT FILE'S VERSION
	MOVEM	A,XVER		;[252] PRESERVE IT ACROSS THE "EB" COMMAND
	PUSHJ	P,OPNOU		;[252] OPEN/INITIALIZE OUTPUT CHANNEL
	PUSHJ	P,WTFIL		;[252] AND CREATE THE NEW OUTPUT FILE
	TXO	FF,UWRITE	;EW SUCCESSFULLY INITIATED
	PJRST	EBAKU5		;DO A Y IF FROM A TECO COMMAND


U TMPTEC,1			;SAVE FOR ###TEC. FILE NAME
U FDAEM,1			;NON-ZERO MEANS FTFDAE ON IN MON.
U EBSTS,1			;SAVED MODE FOR EB DEVICE
	EBOPN==EBSTS		;ALTERNATE NAME
U EBDEV,1			;DEVICE FOR EB
U EBBUF,1			;BUFFER ADDR (NOT USED)
U EBCHR,1			;EB DEVICE DEVCHR
U EBPTH,2			;PATH BLOCK HEADER (NOT USED)
U EBPPN,1			;PPN THAT EB FILE CAME FROM
U EBSFD,5			;SFD'S IN EB FILE'S PATH
U EBNAM,1			;EB FILE NAME
U EBEXT,1			;EB EXTENSION
U EBPROT,1			;LH=-1 IF EDITING OWNER'S <2XX>
				; FILE, RH=ORIGINAL FILE'S PROT
;INPUT FILE LOOKUP ERROR

LKUPER:	PUSHJ	P,ZAPIN		;ZAP THE INPUT CHANNEL
	TXZ	FF,UREAD+FINF	;LET GO OF INPUT DEVICE
	$FATAL (LKP,,<LOOKUP error 03 for 09>)

;TYPE OUTPUT ERROR

ENTERR:	PUSHJ	P,ZAPOU		;ZAP THE OUTPUT FILE
	TXZ	FF,UWRITE+UBAK	;LET GO OF OUTPUT DEVICE & EB FLAG
	LDB	E,[POINT 15,XEXT,35]  ;ERROR CODE
	CAIE	E,ERPRT%	;MAYBE DTA FULL?
	JRST	ENTER2		;NO
	MOVE	A,OUCHR		;YES
	TXNE	A,DV.DTA	;IF DTA ITS FULL, ELSE ENTER ERROR
	$FATAL	(FUL,,<Device 04: directory full>)
ENTER2:	$FATAL	(ENT,,<ENTER error 03 for 01>)
;EZ	SELECTS THE OUTPUT DEVICE, ISSUES A REWIND COMMAND TO IT,
;	ISSUES A COMMAND TO ZERO ITS DIRECTORY, AND OPENS THE FILE
;	SPECIFIED (IF ANY).

;EW	SELECTS THE OUTPUT DEVICE AND OPENS THE FILE SPECIFIED (IF ANY)

EZ:	TXOA	FF,EZTMP	;FLAG EZ COMMAND, NOT EW
EW:	TXZ	FF,EZTMP	;THIS IS A REAL EW COMMAND
	TXNE	FF,UBAK		;EB IN PROGRESS?
	$FATAL	(EBO,,<E00 Before Current EB Job Closed>)
	PUSHJ	P,EF		;GIVE HIM A FREE EF ON OLD FILE
	SETZM	SWITC		;NO I/O SWITCHES TYPED YET
	MOVEI	B,TXTSWT	;TEXT FILE SWITCHES
	PUSHJ	P,FILSPC	;PARSE NEW FILE SPEC, SET UP X???
	MOVE	E,SWITC		;GET SWITCHES HE TYPED
	TXC	E,GENLSN+SUPLSN	;CHECK FOR BOTH BEING ON
	TXCN	E,GENLSN+SUPLSN	;WITH TRIED & TRUE TXC, TXCN TRICK
	 $FATAL	(COS,,<Contradictory switches>)
	MOVEM	E,OUTSWT	;OK, STORE WHAT HE TYPED
	MOVE	E,[<"00000">B34+1]  ;SETUP INITIAL LSN
	MOVEM	E,LSNCTR	;FOR OUTPUT FILE
	SETZM	OPNSTS		;ASCII MODE
	PUSHJ	P,OPNOU		;OPEN OUTPUT DEVICE, SETUP BUFFERS
	TXZN	FF,EZTMP	;WAS THIS AN EZ COMMAND?
	JRST	OPNWR0		;NO, CONTINUE
	UTPCLR	OUTCHN,		;YES, ZERO DIRECTORY
	MTREW.	OUTCHN,		;AND REWIND THE "DECTAPE"
	MTWAT.	OUTCHN,		;WAIT FOR IT IN CASE MTA
OPNWR0:	MOVEI	E,OUTCHN	;LOAD E WITH THE OUTPUT CHANNEL
	DEVNAM	E,		;FIND OUT THE "REAL" DEVICE NAME
	  JFCL			;WELL, WE LOSE.
	CAME	E,[SIXBIT/NUL/]	;IS IT NUL:?
	JRST	OPNWRA		;NO - CONTINUE.
	$WARN	(OTN,,<Output is to NUL:>)

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

OPNWRA:	MOVE	E,OPNCHR	;DEVCHR OF DEVICE WE JUST OPENED
	TXNN	E,DV.DIR	;A DIRECTORY DEVICE?
	JRST	OPNWR3		;NO, CAN'T SUPERSEDE EXISTING FILE
	TLC	E,-1-<(DV.TTA)>	;CAN NEVER SUPERCEDE
	TLCN	E,-1-<(DV.TTA)>	; ON DEVICE NUL:
	JRST	OPNWR3		;YUP, IT'S NUL:. DON'T CHECK.
	TXNE	E,DV.DTA	;IF A DECTAPE..
	JRST	OPNWR1		;MUST GO DO SHORT LOOKUP
	LOOKUP	OUTCHN,XFILNM	;SEE IF HE'S GOING TO SUPERSEDE
	  JRST	OPNWR3		;NOT A CHANCE
	MOVEI	E,OUTCHN	;MAYBE, SEE IF THE FILE
	MOVEM	E,PTHBLK	;IS REALLY WHERE HE SAID IT WAS
	MOVE	E,[PTHLEN,,PTHBLK]  ;OR ON SOME LIB
	PATH.	E,		;BY DOING A PATH UUO & COMPARING
	  JRST	OPNWR3		;?? OH WELL, MESSAGE NOT CRITICAL
	PUSHJ	P,CHKPTH	;COMPARE FOUND WITH SOUGHT
	  JRST	OPNWR3		;FOUND IN A LIB, IGNORE IT
	JRST	OPNWR2		;WILL SUPERSEDE, WARN USER

;HERE IF WRITING TO A DECTAPE

OPNWR1:	LOOKUP	OUTCHN,SFILNM	;DO SHORT LOOKUP
	  JRST	OPNWR3		;NOT THERE
OPNWR2:	$WARN	(SEF,,<Superseding existing file>)
OPNWR3:	CLOSE	OUTCHN,		;WE DON'T WANT UPDATE MODE (!!)
	PUSHJ	P,FILALT	;RE-SET UP THE ENTER BLOCK
	PUSHJ	P,WTFIL		;DO ENTER ON OUTPUT FILE
	TXO	FF,UWRITE	;OUTPUT FILE NOW OPEN
	POPJ	P,		;DONE
;SUBROUTINE TO OPEN THE OUTPUT DEVICE AND SETUP THE OUTPUT BUFFERS
;USES E,T

OPNOU:	MOVSI	E,OBUF		;SETUP ADDR OF OUTPUT HEADER
	MOVEM	E,OPNBUF	;IN OPEN BLOCK
	OPEN	OUTCHN,OPNBLK	;FIND THE DEVICE
	 $FATAL	(ODV,,<Output device 04 not available>)
	SETZM	BOCNT		;NO BUFFERED OUTPUTS YET
	MOVE	E,OPNDEV	;GET DEVICE WE JUST OPENED
	MOVEM	E,OUDEV		;SAVE FOR ERRORS
	MOVE	E,OPNCHR	;NEED DEVCHR, TOO
	MOVEM	E,OUCHR		;(SEE ENTERR)
	MOVEI	A,OPNBLK	;ADDRESS OF OPEN BLOCK
	DEVSIZ	A,		;ASK MONITOR FOR BUFFER SIZE
	  CAIA			;DUH?
	TXNE	E,DV.DSK	;A DISK OUTPUT DEVICE?
	MOVE	A,[DSKBFN,,DSKBSZ+3]  ;YES, USE OUR OWN DEVSIZ THEN
	MOVEI	B,OBUF		;OUTPUT BUFER RING HEADER
	PUSHJ	P,GETBF		;ALLOCATE AND INITIALIZE BUFFER RING
	 $FATAL	(NOS,,<No space for output buffers>)
	DMOVEM	A,OUDSZ		;REMEMBER FOR LATER RECLAIMATION
	POPJ	P,		;DONE
;SUBROUTINE TO ENTER OUTPUT FILE. DOES SHORT ENTER IF DTA. USES E.

WTFIL:	MOVE	E,[XNAM,,OUNAM]	;SAVE FILENAME & EXTENSION
	BLT	E,OUEXT		;FOR PRETTY ERROR MESSAGES
	MOVE	E,OPNCHR	;SHORT ENTER IF DTA
	TXNE	E,DV.DTA	;IS IT?
	JRST	WTFIL1		;YES
	MOVE	T,Z		;NO, DISK. END CHARACTER ADDRESS
	SUB	T,BEG		;STARTING CHARACTER ADDRESS
	ADD	T,INSIZ		;PLUS ANY WE KNOW TO BE LEFT IN INPUT FILE
	IDIVI	T,5*^D128	;T:=ESTIMATED BLOCKSIZE OF OUTPUT FILE
	ADDI	T,20		;PLUS A LITTLE FOR EXPANSION
	MOVEM	T,XEST		;TELL MONITOR OUR GUESS
	ENTER	OUTCHN,XFILNM	;DO EXTENDED ENTER
	  JRST	ENTERR		;WARN OF FAILURE
	MOVEI	E,OUTCHN	;DETERMINE PATH TO FILE CREATED
	MOVEM	E,PTHBLK	;BY DOING PATH UUO ON CHANNEL
	MOVE	E,[10,,PTHBLK]	;POINT TO PATH BLOCK
	PATH.	E,		;READ THE PATH TO THE FILE
	 POPJ	P,		;NOT A DIRECTORY DEVICE
	MOVE	E,[PTHPPN,,OUPPN]  ;NOW SAVE PATH AWAY
	BLT	E,OUPPN+5	;IN CASE OF OUTPUT ERRORS
	POPJ	P,		;SUCCESS

;HERE IF DTA

WTFIL1:	ENTER	OUTCHN,SFILNM	;SHORT ENTER FOR DTA
	  JRST	ENTERR		;FULL?
	POPJ	P,		;OK, RETURN



U	OUDEV,1
U	OUBUF,1
U	OUCHR,1
U	OUPTH,2
U	OUPPN,1
U	OUSFD,6
U	OUNAM,1
U	OUEXT,1
U	OUDSZ,2			;OUTPUT BUFARG AND ADDRESS WORDS
;EF	FINISHES OUTPUT ON THE CURRENT OUTPUT FILE WITHOUT
;	SELECTING A NEW OUTPUT FILE.

EF:	PUSHJ	P,TEBURB	;FORCE UPDATE OF RECOVERY FILE NOW
	TXNN	FF,UWRITE	;..
	POPJ	P,
	CLOSE	OUTCHN,		;CLOSE OUTPUT COMPLETELY
	STATZ	OUTCHN,IO.ERR	;ANY LAST MOMENT ERRORS?
	JRST	OUTERR
	TXZ	FF,UWRITE	;CLEAR NOW IN CASE ERROR IN BAKCLS
	TXNE	FF,UBAK		;EB IN PROGRESS?
	PUSHJ	P,BAKCLS	;YES
	TXZ	FF,UBAK		;CLEAR WRITE AND EB FLAGS
	PJRST	ZAPOU		;ZAP THE OUTPUT CHANNEL NOW



;EK	KILL (ABORT) OUTPUT FILE

EK:	MOVEI	A,OUTCHN	;OUTPUT FILE CHANNEL
	RESDV.	A,		;STOMP IT DEAD
	 JFCL			;HO HUM
	TXZ	FF,UWRITE!UBAK	;NO FILE FOR OUTPUT ANYMORE
	PJRST	ZAPOU		;RECLAIM BUFFERS ETC.



;EM	EXECUTE MTAPE UUO.

EM:	TXNN	FF,UREAD
	 $FATAL	(EMD,,<EM with no input device open>)
	PUSHJ	P,CHK2
	CAIGE	B,1
	 $FATAL	(EMA,,<EM With Illegal Argument 06>)
	WAIT	INCHN,		;WAIT FOR BUFFERS TO FILL
	MTAPE	INCHN,0(B)
	HRRZ	A,IBUF+.BFADR	;GET ADDR OF FIRST BUFFER
	MOVE	E,A		;COPY TO TEMP AC
	MOVX	T,BF.IOU	;GET "BUFFER IN USE" BIT
EMTAP1:	ANDCAM	T,.BFHDR(E)	;CLEAR IT IN CURRENT BUFFER
	HRRZ	E,.BFHDR(E)	;PICKUP ADDRESS OF NEXT
	CAME	E,A		;DONE WITH ALL BUFFERS IN RING?
	JRST	EMTAP1		;NO, LOOP
	SETOM	IBUF+.BFCTR	;INSURE NEXT IN GETS NEW RECORD
	MTWAT.	INCHN,		;MAKE SURE SPACING COMPLETES
	POPJ	P,		;END OF COMMAND
;THIS ROUTINE IS CALLED AT EF IF AN EB WAS DONE. IT DOES
;THE WORK OF MAKING THE INPUT FILE HAVE THE EXTENSION .BAK ,
;DELETING ANY PREVIOUS FILE.BAK, AND RENAMING THE NEW OUTPUT
;FILE AS THE ORIGINAL FILE.EXT

BAKCLS:	TXZ	FF,UREAD+FINF	;AN EB EF WIPES INPUT CHANNEL, TOO
	PUSHJ	P,ZAPIN		;ZAP ANY INPUT FILE
	MOVE	E,[EBOPN,,OPNBLK]  ;RETRIEVE EB DEVICE
	BLT	E,OPNDEV	;FROM EB SAVE AREA
	SETZM	OPNBUF		;NO BUFFERS NEEDED FOR RENAMES
	OPEN	INCHN,OPNBLK	;RE-GRAB DEVICE
	 $FATAL	(IRN,,<Cannot re-init device 04 for rename process>)
	SETZM	XFILNM		;SETUP LOOKUP BLOCK
	MOVE	E,[XFILNM,,XFILNM+1]  ; TO DELETE OLD BAK FILE
	BLT	E,XFILNM+XFILEN-1  ;FIRST, BLT TO ZERO
	MOVE	E,[-XFILEN,,XFILNM-1]  ;SET UP PDL TO XFILNM
	PUSH	E,[XFILEN-1]	;SETUP LENGTH OF BLOCK
	PUSHJ	P,STOMP		;PUT THE RIGHT THING IN .RBPPN
	PUSH	E,EBNAM		;SET .RBNAM TO ORIG FILE NAME
	PUSH	E,['BAK   ']	;EXTENSION IS BAK
	MOVE	E,EBCHR		;GET EB DEV CHARACTERISTICS
	TXNE	E,DV.DTA	;IS IT A DECTAPE?
	JRST	BKCLS2		;YES, GO DO DTA'ISH THINGS
	SETZM	PTHBLK		;NO, CLEAR OUT PATH BLOCK
	SETZM	PTHFLG		;SINCE MONITOR LOOKS AT FLAGS
	MOVE	E,[EBPPN,,PTHPPN]  ;RESTORE PATH FROM EB SAVE
	BLT	E,PTHBLK+PTHLEN-2  ;EBPPN IS ONLY 5 WORDS
	SETZM	PTHBLK+PTHLEN-1	;PTHBLK HAS XTRA 0 ON END
	HRRZ	B,EBPROT	;SETUP AC B TO BE PROTECTION THAT
	ANDCMI	B,300		;  WE WILL GIVE .BAK FILE IF NONE
	SKIPN	FDAEM		;  NOW EXISTS
	ANDCMI	B,400		;  (I.E <0XX> OR <4XX> IF FDAEM)
	LOOKUP	INCHN,XFILNM	;FIND OLD .BAK FILE
	  JRST	BKCLS3		;NONE THERE, GO MAKE ONE
	LDB	B,[POINT 9,XPRV,8]  ;MAKE NEW .BAK HAVE SAME
				;PROTECTION AS OLD ONE DID
	SETZM	XNAM		;DELETE OLD .BAK FILE
	RENAME	INCHN,XFILNM	;BY RENAMING TO 0 . . .
	 $FATAL	(BAK,,<Cannot delete old backup file>)
	JRST	BKCLS3		;OK, GO RENAME SOURCE TO BAK

;HERE IF OLD BAK FILE SOUGHT ON A DECTAPE. USE SHORT LOOKUP/RENAME

BKCLS2:	LOOKUP	INCHN,SFILNM	;LOOK FOR THE FILE
	  JRST	BKCLS3		;NONE, DON'T SWEAT IT
	SETZM	XNAM		;DELETE BY RENAMING TO ZERO
	RENAME	INCHN,SFILNM	;..
	 $FATAL	(BAK,,<Cannot delete old backup file>)
;HERE TO RENAME THE OLD SOURCE FILE TO FILE.BAK

BKCLS3:	MOVE	E,[-XFILEN+1,,XFILNM]	;RESET THINGS TO EB FILE
	PUSHJ	P,STOMP		;LAST LOOKUP MIGHT HAVE WIPED PPN
	PUSH	E,EBNAM		;WE WIPED XNAM
	PUSH	E,EBEXT		;EXTENSION DEFINITELY ISN'T BAK
	MOVE	E,EBCHR		;GET ORIGINAL EB DEVICE DEVCHR
	TXNE	E,DV.DTA	;DECTAPE?
	JRST	BKCLS5		;YES, DO SHORT LOOKUP/RENAME
	SETZM	PTHBLK		;NO, MAKE SURE PTHBLK SETUP RIGHT
	SETZM	PTHFLG		;MONITOR RETURNS STUFF ON LOOKUP
	LOOKUP	INCHN,XFILNM	;FIND ORIGINAL SOURCE FILE
	 $FATAL	(ILR,,<Cannot Lookup input file 10 to rename it>)
	SKIPL	EBPROT		;NEED TO LOWER PROTECTION?
	JRST	BKCLS4		;NO, JUST RENAME IT TO .BAK
	MOVX	E,<300>B8	;CLEAR THESE BITS
	ANDCAM	E,XPRV		;TO MAKE PROTECTION REASONABLE
	RENAME	INCHN,XFILNM	;DOWN GOES THE PROTECTION
	 $FATAL	(IRB,,<Cannot Rename input file 10 to 08.BAK>)
BKCLS4:	MOVE	A,XEXT		;SAVE DATES FOR ERROR RECOVERY
	MOVSI	E,'BAK'		;NEW FILE NAME IS FILE.BAK
	HLLM	E,XEXT		;KEEP SAME DATES ETC.
	DPB	B,[POINT 9,XPRV,8]  ;STORE BAK FILE PROTECTION
	RENAME	INCHN,XFILNM	;MAKE OLD SOURCE INTO BAK
	  CAIA			;TRY TO RECOVER
	JRST	BKCLS6		;NOW GO MAKE .TMP FILE NEW SOURCE

;HERE IF RENAMING THE OLD SOURCE FILE TO FILE.BAK WITH A LOWER
;PROTECTION FAILED. IT COULD BE THAT THE FILE IS PROTECTED RENAME
;BUT NO CHANGE PROTECTION AGAINST US. IF THIS IS THE CASE, WE WILL
;GO AHEAD AND CHANGE THE EXTENSION TO BAK, BUT LEAVE THE PROTECTION
;ALONE.
	LDB	E,[POINT 15,XEXT,35]  ;PICKUP RENAME ERROR CODE
	CAIE	E,ERPRT%	;PROTECTION FAILURE?
	 $FATAL	(IRB,,<Cannot Rename input file 10 to 08.BAK>)
	MOVEM	A,XEXT		;YES, RESTORE DATES WIPED BY ERROR
	LOOKUP	INCHN,XFILNM	;LOOKUP OLD SOURCE AGAIN
	 $FATAL	(ILR,,<Cannot Lookup input file 10 to rename it>)
	MOVSI	E,'BAK'		;NEW EXTENSION
	HLLM	E,XEXT		;CHANGE ONLY EXTENSION
	RENAME	INCHN,XFILNM	;TRY IT AGAIN
	 $FATAL	(IRB,,<Cannot Rename input file 10 to 08.BAK>)
	JRST	BKCLS6		;WON, GO MAKE .TMP NEW SOURCE
;HERE TO MAKE FILE.SRC BE FILE.BAK IF ON A DTA

BKCLS5:	LOOKUP	INCHN,SFILNM	;FIND OLD SOURCE FILE
	 $FATAL	(ILR,,<Cannot Lookup input file 10 to rename it>)
	MOVSI	E,'BAK'		;NEW EXTENSION IS .BAK
	HLLM	E,XEXT		;KEEP DATES ETC.
	RENAME	INCHN,SFILNM	;CHANGE NAME TO FILE.BAK
	 $FATAL	(IRB,,<Cannot Rename input file 10 to 08.BAK>)

;HERE TO FIND OUTPUT NNNTEC.TMP FILE, AND RENAME IT TO NEW SOURCE FILE.

BKCLS6:	PUSHJ	P,ZAPIN		;MAKE SURE INPUT DEVICE FINISHED
	SETZM	XFILNM		;CAN'T BE TOO CAREFUL
	MOVE	E,[XFILNM,,XFILNM+1]  ;SO BLT LOOKUP BLOCK TO 0
	BLT	E,XFILNM+XFILEN-1  ;..
	MOVE	E,[-XFILEN,,XFILNM-1]  ;SETUP PDL TO LOOKUP BLOCK
	PUSH	E,[XFILEN-1]	;RESET LENGTH WORD
	PUSHJ	P,STOMP		;RESET .RBPPN
	PUSH	E,TMPTEC	;SET .RBNAM TO NNNTEC
	PUSH	E,['TMP   ']	;EXTENSION IS TMP
	MOVE	E,EBCHR		;DEVCHR OF EB DEVICE
	TXNE	E,DV.DTA	;DECTAPE?
	JRST	BKCLS8		;YES, DO SHORT LOOKUPS
	SETZM	PTHBLK		;ZAP BITS MONITOR RETURNS
	SETZM	PTHFLG		;ON LOOKUPS OR RENAMES
	LOOKUP	OUTCHN,XFILNM	;FIND THE .TMP FILE
	 $FATAL	(OLR,,<Cannot Lookup output file 02 to rename it>)
	SKIPL	EBPROT		;NEED TO LOWER PROTECTION?
	JRST	BKCLS7		;NO, GO CHANGE NAME
	SKIPN	FDAEM		;FILE DAEMON MONITOR?
	SKIPA	A,[POINT 3,XPRV,2]  ;NO, OWNER FIELD 3 BITS
	MOVE	A,[POINT 2,XPRV,2]  ;YES, ONLY 2 BITS
	SETZ	E,		;LOWEST POSSIBLE PROTECTION
	DPB	E,A		;STORE IN OWNER FIELD
	RENAME	OUTCHN,XFILNM	;LOWER PROTECTION OF FILE
	 $FATAL	(RNO,,<Cannot Rename output file 01>)
BKCLS7:	MOVE	E,EBNAM		;GET SOURCE FILE NAME
	MOVEM	E,XNAM		;STORE FOR RENAME
	MOVE	E,EBEXT		;GET SOURCE EXTENSION
	HLLM	E,XEXT		;STORE WITHOUT TOUCHING DATES
	MOVE	E,EBPROT	;MAKE PROTECTION SAME AS OLD
	DPB	E,[POINT 9,XPRV,8]  ;..
	RENAME	OUTCHN,XFILNM	;TURN TMP FILE INTO NEW SOURCE
	 $FATAL	(RNO,,<Cannot Rename output file 01>)
	POPJ	P,		;ALL DONE
;HERE TO RENAME TMP FILE TO NEW SOURCE FILE ON A DTA

BKCLS8:	LOOKUP	OUTCHN,SFILNM	;DO SHORT LOOKUP TO FIND FILE
	 $FATAL	(OLR,,<Cannot Lookup output file 02 to rename it>)
	MOVE	E,EBNAM		;GET SOURCE FILE NAME
	MOVEM	E,XNAM		;STORE FOR RENAME
	MOVE	E,EBEXT		;PICKUP EB EXTENSION
	HLLM	E,XEXT		;STORE WITHOUT TOUCHING DATES
	RENAME	OUTCHN,SFILNM	;LAST RENAME OF THE JOB
	 $FATAL	(RNO,,<Cannot Rename output file 01>)
	POPJ	P,		;DONE


;  THIS ROUTINE POINTS TO THE PATH BLOCK IF SUB FILE DIRECTORIES ARE
;IMPLEMENTED, OTHERWISE IT WILL PUT THE PPN IN .RBPPN.

STOMP:	TXNN	F2,SFDS		;SEE IF SUB FILE DIRECTORIES EXIST
	JRST	.+3		;THEY DON'T
	PUSH	E,[PTHBLK]	;YES, POINT TO THE PATH BLOCK
	POPJ	P,		;..
	PUSH	E,COMPPN	;USE THE GIVEN PPN OR THE DEFAULT PPN
	POPJ	P,		;..
;ROUTINE TO DETERMINE IF THE FILE FOUND BY A LOOKUP UUO WAS
;ACTUALLY FOUND WHERE THE USER SPECIFIED, OR ON SOME LIBRARY
;AREA. IT EXPECTS THE USER'S LAST COMMAND TO STILL BE IN COM???,
;THE FILE TO HAVE BEEN LOOKED UP USING THE XFILNM BLOCK, AND A PATH
;UUO ON THE CHANNEL TO HAVE BEEN DONE INTO THE PTHBLK BLOCK.
;CALL:
;	PUSHJ	P,CHKPTH
;	 HERE IF FOUND ON A LIBRARY AREA
;	HERE IF FOUND WHERE SOUGHT
;USES AC'S A AND E.


;HERE WHEN CPATH & PTHBLK SET UP. COMPARE THE PATHS.
CHKPTH:	SKIPN	E,COMDEV	;GET DEVICE USER TYPED
	MOVSI	E,'DSK'		;BLANK DEFAULTS TO DSK:
	MOVEM	E,CPATH		;STORE IN OUR PATH BLOCK
	MOVE	E,[CPTLEN,,CPATH]  ;DO A PATH UUO ON IT
	PATH.	E,		;TO SEE IF USER MEANT HIS PPN
	  JFCL			;PROBABLY MTA: OR TSK:
	MOVE	E,CFLG		;PICKUP FLAGS WORD
	TXNN	E,PT.IPP	;IS THIS AN ERSATZ DEVICE?
	JRST	CMPDSK		;NO, MUST BE DSK: OF SOME SORT

;HERE IF AN ERSATZ DEVICE. COPY SFD'S FROM USER SPECIFICATION, SINCE
;AN ERSATZ DEVICE OVERRIDES ONLY THE PPN PORTION OF THE PATH.
	MOVE	E,[COMSFD,,CSFD]  ;COPY SFD'S ONLY
	BLT	E,CPATH+CPTLEN-1  ;..
	JRST	CMPPTH		;NOW GO COMPARE PATHS

;HERE IF DEVICE DOES NOT IMPLY A PPN. PATH BLOCK IS OK IF USER
;DIDN'T SPECIFY A PPN, OTHERWISE WE MUST COPY OVER WHAT HE TYPED.
CMPDSK:	SKIPG	COMPPN		;IS DEFAULT PATH OK?
	JRST	CMPPTH		;YES, GO COMPARE WITH FOUND
	MOVE	E,[COMPPN,,CPPN]  ;NO, GET WHAT USER SAID
	BLT	E,CPATH+CPTLEN-1  ;ONLY PPN & SFD'S
CMPPTH:	SETZ	A,		;SETUP TO LOOP OVER PATH
CMPLUP:	MOVE	E,CPPN(A)	;GET NEXT WORD OF PATH
	CAME	E,PTHPPN(A)	;MATCH WHERE IT WAS FOUND?
	POPJ	P,		;NO, IN A LIBRARY
	SKIPE	E		;DONE IF ZERO
	AOJA	A,CMPLUP	;ELSE COMPARE MORE SFD'S
	AOS	(P)		;PATHS WERE THE SAME
	POPJ	P,		;SO GIVE SKIP RETURN
;ROUTINE TO TYPE THE "%FILE FOUND IN ..." MESSAGE. EXPECTS
;THE PATH TO BE IN PTHBLK. USES A,B,C,CH,TT

TYPFFI:	$WARN	(FFI,,<File found in 05>)
	POPJ	P,
;ROUTINE TO PARSE FILE DESIGNATOR
;STORES WHAT USER TYPED IN COM???, AND COPIES IT INTO X????,
;READY TO DO A LOOKUP OR ENTER. NULL DEVICE DEFAULTS TO DSK:
;
;CALL WITH ADDRESS OF SWITCH TABLE IN B.
;
;ENTER AT FILALT TO COPY COM??? AREA TO X???? AREA.
;
;USES AC'S A, AA, B, E, CH

FILSPC:	TXZ	FF,FEXTF	;INITIALIZE FILE SCANNING FLAGS
	SETZM	COMZR		;ZERO AREA THAT WE USE
	MOVE	AA,[COMZR,,COMZR+1]  ;INCLUDES COM???, X????
	BLT	AA,COMEZR	;..
	MOVEM	B,SWITAB	;SET SWITCH TABLE ADDRESS

;BACK HERE TO PARSE A NEW FIELD OF THE FILE SPECIFICATION

NEWFLD:	PUSHJ	P,FILWRD	;ACCUMULATE SIXBIT INTO AC E
	CAIN	CH,":"		;WAS TERMINATOR A COLON?
	JRST	FILDEV		;YES, GO PROCESS DEVICE
	CAIN	CH,"."		;A PERIOD?
	JRST	FILNAM		;YES, STORE FILENAME & FLAG EXT.
	PUSHJ	P,STRFLD	;ALL OTHER TERMINATORS START A
				;FIELD, SO STORE END OF LAST ONE
	CAIN	CH,"["		;PATH DESIGNATOR?
	JRST	FILPTH		;YES, GO READ IN PATH
	CAIN	CH,"/"		;A SWITCH?
	JRST	FILSWT		;YES, GO READ IT
	CAIE	CH,.CHESC	;ONLY OTHER DELIMITER AN ALT
	$FATAL	(IFN,,<Illegal character "00" in file specification>)

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;HERE WHEN FILESPEC FINISHED (ALTMODE SEEN). COPY COM??? TO X??? & POPJ.
;
;USES A AND AA.

FILALT:	SETZM	XFIBLK		;ZERO LOOKUP BLOCK AGAIN
	MOVE	AA,[XFIBLK,,XFIBLK+1]  ;INCASE ENTRY AT FILALT
	BLT	AA,XFIBLK+XFILEN-1  ;BUT NOT TOO FAR
	SKIPN	AA,COMDEV	;PICKUP USER DEVICE IF ANY
	MOVSI	AA,'DSK'	;NONE, SO USE DSK:
	MOVEM	AA,OPNDEV	;STORE FOR OPEN
	DEVCHR	AA,		;ALSO NEED CHARACTERISTICS
	MOVEM	AA,OPNCHR	;SO WE CAN TELL DECTAPES FROM DSK:
	TXNE	AA,DV.TTY	;IS IT A TTY?
	TXNN	AA,DV.TTA	;YES, CONTROLLING A JOB (OURS)?
	CAIA			;NO TO EITHER
	 $FATAL	(TTY,,<Illegal TTY I/O device>)
	MOVE	A,[-XFILEN,,XFILNM-1]  ;SETUP PDL INTO LOOKUP BLK
	PUSH	A,[XFILEN-1]	;FIRST WORD IS LENGTH
	SKIPG	COMPPN		;DID USER SPECIFY A PATH?
	TDZA	AA,AA		;NO, USE A ZERO FOR DEFAULT
	MOVEI	AA,PTHBLK	;YES, POINT TO PATH BLOCK
	TXNN	F2,SFDS		;SEE IF SFDS ARE USED
	MOVE	AA,COMPPN	;IF NOT, THEN USE A PPN.
	PUSH	A,AA		;STORE PATH POINTER OR ZERO OR PPN
	PUSH	A,COMNAM	;STORE FILE NAME
	PUSH	A,COMEXT	;EXTENSION
	SETZM	PTHBLK		;SETUP PTHBLK FROM COMPPN
	SETZM	PTHFLG		;ZERO 1ST 2 WORDS FOR MONITOR
	MOVE	A,[COMPPN,,PTHPPN]  ;COPY REST FROM COMMAND
	BLT	A,PTHBLK+PTHLEN-2  ;..
	SETZM	PTHBLK+PTHLEN-1	;MAKE SURE IT TERMINATES WITH A 0
	POPJ	P,
;HERE WHEN ":" TYPED. STORE THE DEVICE NAME.

FILDEV:	SKIPE	E		;USER TYPE A DEVICE?
	TXNE	FF,FEXTF	;MAYBE, REALLY AN EXTENSION?
	 $FATAL	(NDV,,<Null device illegal>)
	MOVEM	E,COMDEV	;YES, STORE IT
	JRST	NEWFLD		;AND GO PARSE THE NEXT FIELD

;HERE WHEN "." TYPED. STORE ANY FILE NAME THAT'S BEEN ACCUMULATING
;ALSO, SET FLAG SO NEXT FIELD SEEN WILL BE STORED AS EXTENSION

FILNAM:	TXOE	FF,FEXTF	;SET EXTENSION FLAG
	 $FATAL	(DEX,,<Double extension illegal>)
	JUMPE	E,NEWFLD	;MAYBE NO FILENAME (FOO[,].BAR)
	SKIPE	COMNAM		;THERE IS, DUPLICATE?
	 $FATAL	(DFN,,<Double filename illegal>)
	MOVEM	E,COMNAM	;NO, STORE THE FILE NAME
	JRST	NEWFLD		;READY FOR THE NEXT FIELD

;HERE WHEN "/" OR "[" OR <ALT> TYPED. STORE FILE OR EXT. FIRST

STRFLD:	TXZE	FF,FEXTF	;WAITING FOR AN EXTENSION?
	JRST	STREXT		;YES, GO STORE IT
	JUMPE	E,CPOPJ		;DON'T STORE IF NOTHING THERE
	SKIPE	COMNAM		;FILE NAME ALREADY SEEN?
	 $FATAL	(DFN,,<Double filename illegal>)
	MOVEM	E,COMNAM	;NO, STORE THE FILE NAME
	POPJ	P,		;RETURN
;HERE IF WE SHOULD STORE AN EXTENSION
STREXT:	JUMPE	E,CPOPJ		;DON'T STORE IF NOT TYPED
	SKIPE	COMEXT		;DOUBLE EXTENSION?
	 $FATAL	(DEX,,<Double extension illegal>)
	HLLZM	E,COMEXT	;NO, STORE EXTENSION
	POPJ	P,		;DONE
;HERE WHEN "[" TYPED. READ IN A PATH SPECIFICATION.

FILPTH:	SKIPE	COMPPN		;ONLY ONE PER CUSTOMER
	 $FATAL	(DDI,,<Double directory illegal>)
	PUSHJ	P,FILOCT	;READ THE PROJECT
	CAIN	CH,"-"		;[-] MEANS DEFAULT PATH
	JUMPE	E,FILDFP	;BUT [123-] DOESN'T
	CAIN	CH,","		;ONLY LEGAL TERMINATOR IS ","
	TDNE	E,[-1,,400000]	;AND PROJECT MUST BE .LE. 377777
	 $FATAL	(IPJ,,<Improper project number>)
	SKIPN	E		;[, ???
	HLRZ	E,.MYPPN##	;YES, USE LOGGED-IN PROJECT
	MOVSM	E,COMPPN	;STORE FOR RETURN
	PUSHJ	P,FILOCT	;GET PROGRAMMER
	TLNE	E,-1		;ONLY HALF WORD ALLOWED
	 $FATAL	(IPG,,<Improper programmer number>)
	SKIPN	E		;[FOO,]??
	HRRZ	E,.MYPPN##	;YES, USE LOGGED IN PROGRAMMER
	HRRM	E,COMPPN	;STORE ANSWER
	CAIN	CH,.CHESC	;ALLOW X:Y.Z[,<ALT>
	JRST	FILALT		; ..
	CAIN	CH,"]"		;END OF SPEC?
	JRST	NEWFLD		;YES, GO READ MORE
	CAIE	CH,","		;LAST CHANCE
	$FATAL	(IFN,,<Illegal character "00" in file specification>)

;HERE TO COLLECT SFD'S FROM THE COMMAND STRING

	MOVE	B,[XWD -5,COMSFD]  ;MAX SFD'S ALLOWED
FILSFD:	PUSHJ	P,FILWRD	;PARSE SFD NAME
	SKIPN	E		;MUST BE ONE
	 $FATAL	(NSF,,<Null SFD illegal>)
	MOVEM	E,(B)		;OK, STORE IT
	CAIN	CH,.CHESC	;END OF IT ALL?
	JRST	FILALT		;FINISH UP
	CAIN	CH,"]"		;NO, END OF PATH?
	JRST	NEWFLD		;YES, LOOK FOR SWITCHES ETC
	CAIE	CH,","		;MORE SFD'S?
	$FATAL	(IFN,,<Illegal character "00" in file specification>)
	AOBJN	B,FILSFD	;GO AFTER MORE SFD'S
	 $FATAL	(SFD,,<SFDs nested too deep>)

;HERE ON "[-". SET COMPPN TO -1 TO INDICATE DEFAULT PATH.

FILDFP:	SETOM	COMPPN		;DEFAULT PATH
	PUSHJ	P,FILCHR	;NEXT CHARACTER
	CAIN	CH,.CHESC	;ALLOW IT TO END HERE
	JRST	FILALT		;FINISH UP
	CAIE	CH,"]"		;ELSE MUST FINISH RIGHT
	$FATAL	(IFN,,<Illegal character "00" in file specification>)
	JRST	NEWFLD		;GO GET MORE
;HERE ON A "/". READ IN THE SWITCH.

FILSWT:	PUSHJ	P,FILWRD	;READ THE SWITCH NAME
	MOVEM	E,SWITHL	;STORE FOR ERROR MSGS
	MOVE	B,SWITAB	;POINT TO SWITCH TABLE
FILSWL:	SKIPN	(B)		;DONE?
	 $FATAL	(UIS,,<Unknown I/O switch>)
	CAME	E,(B)		;MATCH?
	AOJA	B,FILSWL	;NO, TRY NEXT
	SUB	B,SWITAB	;CONVERT SWITCH TO OFFSET
	MOVNS	B		;NEED NEGATIVE FOR LSH
	MOVSI	E,(1B0)		;1B0 IS 1ST SWITCH, 1B1 IS SECOND
	LSH	E,(B)		;CONVERT TO RIGHT BIT
	IORM	E,SWITC		;STORE FOR RETURN
	CAIN	CH,"/"		;ANOTHER SWITCH COMING?
	JRST	FILSWT		;YES, PROCESS IT
	CAIN	CH,.CHESC	;END OF IT ALL?
	JRST	FILALT		;YES, GO FINISH UP
	$FATAL	(IFN,,<Illegal character "00" in file specification>)



;FILE SELECTION COMMAND SWITCH TABLE

TXTSWT:	SIXBIT	/GENLSN/	;GENERATE LINE SEQ#'S ON OUTPUT
	SIXBIT	/SUPLSN/	;SUPPRESS LSN (INPUT OR OUTPUT)
	0

;COMMAND FILE SWITCH TABLE

CMFSWT:	SIXBIT	/ECHO/		;ALLOW ECHOING OF COMMAND CHARACTERS INPUT
	SIXBIT	/TYO/		;ALLOW REGULAR PROGRAM OUTPUT
	0			;END OF SWITCH TABLE



U SWITAB,1			;ADDRESS OF SWITCH TABLE
U INSWT,1			;INPUT SWITCHES
U OUTSWT,1			;OUTPUT SWITCHES
U LSNCTR,1			;LSN GENERATION CTR

;SWITCH BITS -- LEFT HALF

GENLSN==1B0
SUPLSN==1B1
;HERE TO READ AN ALFAMERIC WORD INTO E IN SIXBIT. USES A.

FILWRD:	SETZ	E,		;INITIALIZE ACCUMULATOR AC
	MOVE	A,[POINT 6,E]	;SETUP TO STORE IN IT
FILWRL:	PUSHJ	P,FILCHR	;GET NEXT CHAR
	CAIL	CH,"A"		;A LETTER?
	CAILE	CH,"Z"		;MAYBE, IS IT?
	CAIA			;NO, COULD BE A DIGIT
	JRST	FILWR1		;IT IS A LETTER. STORE IT.
	CAIL	CH,"0"		;DIGIT?
	CAILE	CH,"9"		;IS IT?
	POPJ	P,		;NOPE, END OF WORD
FILWR1:	SUBI	CH,"A"-'A'	;CONVERT TO SIXBIT
	TLNE	A,770000	;AC E FULL YET?
	IDPB	CH,A		;NO, STORE THE CHARACTER
	JRST	FILWRL		;LOOP FOR ENTIRE WORD

;HERE TO READ AN OCTAL NUMBER INTO E.

FILOCT:	SETZ	E,		;INITIALIZE ANSWER
FILOCL:	PUSHJ	P,FILCHR	;GET NEXT DIGIT
	CAIL	CH,"0"		;A DIGIT?
	CAILE	CH,"7"		;(OCTAL, THAT IS)
	POPJ	P,		;NO, END OF OCTAL NUMBER
	LSH	E,3		;YES, MAKE ROOM
	ADDI	E,-"0"(CH)	;ADD IN NEXT DIGIT
	JRST	FILOCL		;LOOP FOR ENTIRE NUMBER

;GET A CHAR FOR FILEPSPECIFICATION
;IGNORE SPACE, TAB, LF, VT, FF, CR; CONVERT LC TO UC

FILCHR:	PUSHJ	P,SKRCH
	$FATAL	(UFS,,<Macro ending with unterminated file selection command>)
	CAIL	CH,"a"
	CAILE	CH,"z"
	JRST	.+2
	TRZ	CH,40
	CAIN	CH," "
	JRST	FILCHR
	CAIL	CH,.CHTAB
	CAILE	CH,.CHCRT
	POPJ	P,
	JRST	FILCHR
;ZAPTT  --  ZAP THE TERMINAL CHANNEL

ZAPTT:	CLOSE	TTYCHN,		;FLUSH OUT ANY OUTPUT STILL PENDING
	SETSTS	TTYCHN,.IOASC	;CLEAR OUT FUNNY MODES
	PUSHJ	P,TTYRST	;RESTORE TTY STATE
	RELEAS	TTYCHN,		;AND RELEASE CONTROL OF THE TERMINAL
	POPJ	P,		;ALL DONE


;ZAPIN  --  ZAP THE INPUT FILE AND BUFFERS (IF ANY)

ZAPIN:	RELEAS	INCHN,		;TOSS OUT INPUT FILE
	SETZM	INVER		;[252] NO MORE INPUT FILE VERSION
	SKIPN	INDSZ		;INPUT BUFFERS SETUP?
	POPJ	P,		;NO, ALL DONE
	DMOVE	A,INDSZ		;YES, GET BUFARG AND ADDRESS
	MOVEI	B,IBUF		;AND RING HEADER ADDRESS
	PUSHJ	P,FREBF		;DEALLOCATE THE INPUT BUFFER RING
	 HALT	.+1		;CAN'T HAPPEN
	SETZM	INDSZ		;NO BUFFERS NOW
	SETZM	BICNT		;NOR BUFFERED INPUTS EITHER
	POPJ	P,		;ALL DONE


;ZAPOU  --  ZAP THE OUTPUT FILE AND BUFFERS (IF ANY)

ZAPOU:	RELEAS	OUTCHN,		;TOSS OUT THE OUTPUT FILE
	SKIPN	OUDSZ		;OUTPUT BUFFERS SETUP?
	POPJ	P,		;NO, ALL DONE
	DMOVE	A,OUDSZ		;YES, GET BUFARG AND ADDRESS
	MOVEI	B,OBUF		;AND RING HEADER ADDRESS
	PUSHJ	P,FREBF		;DEALLOCATE THE OUTPUT BUFFER RING
	 HALT	.+1		;CAN'T HAPPEN
	SETZM	OUDSZ		;NO OUTPUT BUFFERS NOW
	SETZM	BOCNT		;NOR BUFFERED OUTPUTS EITHER
	POPJ	P,		;ALL DONE
;GETBF  --  ALLOCATE AND CONSTRUCT I/O BUFFERS
;SETBF  --  CONSTRUCT I/O BUFFERS
;FREBF  --  DEALLOCATE I/O BUFFERS
;CALL IS:
;
;	MOVX	A,<BUFARG>
;	MOVX	AA,<ADDR>	;SETBF/FREBF ONLY
;	MOVX	B,<RHDR>
;	PUSHJ	P,GETBF/SETBF/FREBF
;	 ERROR RETURN
;	NORMAL RETURN
;
;WHERE <BUFARG> IS COUNT OF DESIRED BUFFERS IN RING STRUCTURE IN THE LEFT
;HALF AND SIZE OF INDIVIDUAL BUFFER IN THE RIGHT HALF (SAME FORMAT AS THAT
;RETURNED ON A DEVSIZ MONITOR CALL); <ADDR> (SETBF ONLY) IS THE ADDRESS OF
;THE .BFHDR WORD OF THE FIRST BUFFER; AND <RHDR> IS THE ADDRESS OF THE
;BUFFER RING HEADER CONTROL BLOCK.
;
;ON ERROR RETURN (GETBF ONLY) NO PAGES WERE AVAILABLE IN WHICH TO CONSTRUCT
;EVEN ONE BUFFER.
;
;ON NORMAL RETURN (GETBF) THE PAGES NEEDED TO HOLD THE RING STRUCTURE HAVE
;BEEN ALLOCATED, (GETBF AND SETBF) THE BUFFER RING STRUCTURE HAS BEEN LINKED
;TOGETHER AND INITIALIZED (READY FOR FIRST IN/OUT) AND A/AA WILL CONTAIN
;<BUFARG> AND <ADDR> AS ABOVE. ON NORMAL RETURN FROM FREBF THE PAGES WHICH
;CONTAINED THE RING STRUCTURE HAVE BEEN DEALLOCATED.
;
;USES T, TT, TT1.

GETBF:	PUSH	P,A		;SAVE BUFARG
	HLRZ	AA,A		;COUNT OF BUFFERS
	IMULI	AA,(A)		;TOTAL WORDS NEEDED
	MOVE	A,AA		;POSITION COUNT FOR GETPW TO
	PUSHJ	P,GETPW		;GET SOME FREE PAGES FOR RING STRUCTURE
	 SKIPA	A,(P)		;NOT ENOUGH PAGES
	JRST	GETBF3		;AA HAS PAGES ALLOCATED
	ANDI	A,-1		;TRY FOR JUST ONE PAGE (OR BUFFER IF LARGER)
	PUSHJ	P,GETPW		;MINIMUM AVAILABLE?
	 JRST	[POP	P,A	;NO, RESTORE STACK
		POPJ	P,]	;AND TAKE ERROR RETURN
	MOVEI	T,PAGSIZ	;SIZE OF MINIMUM REQUEST
	IDIVI	T,(A)		;HOW MANY BUFFERS?
	CAIGE	TT,1		;AT LEAST ONE?
	MOVEI	TT,1		;YES - BY DEFINITION AT LEAST ONE
	HRLM	TT,(P)		;CONTRUCT APPROPRIATE BUFARG
GETBF3:	POP	P,A		;RESTORE BUFARG FOR SETBF
	LSH	AA,PG2WRD	;WORD ADDRESS FOR RING STRUCTURE

;FALL INTO SETBF

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

SETBF:	CAIGE	B,.JBDA		;REASONABLE ADDRESS?
	  HALT	.		;BLETCH
	ADDI	AA,.BFHDR	;RELOCATE TO LINK WORD OF FIRST BUFFER
	HLRZ	T,A		;COUNT OF BUFFERS IN RING
	HRRZ	TT,AA		;START OF RING (FIRST BUFFER)
	HRRZ	TT1,TT		;START OF START OF NEXT BUFFER IN RING
	TLOA	TT1,-2(A)	;SET DATA SIZE + 1 IN LH OF .BFHDR WORD
SETBF3:	ADDI	TT,(A)		;ADDRESS OF NEW CURRENT BUFFER
	ADDI	TT1,(A)		;ADDRESS OF NEXT POSSIBLE BUFFER IN RING
	MOVEM	TT1,(TT)	;LINK CURRENT BUFFER TO NEXT BUFFER
	SOJG	T,SETBF3	;LOOP TILL LAST BUFFER IN RING
	HRRM	AA,(TT)		;LINK LAST BUFFER TO FIRST BUFFER
	TXO	AA,BF.VBR	;THE VIRGIN BUFFER RING BIT
	MOVEM	AA,(B)		;LINK CONTROL BLOCK TO RING STRUCTURE
	TXZ	AA,BF.VBR	;RESTORE JUST ADDRESS
	JRST	CPOPJ1		;I/O BUFFERS ALL SET FOR I/O

FREBF:	SETZM	.BFADR(B)	;BREAK RING STRUCTURE FROM HEADER
	HLRZ	T,A		;COUNT OF BUFFERS
	IMULI	T,(A)		;COUNT OF WORDS USED BY BUFFERS
	MOVE	A,T		;POSITION FOR FREPW TO
	PUSHJ	P,FREPW		;FREE UP I/O PAGES
	 HALT	.+1		;CAN'T HAPPEN
	JRST	CPOPJ1		;ALL DONE
;Y	RENDER THE BUFFER EMPTY.  READ INTO THE BUFFER UNTIL
;	(A)  A FORM FEED CHARACTER IS READ, OR
;	(B)  THE BUFFER IS WITHIN ONE THIRD OR
;128 CHARACTERS OF CAPACITY AND A LINE FEED IS READ, OR
;	(C)  AN END OF FILE IS READ, OR
;	(D)  THE BUFFER IS COMPLETELY FULL.
;THE FORM FEED (IF PRESENT) DOES NOT ENTER THE BUFFER.

YANK:	SKIPN	EQM		;IF IN A MACRO, ALLOW OLDE "Y" COMMAND
	 $WARN	(UEY,,<Use "EY" rather than "Y">)
EY:
YANK1:	MOVE	OU,BEG
	MOVEM	OU,PT		;PT:=BEG
	TXZ	F2,LSNINF	;CLEAR THE CLEARING FLAG

YANK2:	TXNE	FF,FINF		;IF WE FINISHED ALREADY
	JRST	YANK51		;THEN GET OUT
	TXZ	FF,FORM		;RESET THE YANK,APPEND FORM FEED FLAG
	TXNN	FF,UREAD	;ERROR IF INPUT NOT SPECIFIED
	 $FATAL	(NFI,,<No file for input>)

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;MAINTAIN AT LEAST A MINIMUM SIZE BUFFER OF 3000
;CHARACTERS AT ALL TIMES, WHEN TECO ASKS FOR INPUT FROM
;ANYTHING BUT THE CONSOLE.

	MOVE	C,PT		;GET .
	MOVEM	C,Z		;TELL NROOM IT'S AN EXPAND
	SUBM	OU,C		;BUT EXPAND WITH REAL Z IN MIND
	ADDI	C,^D3000	;NEED 3000 ABOVE Z
	MOVEM	OU,NRMGCZ	;SET BIZARRE GARBAGE-COLLECTION FLAG
	PUSHJ	P,NROOM
YANK6:	ADD	OU,RREL		;RELOCATE IN CASE GARBAGE COLLECTION DONE
	MOVE	TT,MEMSIZ	;TOP OF BUFFER
	MOVE	CH,TT
	SUB	TT,OU
	IDIVI	TT,3
	SUBM	CH,TT
	MOVEM	TT,M23		;M23 HAS 2/3 PT
	SUBI	CH,200
	MOVEM	CH,M23PL	;M23PL HAS 200 BELOW TOP
YANK4:	CAMGE	OU,M23		;2/3 FULL YET?
	JRST	YANK3		;NO, KEEP GOING
	CAMG	OU,M23PL	;YES, GETTING NEAR TOP?
	CAIN	CH,.CHLFD	;NO. LINE FEED?
	JRST	YANK51		;YES. THAT'S ALL.
				;NO. GET MORE.

YANK3:	SOSLE	IBUF+.BFCTR	;IS DEVICE BUFFER EMPTY?
	JRST	YANK5		;NO.
	TXNE	FF,FINF		;YES, HAVE WE ALREADY EA'ED IT ALL?
	JRST	YANK37		;YES, THEN ALL USED UP
	AOS	BICNT		;COUNT IN'S DONE IN CASE LATER EA
	IN	INCHN,		;ASK FOR ANOTHER BUFFER
	JRST	YANK5		;GOT IT, COUNT IT DOWN
	STATZ	INCHN,IO.ERR	;ERROR?
	JRST	INERR		;YES.
	STATO	INCHN,IO.EOF	;NO. END OF FILE?
	 HALT	.+1		;NO??? SOMEBODY IS MESSED UP!
YANK37:	TXO	FF,FINF		;YES, MARK NO MORE INPUT
	JRST	YANK51		;CLEAR BUFFER AND RETURN.
YANK5:	ILDB	CH,IBUF+.BFPTR	;CH:=NEXT CHARACTER.
	SOS	INSIZ		;COUNT DOWN BYTES LEFT (FOR EA)
	TXZN	F2,LSNINF	;WAS THE LAST THING A SUPPRESSED LSN?
	JRST	YANK52		;NO
	CAIE	CH,.CHCRT	;YES, IGNORE THE NEXT CHARACTER
	CAIN	CH,.CHTAB	;IF IT'S A CR (FOR SOS) OR A TAB
	JRST	YANK3		; IGNORE IT
YANK52:	JUMPE	CH,YANK3	;IF NULL, IGNORE IT.
	HRRZ	T,IBUF+.BFPTR	;GET BYTE POINTER'S ADDRESS FIELD
	MOVE	T,0(T)		;GET CURRENT DATA WORD
	TRNE	T,1		;SEQUENCE NUMBER?
	JRST	YNKSEQ		;YES
YANK50:	PUSHJ	P,PUT		;NO. PUT CHARACTER IN DATA BUFFER.
	CAIE	CH,.CHFFD	;FORM FEED?
	AOJA	OU,YANK4	;NO. UPDATE DATA BUFFER PTR AND CHECK FOR OVERFLOW.
	TXO	FF,FORM		;YANK AND/OR APPEND TERMINATED ON A FORM FEED
YANK51:	MOVEM	OU,Z		;YES. SET END OF DATA BUFFER AND RETURN
	POPJ	P,

YNKSEQ:	MOVE	T,INSWT		;SUPPRESS SEQ# FLAG ON?
	TXNE	T,SUPLSN
	JRST	YNKSEZ		;YES, STRIP THEM OFF AS IN DAYS OF YORE
	TXON	FF,SEQF		;SET SEQ FILE AND
				;JRST IF ALREADY SEEN
	TXNE	T,GENLSN	;DOES USER WANT LSN'S?
	JRST	YANK50		;IF SO DON'T BOTHER HIM

;HERE IF NO LSN SWITCH AND SEQUENCED FILE. TELL USER WHAT'S ABOUT TO HAPPEN

	MOVE	T,CH		;SAVE THE CHARACTER
	PUSHJ	P,INBMES	;OUTPUT THE MESSAGE
	ASCIZ	/% Line Sequence Number detected in input file/
	MOVE	CH,T		;RESTORE CHARACTER
	JRST	YANK50		;..

YNKSEZ:	MOVEI	T,4		;CTR FOR REST OF SEQ #
	IBP	IBUF+.BFPTR	;MOVE PTR OVER THIS CHAR
	SOS	IBUF+.BFCTR	;& CTR TOO
	SOJG	T,.-2
	TXO	F2,LSNINF!LSNF	;IGNORE NEXT CHAR IF TAB
	TXO	FF,SEQUIN	;IGNORE NEXT CHAR IF IT IS A TAB
	JRST	YANK3

INERR:	GETSTS	INCHN,B		;SAVE ERROR FLAGS
	PUSHJ	P,ZAPIN		;ZAP ANY INPUT FILE
	TXZ	FF,UREAD
	$FATAL (INP,,<Input error 11 on file 09>)
;A   APPEND TO THE END OF THE BUFFER FROM THE SELECTED INPUT
;	TERMINATING THE READ IN THE SAME MANNER AS Y.  THE POINTER
;	IS NOT MOVED BY A.

APPEND:	MOVE	OU,Z		;STORE DATA AT END OF BUFFER.
	PUSHJ	P,YANK2
	JRST	RET



;INSERT TRAILING FORM FEED IF NEEDED

TRLFF:	TXZN	FF,FORM		;ALREADY HAVE NEED OF A <FF>?
	POPJ	P,		;NO
	PUSH	P,PT		;PRESERVE "." ACCROSS INSERT
	MOVE	OU,Z		;POINT TO END OF BUFFER
	MOVEM	OU,PT		;SET "." THERE
	MOVEI	CH,.CHFFD	;GET A <FF> CHARACTER
	PUSHJ	P,TAB2		;INSERT A <FF> THE HARD WAY
	POP	P,PT		;RESTORE "." AFTER INSERT
	SKIPE	CH,RREL		;ALLOW FOR RELOCATION OF TEXT
	ADDM	CH,PT		; (IF ANY)
	POPJ	P,		;RETURN
;^ITEXT$	INSERTS AT THE CURRENT POINTER LOCATION THE ^I (TAB)
;	AND THE TEXT FOLLOWING THE ^I UP TO BUT NOT INCLUDING THE
;	ALT MODE.  THE POINTER IS PUT TO THE RIGHT OF THE INSERTED
;	MATERIAL.

TAB:	TXZ	FF,ARG!SLSL	;NO ARGUMENT WANTED
	TXO	FF,TABSRT	;FLAG THIS IS A TABBED INSERT
				;AND TREAT AS NORMAL (ALMOST) INSERT

;ITEXT$	INSERT, AT THE CURRENT POINTER LOCATION, THE TEXT FOLLOWING
;	THE I UP TO BUT NOT INCLUDING THE FIRST ALT. MODE.  THE
;	POINTER IS PUT TO THE RIGHT OF THE INSERTED MATERIAL.

INSERT:	TXNE	FF,ARG		;IS THERE AN ARGUMENT?
	JRST	INS1A		;YES. NI COMMAND.

;ENTER HERE FOR "FR" COMMAND

INSERA:	MOVEI	CH,.CHESC	;NORMAL TERMINATOR
	TXZN	FF,SLSL		;DID @ PRECEED I?
	JRST	INSERB		;NO, TERMINATOR = ALTMODE
	PUSHJ	P,SKRCH		;YES. CH:=USER SELECTED TERMINATOR.
	$FATAL	(UIN,,<Unterminated input string>)

;ENTER HERE FOR "FS", "FN", AND "F_" COMMANDS TO SCAN INSERT ARGUMENT

INSERB:	MOVEI	B,(CH)		;B=INSERTION TERMINATOR.
	PUSH	P,COMPTR	;SAVE CURRENT POSITION IN CMD STRING
	PUSH	P,COMPTX	; (DOUBLE-WORD POINTER ADDRESS)
	PUSH	P,COMCNT	;SAVE COMMAND CHARACTER COUNT TOO
	TXNN	FF,TABSRT	;IS THIS A TABBED INSERT?
	TDZA	C,C		;NO, REGULAR INSERT
	MOVEI	C,1		;YES, THEN TAB IS FIRST CHARACTER
	MOVEI	CH,IN5T1B	;ASSUME MODERN ('80S) CONVENTIONS
	CHKEO	EO21,[MOVEI CH,IN3T1B	;GUESSED WRONG
		JRST	INSERC]		;USE ANCIENT CONVENTIONS
	CHKEO	EO25,[MOVEI CH,IN1T1B	;GUESSED WRONG
		JRST	INSERC]		;USE OLD CONVENTIONS
INSERC:	MOVEM	CH,CHTB		;REMEMBER CHARACTER DISPATCH TABLE

;COUNT # CHARACTERS TO INSERT IN C AND MOVE COMPTR TO END OF STRING.

INSER0:	PUSHJ	P,SKRCH		;GET NEXT CHARACTER
	$FATAL	(UIN,,<Unterminated input string>)
	CAIN	CH,(B)		;IS IT THE TERMINATOR?
	JRST	INSER2		;YES, END OF 1ST PASS
	TXO	FF,F.NNUL	;[MHK] FLAG NON NULL INSERT
	MOVE	T,CHTB		;CHECK FOR SPECIAL CONTROL CHARACTERS
	TXNE	F2,TXTCTL	;^T FLAG ON?
	ADDI	T,IN2T1B-IN1T1B	;YES, USE RESTRICTED TABLE
	PUSHJ	P,DISP1
	TXNN	F2,TXTCTL	;IF ^T ON, ALL OTHER CTL-CHARS LEGAL TEXT
	PUSHJ	P,CKNCC		;CHECK FOR OTHER ILLEGAL CONTROL-CHARS
INSER1:	AOJA	C,INSER0	;COUNT TEXT CHARACTERS
;SETUP FOR INSERT (CHAR COUNT IN C)

INSER2:	MOVEM	C,VVAL		;SAVE LENGTH OF STRING
	TXZ	F2,TXTCTL	;REFRESH ^T FLAG
	TXNE	F2,S.REPL	;DOING FS OR FN?
	JRST	SERCHJ		;YES
	POP	P,COMCNT	;RESET TO BEGINNING OF INSERT TEXT
	POP	P,COMPTX	; (DOUBLE-WORD POINTER ADDRESS)
	POP	P,COMPTR	;AND COMMAND BYTE POINTER
	TXNN	F2,S.FRCM	;IF REGULAR INSERT COMMAND, THEN
	JRST	INSE2N		;JUST DO INSERT
	SKIPG	C,VVALFR	;FR COMMAND, GET LAST STRING ARG SIZE
	ADDM	C,PT		;RELOCATE "." TO START OF LAST STRING ARG
				; AND IF THE USER HAS MOVED SINCE THEN,
				; IT'S HIS TOUGH LUCK (WHO KNOWS, HE MIGHT
				; EVEN KNOW WHAT HE'S DOING!)
	MOVMS	C		;ABSOLUTE SIZE OF PREVIOUS STRING ARG
	MOVNS	C		;(DON'T HAVE SUB AC FROM MEMORY)
	ADD	C,VVAL		;C:=DIFFERENCE IN STRING SIZES
	CAIA			;GROW/SHRINK TEXT BUFFER AS NEEDED
INSE2N:	PJUMPE	C,CPOPJ		;EXIT IF NULL INSERT
	CAIE	C,0		;DON'T TRY TO EXPAND/CONTRACT IF NOT NEEDED
	PUSHJ	P,NROOM		;MOVE FROM PT THROUGH Z UP C POSITIONS.
	TXNN	F2,S.FRCM	;IF REGULAR INSERT,
	JRST	INS1B		;JUST DO THE INSERT
	SKIPN	VVAL		;FR COMMAND, DO THE INSERT IF ANYTHING TO INSERT
	POPJ	P,		;UNLESS ONLY "-ND" EFFECT WANTED
				; I.E., "FR$" COMMAND

;MOVE INSERTION INTO DATA BUFFER

INS1B:	MOVE	OU,PT		;INSERT STARTING AT "."
	MOVEI	CH,IN5T2B	;ASSUME MODERN CONVENTIONS
	CHKEO	EO21,[MOVEI CH,IN3T2B	;GUESSED WRONG
		JRST	INS1B2]		;USE ANCIENT CONVENTIONS
	CHKEO	EO25,[MOVEI CH,IN1T2B	;GUESSED WRONG
		JRST	INS1B2]		;UES OLD CONVENTIONS
INS1B2:	MOVEM	CH,CHTB		;REMEMBER CHARACTER DISPATCH TABLE
	TXZE	FF,TABSRT	;IS THIS A TABBED INSERT?
	SKIPA	CH,[.CHTAB]	;YES, FIRST INSERT A TAB
INS1C:	PUSHJ	P,GCH		;CH:=CHARACTER FROM COMMAND STRING.
INS1F:	CAIN	CH,(B)		;IS IT THE TERMINATOR?
	JRST	INS1L		;YES. DON'T STORE IT.
	MOVE	T,CHTB		;CHECK FOR CONTROL CHARACTERS
	TXNE	F2,TXTCTL	;^T FLAG ON?
	ADDI	T,IN2T2B-IN1T2B	;YES, USE RESTRICTED TABLE
	PUSHJ	P,DISP1
INS1E:	PUSHJ	P,CASE		;CONVERT UC TO LC IF FLAGS WARRANT
INS1D:	PUSHJ	P,PUT		;NO. STORE CHARACTER IN DATA BUFFER
	AOJA	OU,INS1C	;ADVANCE "." AND LOOP

INS1L:	MOVEM	OU,PT		;SET NEW "."
	POPJ	P,		;AND RETURN SANS STORING THE TERMINATOR
;EO=1,2 DISPATCH TABLE FOR INSERT STRING CONTROL CHARACTERS (COUNT PASS)

IN1T1B:	XWD	INSER0,.CHCNV	;^V
	XWD	INSER0,.CHCNW	;^W
	XWD	INSER0,36	;^^
IN2T1B:	XWD	INSER4,.CHCNT	;^T
	XWD	INSER3,.CHCNR	;^R
IN3T1B:	XWD	0,0		;END OF LIST

;EO=3 DISPATCH TABLE FOR INSERT STRING CONTROL CHARACTERS (COUNT PASS)

IN5T1B:	XWD	INSER0,.CHCNA	;^A (LOWER CASE)
	XWD	INSER0,.CHCNB	;^B (UPPER CASE)
	XWD	INSER0,36	;^^ (SORTA SHIFT)
	XWD	INSER4,.CHCNT	;^T (LITERAL TEXT)
	XWD	INSER3,.CHCNV	;^V (QUOTE CHARACTER)
	XWD	0,0		;END OF TABLE



;EO=1,2 DISPATCH TABLE FOR INSERT STRING CONTROL CHARACTERS (INSERT PASS)

IN1T2B:	XWD	INSLOW,.CHCNV	;^V
	XWD	INSSTD,.CHCNW	;^W
	XWD	INSSPC,36	;^^
IN2T2B:	XWD	INSMAC,.CHCNT	;^T
	XWD	INSIGR,.CHCNR	;^R
IN3T2B:	XWD	0,0		;END OF LIST

;EO=3 DISPATCH TABLE FOR INSERT STRING CONTROL CHARACTERS (INSERT PASS)

IN5T2B:	XWD	INSLOW,.CHCNA	;^A (LOWER CASE)
	XWD	INSSTD,.CHCNB	;^B (UPPER CASE)
	XWD	INSSPC,36	;^^ (SORTA SHIFTED)
	XWD	INSMAC,.CHCNT	;^T (LITERAL TEXT)
	XWD	INSIGR,.CHCNV	;^V (QUOTED CHARACTER)
	XWD	0,0		;END OF LIST
;QUOTE NEXT CHARACTER

INSER3:	PUSHJ	P,SKRCH		;READ IN THE QUOTED CHARACTER
	$FATAL	(UIN,,<Unterminated input string>)
	JRST	INSER1		;AND COUNT AS ONLY ONE CHARACTER FOR INSERT


;CHANGE NO-CONTROL-COMMANDS FLAG

INSER4:	TXC	F2,TXTCTL
	JRST	INSER0		;DON'T COUNT ^T


;EO=1,2:
; ^V CAUSES THE NEXT CHARACTER TO BE CONVERTED TO LOWER CASE (IF UPPER CASE)
; ^V^V SETS LOWER CASE MODE UNTIL THE END OF THE TEXT STRING (OR FURTHER NOTICE)
;EO=3:
; ^A CAUSES THE NEXT CHARACTER TO BE CONVERTED TO LOWER CASE (IF UPPER CASE)
; ^A^A SETS LOWER CASE MODE UNTIL THE END OF THE TEXT STRING (OR FURTHER NOTICE)

INSLOW:	PUSHJ	P,C.VA		;SET ^V/^A FLAGS
	JRST	INS1C		;CONTINUE TO NEXT CHAR.

;EO=1,2:
; ^W CAUSES NEXT CHAR. TO BE TAKEN AS IS (STANDARD MODE)
; ^W^W SETS STANDARD MODE UNTIL END OF TEXT STRING (OR FURTHER NOTICE)
;EO=3:
; ^B CAUSES NEXT CHAR. TO BE TAKEN AS IS (STANDARD MODE)
; ^B^B SETS STANDARD MODE UNTIL END OF TEXT STRING (OR FURTHER NOTICE)

INSSTD:	PUSHJ	P,C.WB		;SET ^W/^B FLAGS
	JRST	INS1C		;CONTINUE TO NEXT CHAR.

;EO=1,2:
; ^R UNCONDITIONALLY QUOTES THE NEXT CHARACTER (TREATS AS TEXT)
;EO=3:
; ^V UNCONDITIONALLY QUOTES THE NEXT CHARACTER (TREATS AS TEXT)

INSIGR:	PUSHJ	P,GCH		;GET NEXT CHAR.
	JRST	INS1E		;TREAT AS TEXT

;^^ -- IF NEXT CHAR IS @,[,\,],^, OR _, CONVERT IT TO LC RANGE

INSSPC:	PUSHJ	P,GCH		;GET NEXT CHAR
	PUSHJ	P,CVTSPC	;CONVERT IF WARRANTED
	JRST	INS1F

;^T -- CHANGE NO-CONTROL-COMMANDS MODE

INSMAC:	TXC	F2,TXTCTL	;COMPLEMENT ^T FLAG
	JRST	INS1C		;GO ON TO NEXT CHAR
;SET ^V/^A FLAGS

C.VA:	TXON	F2,CTLVA	;SET ^V/^A FLAG -- WAS IT ON BEFORE?
	POPJ	P,		;NO
	TXZ	F2,CTLVA+CTLWWB	;YES, SET ^V^V/^A^A FLAG & CLR OTHERS
	TXO	F2,CTLVVA
	POPJ	P,

;SET ^W/^B FLAGS

C.WB:	TXON	F2,CTLWB	;SET ^W/^B FLAG -- WAS IT ON BEFORE?
	POPJ	P,		;NO
	TXZ	F2,CTLWB+CTLVVA	;YES, SET ^W^W/^B^B FLAG & CLR OTHERS
	TXO	F2,CTLWWB
	POPJ	P,
;CONVERT ALPHABETIC CH TO UPPER OR LOWER CASE ACCORDING TO CASE CONTROL FLAGS

CASE:	CAIL	CH,"A"		;IS CHAR IN UPPER CASE RANGE?
	CAILE	CH,"Z"
	CAIL	CH,"A"+40	;IS IT IN LOWER CASE RANGE?
	CAILE	CH,"Z"+40
	JRST	CASE3		;NO
CASE2:	TXNE	F2,LCASE	;PREVAILING LOWER CASE?
	TRO	CH,40		;YES, CONVERT TO LOWER
	TXNE	F2,UCASE	;PREVAILING UPPER CASE?
	TRZ	CH,40		;YES, CONVERT TO UPPER
	TXNE	F2,CTLVVA	;DOUBLE ^V/^A ON?
	TRO	CH,40		;YES, CONVERT TO LC
	TXNE	F2,CTLWWB	;DOUBLE ^W/^B ON?
	TRZ	CH,40		;YES, CONVERT TO UC
	TXZE	F2,CTLVA	;SINGLE ^V/^A ON?
	TRO	CH,40		;YES, CONVERT TO LC
	TXZE	F2,CTLWB	;SINGLE ^W/^B ON?
	TRZ	CH,40		;YES, CONVERT TO UC
CASE3:	TXZ	F2,CTLVA+CTLWB	;CLR IN CASE NO CONVERSION
	POPJ	P,



;CONVERT @, [, \, ], ^, AND _ TO THE EQUIVALENT LC CHARACTER

CVTSPC:	CAIL	CH,"["
	CAILE	CH,"_"
	CAIN	CH,"@"
	TRO	CH,40		;CONVERT TO LOWER CASE RANGE
	POPJ	P,



;CHECK FOR NON-CONTROL CHARACTERS
;IF <CH LT 10>, OR <15 LT CH LT 33>, OR <33 LT CH LT 40>,
; THEN CH IS AN ILLEGAL CONTROL-CHAR

CKNCC:	CAIGE	CH," "
	CAIG	CH,.CHCRT
	CAIGE	CH,.CHCNH
	CAIN	CH,.CHESC
	POPJ	P,		;IT IS 10-15 OR 33 OR 40+
	MOVEI	B,(CH)		;SAVE CHAR FOR ERROR MSG ROUTINE
	$FATAL	(ICT,,<Illegal control command 18 in text argument>)
;NI	INSERT AT THE POINTER A CHARACTER WHOSE 7-BIT ASCII CODE IS N
;	(BASE 10).  THE POINTER IS MOVED TO THE RIGHT OF THE NEW CHARACTER.

INS1A:	CHKEO	EO21,INS1X	;IF EO=1 SKIP NEXT STUFF
	PUSHJ	P,SKRCH		;GET CHAR AFTER I
	$FATAL	(NAI,,<No Altmode before nI>)
	CAIE	CH,.CHESC	;IT HAD BETTER BE AN ALTMODE
	$FATAL	(NAI,,<No Altmode before nI>)
INS1X:	MOVE	CH,NUM		;CH:=NUM

;INSERT CH IN DATA BUFFER AT PT

TAB2:	MOVEI	C,1		;MOVE FROM PT THROUGH Z UP 1 POSITION.
	PUSHJ	P,NROOMC
	AOS	OU,PT		;PT:=PT+1
	SOJA	OU,PUT		;STORE CH AT PT-1

;NBACKSLASH	INSERT AT THE CURRENT POINTER LOCATION THE ASCII NUMBERS
;	EQUAL TO N.

NBAKSL:	MOVE	T,[POINT 7,STAB];STORE NUMBER IN STAB MOMENTARILY
	MOVEI	C,0		;COUNT # DIGITS IN C.
	XMOVEI	A,NBAKS9	;SET DPT TO RETURN TO NBAKS9
	PUSHJ	P,DPT		;CONVERT C(B) TO ASCII AND STORE STRING IN STAB.
	MOVE	B,[POINT 7,STAB];POINTER TO NUMBER (DIGIT STRING)
	PUSHJ	P,NROOMC	;MOVE FROM PT THROUGH Z UP C POSITIONS.
NBAKS5:	MOVE	OU,PT		;POSITION TO PUT CHAR IN
	ILDB	CH,B		;GET NEXT CHAR OF THE #
	PUSHJ	P,PUT		;STORE THE CHAR
	AOS	PT		;MOVE THE POINTER
	SOJG	C,NBAKS5	;DECREMENT THE CHAR CTR
	TXZ	F2,OCTALF	;CLEAR USED-UP RADIX FLAG
	JRST	RET

NBAKS9:	IDPB	CH,T		;STORE DIGIT IN STAB
	AOJA	C,CPOPJ		;C:=C+1. RETURNS TO DPT CALL + 1 ON COMPLETION.
;NT	TYPE OUT THE STRING OF CHARACTERS STARTING AT THE RIGHT OF THE
;	POINTER AND CONTINUING THROUGH THE NTH LINE FEED ENCOUNTERED.
;	IF N IS NEGATIVE, N LINES TO THE LEFT OF THE POINTER ARE TYPED.
;T	SAME AS 1T.
;I,JT	TYPE OUT THE (I+1)TH THROUGH THE JTH CHARACTER OF THE BUFFER.

TYPE:	SKIPE	COLUMN		;AT NICE FRESH START OF A COLUMN?
	SKIPE	TYOTCT		;NO, HAS ANYTHING PRECEDED US?
	CAIA			;DON'T DO ANYTHING
	PUSHJ	P,CRR		;FIRST OUTPUT, GET TO A FRESH LINE FOR NEATNESS
				; THIS ALLOWS "<SBLAH$;0TT>" TO LINE UP NICELY
				; ON SUCCESSIVE LINES WHEN ON A VIDEO TERMINAL
	MOVEI	D,TYO		;D:=ADDRESS OF OUTPUT ROUTINE.
	SKIPE	CMFTYO		;SUPPRESSING OUTPUT DUE TO COMMAND FILE?
	MOVEI	D,CPOPJ		;YES
	SETOM	WINFLG		;SO DISPLAY DOESN'T ERASE WHAT GETS TYPED
TYPE0:	PUSHJ	P,GETARG	;C:=FIRST STRING ARGUMENT ADDRESS.
				;B:=SECOND STRING ARGUMENT ADDRESS.
TYPE1:	PUSHJ	P,CHK1		;C:=MAX(C(C),BEG), B:=MIN(C(B),Z)
	MOVE	I,C		;START GETTING CHARACTERS AT C.
TYPE3:	CAML	I,B		;DONE?
	JRST	TYPE5		;YES.
	MOVE	TT,I		;NO. GET NEXT CHAR
	IDIVI	TT,5		;THIS IS A COPY OF GETINC
	LDB	CH,BTAB(TT1)	;COPIED TO SPEED IT UP
	PUSHJ	P,(D)		;OUTPUT IT
	AOJA	I,TYPE3		;LOOP

TYPE5:	TLZE	D,-1		;*** JUST TO MAKE SURE
	HALT	.+1		;*** DUH?
	CAIN	D,PPA		;D=PPA?
	TXNE	FF,ARG2		;[251] YES, "P" COMMAND, I,JP FORM?
	JRST	TYPE7		;[251] DO NOT APPEND <FF>
	MOVEI	CH,.CHFFD	;[251] IF PUNCHING, APPEND FF.
	TXNE	FF,PCHFLG	;[251] IS THIS AN "N" SEARCH?
	TXNE	FF,FORM		;[251] DID LAST Y,A TERMINATE ON A FORM FEED?
	PUSHJ	P,PPA		;[251] APPEND A FORM FEED

TYPE7:	TXNE	FF,TYOF		;[251] ANY OUTPUT LEFT LYING AROUND?
	PJRST	TYOOUT		;[251] YEAH, FORCE IT OUT
	POPJ	P,		;[251] NO, JUST RETURN
PPA:	TXNN	FF,UWRITE	;ERROR IF NO OUTPUT FILE
	$FATAL	(NFO,,<No file for output>)
PPA00:	MOVE	A,OUTSWT	;[250] GET OUTPUT SWITCHES
	TXNN	FF,SEQF		;[250] IF ALREADY LINE-SEQUENCED FILE, OR
	TXNE	A,GENLSN	;[250] IF GENERATING LINE SEQUENCE NUMBERS
	JRST	PPA02		;[250] THEN DO LSN PROCESSING
PPA01:	SOSGE	OBUF+.BFCTR	;[250] ROOM IN BUFFER FOR ANOTHER CHARACTER?
	JRST	PPA01O		;[250] NO, GET ANOTHER BUFFER
	IDPB	CH,OBUF+.BFPTR	;CH TO OUTPUT BUFFER.
	POPJ	P,		;RETURN

PPA01O:	PUSHJ	P,PPAOU		;[250] ADVANCE OUTPUT BUFFER
	JRST	PPA01		;[250] AND TRY AGAIN
;HERE FOR LINE SEQUENCE NUMBER PROCESSING OF SOME SORT

PPA02:	TXNN	FF,SEQUIN	;WAS LAST CHAR AN EOL OR BEG OF BUFR?
	JRST	PPA03		;NO, MIDDLE OF LINE, CHECK FOR EOL

;BEGINING OF A LINE, NEED TO PREFIX A LSN

	MOVE	AA,OUTSWT	;GET OUTPUT SWITCHES
	TXNE	AA,SUPLSN	;SUPPRES SEQ # ?
	JRST	PPA02F		;[250] YES, SKIP PADDING
	PUSHJ	P,PPAZNL	;[250] NO, PAD WITH NULLS TO WORD BOUNDRY
PPA02F:	TXZ	FF,SEQUIN	;MOVED DOWN FROM PPA07-1
	TXNE	FF,SEQF		;REMOVE PPA06 LABEL
				;GENERATE NEW LSN OR OUTPUT EXISTING LSN?
	JRST	PPA04		;OUTPUT EXISTING LSN
	CAIN	CH,.CHFFD	;HANDLE A FORM-FEED?
	JRST	PPA14		;GO DO IT.
	MOVE	A,LSNCTR	;GET LAST CREATED LSN WITH BIT 35 ON
	ADD	A,[BYTE (7)106,106,106,107]  ;& ADD ASCII 10 TO IT
	MOVE	T,A
	AND	T,[BYTE (7)60,60,60,60]
	LSH	T,-3
	MOVE	TT,A
	AND	TT,[BYTE (7)160,160,160,160]
	IOR	T,TT
	SUB	A,T
	ADD	A,[BYTE (7)60,60,60,60]
	MOVEM	A,LSNCTR	;STORE NEW LSN
PPA02L:	AOS	OBUF+.BFPTR	;& OUTPUT THE 5 DIGITS + BIT 35
	HRRZ	T,OBUF+.BFPTR	;EXTRACT BYTE POINTER ADDRESS FIELD
	MOVEM	A,(T)		;STASH THE 5 FULL BYTES
	MOVEI	A,.CHTAB	;FOLLOWED BY TAB
	IDPB	A,OBUF+.BFPTR
	MOVNI	A,6		;[250] ACCOUNT FOR THE 6 CHARACTERS
	ADDM	A,OBUF+.BFCTR	;[250] HALLUCINATED BY THE ABOVE
PPA03:	PUSHJ	P,CKEOL		;IS THIS CHAR AN EOL?
	JRST	PPA01		;NO
	TXO	FF,SEQUIN	;YES, SET EOL FLAG
	CAIN	CH,.CHFFD	;[250] A FORM FEED?
	TXNE	AA,SUPLSN	;[250] YES, SUPPRESSING LSN'S?
	JRST	PPA01		;[250] OUTPUT CHARACTER DIRECTLY
	PUSHJ	P,PPAZCL	;[250] PAD TO WORD BOUNDRY, WITH <CR><LF>
	JRST	PPA14		;MARK THE PAGE
;OUTPUT EXISTING LSN WITH LEADING ZEROS

PPA04:	MOVEI	A,4		;INIT 5 DIGIT CTR
	MOVEM	A,LSNCTR
	MOVE	A,[<"00000">B34];INIT LSN ACCUMULATOR
	CAIL	CH,"0"		;IS CURRENT CHAR A DIGIT?
	CAILE	CH,"9"
	JRST	PPA08		;NO, FILL IN 5 SPACES
	JRST	PPA12
PPA10:	SOSGE	LSNCTR		;DONE 5 DIGITS YET?
	JRST	PPA09		;YES
PPA12:	LSH	A,7		;PUT DIGIT INTO ACCUMULATOR
	DPB	CH,[POINT 7,A,34]
	CAML	I,B
	JRST	PPA09
	PUSHJ	P,GETINC	;GET NEXT BUFFER CHAR
	CAIL	CH,"0"		;IS IT A DIGIT?
	CAILE	CH,"9"
	JRST	PPA09		;NO
	JRST	PPA10		;YES, STORE IT

PPA08:	MOVE	A,[<"     ">B34];GET 5 SPACES
PPA08X:	CAIE	CH," "		;SPACE?
	JRST	PPA08B		;NO, INSERT 5 SPACES
	SOSGE	LSNCTR		;HAVE WE SEEN 5 SPACES
	JRST	PPA08C		;IF SO CHECK FOR TAB
	PUSHJ	P,GETINC	;GET NEXT CHARACTER
	JRST	PPA08X		;TRY AGAIN

;	HERE IF WE'VE SEEN 5 SPACES MAY BE TECO BLANK SEQUENCE NUMBER,
;	SOS PAGE MARK, OR SPACES THE USER HAS INSERTED.

PPA08C:	PUSHJ	P,GETINC	;PICK IT UP AND
	CAIE	CH,.CHCRT	;TEST FOR CR (FOR SOS) OR
	CAIN	CH,.CHTAB	;TAB TO BE OUTPUT WITH SPACES
	JRST	PPA09		;OUTPUT 5 SPACES + CHAR IN CH
;	JRST	PPA08B		;MUST BE USER'S SPACES!

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;	HERE IF NOT 5 SPACES FOLLOWED BY TAB OR CR.  THIS IMPLIES
;	THAT ANY SPACES SEEN WERE USER'S TEXT.

PPA08B:	SUBI	I,5		;BACK UP TO FIRST CHARACTER
	ADD	I,LSNCTR	;AND OUTPUT IT WITH BLANK LSN
	PUSHJ	P,GETINC	;GET PROPER CHARACTER
	MOVE	AA,OUTSWT	;GET SWITCHES
	TXNE	AA,SUPLSN	;SUPPRESS SEQ#
	JRST	PPA01		;YES
	TRO	A,1		;NO, SET BIT 35
	JRST	PPA02L		;OUTPUT SEQ# WITH A TAB
PPA09:	MOVE	AA,OUTSWT	;GET SWITCHES
	TXNE	AA,SUPLSN	;SUPPRESS SEQ#'S?
	JRST	PPA13		;YES
	TRO	A,1		;SET BIT 35
	AOS	OBUF+.BFPTR	;& OUTPUT SEQ #
	HRRZ	T,OBUF+.BFPTR	;EXTRACT ADDRESS FIELD FROM BYTE POINTER
	MOVEM	A,(T)		;STASH 5 BYTES
	MOVNI	A,5		;[250] ADJUST THE CHAR COUNT
	ADDM	A,OBUF+.BFCTR	;[250] BY 5 DIGIT'S WORTH
	JRST	PPA03		; CONTINUE

PPA13:	CAIE	CH,.CHCRT	;ELIMINATE CR (FOR SOS)
	CAIN	CH,.CHTAB	;IS TERMINATOR A TAB?
	AOSA	OBUF+.BFCTR	;YES, FIX POINTER AND
	JRST	PPA01		;NO, OUTPUT IT
	POPJ	P,		;OMIT IT
;
;	HERE TO INSERT A SOS STYLE PAGE MARK.
;
PPA14:	MOVE	A,OBUF+.BFPTR	;[250] A BIT OF PARANOIA
	TLNE	A,320000	;[250] SHOULD BE ON A WORD BOUNDRY!
	HALT	.+1		;[250] HO HUM
	MOVE	A,[<ASCII\     \>+1]  ;[250] FIVE SPACES + B35
	AOS	OBUF+.BFPTR	;OUTPUT IT
	HRRZ	T,OBUF+.BFPTR	;ADDRESS FROM BYTE POINTER
	MOVEM	A,(T)		;STASH THESE FIVE BYTES
	MOVE	A,[BYTE(7) .CHCRT,.CHFFD,0,0,0]  ;AND CR,FF
	AOS	OBUF+.BFPTR	;INCREMENT THE POINTER
	HRRZ	T,OBUF+.BFPTR	;INCREMENTED ADDRESS
	MOVEM	A,(T)		;AND DEPOSIT
	MOVNI	A,12		;[250] ALLOW FOR 10 CHARACTERS
	ADDM	A,OBUF+.BFCTR	;[250] MUNGED BY THE ABOVE
	TXO	FF,SEQUIN	;SET THE EOL FLAG
	MOVE	A,[<ASCII\00000\>+1]  ;[250] RESET THE LSN
	MOVEM	A,LSNCTR
	POPJ	P,		;[] AND RETURN
PPAZCL:	MOVEI	A,.CHCRT	;[250] CARRIAGE RETURN
	PUSHJ	P,PPAZZC	;[250] STUFF IN BUFFER
	MOVEI	A,.CHLFD	;[250] SECOND HALF OF <CR><LF>
	PUSHJ	P,PPAZZC	;[250] STUFF IN BUFFER
PPAZNL:	MOVE	A,OBUF+.BFPTR	;[250] OUTPUT BYTE POINTER
	TLNN	A,320000	;[250] ON A WORD BOUNDRY?
	JRST	PPAZNW		;[250] YES
PPAZNO:	SETZ	A,		;[250] NO
	PUSHJ	P,PPAZZC	;[250] PAD WITH A NULL
	JRST	PPAZNL		;[250] KEEP WORKING ON IT

PPAZNW:	SKIPG	A,OBUF+.BFCTR	;[250] ROOM LEFT IN BUFFER
	JRST	PPAZNZ		;[250] EMPTY, GET FRESH BUFFER
	CAIGE	A,^D10		;[250] LSN'S NEED AT LEAST TWO WORDS
	JRST	PPAZNO		;[250] PAD OUT BUFFER
	POPJ	P,		;[250] ALL SET

PPAZNZ:	PUSHJ	P,PPAOU		;[250] GET FRESH BUFFER
	JRST	PPAZNW		;[250] VERIFY IT


PPAZZC:	SOSGE	OBUF+.BFCTR	;[250] ROOM FOR ANOTHER CHARACTER?
	JRST	PPAZZO		;[250] NO, NEED ANOTHER BUFFER
	IDPB	A,OBUF+.BFPTR	;[250] STUFF CHARACTER
	POPJ	P,		;[250] RETURN

PPAZZO:	PUSHJ	P,PPAOU		;[250] FLUSH OUTPUT BUFFER
	JRST	PPAZZC		;[250] TRY AGAIN


PPAOU:	AOS	BOCNT		;[250] COUNT BUFFERED OUT'S FOR EP
	OUT	OUTCHN,0	;[250] BUFFERED MODE, ADVANCE TO NEW BUFFER
	POPJ	P,		;[250] RETURN TO FILL EMPTY BUFFER
	GETSTS	OUTCHN,AA	;[250] GET OUTPUT I/O STATUS
	TXNE	AA,IO.ERR	;[250] ACTUAL I/O ERROR?
	JRST	PPAOUE		;[250] YES, REPORT IT
	MOVE	A,OUCHR		;..
	TXNE	A,DV.MTA	;..
	TXNN	AA,IO.EOT	;[250] IF MTA AND EOT
	POPJ	P,		;[250] NO, IGNORE (???)
PPAOUE:	SKIPA	B,AA		;[250] MAGTAPE HIT EOT, CALL THAT ERROR TOO

OUTERR:	GETSTS	OUTCHN,B	;SAVE ERROR FLAGS
	PUSHJ	P,ZAPOU		;ZAP ANY OUTPUT DEVICE
	TXZ	FF,UWRITE+UBAK	;CLEAR OUTPUT FILE OPEN INDICATOR.
	$FATAL (OUT,,<Output error 11 - output file 01 closed>)
;PW	OUTPUT THE ENTIRE BUFFER, FOLLOWED BY A FORM FEED CHARACTER.
;	TO THE SELECTED OUTPUT DEVICE.  BUFFER IS UNCHANGED AND POINTER
;	IS UNMOVED.
;P	IS IDENTICAL TO PWY.
;NP	IS IDENTICAL TO PP...P (P PERFORMED N TIMES).
;I,JP	OUTPUTS (I+1)TH THROUGH JTH CHARACTERS OF BUFFER.  NO FORM
;	FEED IS PUT AT THE END.  BUFFER UNCHANGED; POINTER UNMOVED.

PUNCHA:	MOVEI	D,PPA		;SELECT PPA FOR OUTPUT
	TXNE	FF,ARG2		;I,JP?
	JRST	TYPE0		;YES. GET STRING ARGUMENTS AND OUTPUT.
	MOVE	E,B		;NO. E:=N
	PUSHJ	P,PKRCH		;PEEK AHEAD ONE COMMAND CHARACTER
	 SETO	CH,		;NONE LEFT
	MOVE	T,CH		;PROTECT PEEK'ED CHARACTER
	TRZ	T,40		;FILTER L.C.
	JUMPL	E,CPOPJ		;IF N LT 0, IGNORE P.
	CHKEO	EO21,PUN1	;OLD STYLE P ALWAYS GIVES FORM FEED
	CAIE	T,"W"		;PW ALWAYS GIVES FORM FEED
	TXO	FF,PCHFLG	;OTHERWISE, FORM GOES OUT ONLY IF FORM CAME IN
PUN1:	PUSHJ	P,PUNCHR	;PUNCH OUT BUFFER
	SKIPE	COMCNT		;IF NO COMMANDS LEFT
	CAIE	T,"W"		;OR COMMAND IS NOT W
	JRST	PUN3		;READ NEXT PAGE
	CAIG	E,1		;ARG DOWN TO 1 YET?
	PUSHJ	P,RCH		;YES, THROW AWAY THE W
PUN4:	MOVE	C,Z
	CAMN	C,BEG		;EMPTY BUFFER?
	TXNN	FF,FINF		;NO. QUIT ON EOF
	SOJG	E,PUN1		;YES. E:=E-1. DONE?
CPOPJ:	POPJ	P,		;YES

PUN2:	MOVE	OU,BEG		;IF NOTHING READ IN, CLEAR THE BUFFER
	MOVEM	OU,PT
	TXZ	FF,FORM		;AND THE FORM FEED FLAG
	JRST	YANK51		;SET Z=BEG & POPJ

PUNCHR:	MOVE	C,BEG		;OUTPUT DATA BUFFER.
	MOVE	B,Z
	MOVEI	D,PPA
	CAME	B,C		;IS PAGE BUFFER EMPTY?
	JRST	TYPE1		;NO; IF SEQUENCED FILE, START PAGE WITH SEQ#
				;EDIT 173 OBSOLECES PUNCH1

	TXNE	FF,FORM		;YES, IS THERE A FORM-FEED ON THIS BLANK PAGE?
	JRST	TYPE5		;YES, OUTPUT IT
	POPJ	P,		;NO, DON'T OUTPUT ANYTHING

PUN3:	TXNE	FF,UREAD	;ANY INPUT FILE?
	TXNE	FF,FINF		;DONT TRY TO READ IF NO DATA LEFT
	JRST	PUN2
	PUSHJ	P,YANK1		;RENEW BUFFER
	JRST	PUN4		;CONTINUE
;NJ	MOVE THE POINTER TO THE RIGHT OF THE NTH CHARACTER IN THE
;	BUFFER. (I.E., GIVE "." THE VALUE N.)
;J	SAME AS 0J.

JMP:	ADD	B,BEG		;PT:=N+BEG
	JRST	JMP1



;NR	SAME AS .-NJ.

REVERS:	PUSHJ	P,CHK2		;MAKE SURE THERE IS AN ARGUMENT
	MOVNS	B		;B:=-C(B)
	SKIPA

;NC	SAME AS .+NJ.  NOTE THAT N MAY BE NEGATIVE.

CHARAC:	PUSHJ	P,CHK2		;MAKE SURE THERE IS AN ARGUMENT
	ADD	B,PT		;B:=PT+C(B)

;IF B LIES BETWEEN BEG AND Z, STORE IT IN PT.

JMP1:	PUSHJ	P,CHK		;IS C(B) WITHIN DATA BUFFER?
	MOVEM	B,PT		;YES. PT:=C(B)
	JRST	RET

;NL	N GT 0:	MOVE POINTER TO THE RIGHT, STOPPING WHEN IT HAS
;		PASSED OVER N LINE FEEDS.
;	N LT 0:	MOVE POINTER TO THE LEFT; STOP WHEN IT HAS PASSED
;		OVER N+1 EOL'S AND THEN MOVE IT TO THE RIGHT OF
;		THE LAST EOL PASSED OVER.
;L	SAME AS 1L.

LCMD:	PUSHJ	P,LINE		;DO THE WORK
	JRST	RET		;BACK TO COMMAND PROCESSOR

LINE:	TXNE	FF,ARG2		;ERROR IF THERE ARE 2 ARGS
	 $FATAL	(TAL,,<Two arguments with L>)
	PUSHJ	P,GETARG	;NO. C:=FIRST STRING ARGUMENT ADDRESS,
				;B:=SECOND STRING ARGUMENT ADDRESS.
	XOR	B,C
	XORM	B,PT
	POPJ	P,		;DONE
;NK	PERFORM NL BUT DELETE EVERYTHING THE POINTER MOVES OVER.
;M,NK	DELETE THE (M+1)TH THROUGH THE NTH CHARACTER FROM THE BUFFER.
;	THE POINTER IS THEN PUT WHERE THE DELETION TOOK PLACE.
;K	SAME AS 1K

KILL:	PUSHJ	P,GETARG	;C:=FIRST STRING ARG. ADDRESS
				;B:=SECOND STRING ARG. ADDRESS
	PUSHJ	P,CHK1		;C:=MAX(C(C),BEG), B:=MIN(C(B),Z)
	MOVEM	C,PT		;PT:=C(C)
	SUB	B,C		;B:=NO. OF CHARACTERS TO KILL.
	JUMPE	B,RET		;IF NONE, RETURN. OTHERWISE, FALL INTO DELETE


;ND	DELETE N CHARACTERS FROM THE BUFFER: IF N IS POSITIVE, DELETE
;	THEM JUST TO THE RIGHT OF THE POINTER; IF N IS NEGATIVE, DELETE
;	THEM JUST TO ITS LEFT.
;D	SAME AS 1D

DELETE:	PUSHJ	P,CHK2		;MAKE SURE B CONTAINS AN ARGUMENT
	PUSHJ	P,DELN		;DELETE "N" CHARACTERS AS APPROPRIATE
	JRST	RET		;RETURN


;DELETE C(B) CHARACTERS FROM "."

DELN:	MOVM	C,B
	MOVNS	C		;C:=-ABS(B)
	ADD	B,PT		;B:=PT+B
	PUSHJ	P,CHK		;STILL IN DATA BUFFER?
	CAMGE	B,PT		;YES. IS N NEGATIVE?
	MOVEM	B,PT		;YES. MOVE PT BACK FOR DELETION.
	JUMPE	C,RET		;THE SIMPLE CASE IS REALLY SIMPLE!
	PUSHJ	P,NROOM		;MOVE FROM PT+ABS(C) THROUGH Z DOWN ABS(C) POSITIONS
DELED:	MOVNI	B,3		;COMMAND EXECUTION COUNT
	MOVEM	B,TOOBIG	;TO TRY TO RECLAIM MEMORY PAGES
	POPJ	P,		;ALL DONE HERE



;HK - DELETE ENTIRE BUFFER

HK:	MOVE	B,BEG		;START OF BUFFER
	MOVEM	B,PT		;SET NEW "."
	MOVEM	B,Z		;AND NEW END OF BUFFER
	JRST	DELED		;NOTE SOMETHING DELETED
;ROUTINE TO CHECK DATA BUFFER POINTER
;CALL	MOVE B,POINTER
;	PUSHJ P,CHK
;	RETURN IF B LIES BETWEEN BEG AND Z

CHK:	CAMG	B,Z
	CAMGE	B,BEG
	 $FATAL	(POP,,<Attempt to move pointer off page with 00>)
	POPJ	P,

;ROUTINE TO PUT STRING ARGUMENT ADDRESSES WITHIN DATA BUFFER
;BOUNDS AND CHECK ORDER RELATION.
;CALL	MOVE C,FIRST STRING ARGUMENT ADDRESS
;	MOVE B,SECOND STRING ARGUMENT ADDRESS
;	PUSHJ P,CHK1
;	RETURN

CHK1:	CAMLE	C,B		;C GT B?	(CHECK FIRST!)
	 $FATAL	(SAL,,<Second argument less than first>)
	CAMGE	C,BEG		;C:=MAX(C(C),BEG)
	MOVE	C,BEG		;..
	CAMLE	C,Z		;C:=MIN(C(C),Z)
	MOVE	C,Z		;..
	CAMGE	B,BEG		;B:=MAX(C(B),BEG)
	MOVE	B,BEG		;..
	CAMLE	B,Z		;B:=MIN(C(B),Z)
	MOVE	B,Z		;
	CAMN	C,BEG		;YES; BEG OF BUFFER?
	JRST	CHK1.5		;YES
	MOVE	TT,C		;NO; BEG OF LINE?
	SUBI	TT,1		;GET PREV CHAR
	IDIVI	TT,5		;WORD ADDRESS
	LDB	CH,BTAB(TT1)	;
	PUSHJ	P,CKEOL		;PREV CHAR = EOL?
	POPJ	P,		;NO; RETURN
CHK1.5:	TXO	FF,SEQUIN	;YES; SET FLAG
	POPJ	P,		;RETURN


;ROUTINE TO RETURN CURRENT ARGUMENT IN B
;ASSUMES A VALUE OF 1 WITH SIGN OF LAST OPERATOR IF THERE IS NO CURRENT ARGUMENT
;CALL	PUSHJ P,CHK2
;	RETURN WITH B:=CURRENT ARG.,+1 OR -1

CHK2:	TXOE	FF,ARG		;IS THERE AN ARGUMENT?
	POPJ	P,		;YES. IT'S ALREADY IN B.
CHK22:	LDB	B,[XWD 340200,DLIM]  ;B:=1 WITH SIGN OF LAST OPERATOR.
	MOVNS	B
	AOJA	B,CPOPJ
;DECREMENT ASCII BYTE PTR

DBP:	ADD	TT,[7B5]	;BACK UP POINTER
	JUMPGE	TT,.+2		;SKIP IF P NOT NOW 44 OR MORE
	SUB	TT,[43B5+1]	;FIX FUNNY POINTERS
	POPJ	P,

;ROUTINE TO ADJUST BYTE ASCII BYTE POINTER IN TT BY A BYTES

ADJUST:	IDIVI	A,5		;LEAVES WORDS WORTH OF MODIFICATION IN A
				;AND LEFTOVER BYTE QUANTITY IN AA
	ADD	TT,A		;ACCOUNT FOR FULL WORDS'S WORTH
	LSH	AA,36		;PUT BYTE COUNT IN P FIELD
	IMULI	AA,7		;CHANGE TO BIT COUNT
	SUB	TT,AA		;MODIFY BYTE POINTER P FIELD
	JUMPGE	TT,CPOPJ	;EXIT UNLESS FUNNY RESULTANT P FIELD
	CAILE	AA,0		;FUNNY P; HOW TO FIX IT ??
	ADD	TT,[43B5+1]	;ADD IF POSITIVE ADJUSTMENT
	CAIGE	AA,0
	SUB	TT,[43B5+1]	;SUBTRACT FOR NEGATIVE ADJUSTMENT
	POPJ	P,
;ROUTINE TO SKIP ON NON-UPPER CASE CHARACTER

SNUPER:	CAIL	CH,101
	CAILE	CH,132
	AOS	(P)
	POPJ	P,

;ROUTINE TO SKIP ON NON-LOWER CASE LETTER

SNLOWR:	CAIL	CH,"a"
	CAILE	CH,"z"
	AOS	(P)
	 POPJ	P,

;ROUTINE TO SKIP IF CHARACTER SHOULD BE FLAGGED (WRONG CASE OR CONTROL)

SFLAGC:	CAIGE	CH," "		;IS CHARACTER A CONTROL ??
	JRST	SFLGC2		;YES, SO IT IS A FLAGGED CHARACTER
	TXNN	F2,LINCHR+TYMSGF;DON'T FLAG IF TTY LC OR TYPING MESSAGE
	SKIPGE	TYCASF		;CASE SWITCH UPPER ??
	POPJ	P,		;CASE SWITCH 0, NO FLAG
	SKIPG	TYCASF		;SKIP IF FLAGGING UPPERS
	JRST	SFLGC1		;FLAGGING LOWERS
	PUSHJ	P,SNUPER	;SKIP IF THIS CHAR NOT UPPER CASE
	AOS	(P)		;SKIP, BECAUSE CH IS UPPER CASE AND WE'RE FLAGGING THEM
	POPJ	P,
SFLGC2:	CAIE	CH,.CHTAB	;<TAB>?
	CAIN	CH,.CHCRT	;OR <CR>?
	POPJ	P,		;YES, NO FLAGGING
	CAIE	CH,.CHESC	;ALTMODE AS CONTROL IS NOT ^[, SO NO FLAG
	AOS	(P)		;YES
	POPJ	P,
SFLGC1:	PUSHJ	P,SNLOWR	;SWITCH LOWER, IS THIS CH LOWER ??
	AOS	(P)
	POPJ	P,		;NO, SO NO FLAG

CFLAG=="'"			;CHARACTER FOR FLAGGING WRONG CASE
	SUBTTL	SEARCHING

;FN, FS, F_, FD, FK, AND FR COMMANDS

FCMD:	PUSHJ	P,SKRCH		;GET CHAR AFTER F
	$FATAL	(MEF,,<Macro ending with F>)
	TXO	F2,S.REPL	;SET F-SEARCH FLAG
	MOVEI	T,FCTABL	;INDEX DISPATCH TABLE
	PUSHJ	P,DISPAT
	$FATAL	(IFC,,<Illegal character "00" after F>)

;F-COMMAND DISPATCH TABLE

FCTABL:	XWD	SERCHP,	"N"	;FN SEARCH
	XWD	SERCH,	"S"	;"S" SEARCH AND REPLACE
	XWD	LARR,	"_"	;"_" SEARCH AND REPLACE
	XWD	FD,	"D"	;"S" SEARCH AND DELETE
	XWD	FK,	"K"	;"S" SEARCH AND KILL (OLD "." TO NEW ".")
	XWD	FR,	"R"	;REPLACE WITH NO SEARCH
	XWD	FV,	"V"	;RETURN LAST STRING "VALUE" (SIZE)
	XWD	0,	0

FD:	TXOA	F2,S.DELE	;DELETE THE MATCHED STRING
FK:	TXO	F2,S.KILL	;KILL INCLUSIVELY TO MATCHED STRING
	TXZ	F2,S.REPL	;NOT A "REPLACE" OPERATION
	JRST	SERCH		;GO DO THE SEARCH

FR:	TXNE	FF,ARG!ARG2	;FR DOESN'T UNDERSTAND NUMBERS IN FRONT
	$FATAL	(FRA,,<FR command with numeric arguments illegal>)
	MOVE	E,VVAL		;GET LAST STRING ARGUMENT SIZE
	MOVNM	E,VVALFR	;SAVE FOR "-ND" EFFECT
	TXC	F2,S.REPL!S.FRCM;NOTE JUST FR COMMAND, NO SEARCH WANTED
	PUSHJ	P,INSERA	;GO DO THE "RETROACTIVE" REPLACE
	JRST	RET		;RETURN F-COMMAND STYLE

FV:	MOVN	A,VVAL		;LAST STRING SIZE
	JRST	VALRET		;RETURN THAT AS VALUE
;_ SEARCH

LARR:	TXOA	FF,FINDR	;FINDR:=1 FOR LEFT ARROW SEARCH

;N SEARCH

SERCHP:	TXO	FF,PCHFLG	;PCHFLG:=1 FOR N SEARCH

;S SEARCH

SERCH:	TXZ	F2,S.MINS	;CLEAR MINUS SEARCH FLAG
	MOVE	E,PT		;OLD POINT
	MOVEM	E,SCHPT		;SAVE IN CASE THE SEARCH FAILS
	MOVEM	E,UPPERB	;PT IS UPPER BOUND ON BACKWARD SEARCHES
	PUSHJ	P,SETQTE	;SETUP QUOTING CHARACTERS
	SETZ	E,		;ASSUME FIRST OCCURRENCE IN CASE BOUNDED
	TXZE	FF,ARG2		;TWO ARGS = BOUNDED SEARCH
	JRST	BOUNDS		;BOUNDED SEARCH
	SETZM	LOWERB		;SAVE AS DEFAULT LOWER BOUND
	PUSHJ	P,CHK2		;GET 1ST ARG
	SKIPE	B		;ZERO?
	JRST	SERC33		;NO
	TXNE	FF,ARG		;THERE MUST BE NO ARG
	$FATAL	(ISA,,<06 Argument with 00 search>)
SERC33:	SKIPGE	E,B		;GET ARG WHERE IT WANTS IT
	TXOA	F2,S.MINS	;MINUS SEARCH
	SETZM	UPPERB		;NO UPPERBOUND ON FORWARD SEARCHES
	JRST	SERCHA
;HERE IF BOUNDED SEARCH, SET UP BOUNDS

BOUNDS:	PUSHJ	P,GETAG6	;GET THE STRING POINTERS
	TXZ	FF,PCHFLG!FINDR!ARG	;FN + N GO TO FS AND S
	CAMLE	C,Z		;TOO BIG
	MOVE	C,Z
	CAMGE	C,BEG		;TOO SMALL
	MOVE	C,BEG
	MOVEM	C,PT		;PLACE TO START SEARCHIN'
	CAML	B,C		;MINUS IMPLIED?
	JRST	SAVESH		;NO, SAVE BOUNDS
	EXCH	C,B		;YES, EXCHANGE ARGS
	TXO	F2,S.MINS	;SAY MINUS SEARCH
SAVESH:	MOVEM	C,LOWERB
	MOVEM	B,UPPERB

;ADJUST UPPER AND LOWER BOUNDS

SERCHA:	MOVE	A,BEG		;GOOD LOWER BOUND
	MOVE	B,Z		;GOOD UPPER BOUND
	CAMLE	A,LOWERB
	MOVEM	A,LOWERB
	CAMGE	B,LOWERB
	MOVEM	B,LOWERB
	SKIPE	UPPERB		;FIX ZERO UPPER BOUND
	CAMGE	B,UPPERB
	MOVEM	B,UPPERB
	CAMLE	A,UPPERB
	MOVEM	A,UPPERB
	MOVMS	E		;FOR CORRECT MINUS SERCH
	MOVEI	CH,.CHESC	;USE ALT-MODE DELIMITER IF NO @ SEEN
	TXZN	FF,SLSL		;@ SEEN?
	JRST	SERCHB		;NO, TERMINATOR = ALTMODE
	PUSHJ	P,SKRCH		;YES. CH:=USER SPECIFIED DELIMITER.
	$FATAL	(USR,,<Unterminated search command>)


;DETERMINE WHETHER WE CAN USE THE PREVIOUS PATTERN

SERCHB:	MOVEM	CH,B		;B:=PATTERN SOURCE STRING DELIMITER
	MOVEM	CH,FSNTRM	;SAVE DELIMITER FOR FS INSERTION
	SETZM	SCNEST		;SEARCH NEST LEVEL IS ZERO
	PUSHJ	P,SKRCH		;LOOK AHEAD 1 CHARACTER
	$FATAL	(USR,,<Unterminated search command>)
	CAIE	CH,(B)		;IS IT THE DELIMITER?
	JRST	SERCHT		;NO, AN ARGUMENT IS GIVEN
	SKIPL	SCHCTR		;YES, USE PREVIOUS PATTERN STRING
				; UNLESS THERE WAS NONE OR LAST HAD ERROR
	$FATAL	(SNA,,<Initial search with no argument>)
	SKIPN	SCTLGA		; BUT NOT IF REMEMBERED PATTERN SOURCE USED ^GI
	JRST	SCH.E		;OK, USE PREVIOUS MATRICES

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;MOVE A NEW PATTERN SOURCE TO STORAGE

SERCHT:	TXZ	F2,XMATCH	;CLEAR EXACT MATCH FLAG
	STORE	A,SMATRX,SMATRX+SCLRLN-1,0 ;CLEAR PREVIOUS MATRICES
	SETZM	SCHCTR		;CLEAR SOURCE PATTERN LENGTH COUNTER
	SETZM	SCTLGA		;ASSUME PATTERN SOURCE DOESN'T USE ^GI
	MOVE	AA,[POINT 7,SCHARG] ;POINT TO START OF STORAGE AREA
	JRST	SERCHD		;1ST CHARACTER ALREADY IN

SERCHC:	PUSHJ	P,SKRCH		;GET NEXT CHARACTER OF PATTERN SOURCE
	$FATAL	(USR,,<Unterminated search command>)
SERCHD:	CAME	CH,CHQTE	;QUOTING CHARACTER?
	CAMN	CH,CHQTE2	;OR ALTERNATE QUOTING CHARACTER?
	JRST	SERCHG		;YES, NEXT CHARACTER IS TEXT
	CAIN	CH,(B)		;THE DELIMITER?
	JRST	SERCHX		;YES
	CAMN	CH,CCQTE	;CONTROL-CHARACTER QUOTER?
	JRST	SERCHU		;YES
	TXNE	F2,TXTCTL	;CONTROL-CHARACTER QUOTE FLAG ON?
	JRST	SERCHF		;YES, LOWER/UPPER CASE QUOTERS NORMAL TEXT
;RDH	CAME	CH,LCQTE	;LOWER-CASE QUOTER?
;RDH	CAMN	CH,UCQTE	;UPPER-CASE QUOTER?
;RDH	TXO	F2,XMATCH	;YES, SET EXACT MATCH FLAG

SERCHF:	AOS	A,SCHCTR	;BUMP STRING COUNTER
	CAILE	A,SRCHMX	;STILL FIT IN STORE?
	$FATAL	(STL,,<Search string too long>)
	IDPB	CH,AA		;YES, STORE CHARACTER
	JRST	SERCHC		; AND GO BACK FOR MORE

SERCHG:	AOS	A,SCHCTR	;COUNT THE QUOTING CHARACTER
	CAILE	A,SRCHMX	;WILL IT FIT?
	$FATAL	(STL,,<Search string too long>)
	IDPB	CH,AA		;YES, STORE IT
	PUSHJ	P,SKRCH		;GET NEXT CHARACTER
	$FATAL	(USR,,<Unterminated search command>)
	JRST	SERCHF		; AND STORE IT AS TEXT

SERCHU:	TXC	F2,TXTCTL	;COMPLEMENT CONTROL COMMAND SWITCH
	JRST	SERCHF
SERCHX:	TXZ	F2,TXTCTL	;REFRESH CONTROL-CHARACTER QUOTE FLAG
	MOVE	B,SCHCTR	;SET SOURCE PATTERN LENGTH COUNTER
	MOVE	AA,[POINT 7,SCHARG] ; AND POINTER
	MOVEI	D,0		;START AT BEGINNING OF PATTERN

;Set up a 131 by 36 bit table based on the pattern source.
;The table is implemented as a four word by 36 table, with the first
; 32 bits of the words used for the four portions of the ASCII character
; set (i.e. 0-37, 40-77, 100-137, 140-177) and three of the bits left over
; in the last word used for the "bogus" characters BEGPAG, ENDPAG, and
; SPCTAB.  This is a little harder to set up for single letters in the
; pattern source, but is much easier for ranges and makes the fast search
; algorithm setup much faster.  The table is then rotated into the old
; TECO 36 by 131 bit table for the actual search matrix.

SCH.1:	ILDB	CH,AA		;CH:=NEXT PATTERN SOURCE CHARACTER
	SOJL	B,SCH.8		;END OF STRING?
	CAME	CH,CHQTE	;QUOTING CHARACTER?
	CAMN	CH,CHQTE2	;OR ALTERNATE QUOTING CHARACTER?
	JRST	CNTLQ		;YES, ACCEPT NEXT CHARACTER VERBATIM
	CAMN	CH,CCQTE	;CONTROL-CHARACTER QUOTING?
	JRST	CNTLT		;YES, TOGGLE CONTROL-CHAR CONTROL
	MOVEI	T,S2TABL	;NORMAL CONTROL-CHARACTER DISPATCH
	TXNE	F2,TXTCTL	;CONTROL-CHARACTER QUOTE FLAG ON?
	MOVEI	T,S3TABL	;YES, OTHER CONTROL'S ARE TEXT
	PUSHJ	P,DISP1		;DISPATCH ON SPECIAL CONTROL'S
	CAMN	CH,LCQTE	;LOWER-CASE QUOTER?
	JRST	CNTLV		;YES, NEXT CHAR MUST BE LOWER-CASE ONLY
	CAMN	CH,UCQTE	;UPPER-CASE QUOTER?
	JRST	CNTLW		;YES, NEXT CHAR MUST BE UPPER-CASE ONLY
SCH.1T:	CHKEO	EO21,SCH.4	;NOT CONTROL, IF EO=1, FORCE EXACT MODE
	TXNN	F2,TXTCTL	;IF ^T FLAG ON, ALL CONTROL CHARACTERS ARE LEGAL
	PUSHJ	P,CKNCC		;OFF, ALL OTHER CONTROL CHARACTERS ARE ILLEGAL
				; (DON'T RETURN IF ANY)
SCH.2:	TXNE	F2,EMATCH	;FORCED EITHER MATCH ON?
	JRST	SCH.3		;YES, MATCH EITHER
	TXNN	F2,XCASE	;NO, WANT AN EXACT MATCH?
	TXNE	FF,PMATCH	;NO, WANT GLOBAL EXACT MATCH?
	JRST	SCH.4		;ASKED FOR EXACT MATCH
SCH.3:	CAIL	CH,"a"		;MATCH EITHER, IS IT LOWER CASE?
	CAILE	CH,"z"
	JRST	.+2		;NO
	SUBI	CH,"a"-"A"	;YES, MAKE IT UPPER CASE
	CAIL	CH,"A"		;IS IT UPPER CASE?
	CAILE	CH,"Z"
	JRST	SCH.5		;NO
	MOVSI	TT1,400000	;YES, CONVERT CHARACTER TO BIT OF 131
	MOVNI	TT,-"@"(CH)	; WANT - (<CH>-100) FOR LSH
	LSH	TT1,0(TT)	;POSITION BIT TO LETTER RANGE
	IORM	TT1,BITMAT+2(D)	;SET MATCH ON UPPER CASE
	IORM	TT1,BITMAT+3(D)	; AND LOWER CASE CHARACTERS
	JRST	SCH.6
SCH.4:	PUSHJ	P,CASE		;EXACT MODE, ADJUST PATTERN CHARACTER CASE
SCH.5:	MOVSI	T,400000	;CONVERT CHARACTER TO BIT OF 131
	MOVE	TT,CH		;COPY OF CHARACTER
	IDIVI	TT,^D32		;USING 32 BITS PER WORD, FIGURE WORD AND BIT
	ADDI	TT,0(D)		; WORD PLUS CURRENT PATTERN POSITION
	MOVNS	TT1		;NEGATIVE OF REMAINDER FOR BIT SHIFT
	LSH	T,0(TT1)	;POSITION BIT WITHIN 32 BIT RANGE FOR EACH WORD
	IORM	T,BITMAT(TT)	; AND INCLUDE IT IN APPROPRIATE WORD
SCH.6:	SKIPE	SCNEST		;NESTED? (^N, ^E[], ^GI)
	POPJ	P,		;YES, RETURN TO CALLER
	ADDI	D,4		;END OF A PATTERN POSITION, ON TO NEXT
	JUMPE	B,SCH.8		;DONE IF NO MORE CHARACTERS IN PATTERN SOURCE
	CAILE	D,^D36*4	; AND ERROR IF MORE THAN 36 POSITIONS IN PATTERN
	$FATAL	(STL,,<Search string too long>)
	JRST	SCH.1		;MORE PATTERN SOURCE, GET SOME

;FINISHED BUILDING THE 131 BY 36 BIT SEARCH TABLE

SCH.8:	SKIPE	SCNEST		;IN A NEST (^E[ WITH NO ] OR ^GI)
	POPJ	P,		;YES, LET CALLER CARRY ON
	LSH	D,-2		;FINISHED, CONVERT INDEX TO PATTERN LENGTH
	MOVEM	D,PATLEN	; AND SAVE IT
	MOVNS	SCHCTR		;FLAG SOURCE PATTERN LENGTH AS BEING LEGAL
	JRST	ROTATE		;SKIP 131 BY 36 BUILD SUBROUTINES TO ROTATE
;CONTROL CHARACTER DISPATCH TABLE FOR SECOND SCAN OF PATTERN SOURCE

S2TABL:	XWD	CNTLE,.CHCNE	;^E
	XWD	CNTLX,.CHCNX	;^X (SUPERSEDED BY ^EX)
	XWD	CNTXN,.CHCNN	;^N (SUPERSEDED BY ^EN)
	XWD	CNTLS,.CHCNS	;^S (SUPERSEDED BY ^E5)
	XWD	CNTLBS,.CHCBS	;^\
	XWD	CNTXCF,.CHCCF	;^^

;SHORTER TABLE USED FOR ^T ON MODE STARTS HERE

S3TABL:	XWD	CNTLLB,.CHESC	;ESCAPE
	XWD	0,0		;END OF LIST


;CONTROL S MATCHES ANY NON-RADIX 50 CHARACTER

CNTLS:	OUTSTR	[ASCIZ	|% Use ^E5 instead of ^S|]
	JRST	CNTLE5


;CONTROL X MATCHES ANY SINGLE CHARACTER

CNTLX:	OUTSTR	[ASCIZ	|% Use ^EX instead of ^X|]
	JRST	CNTLEX
;QUOTE THE NEXT 7-BIT CHARACTER

CNTLQ:	ILDB	CH,AA		;GET THE NEXT CHARACTER
	SOJA	B,SCH.2		; AND PROCESS IT AS ORDINARY TEXT


;SET LOWER-CASE FOR THE NEXT CHARACTER, AND POSSIBLLY PERMANENTLY
;IF TWO CONSECUTIVE LOWER-CASE QUOTERS

CNTLV:	CHKEO	EO21,SCH.5	;IF EO=1, ^V IS JUST TEXT
	PUSHJ	P,C.VA		;SET LOWER-CASE'ING
	JRST	SCH.1		; AND ON TO NEXT CHARACTER


;SET UPPER CASE FOR THE NEXT CHARACTER, AND POSSIBLY PERMANENTLY
;IF TWO CONSECUTIVE UPPER-CASE QUOTERS

CNTLW:	CHKEO	EO21,SCH.5	;IF EO=1, ^W IS JUST TEXT
	PUSHJ	P,C.WB		;SET UPPER-CASE'ING
	JRST	SCH.1		; AND ON TO NEXT CHARACTER


;CONTROL \ INVERTS CASE MATCH MODE, STARTING AT ACCEPT EITHER

CNTLBS:	CHKEO	EO21,SCH.5	;IF EO=1, ^\ IS JUST TEXT
	TXC	F2,EMATCH	;COMPLEMENT ACCEPT EITHER FLAG
	JRST	SCH.1		; AND ON TO NEXT CHARACTER


;WHEN SEARCHING FOR ALTMODE UNDER EO=1, BOTH ESCAPE AND ALTMODE MATCH

CNTLLB:	CHKEO	EO21,.+2	;EO=1?
	JRST	SCH.5		;NO, ACCEPT ESCAPE ONLY
	MOVEI	T,000040	;YES, MARK ALTMODE AS AN ACCEPTABLE CHARACTER
	IORM	T,BITMAT+3(D)
	JRST	SCH.5		; AND ESCAPE


;CONTROL CIRCUMFLEX CAUSES IMMEDIATELY FOLLOWING @[\]^_ TO BE CONVERTED TO
; THE APPROPRIATE CHARACTER IN THE LOWER CASE RANGE

CNTXCF:	CHKEO	EO21,SCH.5	;IF EO=1, ^^ IS JUST TEXT
	JUMPE	B,SCH.1		;IF NO NEXT CHARACTER, IGNORE
	ILDB	CH,AA		;GET THE NEXT CHARACTER
	PUSHJ	P,CVTSPC	;CONVERT IT TO LOWER CASE IF APPROPRIATE
	SOJA	B,SCH.2		; AND GO PROCESS IT
;INVERT THE CONTROL CHARACTER INTERPRETATION SWITCH
; THE INITIAL SETTING IS THAT ALL CONTROL CHARACTER COMMANDS ARE ACTIVE
; WITH THE SWITCH ON, ONLY ^Q, ^R, AND ^T COMMANDS EXIST, BUT ALL OTHER
;  CONTROL CHARACTERS ARE LEGAL

CNTLT:	CHKEO	EO21,SCH.5	;IF EO=1, ^T IS JUST TEXT
	TXC	F2,TXTCTL	;COMPLEMENT CURRENT SETTING
	JRST	SCH.1		; AND ON TO NEXT CHARACTER


;INVERT THE SENSE OF THE FOLLOWING "CHARACTER", I.E. ACCEPT
; ANYTHING BUT THE SPECIFIED CHARACTER

CNTXN:	OUTSTR	[ASCIZ	|% Use ^EN instead of ^N|]
	JRST	CNTLEN
;CONTROL E COMMANDS ALL GO THROUGH HERE

CNTLE:	CHKEO	EO21,SCH.5	;IF EO=1, ^E IS JUST TEXT
	ILDB	CH,AA		;GET CHARACTER AFTER THE ^E
	SOJL	B,CNTLER	;IF NONE, AN ERROR
	MOVEI	T,S4TABL	;SET TO SEARCH FOR ^E COMMAND CHARACTERS
	PUSHJ	P,DISPAT	; AND LOOK FOR LEGAL COMMANDS (NO RETURN IF GOOD)
CNTLER:	$FATAL	(ICE,,<Illegal Control-E command in search argument>)

;DISPATCH TABLE FOR ^E COMMANDS

S4TABL:	XWD	CNTLE5,"5"	;^E5	ACCEPT ANY NON-RADIX 50 CHARACTER
	XWD	CNTLEA,"A"	;^EA	ACCEPT ANY ALPHA
	XWD	CNTLEV,"V"	;^EV	ACCEPT ANY LOWER CASE ALPHA
	XWD	CNTLEW,"W"	;^EW	ACCEPT ANY UPPER CASE ALPHA
	XWD	CNTLED,"D"	;^ED	ACCEPT ANY DIGIT
	XWD	CNTLEL,"L"	;^EL	ACCEPT ANY END OF LINE CHARACTER
	XWD	CNTLEN,"N"	;^EN	ACCEPT ANY CHARACTER BUT THE FOLLOWING
	XWD	CNTLES,"S"	;^ES	ACCEPT A STRING OF SPACES AND/OR TABS
	XWD	CNTLEX,"X"	;^EX	ACCEPT ANY SINGLE CHARACTER
	XWD	CNTLEO,"<"	;^E<N>	ACCEPT THE ASCII CHARACTER <N>
				;	(ANGLES MATCHED AT CNTLEO)
	XWD	CNTLEB,"["	;^E[A,B,C] ACCEPT A OR B OR C OR ...
	XWD	0,0		;END OF LIST


;CONTROL EA - ACCEPT ANY ALPHABETIC CHARACTER

CNTLEA:	MOVX	T,<XWD	377777,777000> ;ALL LETTERS
	IORM	T,BITMAT+2(D)	; UPPER CASE ON

;CONTROL EV - ACCEPT ANY LOWER CASE ALPHABETIC CHARACTER

CNTLEV:	MOVX	T,<XWD	377777,777000> ;ALL LETTERS
	IORM	T,BITMAT+3(D)	; LOWER CASE ON
	JRST	SCH.6		; AND ON TO NEXT CHARACTER

;CONTROL EW - ACCEPT ANY UPPER CASE ALPHABETIC CHARACTER

CNTLEW:	MOVX	T,<XWD	377777,777000> ;ALL LETTERS
	IORM	T,BITMAT+2(D)	; UPPER CASE ON
	JRST	SCH.6		; AND ON TO NEXT CHARACTER

;CONTROL ED - ACCEPT ANY DIGIT

CNTLED:	MOVX	T,<XWD	000003,776000> ;ALL DIGITS
	IORM	T,BITMAT+1(D)	; ON
	JRST	SCH.6		; AND ON TO NEXT CHARACTER

;CONTROL EL - ACCEPT ANY END OF LINE CHARACTER (INCLUDING BUFFER END)

CNTLEL:	MOVX	T,<XWD	000340,000000>	;LF, VT, AND FF
	IORM	T,BITMAT(D)	; ON
	MOVX	T,<XWD	000000,000004> ; END OF PAGE
	IORM	T,BITMAT+3(D)	; ON
	JRST	SCH.6		; AND ON TO NEXT CHARACTER
;CONTROL EN - ACCEPT ANY CHARACTER BUT THE FOLLOWING

CNTLEN:	MOVSI	T,-4		;AOBJN COUNT FOR THE 4 WORDS OF THIS POSITION
	HRR	T,D		; OF THE PATTERN
	PUSH	P,BITMAT(T)	;SAVE THE CURRENT STATUS OF THE PATTERN (IN CASE
				; OF ^E[A,^N^EW] FOR EXAMPLE)
	SETZM	BITMAT(T)	;START OVER AGAIN
	AOBJN	T,.-2		;LOOP THROUGH THIS POSITION
	AOS	SCNEST		;GO UP A LEVEL IN COMPLEXITY
	PUSHJ	P,SCH.1		;BUILD THE TABLE FOR THE CHARACTER
	SOS	SCNEST		;NOW LESS COMPLEX
	MOVEI	T,4		;NOW GO BACK THROUGH THE 4 WORDS
	MOVEI	TT,BITMAT+3(D)	;STARTING AT THE HIGH END 'CAUSE OF STACK
CTLEN1:	SETCM	TT1,0(TT)	; COMPLEMENTING THE RESULTING SETTING
	TRZ	TT1,17		;  (REMEMBERING ONLY USING 32 BITS PER WORD)
	POP	P,0(TT)		;GET BACK THE ORIGINAL BITS
	IORM	TT1,0(TT)	;INCLUDE THE NEW BITS WANTED
	SUBI	TT,1		;BACK UP TO PREVIOUS WORD (NEED A ASOBJN)
	SOJG	T,CTLEN1	; AND LOOP THROUGH ALL 4 WORDS
	JRST	SCH.6		;DONE THIS "CHARACTER" POSITION
;CONTROL ES - ACCEPT ANY STRING OF SPACES AND/OR TABS

CNTLES:	MOVX	T,<XWD	000400,000000> ;A TAB
	IORM	T,BITMAT(D)	; ON
	MOVX	T,<XWD	400000,000000> ;A SPACE
	IORM	T,BITMAT+1(D)	; ON
	MOVX	T,<XWD	000000,000002> ;THE SPECIAL SPACE/TAB BIT
	IORM	T,BITMAT+3(D)	; ON
	JRST	SCH.6		; AND ON TO NEXT CHARACTER

;CONTROL EX - ACCEPT ANY SINGLE CHARACTER

CNTLEX:	MOVX	T,<XWD	377777,777760> ;ALL CONTROL CHARACTERS EXCEPT NULL (?)
	IORM	T,BITMAT(D)	; ON
	TLO	T,400000	;PLUS SPACE @ GRAVE
	IORM	T,BITMAT+1(D)	; ALL SPECIALS AND NUMBERS
	IORM	T,BITMAT+2(D)	; ALL UPPER CASE
	IORM	T,BITMAT+3(D)	; ALL LOWER CASE
	JRST	SCH.6		;TO NEXT CHARACTER

;CONTROL E5 - ACCEPT ANY NON-RADIX 50 CHARACTER

CNTLE5:	MOVX	T,<XWD	377777,777760> ;ALL CONTROL CHARACTERS BUT NULL (?)
	IORM	T,BITMAT(D)	; ON
	MOVX	T,<XWD	747764,001760> ;ALL NON-SYMBOL SPECIAL CHARACTERS
	IORM	T,BITMAT+1(D)	; ON
	MOVX	T,<XWD	400000,000760> ;UPPER CASE RANGE SPECIALS
	IORM	T,BITMAT+2(D)	; ON
	MOVX	T,<XWD	400000,000774> ;LOWER CASE RANGE SPECIALS + ENDS OF PAGE
	IORM	T,BITMAT+3(D)	; ON
	JRST	SCH.6		;TO NEXT CHARACTER

;CONTROL E[A,B,C,...] - ACCEPT ANY OF "CHARACTERS" A OR B OR C

CNTLEB:	AOS	SCNEST		;UP ONE NEST LEVEL (DOWN?)
CTEB.1:	PUSHJ	P,SCH.1		;PROCESS THE NEXT "CHARACTER"
	ILDB	CH,AA		;GET THE NEXT PATTERN SOURCE (IF ALREADY OFF END
				; OF STRING, WILL CATCH THAT ANYWAY AT .+1)
	SOJL	B,CNTLER	;ERROR IF OFF END OF STRING
	CAIN	CH,","		;ANOTHER "CHARACTER" TO COME?
	JRST	CTEB.1		;YES, GO INCLUDE IT TOO
	CAIE	CH,"]"		;NO, CORRECT ENDING TO ^E COMMAND?
	$FATAL	(ICE,,<Illegal Control-E command in search argument>)
	SOS	SCNEST		;YES, ONE FEWER LEVEL OF NESTING NOW
	JRST	SCH.6		; AND HAVE FINISHED A "CHARACTER" POSITION
;CONTROL E<NNN> - ACCEPT THE ASCII CHARACTER WHOSE OCTAL REPRESENTATION IS NNN

CNTLEO:	MOVEI	A,0		;CLEAR NUMBER ACCUMULATOR
CTEO.1:	ILDB	CH,AA		;GET AN OIT
	SOJL	B,CNTLER	;ERROR IF RUN OUT
	CAIN	CH,">"		;THE OTHER END OF THE NUMBER?
	JRST	CTEO.2		;YES, DONE
	CAIL	CH,"0"		;IS IT AN OIT?
	CAILE	CH,"7"
	$FATAL	(ICE,,<Illegal Control-E command in search argument>)
	LSH	A,3		;YES, SCALE UP THE PREVIOUS VALUE
	ADDI	A,-60(CH)	; AND ADD IN THE NEW OIT
	JRST	CTEO.1		; THEN GO TRY FOR MORE

CTEO.2:	CAILE	A,177		;MAKE SURE IT'S LEGITIMATE
	$FATAL	(ICE,,<Illegal Control-E command in search argument>)
	MOVE	CH,A		;COPY THE RESULT AS THE CHARACTER
	JRST	SCH.5		; AND GO SET THE APPROPRIATE BIT
;Now we need to build up TECO's standard search table, a 36 bit by 131. word
; table with each pattern position being a slice of the 131 words, with all of
; the acceptable characters for each position marked by a bit on in the word
; reached by using the character directly as an index into the table (the extra
; 3 words are for "beginning of page", "end of page", and "this position matches
; strings of spaces and/or TABs").  At the same time we will set up the two
; simple tables for the fast search algorithm (DELTA0 and DELTA1), since it is
; much quicker to do this now if we use the fast one.
;Since DELTA0 and DELTA1 are the same at all points except for entries which
; are not needed in DELTA1, we will build them as one.
;The conversion is done by rotating the 131. bit by 36 word table 90 degrees.
;Since that table was built first (instead of the normal TECO table as in
; standard TECO), the loop is only needed for as many times as there were
; pattern characters (doing it in the other order requires a loop through all
; 131 characters with no possibility for less).

;AC usage: (Other than poor, I want P1-P4)
;D	AOBJN pointer with "virtual" index into 131 by 36 table (word index/4)
;I	actual word index into 131 by 36 table
;A	bit mask specifying pattern position we're currently doing
;AA	AOBJN pointer into the 131 bits of an entry of the 131 by 36 table
;TT+TT1	current words worth of the 131 bits and the JFFO result

SLARGE==10777777		;A SPECIAL LARGE NUMBER FOR DELTA0 USED FOR
				; THE CHARACTERS DEFINING THE RIGHTMOST PATTERN
				; POSITION
ROTATE:	MOVN	D,PATLEN	;GET THE NUMBER OF PATTERN POSITIONS USED
	HRLZS	D		; AS AN AOBJN POINTER
	MOVEI	I,0		;CLEAR THE ACTUAL INDEX
	MOVE	A,PATLEN	;INITIALIZE DELTA0 AND DELTA1 TO THE NUMBER
	MOVEM	A,DELTA0	; OF POSITIONS IN THE PATTERN
	MOVE	AA,[XWD	DELTA0,DELTA0+1]
	BLT	AA,DELTA0+SPCTAB
	SUBI	A,1		;PATTERN LENGTH - 1 IS THE DISTANCE WE ARE FROM
	MOVEM	A,ROTLEN	; THE END OF THE PATTERN AT THE MOMENT
	MOVSI	A,400000	;START MASK AT FIRST PATTERN POSITION
ROTA.1:	MOVSI	AA,-BITMLN	;SET AOBJN POINTER INTO THE 131 BITS
ROTA.2:	SKIPE	TT,BITMAT(I)	;GET 32 OF THOSE, SEEING IF ANY ARE ON
ROTA.3:	JFFO	TT,[MOVSI CH,400000	;GOT ONE, MAKE A MASK TO TURN IT OFF
		MOVN	T,TT1
		LSH	CH,0(T)
		ANDCM	TT,CH		; AND DO SO
		ADDI	TT1,0(AA)	;ADD 0, 32, 64, OR 96 TO THE BIT NUMBER
		IORM	A,SMATRX(TT1)	; AND TURN ON THE POSITION BIT
		SKIPN	CH,ROTLEN	;GET THE DISTANCE FROM THE RIGHT END
		MOVX	CH,SLARGE	;AT RIGHT, CHANGE TO THE SPECIAL NUMBER
		MOVEM	CH,DELTA0(TT1)	;SET THAT IN FAST LOOP TABLE
		JRST	ROTA.3]		;ON TO NEXT BIT
	ADDI	I,1		;FINISHED A WORD OF THE 131 BIT STRING
	ADDI	AA,^D31		;NEXT WORD IS 32 FARTHER INTO THE 36X131 TABLE
	AOBJN	AA,ROTA.2	;LOOP UNTIL ALL 131 BITS DONE
	LSH	A,-1		;ON TO THE NEXT PATTERN MASK POSITION
	SOS	ROTLEN		; AND DISTANCE FROM THE END
	AOBJN	D,ROTA.1	; AND LOOP THROUGH ALL USED PATTERN POSITION

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;Now determine which search method we will use.  If ^ES appeared we have to use
; the old slow method.  Initially if we need to match BEGPAG or ENDPAG, we will
; use the old method.  Also we will arbitrarily select 3 as the shortest string
; which will benefit from using the new search.  As an aid, turn off the BEGPAG
; and ENDPAG bits which don't appear at the appropriate end of the pattern,
; since they obviously won't match except there.

FIGSCH:	SETZB	A,SCHTYP	;ASSUME AN OLD STYLE SEARCH
	MOVN	D,PATLEN	;GENERATE A BIT MASK FOR THE LAST PATTERN
	MOVSI	AA,400000	; POSITION USED IN THIS SEARCH
	ANDM	AA,SMATRX+BEGPAG; (WITH A SIDE EFFECT OF
	LSH	AA,1(D)		;  CLEARING EXTRA BEGIN PAGE BITS)
	MOVE	D,PATLEN	;NOW SEE HOW LONG THE PATTERN IS
	CAILE	D,2		;IF IT IS FEWER THAN 3 POSITIONS LONG,
	SKIPE	SMATRX+SPCTAB	; OR IF THERE WERE ANY ^ES POSITIONS,
	JRST	SCH.E		; JUST GO USE THE OLD SEARCH
	ANDM	AA,SMATRX+ENDPAG;PATTERN IS .GT. 1, SO CLEAR EXTRA END PAGE BITS
	SKIPN	SMATRX+BEGPAG	;IF EITHER END OF BUFFER WILL MATCH,
	SKIPE	SMATRX+ENDPAG	; ...
	JRST	SCH.E		; GO USE OLD SEARCH
	SETOM	SCHTYP		;WE WIN WITH THE NEW ONE, REMEMBER THAT IN CASE
				; THIS WAS AN NSFOO$ TYPE

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;We are going to use the new search, set up the more costly DELTA2 table.
;This table is based on the arrangement of characters in the pattern.
;It uses the existence (or non-existance) of matching substrings in the
; pattern to be able to shift the pattern farther than would be indicated by
; DELTA1, e.g. if the pattern is ACACACACACAABC and the part of the searched
; string being examined is CABC, DELTA1 will only shift the pattern right 3
; positions, while "looking" at the pattern will tell a human observer that
; the pattern can be shifted its whole length without missing any possible
; matches.
;
;A FEW BITS IN B FOR USE DURING THE DELTA2 SETUP

NEDSET==1B35		;THIS POSITION OF DELTA2 STILL NEEDS SETTING UP
WNTOFF==1B34		;WE SHIFTED OFF THE END OF THE PATTERN THIS PASS
FSTIME==1B33		;THIS IS THE FIRST PASS - USE A SPECIAL VALUE INSTEAD OF
			; HAVING TO INITIALIZE THE INDEX MATRIX (INDMAT)

;AC usage (see comment at ROTATE)
;
;A	the highest entry currently being used in INDMAT
;AA	a number used to indicate how far the pattern can be shifted when we
;	 find a mismatch between sub-pattern strings
;B	used for the above flag bits
;C	index into INDMAT for updates to it as matches occur in sub-patterns
;CH	index into INDMAT for loop
;I	index into pattern (*4 since 4 words per pattern position)
;J	temporary index into pattern (also *4)

;We want to look for sub-strings in the pattern matching rightmost sub-strings
; of the pattern.  If none are found, then as in the above example when more than
; one pattern position has been matched we know we can shift farther than to
; the next occurance of single pattern characters.  If some matches are found
; then we can try them next immediately.
;The examination is implemented by using an array of pointers (indices into
; the pattern) (INDMAT), stored in decreasing order and overwritten each pass
; by the pointers for the next pass.  When I points to the beginning of the
; rightmost n characters of the pattern, then each pointer in INDMAT points
; to the beginning of a sub-string which matches those n characters.  When
; INDMAT has been emptied, all of these sub-strings have been matched and the
; rest of DELTA2 can be set to shift the pattern its entire length.  The
; initial setting of INDMAT (implemented by FSTIME) is such that every pattern
; position is examined on the first pass.

	MOVEI	A,-1(D)		;START THE TOP OF INDMAT AT PATTERN LENGTH - 1
	MOVEI	AA,-1(D)	;START THE NON-MATCH SHIFT AT PATTERN LENGTH
				; (ADJUSTED BECAUSE A 0-INDEX IS SUBTRACTED FROM IT)
	MOVX	B,NEDSET!FSTIME	;THE FIRST SETTING IS NEEDS SETTING, FIRST PASS,
				; AND HAVEN'T GONE OFF THE END
	MOVEI	I,-1(D)		;START AT RIGHT END OF PATTERN (0-INDEXED)
	LSH	I,2		; ADJUSTED FOR BEING 4 WORD BIT STRINGS
	MOVEI	D,0(I)		;SET INITIAL INDMAT VALUE TO SHIFT ALL LESS 1
				; REMEMBERING THE FIRST SUBI 4

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

SET2.2:	MOVEI	C,0		;START USED INDMAT ENTRY INDEX OFF AT NONE
	MOVN	CH,A		;MAKE AN AOBJN POINTER FOR LOOP THROUGH INDMAT
	HRLZS	CH

SET2.3:	TXNN	B,FSTIME	;GET THE APPROPRIATE INDMAT ENTRY
	SKIPA	D,INDMAT(CH)	;NOT THE FIRST TIME, USE THE REAL ARRAY
	SUBI	D,4		;THE FIRST PASS, USE OUR FAKE VALUE
	MOVE	TT,BITMAT(I)	;FIGURE OUT IF ANY OF THE CHARACTERS MATCHED
	AND	TT,BITMAT(D)	; BY THE POSITION WE ARE LOOKING AT AT HIGHEST
	MOVE	TT1,BITMAT+1(I)	; LEVEL (I) ALSO MATCH AT THE POSITION INDICATED
	AND	TT1,BITMAT+1(D)	; BY THE SUBSTRING TABLE (INDMAT - D)
	OR	TT,TT1
	MOVE	TT1,BITMAT+2(I)	;(AND THE STRINGS TOGETHER, IF RESULT IS ZERO
	AND	TT1,BITMAT+2(D)	; THEN NO CHARACTERS MATCH)
	OR	TT,TT1
	MOVE	TT1,BITMAT+3(I)
	AND	TT1,BITMAT+3(D)
	OR	TT,TT1
	JUMPE	TT,SET2.5	;IF ZERO, NO MATCHES HERE
	JUMPE	D,SET2.4	;DID WE JUST MATCH WITH THE LEFTMOST POSITION?
	MOVEI	T,-4(D)		;NO, UPDATE INDEX MATRIX TO CHECK THE POSITION
	MOVEM	T,INDMAT(C)	; IN FRONT OF THIS FOR FINDING SUBSTRINGS
	AOSA	C		;REMEMBER WE USED ANOTHER ELEMENT OF INDMAT
SET2.4:	TXO	B,WNTOFF	;MATCHED AT THE LEFT END, THAT GOES OFF THE END
SET2.5:	TXNN	B,NEDSET	;DO WE STILL NEED TO SET UP THIS POSITION?
	JRST	SET2.6		;NO, SKIP ALL THE LOGICAL STUFF
	MOVE	TT,BITMAT(D)	;YES, WE NEED TO FIGURE OUT IF THE SUBSTRING
	ANDCM	TT,BITMAT(I)	; INDICATED POSITION (D) CHARACTER SET IS A
	MOVE	TT1,BITMAT+1(D)	; SUBSET OF THE HIGH LEVEL (I) CHARACTER SET
	ANDCM	TT1,BITMAT+1(I)	; (DONE BY D .AND. .NOT. I .NE. 0)
	IOR	TT,TT1
	MOVE	TT1,BITMAT+2(D)
	ANDCM	TT1,BITMAT+2(I)
	IOR	TT,TT1
	MOVE	TT1,BITMAT+3(D)
	ANDCM	TT1,BITMAT+3(I)
	IOR	TT,TT1
	JUMPE	TT,SET2.6	;SKIP OUT IF IT'S NOT
	TXZ	B,NEDSET	;IT IS, DON'T DO THIS AGAIN
	MOVNI	T,4(D)		;WE NOW KNOW THAT WE CAN SHIFT AT LEAST AS MUCH
	ASH	T,-2		; AS THE DISTANCE FROM HERE TO THE RIGHT END
	ADD	T,PATLEN	; SINCE NO SUBSTRINGS MATCHED FROM HERE TO THERE
	MOVE	TT1,I		;FIGURE OUT WHERE TO PUT IT WITH
	LSH	TT1,-2		; A WORD TABLE
	MOVEM	T,DELTA2(TT1)	;PUT IT THERE

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

SET2.6:	AOBJN	CH,SET2.3	;LOOP THROUGH CURRENT INDEX MATRIX
	TXZ	B,FSTIME	;FINISHED THE FIRST PASS
	MOVE	A,C		;REMEMBER THE HIGHEST INDEX MATRIX ELEMENT USED
	TXOE	B,NEDSET	;DO WE STILL NEED TO SET THIS POSITION?
	JRST	[MOVE	T,AA		;YES, THEN WE CAN SHIFT IT BASED ON HOW
		MOVE	TT,I		; FAR THE HIGHEST LEVEL LOOP IS FROM
		LSH	TT,-2		; THE RIGHT END OF THE PATTERN
		SUB	T,TT
		ADD	T,PATLEN
		MOVEM	T,DELTA2(TT)
		JRST	.+1]
	TXZE	B,WNTOFF	;DID THIS PASS GO OFF THE END OF THE PATTERN
	JRST	[MOVEI	AA,-4(I)	;YES, NEED TO ADJUST THE AMOUNT WE
		LSH	AA,-2		; CAN SHIFT WHEN NEDSET IS USED
		JRST	.+1]		; IMMEDIATELY ABOVE
	SUBI	I,4		;NOW LOOK A POSITION TO THE LEFT OF LAST LOOP
	SKIPE	A		; UNLESS THERE IS NO NEED TO CAUSE NO MATCHES
	JUMPGE	I,SET2.2	; OR BECAUSE WE LOOKED AT ALL  OF THEM
	JUMPL	I,SET2.E	;DID WE LOOK AT ALL OF THEM?
	ADD	AA,PATLEN	;NO, NEED TO FILL IN THE REST WITH THE LARGEST
	LSH	I,-2		; POSSIBLE NUMBER BASED ON HOW FAR WE ARE FROM
	SUB	AA,I		; THE RIGHT END OF THE PATTERN AND HOW FAR THE
				; SETUP GOT
	MOVEM	AA,DELTA2(I)
	ADDI	AA,1		;EACH POSITION TO THE LEFT CAN SHIFT ONE FARTHER
	SOJGE	I,.-2

SET2.E:

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;NOW, IF F SEARCH, SCAN INSERT ARGUMENT

SCH.E:	TXNN	F2,S.REPL	;F? SEARCH?
	JRST	WCHSCH		;NO, GO START SEARCH
	TXZ	F2,TXTCTL	;REFRESH ^T FLAG
	MOVE	CH,FSNTRM	;GET FS/FN DELIMITER BACK
	TXZ	FF,F.NNUL	;RESET NON-NULL STRING FLAG
	JRST	INSERB		;GO SCAN INSERT ARGUMENT

SERCHJ:	POP	P,FSNCNT	;SAVE POINTERS FOR THE INSERTION (COMCNT)
	POP	P,FSNPTX	; (COMPTX)
	POP	P,FSNPTR	; (COMPTR)
				;AND FALL INTO SEARCH

;HERE TO CALL THE APPROPRIATE SEARCH

WCHSCH:	TXNN	F2,S.MINS	;IF THIS TIME IS MINUS SEARCH, FORCE OLD SEARCH
	SKIPN	SCHTYP		;WHICH ONE ARE WE USING?
	JRST	SLOSCH		;THE OLD ONE
	JRST	FSTSCH		;THE NEW ONE, FALL INTO IT
;This is an implementation of the algorithm of Boyer and Moore, published
; in the Communications of the ACM, October 1977, Vol. 20 Number 10, page 762.
; This article serves as the primary documentation for this routine (and the
; DELTA? table setup routines).
;
;This is the actual search, which uses the numbers in DELTA0, DELTA1, and
; DELTA2 for determining where in the searched string to look.  The actual
; character comparisons are done in the tried and true TECO way, with TECO's
; original bit map (there can't be a better way).
;
;AC usage (ditto)
;A	During the slow loop, counts down through the pattern
;AA	Contains the bit mask for the last pattern position
;B	The base register into the byte pointer table, including (C)
;C	A negative index into the byte pointer table
;D	The length of the string to be searched
;T	During the slow loop, shifts the bit mask through the pattern
;TT	The word address of the first byte of the portion of the searched
;	 string currently being examined
;TT1	The value of C at the start of the current FAST and SLOW loop execution
;
;The bytes in the searched string are obtained through a window by a table of
; constant byte pointers indexed into by B, C, and TT.

FSTSCH:	MOVN	T,PATLEN	;GENERATE THE BIT MASK FOR THE RIGHTMOST
	MOVSI	AA,400000	; PATTERN POSITION
	LSH	AA,1(T)
	MOVE	I,PT		;START SEARCHING AT .
	MOVE	D,UPPERB	;FIGURE OUT HOW MANY CHARACTERS ARE TO BE SEARCHED
	SUB	D,I		; I.E. THE LENGTH OF THE SEARCHED STRING
	ADDI	D,1		;*NOTE THAT ALL THIS CODE MUST USE FULL WORD
				; ARITHMETIC WHEN REFERRING TO I, SINCE ITS
				; MAXIMUM VALUE IS 128K * 5 CHARACTERS*
	TXNE	FF,ARG		;IS THIS AN NSFOO$$?
	JUMPLE	E,FND		;YES, DONE IF WE'VE FOUND THAT MANY
	MOVSI	B,(IFIW 0(C))	;IFIW INDEXING USING AC "C"
FSTS.1:	MOVE	TT,I		;CONVERT I INTO A WORD AND BYTE ADDRESS
	IDIVI	TT,5
	MOVE	T,D		;FIGURE THE CURRENT BYTE POINTER WINDOW LENGTH
	CAILE	T,SCHBPL	; THE LENGTH OF STRING LEFT
	MOVEI	T,SCHBPL	; OR THE WINDOW SIZE, WHICHEVER IS LESS

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

	MOVN	C,T		;COPY THAT AS NEGATIVE INDEX INTO TABLE
	ADD	T,TT1		;ADD THE BYTE IN WORD OFFSET
	ADDI	T,SCHBPT-1	; PLUS THE ADDRESS OF THE START OF THE TABLE
	HRR	B,T		; EQUALS THE BASE ADDRESS TO BE NEGATIVELY
				; INDEXED FROM
	ADD	C,PATLEN	;THIS SEARCH STARTS AT THE RIGHT END OF THE PATTERN
	JUMPG	C,NOFND3	;IF THAT IS TO THE RIGHT OF THE LAST CHARACTER
				; OF THE STRING, THEN WE DIDN'T FIND IT
	MOVE	TT1,C		;SAVE C AT THE START OF THE LOOP, SO WE CAN
				; TELL HOW MANY CHARACTERS WE'VE SKIPPED
;FAST:				;THE FAST LOOP IN THE ACM ARTICLE

FSTS.3:	LDB	CH,@B		;GET A CHARACTER FROM THE SEARCHED STRING
	ADD	C,DELTA0(CH)	;SHIFT DOWN BASED ON EXISTANCE IN THE PATTERN
	JUMPLE	C,FSTS.3	; AND LOOP UNLESS IT'S THE RIGHTMOST POSITION
				; I.E. IF WE JUST HAD A MATCH (SEE LARGE)
	TLON	C,-1		;DID IT MATCH (SLARGE MAKES THE LEFT HALF 7)
	JRST	FSTS.5		;NO, WE USED UP OUR WINDOW (LEFT HALF IS ZERO)
	MOVE	T,AA		;START AT RIGHT END OF PATTERN BIT MASK
	MOVE	A,PATLEN	; FOR THAT MANY CHARACTERS

;SLOW:				;SLOW LOOP IN ACM ARTICLE

FSTS.4:	SOJLE	A,FSTS.6	;IF WE RUN OUT OF PATTERN CHARACTERS, IT MATCHED
	LSH	T,1		;SET BIT MASK TO PREVIOUS PATTERN POSITION
	LDB	CH,@B		;GET THE NEXT SEARCHED STRING CHARACTER
	TDNE	T,SMATRX(CH)	;DOES IT MATCH?
	SOJA	C,FSTS.4	;YES, BACK UP BYTE POINTER INDEX ONE AND LOOP
	MOVE	T,DELTA0(CH)	;NO, FIGURE WHICH TABLE SHIFT US THE MOST
	TLNN	T,-1		;IF WE JUST GOT SLARGE, USE DELTA2 ALWAYS
	CAMGE	T,DELTA2-1(A)
	MOVE	T,DELTA2-1(A)
	ADD	C,T		;UPDATE OUR CURRENT POSITION BY THAT MUCH
	JUMPL	C,FSTS.3	; AND GO BACK TO FAST UNLESS WE EXCEEDED WINDOW

;SEARCH FAILED IN THIS WINDOW, SEE WHAT TO DO

FSTS.5:	JUMPLE	D,NOFND3	;NOT FOUND IF THERE IS NO SEARCHED STRING LEFT
	SUB	C,TT1		;SEE HOW MANY CHARACTERS WE SKIPPED
	ADDI	I,0(C)		;UPDATE CURRENT POSITION BY THAT MUCH
	SUBI	D,0(C)		; AND AMOUNT LEFT BY THAT MUCH
	JRST	FSTS.1		; AND TRY AGAIN

;HERE WHEN STRING FOUND, DECIDE WHERE THE RIGHT END OF THE PATTERN IS

FSTS.6:	SUB	C,TT1		;HOW MUCH WE MOVED
	ADD	I,C		;ADJUST POINTER BY THAT MUCH
	ADD	I,PATLEN	; BUT WE SCANNED BACK BY THAT MUCH TOO
	MOVEM	I,PT		;UPDATE . TO THAT POINT
	ADD	I,PATLEN	;NOW GET TO RIGHT END OF PATTERN
	JRST	FND		;WE DID IT
;BUILD THE FIXED BYTE POINTER TABLE.  THE FOLLOWING CODE IS DONE AGAIN
; UNDER AN XLIST

SCHBPL==^D200			;LENGTH OF WINDOW OF BYTE POINTERS
$A==0				;START THE BASE ADDRESS AT ZERO

;SCHBPT:REPEAT	SCHBPL/5+1,<	;Build 5 for each word of bytes, plus extra for
;				; the fact that the first byte may be one of 5
;	$M==177B6		;A mask for the current character of the word
;		REPEAT	5,<		;For each word of bytes
;			POINTR	$A(TT),$M	;Build 5 pointers
;		$M==$M_-7			;Moving mask each time
;		>
;	$A==$A+1		;To next word
;	>
	XLIST
SCHBPT:
IF1,<
	BLOCK	SCHBPL+5
>
IF2,<
	REPEAT	SCHBPL/5+1,<
$M==177B6
	REPEAT	5,<
	POINTR	$A(TT),$M
$M==$M_-7
>
$A==$A+1
>
>
	LIST
;SLOW SEARCH COMES HERE

SLOSCH:	MOVN	T,PATLEN	;FIGURE OLD END OF SEARCH COMPARATOR
	MOVSI	AA,400000
	LSH	AA,0(T)		;WHICH IS BIT ONE PAST END OF PATTERN
	MOVE	I,PT		;START SEARCHING AT PT
S1:	TXNE	FF,ARG		;IS THERE AN ARGUMENT?
	JUMPLE	E,FND		;YES. SEEN STRING N TIMES?
	MOVE	TT,I		;NO, FORM BYTE PTR WHICH WILL BE
	IDIVI	TT,5		;INCREMENTED BEFORE USE
	HLLZ	TT1,BTAB-1(TT1)	;GET PROTOTYPE BYTE POINTER
	TLZ	TT1,77		;MASK OUT INDEXING/ETC
	SKIPE	SECTN		;PC IN EXTENDED SECTION?
	TLOA	TT1,(1B12)	;YES, MUST USE EXTENDED BYTE POINTER
	HRR	TT1,TT		;NO, MUST USE LOCAL BYTE POINTER
	MOVEM	TT1,SCHPTR	;SET "STATIC" BYTE POINTER
	MOVEM	TT,SCHPTX	;SET "STATIC" BYTE POINTER EXTENDED ADDRESS
	CAMG	I,BEG		;AT BEG OF BUFR?
	SKIPL	SMATRX+BEGPAG	;& 1ST SERCH CHAR = BEG OF BUFR CHAR?
	JRST	S3		;NO
	MOVSI	D,200000	;YES, START SEARCH AT 2ND SEARCH CHAR
	DMOVE	TT,SCHPTR	;SET DYNAMIC PTR = STATIC PTR
	SETOM	BCOUNT		;FLAG 1ST IS BEGPAG
	JRST	S4B		;ENTER SEARCH LOOP
;SLOW SEARCH LOOP

S3:	MOVSI	D,400000	;START SEEKING MATCH FOR 1ST CHAR
	DMOVE	TT,SCHPTR	;SET DYNAMIC PTR = STATIC PTR
	JRST	S4A

S4:	TDNE	D,SMATRX+SPCTAB	;IS SPACE/TAB STRING BIT SET?
	JRST	SPTB		;YES
S4E:	CAML	I,UPPERB	;DON'T ALLOW I OUTSIDE BOUNDS
	JRST	S4D		;...
	ADDI	I,1		;LOOK AT NEXT LOC, XCEPT 1ST TIME THRU
S4C:	LSH	D,-1		;ADVANCE TO NEXT CHAR POSITION
S4B:	CAMN	D,AA		;END OF SEARCH TABLE?
	JRST	FND		;YES.
S4A:	ILDB	CH,TT		;NO, GET NEXT CHAR
	TDNE	D,SMATRX(CH)	;IS IT A MATCH?
	JRST	S4		;YES, GO TO NEXT TABLE ENTRY.
S4D:	AOSN	BCOUNT		;IF WE FAILED WITH BEGPAG
	JRST	S3		;THEN TRY AGAIN WITH 1ST CHAR
	TXNE	F2,S.MINS	;BACKWARDS SEARCH
	JRST	SR4A
	CAML	I,UPPERB	;TOO FAR?
	JRST	NOFND
	AOS	I,PT
	IBP	SCHPTR		;MOVE STATIC BYTE PTR
	JRST	S3		;KEEP LOOKING

SR4A:	SOS	I,PT		;DECREMENT PT
	CAMGE	I,LOWERB	;DONE
	JRST	NOFND
	MOVNI	TT,1		;COUNT OF -1
	ADJBP	TT,SCHPTR	;DECREMENT STATIC BYTE POINTER
	DMOVEM	TT,SCHPTR	;AND LEAVE IT IN PLACE
	JRST	S3		;KEEP ON SEARCHIN'

;SKIP OVER A STRING OF SPACES AND/OR TABS WHILE SEARCHING

SPTB:	CAIE	CH," "		;BUT WAS THE CHARACTER WE MATCHED A SPACE
	CAIN	CH,.CHTAB	; OR A TAB?
	CAIA			;YES, THEN ACCEPT MORE
	JRST	S4E		;NO, LOOK AT NEXT PATTERN POSITION
	DMOVEM	TT,ERR2		;SET INITIAL PEEK-AHEAD POINTER
SPTB.1:	DMOVE	TT,ERR2		;SET REAL POINTER TO LAST SPACE/TAB CHARACTER
	ADDI	I,1		;ADVANCE TO NEXT BUFFER LOCATION
	CAML	I,UPPERB	;END OF BUFFER?
	JRST	S4C		;YES, NO MORE THEN
	ILDB	CH,ERR2		;PEEK AHEAD AT NEXT CHARACTER
	CAIE	CH," "		;IS IT A SPACE?
	CAIN	CH,.CHTAB	; OR A TAB?
	JRST	SPTB.1		;YES, KEEP ON TRUCKING
	JRST	S4C		; AND CONTINUE SEARCH
;HERE WHEN THE SEARCH HAS MATCHED A CHARACTER STRING IN THE TEXT BUFFER

FND:	SETOM	SFINDF		;NO. SFINDF:=-1
	MOVE	A,I
	SUB	A,PT		;COMPUTE LENGTH OF SEARCH ARG
	MOVE	B,I		;SAVE CURRENT POINTER
	TXNN	F2,S.MINS
	JRST	NOTMIN
;	CAMLE	I,SCHPT		;LEGAL FIND?
;	SOSA	I,PT
	SOSA	I,PT
	JRST	WCHSCH		;NO, CONTINUE SEARCH
NOTMIN:	MOVEM	I,PT		;ELSE GO FORWARD
	SOJG	E,WCHSCH	;TRY AGAIN IF HAVEN'T FOUND IT N TIMES
	MOVEM	B,PT
	TXZE	F2,S.DELE	;FIND AND DELETE?
	JRST	FDFND		;YES
	TXZE	F2,S.KILL	;FIND AND KILL?
	JRST	FKFND		;YES
	TXZE	F2,S.REPL	;FIND AND REPLACE?
	JRST	FSFND		;YES
	MOVEM	A,VVAL		;SAVE LENGTH OF STRING
FND2:	TXNN	F2,S.MINS	;BACKWARDS SEARCH?
	JRST	FND3		;NO
	MOVNS	C,VVAL		;YES, INDICATE IN VVAL
	ADDM	C,PT		;AND SET "." TO BACKWARDS END OF SEARCH
FND3:	PUSHJ	P,ZEROTT	;AUTOTYPE ("ES") IF NEEDED
	TXNE	F2,NALTFS	;WAS THIS A BLASTED "FS---$$" STYLE COMMAND?
	JRST	ALTM1		;YES, GET OUT NOW (YECCCCCCH)
	TXZE	FF,COLONF	;COLON MODIFIER?
	JRST	FFOK		;YES, RETURN VALUE
	CHKEO	EOVAL,FND4	;IF OLD TECO, MUST CHECK FOR < ... >
	JRST	RET		;DON'T RETURN A VALUE
FND4:	SKIPL	(P)		;IN AN ITERATION?
	JRST	RET		;NO, RETURN NO VALUE
	MOVSI	A,(MOVE B,)	;YES, IMPLICIT ":"; RESET DELIM
	HLLM	A,DLIM		;SO "-SXXX$" DOESN'T RETURN VALUE OF -(-1)
				; (YES, THIS REALLY SUCKS THE BIG HAIRY ONE,
				;  BUT . . . )
FFOK:	SETOB	A,B		;RETURN VALUE OF -1
				; IN "A" FOR VALRET; IN "B" FOR CLOSEC
	JRST	CLOSEC		;AND CLOSE THE ":"'S FREE "()"
;HERE FOR FD COMMAND TO DELETE THE MATCHED STRING

FDFND:	MOVN	B,A		;B:=SIZE OF MATCHED STRING
	PJRST	FKFND7		;GO DELETE CHARACTERS


;HERE FOR FK COMMAND TO DELETE FROM STARTING POINT THROUGH MATCHED STRING

FKFND:	TXNN	F2,S.MINS	;BACKWARDS SEARCH?
	JRST	FKFND3		;NO
	MOVNS	A		;YES, MINUS LENGTH OF STRING
	ADDM	A,PT		;SET "." TO BACKWARDS END OF SEARCH
FKFND3:	MOVE	B,SCHPT		;GET OLD PT
	SUB	B,PT		;B:=OLD "." TO END OF MATCHED STRING
FKFND7:	PUSHJ	P,DELN		;-ND COMMAND
	SETZM	VVAL		;NO STRING LEFT
	JRST	FND3		;GO CHECK FOR ":" VALUE RETURN



;HERE FOR FN, FS, AND F_ COMMANDS TO REPLACE THE MATCHED STRING

FSFND:	MOVE	C,VVAL		;GET INSERT SIZE
	SUB	C,A		;INSERT MINUS DELETE
	MOVNS	A		;SET PT TO BEGINNING OF STRING FOUND
	ADDM	A,PT
	MOVE	A,FSNCNT	;RESET COMCNT & COMPTR TO BEGINNING
	MOVEM	A,COMCNT	;OF FS/FN INSERT ARGUMENT
	DMOVE	A,FSNPTR	;NOTE: ***MUST *** BE DONE BEFORE CALL
	DMOVEM	A,COMPTR	; TO NROOM SINCE FSNPTR IS NOT RELOCATED!
	CAIE	C,0		;[MHK] DON'T BOTHER IFF SAME SIZE
	PUSHJ	P,NROOM		;STRETCH OR SCRUNCH THE HOLE
	MOVE	B,FSNTRM	;GET FS/FN TERMINATOR TO LOOK FOR
	PUSHJ	P,INS1B		;INSERT THE 2ND ARG
	MOVE	CH,FSNTRM	;THE FS/FN TERMINATOR AGAIN
	TXZN	FF,F.NNUL	;WAS THERE A NON-NULL INSERT?
	CAIE	CH,.CHESC	;ALTMODE TERMINATOR?
	JRST	FND2		;NO
	TXO	F2,NALTFS	;FLAG SO 2ND ALTMODE STAYS AROUND
	JRST	FND2		;YES, FS<STRING>$$ TERMINATES EXECUTION
				; BUT GO CHECK FOR BACKWARDS SEARCH,
				; AUTOTYPEOUT, AND SO FORTH FIRST
;HERE WHEN THE SEARCH FAILS TO MATCH A CHARACTER STRING

NOFND:	TDNN	D,SMATRX+ENDPAG	;ENDPAG GOOD FOR A MATCH HERE?
	JRST	NOFND3		;NO
	CAMN	I,Z		;YES, BUT ONLY IF WE'RE AT Z
	JRST	FND		;ENDPAG MATCHES!

;THE SEARCH REALLY DID FAIL

NOFND3:	MOVE	I,BEG		;SEARCH FAILED
	MOVEM	I,PT		;PT=BEG
	SETZM	SFINDF		;SFINDF=0
	TXNN	F2,S.MINS	;SEE IF THIS NEEDS TO LOOK AT A NEW BUFFER
	TXNN	FF,PCHFLG!FINDR	;MINUS SEARCHES NEVER DO, BUT N AND _ DO
	JRST	RESTPT		;NO NEW BUFFER, THE SEARCH LOST
	MOVEM	E,SCHCNT	;YES. SAVE SEARCH COUNT
	MOVEI	B,1		;PUNCH 1 PAGE ONLY
	TXNE	FF,PCHFLG	;N SEARCH?
	PUSHJ	P,PUNCHA	;YES. PUNCH THIS BUFFER AND REFILL IT.
	TXNN	FF,UREAD	;ANY INPUT FILE?
	JRST	BEGIN1		;NO
	TXNE	FF,FINF		;MORE DATA?
	TXNE	FF,FORM
	JRST	NOFND4		;YES
	MOVE	E,BEG		;EOF & NO FORM SEEN
	CAMN	E,Z		;CHECK BUFFER CONTENTS
	JRST	BEGIN1		;NO MORE DATA

NOFND4:	TXNE	FF,FINDR	;LEFT ARROW SEARCH?
	PUSHJ	P,YANK1		;YES. FILL BUFFER.
	MOVE	E,SCHCNT	;RESTORE SEARCH COUNT.
	MOVE	A,BEG
	MOVEM	A,LOWERB
	MOVE	A,Z
	MOVEM	A,UPPERB
	JRST	WCHSCH		;GO DO SEARCH WITH THIS BUFFER FULL
RESTPT:	CHKEO	EO25,BEGIN1	;LEAVE POINTER AT TOP FOR EO OF 2 OR LESS
	MOVE	A,SCHPT		;GET OLD PT
	MOVEM	A,PT		;RESTORE IT
BEGIN1:	TXZ	FF,PCHFLG+FINDR ;CLEAR N AND _ .
	TXNN	F2,S.REPL	;F-SEARCH?
	JRST	NOFND5		;NO
	MOVE	CH,FSNTRM	;GET FS/FN INSERT TERMINATOR
	TXZN	FF,F.NNUL	;WAS IT A NULL INSERT?
	CAIE	CH,.CHESC	;YES, WAS IT AN ALTMODE TERMINATOR?
	JRST	NOFND5		;NO
	TXO	F2,NALTFS	;FLAG SO SECOND ALTMODE GETS PUT IN *I

NOFND5:	TXZE	FF,COLONF	;COLON MODIFIED?
	JRST	NOFND6		;YES, RETURN A 0
NOFND2:	SKIPL	(P)		;IN AN ITERATION?
	$FATAL	(SRH,,<Cannot find "17">)
	MOVSI	A,(MOVE B,)	;YES, IMPLICIT ":"; RESET DELIM
	HLLM	A,DLIM		;ON G.P.'S
NOFND6:	TXNE	F2,NALTFS	;WAS IT A NULL INSERT?
	JRST	ALTM1		;YES, THAT TERMINATES EXECUTION
	SETZB	A,B		;NO, RETURN A 0
				; IN "A" FOR VALRET; IN "B" FOR CLOSEC
	JRST	CLOSEC		;AND TERMINATE THE FREE "()" FROM THE ":"
;IF AUTOF IS NON-ZERO
;INCLUDE POINTER MARKER = ASCII CHAR IN AUTOF IF AUTOF GT 0

ZEROTT:	TXNE	FF,COLONF	;NO AUTOTYPE ON COLON SEARCHES
	POPJ	P,
	SKIPL	-1(P)		;IN AN ITERATION?
	SKIPN	AUTOF		;AUTOTYPE WANTED?
	POPJ	P,
	TXO	FF,ARG		;DO 0T
	SETZ	B,
	PUSHJ	P,TYPE
	HRRZ	CH,AUTOF
	SKIPL	AUTOF		;PTR MARKER WANTED?
	PUSHJ	P,TYOM		;YES
	MOVEI	B,1		;DO 1T
	PUSHJ	P,TYPE
	TXZ	FF,ARG
	POPJ	P,
;<>	ITERATION BRACKETS.  COMMAND INTERPRETATION IS SENT
;	BACK TO THE < WHEN THE > IS ENCOUNTERED.

LSSTH:	PUSH	P,ITERCT	;SAVE ITERATION COUNT
	PUSH	P,COMMAX	;KEEP MAX. FOR GARBAGE COLLECTION
	PUSH	P,COMPTR	;SAVE COMMAND STATE
	PUSH	P,COMPTX	; (DOUBLE-WORD POINTER ADDRESS)
	PUSH	P,COMCNT	;COMMAND CHARACTER COUNT
	SETOM	ITERCT		;ITERCT:=-1
	PUSH	P,ITERCT	;-1 FLAGS ITERATION ON PDL
	TXZN	FF,ARG		;IS THERE AN ARGUMENT?
	JRST	RET		;NO
	JUMPLE	B,INCMA1	;IF ARG .LE. 0, SKIP OVER <>
	MOVEM	B,ITERCT	;YES. ITERCT:=ARGUMENT
	JRST	RET


GRTH:	SKIPGE	A,(P)		;IS THERE A LEFT ANGLE BRACKET?
	JRST	GRTH2		;YES. OTHERWISE IT'S A MISSING ONE OR
	SOJE	A,GRTH9		;SOMETHING LIKE <...(...>
	$FATAL	(MLA,,<Missing left angle bracket>)
GRTH2:	SOSN	ITERCT		;ITERCT:=ITERCT-1. DONE?
	JRST	INCMA2		;YES
	MOVE	A,-1(P)		;START-OF-ITERATION COMMAND COUNT
	MOVEM	A,COMCNT	;BECOMES NEW CURRENT COMMAND COUNT (AGAIN)
	DMOVE	A,-3(P)		;START-OF-ITERATION COMMAND POINTER
	DMOVEM	A,COMPTR	;BECOMES NEW CURRENT COMMAND POINTER (AGAIN)
	TXNE	FF,TRACEF	;TRACING?
	PUSHJ	P,CRR		;YES. OUTPUT CRLF
	JRST	RET

GRTH9:	$FATAL	(MRP,,<Missing right parenthesis>)

U ITERCT,1			;
U SFINDF,1			;
;;	IF NOT IN AN ITERATION, GIVES ERROR.  IF IN AN ITERATION ("<") AND
;	IF THE MOST RECENT SEARCH FAILED, SEND COMMAND TO FIRST UNMATCHED
;	">" TO THE RIGHT.  OTHERWISE, NO EFFECT.

SEMICL:	SKIPL	(P)		;ERROR IF NOT IN <...>
	$FATAL	(NSI,,<; not in an iteration>)
	TXNN	FF,ARG		;YES. IF NO ARG,
	MOVE	B,SFINDF	;USE LAST SEARCH SWITCH (0 OR -1).
	JUMPL	B,CD		;IF ARG LT 0, JUST RET AND EXECUTE LOOP
INCMA1:	MOVEI	TT1,"<"		;IGNORE <...> STRINGS
	MOVEI	TT,">"		;WHILE SKAN'ING FOR END OF ITERATION
	PUSHJ	P,SKAN
	 $FATAL	(MRA,,<Missing right angle bracket>)
INCMA2:	ADJSP	P,-4		;PITCH THE FLAG, COMCNT, COMPTX, AND COMPTR
	POP	P,COMMAX	;PRESERVE THE COMMAND BUFFER LIMIT WORD
	POP	P,ITERCT	;AND THE ITERATION COUNT/FLAG
	JRST	RET



;!TAG!	TAG DEFINITION.  THE TAG IS A NAME FOR THE LOCATION IT
;	APPEARS IN IN A MACRO, ITERATION OR COMMAND STRING.

EXCLAM:	PUSHJ	P,SKRCH		;LOOK FOR NEXT !
	$FATAL	(UTG,,<Unterminated tag>)
	CAIE	CH,"!"
	JRST	EXCLAM
	JRST	RET
;OTAG$	GO TO THE TAG NAMED TAG.  THE TAG MUST APPEAR IN THE
;	CURRENT MACRO OR COMMAND STRING.

OCMD:	MOVE	A,COMPTR	;CURRENT COMMAND BYTE POINTER
	SKIPE	SECTN		;PC IN EXTENDED SECTION?
	HRR	A,COMPTX	;YES, FAKE UP A PSEUDO ONE-WORD BYTE POINTER
	MOVE	AA,A		;A SCRATCH COPY USED TO
	IDIVI	AA,17		;GENERATE A "HASH" VALUE (SORT OF, MAYBE)
	CAMN	A,TAGSYM(B)	;DO WE ALREADY KNOW ABOUT THIS GUY?
	JRST	OCMD70		;YES, JUST SET NEW COMPTR
	SKIPN	TAGSYM(B)	;NO, IS THIS SLOT EMPTY?
	JRST	OCMD10		;SLOT EMPTY, DON'T KNOW THIS TAG'S VALUE
	CAMN	A,TAGSYM+1(B)	;SLOT FULL - MAYBE IN NEXT SLOT?
OCMD03:	AOJA	B,OCMD70	;YES, WE WIN AFTER ALL!
	SKIPN	TAGSYM+1(B)	;NO, NEXT SLOT EMPTY?
	AOJA	B,OCMD10	;YES, WE MUST SEARCH FOR THE TAG
	CAMN	A,TAGSYM+2(B)	;ONE LAST TRY - LOOK AT THIRD SLOT
	AOJA	B,OCMD03	;GOT IT! THIRD TIME'S THE CHARM . . .
	SKIPN	TAGSYM+2(B)	;NOT IN THIRD EITHER, IS IT EMPTY?
	ADDI	B,2		;YES, SELECT IT FOR OUR "HASH" SLOT

;TAG NOT KNOWN, MUST SEARCH FOR IT, FIRST BUILD TAG NAME IN SEARCH TABLE

OCMD10:	PUSH	P,A		;SAVE CURRENT PSEUDO POINTER
	PUSH	P,B		;SAVE "HASH" INDEX
	MOVEI	T,STAB		;GLOM ONTO SEARCH TABLE FOR OUR USE
OCMD11:	CAILE	T,STAB+STABLN-2	;IS THE TAG TOO LONG?
	$FATAL	(TTL,,<Tag too long>)
	PUSHJ	P,SKRCH		;GET NEXT COMMAND [TAG NAME] CHARACTER
	 $FATAL	(MEO,,<Macro ending with unterminated O command>)
	MOVEM	CH,(T)		;BUILD THE NAME IN THE SEARCH TABLE
	CAIE	CH,.CHESC	;END OF O COMMAND TAG YET?
	AOJA	T,OCMD11	;NO, ACCUMULATE REST OF TAG NAME
	MOVEI	A,"!"		;TAG TERMINATOR
	MOVEM	A,(T)		;GOES INTO THE SEARCH STRING TOO
	SETZM	1(T)		;MARK END OF SEARCH STRING
	MOVE	A,COMCNT	;COUNT OF COMMAND CHARACTERS LEFT
	SUB	A,COMMAX	;NEGATIVE COUNT OF COMMAND CHARACTERS PROCESSED
	ADJBP	A,COMPTR	;BACKUP COMMAND POINTER TO START OF COMMAND
	DMOVEM	A,COMPTR	;RESET COMMAND POINTER FOR SEARCH LOOP
	MOVE	B,COMMAX	;TOTAL NUMBER OF COMMAND CHARACTERS
	MOVEM	B,COMCNT	;RESET COMMAND CHARACTER COUNTER

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;SEARCH THE CURRENT COMMAND BUFFER FOR THE NAMED TAG

OCMD20:	MOVEI	TT,"!"		;SKAN FOR !
	MOVEI	TT1,-1		;NO SECONDARY CHAR.
	PUSHJ	P,SKAN		;SKAN COMMAND STRING UNTIL "!" CHARACTER
	 $FATAL	(TAG,,<Missing tag !12>)
	TXO	F2,NOTRAC	;DON'T TYPE EVERY TAG WHILE TRACING
	MOVEI	T,STAB		;INIT SEARCH STRING TO 1ST CHAR AFTER !

;AT A TAG, SEE IF RIGHT ONE

OCMD22:	SKIPN	(T)		;OVER STRING?
	JRST	OCMD30		;YES - WE FOUND THE DESIRED TAG
	PUSHJ	P,SKRCH		;NO. GET ANOTHER CHARACTER
	 $FATAL	(TAG,,<Missing tag !12!>)
	CAMN	CH,(T)		;THIS CHARACTER MATCH?
	AOJA	T,OCMD22	;YES. MOVE ON.
	CAIN	CH,"!"		;NO, ARE WE AT END OF A TAG?
	JRST	OCMD20		;YES, LOOK FOR THE NEXT TAG

;WRONG TAG, SKIM TO END OF CURRENT TAG

OCMD26:	PUSHJ	P,SKRCH		;GET NEXT CHAR OF [FAILED] TAG
	$FATAL	(UTG,,<Unterminated tag>)
	CAIE	CH,"!"		;END OF THIS TAG YET?
	JRST	OCMD26		;NO, KEEP GOING
	JRST	OCMD20		;YES, LOOK FOR ANOTHER TAG


;HERE WITH WINNING TAG (PUT IT IN SYMBOL TABLE)

OCMD30:	TXZ	F2,NOTRAC	;RE-ENABLE TRACING
	POP	P,B		;GET INDEX TO SYMBOL TABLE
	POP	P,TAGSYM(B)	;SAVE PSEUDO POINTER OF THIS O COMMAND
	MOVE	A,COMCNT	;CHARACTER COUNTER IMMED AFTER TAG
	MOVEM	A,TAGCNT(B)	;SAVE COUNTER IN "SYMBOL" TABLE
	DMOVE	A,COMPTR	;COMMAND BYTE POINTER AFTER TAG
	MOVEM	A,TAGPTR(B)	;SAVE BYTE POINTER IN "SYMBOL" TABLE
	MOVEM	AA,TAGPTX(B)	; (DOUBLE-WORD BYTE POINTER ADDRESS)
	JRST	RET		;RESUME COMMAND EXECUTION FOLLOWING TAG


;HERE WHEN TAG ALREADY KNOWN AND IN SYMBOL TABLE

OCMD70:	MOVE	A,TAGPTR(B)	;SAVED COMMAND BYTE POINTER FOLLOWING TAG
	MOVE	AA,TAGPTX(B)	; (DOUBLE-WORD BYTE POINTER ADDRESS)
	DMOVEM	A,COMPTR	;"JUMP" THE COMMAND BYTE POINTER
	MOVE	A,TAGCNT(B)	;SAVED COMMAND BYTE COUNTER FOLLOWING TAG
	MOVEM	A,COMCNT	;ADJUST TO REFLECT TAG'S POSITION
	JRST	RET		;RESUME COMMAND EXECUTION FOLLOWING TAG
;N"G	SEND COMMAND TO MATCHING ' UNLESS N GT 0.
;N"L	SEND COMMAND TO MATCHING ' UNLESS N LT 0.
;N"E	SEND COMMAND TO MATCHING ' UNLESS N EQ 0.
;N"N	SEND COMMAND TO MATCHING ' UNLESS N NE 0.
;N"F	SEND COMMAND TO MATCHING ' UNLESS N EQ 0 (I.E., "FALSE").
;N"U	SEND COMMAND TO MATCHING ' UNLESS N EQ 0 (I.E., "UNSUCCESSFUL").
;N"T	SEND COMMAND TO MATCHING ' UNLESS N LT 0 (I.E., "TRUE").
;N"S	SEND COMMAND TO MATCHING ' UNLESS N LT 0 (I.E., "SUCCESSFUL").
;N"C	SEND COMMAND TO MATCHING ' UNLESS THE VALUE OF N AS AN ASCII
;	CHARACTER IS A LETTER, NUMBER, PERIOD (.), DOLLAR SIGN ($),
;	OR PER CENT (%).
;N"A	SEND COMMAND TO MATCHING ' UNLESS THE VALUE OF N AS AN ASCII
;	CHARACTER IS ALPHABETIC.
;N"D	SEND COMMAND TO MATCHING ' UNLESS THE VALUE OF N AS AN ASCII
;	CHARACTER IS A DIGIT.
;N"V	SEND COMMAND TO MATCHING ' UNLESS THE VALUE OF N AS AN ASCII
;	CHARACTER IS LOWER CASE ALPHABETIC.
;N"W	SEND COMMAND TO MATCHING ' UNLESS THE VALUE OF N AS AN ASCII
;	CHARACTER IS UPPER CASE ALPHABETIC.

DQUOTE:	TXNN	FF,ARG		;ERROR IF NO ARG BEFORE "
	$FATAL	(NAQ,,<No argument before ">)
	PUSHJ	P,SKRCH		;GET CHAR AFTER "
	$FATAL	(MEQ,,<Macro ending with ">)
	MOVEI	T,DQTABL	;INDEX DISPATCH TABLE
	PUSHJ	P,DISPAT	;DISPATCH FOR CHAR. AFTER "
	$FATAL	(IQC,,<Illegal command "00>)

;" COMMAND DISPATCH TABLE

DQTABL:	XWD	DQ.G,"G"
	XWD	DQ.L,"L"
	XWD	DQ.N,"N"
	XWD	DQ.E,"E"
	XWD	DQ.C,"C"
	XWD	DQ.L,"T"
	XWD	DQ.E,"F"
	XWD	DQ.L,"S"
	XWD	DQ.E,"U"
	XWD	DQ.A,"A"
	XWD	DQ.D,"D"
	XWD	DQ.V,"V"
	XWD	DQ.W,"W"
	XWD	0,0		;END OF LIST
;EXECUTE INDIVIDUAL " COMMANDS

DQ.V:	TRZN	B,40		;EXECUTE "V
	JRST	NOGO		;IF BIT 30 NOT ON IT CAN'T BE L.C.
DQ.A:	TRZ	B,40		;EXECUTE "A -- TREAT UC & LC ALIKE
DQ.W:	CAIL	B,"A"		;EXECUTE "W
	CAILE	B,"Z"
	JRST	NOGO		;IT IS NOT A LETTER
	JRST	RET		;IT IS A LETTER
DQ.D:	CAIL	B,"0"		;EXECUTE "D
	CAILE	B,"9"
	JRST	NOGO		;IT IS NOT A DIGIT
	JRST	RET		;IT IS A DIGIT
DQ.C:	PUSHJ	P,CKSYM1	;EXECUTE "C
	JRST	RET		;IT IS A SYMBOL CHAR
	JRST	NOGO		;IT'S NOT A SYMBOL CHAR
DQ.G:	MOVNS	B		;EXECUTE "G
DQ.L:	JUMPL	B,RET		;EXECUTE "L
	JRST	NOGO		;TEST FAILED
DQ.N:	JUMPN	B,RET		;EXECUTE "N
	JRST	NOGO		;TEST FAILED
DQ.E:	JUMPE	B,RET		;EXECUTE "E, "F, "U
NOGO:	MOVEI	TT,47		;SKAN FOR '
	MOVEI	TT1,42		;IGNORE "...' STRINGS
	PUSHJ	P,SKAN
	$FATAL	(MAP,,<Missing '>)
	JRST	RET
;COMMAND TO COMPLEMENT TRACE MODE. "?" AS A COMMAND

QUESTN:	TXNN	FF,TRACEF	;DID WE TOGGLE INTO TRACE MODE ??
	SETOM	WINFLG		;YES, SO DON'T DISPLAY BUFFER
	TXCE	FF,TRACEF	;COMPLEMENT TRACE FLAG
	PUSHJ	P,CRR		;TYPE CR/LF AFTER TRACE MODE EXIT
	JRST	RET

COMMEN:	SKIPE	COLUMN		;AT NICE FRESH START OF A COLUMN?
	SKIPE	TYOTCT		;NO, HAS ANYTHING PRECEDED US?
	CAIA			;DON'T DO ANYTHING
	PUSHJ	P,CRR		;FIRST OUTPUT, GET TO A FRESH LINE FOR NEATNESS
COMMET:	PUSHJ	P,SKRCH		;GET A COMMENT CHAR
	$FATAL	(UCA,,<Unterminated ^A command>)
	CAIN	CH,.CHCNA	;^A
	JRST	COMMEX		;YES, END OF OUTPUT
	TXNN	FF,TRACEF
	PUSHJ	P,TYOM		;TYPE IT
	JRST	COMMET

COMMEX:	TXNE	FF,TRACEF	;IF TRACING,
	TXNN	FF,TYOF		;OR NO OUTPUT
	CAIA			;DON'T BOTHER
	PUSHJ	P,TYOOUT	;OTHERWISE FORCE OUT ANY OUTPUT
	JRST	RET		;RETURN

;OLD ^G EXIT COMMAND AND ILLEGAL COMMANDS

BELDMP:	CHKEO	EO21,FINISZ	;IF EO=1, DO ^Z,
ERRA:	$FATAL	(ILL,,<Illegal command 00>)

TDDT:	SKIPN	A,.JBBPT	;IS THERE A DDT LOADED?
	$FATAL	(DDT,,<DDT is not loaded>)
	TLNN	A,-1		;ALREADY SPECIFIED A PARTICULAR SECTION?
	HLL	A,SECTN		;NO, SELECT OUR CURRENT PC SECTION
	SETOM	MESFLG		;SCREEN WILL BE ZAPPED
	JSR	@A		;CAUSE UNSOLICITED BREAKPOINT
DDTECO::JRST	RET		;COMMAND IS DONE
;ROUTINE TO TEST CHARACTER FOR $,%,.,0-9,A-Z
;CALL	PUSHJ P,CKSYM
;	RETURN IF $,%,.,0-9,A-Z
;	RETURN ON ALL OTHER CHARACTERS

CKSYM:	MOVEI	B,(CH)		;ENTER AT CKSYM1 IF CHAR ALREADY IN B
CKSYM1:	CAIE	B,"$"		;$ OR %?
	CAIN	B,"%"
	POPJ	P,		;YES
	CAIN	B,"."		;NO. POINT?
	POPJ	P,		;YES.
	CAIGE	B,"0"		;NO. DIGIT OR LETTER?
	JRST	CPOPJ1		;NO
	CAIG	B,"9"		;MAYBE. DIGIT?
	POPJ	P,		;YES.
CKSYM2:	TRZ	B,40		;LC TO UC
	CAIL	B,"A"		;LETTER?
	CAILE	B,"Z"
	JRST	CPOPJ1		;NO.
	POPJ	P,		;YES
;SETUP QUOTING CHARACTERS

SETQTE:	MOVEI	TT1,.CHCNT	;CONTROL-CHARACTER QUOTER
	MOVEM	TT1,CCQTE	;SET IT UP
	CHKEO	EO21,SETQ21	;DO ANCIENT STUFF
	CHKEO	EO25,SETQ25	;DO OLD STUFF
	MOVEI	TT1,.CHCNV	;CHARACTER QUOTER
	MOVEM	TT1,CHQTE	;SET IT UP
	SETOM	CHQTE2		;NO OTHER CHARACTER-QUOTER
	MOVEI	TT1,.CHCNA	;LOWER-CASE QUOTER
	MOVEM	TT1,LCQTE	;SET IT UP
	MOVEI	TT1,.CHCNB	;UPPER-CASE QUOTER
	MOVEM	TT1,UCQTE	;SET IT UPT
	POPJ	P,		;ET C'EST CA

SETQ25:	MOVEI	TT1,.CHCNR	;CHARACTER QUOTER
	MOVEM	TT1,CHQTE	;SET IT UP
	MOVEI	TT1,.CHCNQ	;ALTERNATE CHARACTER QUOTER
	MOVEM	TT1,CHQTE2	;SET IT UP
	MOVEI	TT1,.CHCNV	;LOWER-CASE QUOTER
	MOVEM	TT1,LCQTE	;SET IT UP
	MOVEI	TT1,.CHCNW	;UPPER-CASE QUOTER
	MOVEM	TT1,UCQTE	;SET IT UP
	POPJ	P,		;OLD STYLE NOW SELECTED

SETQ21:	MOVEI	TT1,.CHCNQ	;CHARACTER QUOTER
	MOVEM	TT1,CHQTE	;SET IT UP
	SETOM	CHQTE2		;NO OTHER QUOTER
	SETOM	LCQTE		;NO LOWER-CASE QUOTER
	SETOM	UCQTE		;NO UPPER-CASE QUOTER
	POPJ	P,		;NOTHING ELSE HERE

U	CHQTE,1			;GENERAL CHARACTER QUOTER
U	CHQTE2,1		;ALTERNATE CHARACTER QUOTER
U	CCQTE,1			;CONTROL-CHARACTER QUOTER
U	LCQTE,1			;LOWER-CASE QUOTER
U	UCQTE,1			;UPPER-CASE QUOTER
	SUBTTL	SCREEN DISPLAY ROUTINES

;NV	SCROLL SCREEN DISPLAY BY N LINES
;I,JV	MAKE DISPLAY WINDOW FROM I TO J

VCMD:	SKIPN	SCTYPE		;V IS REALLY T IF NOT IN DISPLAY MODE
	JRST	TYPE		;WE'RE NOT !!
	TXNE	FF,ARG2		;NV OR I,JV?
	JRST	VCMD2		;I,JV
	DMOVE	A,SCRNA		;NV, CURRENT BASE OF SCREEN DISPLAY
	MOVE	D,B		;HOW FAR TO SHIFT IT
	PUSHJ	P,DISMV		;GET ADJUSTED BASE
	PJRST	VUNXTV		;AND DO IMMEDIATE SCREEN UPDATE

;MAKE SCREEN WINDOW BE EXACTLY FROM I (INCLUSIVE) TO J (EXCLUSIVE)

VCMD2:	PUSHJ	P,GETARG	;C:=FIRST STRING ARGUMENT ADDRESS.
				;B:=SECOND STRING ARGUMENT ADDRESS.
	PUSHJ	P,CHK1		;C:=MAX(C(C),BEG), B:=MIN(C(B),Z)
	MOVEM	C,SCRNA		;SET BASE OF SCREEN
	SETZM	SCRNAA		;SKIP NO LINES
	MOVEM	B,SCRNVZ	;AND PREMATURE END OF SCREEN
	PJRST	VUNXTX		;AND DO IMMEDIATE SCREEN UPDATE
;VUPRV  --  VIEW PREVIOUS WINDOW, BUT DON'T CHANGE "."/CURSOR

VUPRV:	SKIPE	MESFLG		;SCREEN MESSED UP (ERROR MSG, ETC.)?
	SKIPE	CMFTYO		;YES - SUPPRESSING TYPEOUT?
	CAIA			;DON'T ERASE SCREEN
	PUSHJ	P,ZAPSCN	;YES, START FROM SCRATCH
	DMOVE	A,SCRNA		;CURRENT SCREEN BASE
	MOVN	D,DLENTH	;ONE SCREENFUL BACKWARDS
	ADDI	D,1		;(ALLOW FOR BLANK LINE AT THE END)
	PUSHJ	P,DISMV		;ADJUST SCREEN POINTERS
	PJRST	VUNXTV		;GO MAKE NEW SCREEN DISPLAY



;VUNXT  --   VIEW NEXT WINDOW, BUT DON'T CHANGE "."/CURSOR

VUNXT:	SKIPE	MESFLG		;SCREEN MESSED UP (ERROR MSG, ETC.)?
	SKIPE	CMFTYO		;YES - SUPPRESSING TYPEOUT?
	CAIA			;DON'T ERASE SCREEN
	PUSHJ	P,ZAPSCN	;YES, START FROM SCRATCH
	DMOVE	A,DISCA		;GET LAST KNOWN MARGIN POINT
VUNXTV:	DMOVEM	A,SCRNA		;AND SET FOR WINFIL
	MOVE	TT,Z		;END OF TEXT BUFFER
	MOVEM	TT,SCRNVZ	;ALLOW TO END OF BUFFER
VUNXTX:	PUSHJ	P,DISPLA	;GENERATE AND DISPLAY NEXT SCREEN
	SETOM	VFREEZ		;REALLY BY DAMN FREEZE THE SCREEN!
	POPJ	P,		;ALL DONE
;WINIT  --  ROUTINE TO CALCULATE STARTING POINT OF SCREEN DISPLAY.
;
;BASICALLY THIS ROUTINE WILL ATTEMPT TO POSITION THE CURSOR APPROXIMATELY
;1/3 OF THE WAY DOWN THE SCREEN WINDOW DISPLAY. FOR A VT50 (12 LINE
;SCREEN, 9 LINES OF DISPLAY WINDOW) THIS RESULTS IN THE POINTER BEING ON
;THE FOURTH LINE (3 LINES ABOVE, 5 LINES BELOW THE POINTER). FOR A VT52
;(24 LINE SCREEN, 19 LINES OF DISPLAY WINDOW) THIS RESULTS IN THE POINTER
;BEING ON THE SEVENTH LINE (6 LINES ABOVE AND 12 LINES BELOW THE POINTER).
;
;ON EXIT, SCRNA HAS THE ABSOLUTE BASE OF THE SCREEN DISPLAY, SCRNAA HAS
;THE COUNT OF LINES TO SKIP BEFORE THE SCREEN STARTS.

WINIT:	MOVE	A,PT		;START WITH "."
	SETZ	AA,		;WE KNOW NOTHING
	MOVN	D,CLENTH	;HOW FAR DOWN WE LIKE THE CURSOR

;POSITION START OF SCREEN C(D) LINES BACK FROM C(I) IF POSSIBLE, STOPPING
;AT BEG IF NECESSARY.

	PUSHJ	P,DISMV		;CALCULATE A NICE SCREEN BASE
	DMOVEM	A,SCRNA		;REMEMBER ABSOLUTE BASE INFORMATION
	POPJ	P,		;RETURN READY FOR WINFIL
;DISMV  --  MOVE DISPLAY POINTERS AROUND
;CALL IS:
;
;	MOVX	A,<BASE>
;	MOVX	AA,<SKIP>
;	MOVX	D,<COUNT>
;	PUSHJ	P,DISMV
;	RETURN
;
;WHERE <BASE> IS THE CURRENT ABSOLUTE BASE OF THE SCREEN; <SKIP> IS THE
;SKIP COUNT TO THE ACTUAL START OF THE SCREEN; AND <COUNT> IS HOW FAR
;TO MOVE (NEGATIVE IS BACKWARDS - TOWARDS BEG).
;
;ON RETURN, A AND AA ARE NEW PROPOSED <BASE> AND <SKIP>. IF <COUNT> WAS
;POSITIVE, I WILL BE THE CHARACTER ADDRESS OF THE NEW SCREEN START
;RE A AND AA.
;
;USES A, AA, B, C, D, I, OU.

DISMV:	MOVE	I,A		;START UP POINTER
	PUSHJ	P,DISINI	;INITIALIZE DISCHR
	ADD	AA,D		;SEE HOW FAR WE HAVE TO MOVE
	CAIN	AA,0		;EXACT MATCH?
	POPJ	P,		;YES - RARE BUT IT DOES HAPPEN
	JUMPL	AA,DISMV5	;NO, FORWARDS OR BACKWARDS?

;MOVE FORWARDS

	SETZ	C,		;START NEW DISPLAY LINE
DISMV2:	PUSHJ	P,DISCHR	;NEXT DISPLAY CHARACTER
	CAIN	CH,.CHCRT	;BEGINING OF END OF DISPLAY LINE?
	MOVNI	C,1		;YES (FOR DISCON'S BENEFIT)
	CAIE	CH,.CHLFD	;END OF DISPLAY LINE?
	AOJA	C,DISMV2	;NO
	SOJG	AA,DISMV2	;MOVED FAR ENOUGH?
	DMOVE	A,DISCA		;YES, GET NEW POSSIBLE BASE/SKIP PAIR
	POPJ	P,		;RETURN

;MOVE BACKWARDS

DISMV5:	MOVN	D,AA		;D:=BACKWARDS SKIP COUNT
DISMV6:	PUSHJ	P,DSBCK		;SETUP BACKWARDS INFORMATION
	CAMG	D,AA		;FOREKNOWLEDGE EXTEND BACK FAR ENOUGH?
	JRST	DISMV9		;YES, ADJUST AS NECESSARY
	CAMG	A,BEG		;NO, STILL HAVE TEXT LEFT?
	JRST	DISMV8		;NO, BIT START OF TEXT BUFFER
	SUBI	D,1(AA)		;YES, D:=NEW BACKWARDS LINE COUNT
	SOS	I,A		;PREVIOUS LIMIT OF FOREKNOWLEDGE
	JRST	DISMV6		;SCAN BACKWARDS SOME MORE

DISMV8:	TDZA	AA,AA		;HIT BEG, SO BASE IS BASE IS BASE
DISMV9:	SUB	AA,D		;AA:=SKIP COUNT FROM BASE
	POPJ	P,		;RETURN ALL SET
;DSBCK  --  BACKWARDS PEEKING HELPER FOR WINIT

DSBCK:	MOVEM	I,OU		;SAVE STARTING POINT
	TDZA	CH,CH		;ENTER LOOP
DSBCK1:	PUSHJ	P,GET		;GET PRECEDING CHARACTER
DSBCK2:	CAMG	I,BEG		;RUN INTO START OF TEXT?
	JRST	DSBCK4		;YES, THEN STOP THERE
	CAIE	CH,.CHVTB	;NOT YET, SEEING A <VT>?
	CAIN	CH,.CHFFD	;OR A <FF>?
	AOJA	I,DSBCK4	;YES, THEN WE KNOW STATE OF SCREEN
	CAIE	CH,.CHLFD	;NO, HOW ABOUT <LF>?
	SOJA	I,DSBCK1	;NO, RANDOM, KEEP LOOKING
	SUBI	I,1		;BACK ONE MORE CHARACTER
	PUSHJ	P,GET		;GET CHARACTER PRECEDING <LF>
	CAIE	CH,.CHCRT	;A <CR>?
	JRST	DSBCK2		;NO, CHECK FOR OTHER STUFF
	ADDI	I,2		;YES, KNOWN STATE, SKIP <CR><LF>

;HERE WITH C(I) BEING A KNOWN FORCED BOL CONDITION (<CR><LF>, <FF>, ETC.)
;SCAN FORWARDS UNTIL WE KNOW WHERE C(OU)'S LINE STARTS

DSBCK4:	PUSHJ	P,DISINI	;START DISCHR FRESH
	MOVE	A,I		;SET ABSOLUTE BASE
	MOVE	B,I		;AND PROPOSED START OF LINE
	SETZB	AA,C		;CLEAR LINES SKIPPED AND CHAR POSITION
	CAMN	I,OU		;BACK WHERE WE STARTED?
	POPJ	P,		;YES, THEN ALL SET
DSBCK6:	PUSHJ	P,DISCHR	;GET NEXT DISPLAY CHARACTER
	CAMGE	I,OU		;GOT BACK TO OUR STARTING POINT YET?
	CAML	I,Z		;JUST CHECKING . . .
	POPJ	P,		;YES, ALL DONE
	CAIN	CH,.CHCRT	;BEGINING OF END OF DISPLAY LINE?
	MOVNI	C,1		;YES (FOR DISCON'S BENEFIT)
	CAIE	CH,.CHLFD	;END OF A DISPLAY LINE?
	AOJA	C,DSBCK6	;NOT YET
	MOVE	B,I		;SAVE NEW START OF LINE
	AOJA	AA,DSBCK6	;COUNT LINES SKIPPED
;WINFIL  --  ROUTINE TO FILL WINEW WITH NEW PICTURE TO BE DISPLAYED
;
;SCRNA HAS THE ABSOLUTE BASE OF THE SCREEN IMAGE AND SCRNAA HAS THE
;NUMBER OF LINES TO SKIP BEFORE STARTING THE SCREEN. THIS IS SO THAT THE
;SCREEN IS ALWAYS "RIGHT" AND CONSISTENT IRRESPECTIVE OF HOW THE SCREEN
;WAS DERIVED (SCANNING FORWARDS OR BACKWARDS). THIS MAY RESULT IN A LOT
;OF COMPUTES FOR THE PSYCHOPATHIC CASES, BUT THEY WILL BE HANDLED!
;
;ON EXIT, SCRNB HAS FIRST CHARACTER ADDRESS ON SCREEN, AND SCRNZ HAS
;THE LAST CHARACTER ADDRESS PLUS ONE ON THE SCREEN (THE FIRST CHARACTER
;TO APPEAR IN THE FOLLOWING SCREEN). DISCA AND DISCAA ARE "PROPOSED"
;SCRNA AND SCRNAA FOR VUNXT TO DISPLAY THE NEXT SCREENFULL.

WINFIL:	DMOVE	A,SCRNA		;GET SCREEN BASE
	SETZ	D,		;SKIP ONLY TO START OF SCREEN DISPLAY TEXT
	PUSHJ	P,DISMV		;GET SCREEN START IN I
WINFI2:	MOVEM	I,SCRNB		;REMEMBER START [CHAR] ADDRESS OF SCREEN
	SKIPGE	DISPTF		;WAS POINTER ALREADY DISPLAYED?
	SETZM	DISPTF		;YES, THEN NOT ON CURRENT SCREEN
				; (THIS FOR GOSC'S BENEFIT)
	MOVE	D,DLENTH	;COUNT OF LINES ON THE DISPLAY WINDOW
	SUBI	D,1		;ONE BLANK LINE TWEEN DISPLAY AND COMMANDS
	SETZM	WINEW		;CLEAR OUT OLD NEW STUFF
	MOVE	A,[WINEW,,WINEW+1]  ;BLT POINTER TO
	BLT	A,WINEW+WINTOP-1;ZERO NEW SCREEN IMAGE AREA
	MOVEI	A,0		;POINTER TO DISPLAY NEW MEMORY
WINFI5:	MOVE	AA,[POINT 7,WINEW(A)]  ;POINTER TO NEW DISPLAY IMAGE
	TDZA	C,C		;ZERO # OF CHARS ON THIS SCREEN LINE SO FAR
WINFI6:	IDPB	CH,AA		;PUT THIS CHAR INTO WINDOW
	PUSHJ	P,DISCHR	;GET DISPLAY CHARACTER FROM BUFFER
	CAIN	CH,.CHCRT	;<CR> (END OF LINE)?
	MOVNI	C,1		;AOJA WILL TURN THIS TO 0
	CAIE	CH,.CHLFD	;LF MEANS END OF SCREEN LINE
	AOJA	C,WINFI6	;COUNT CHARACTER AND GO GET ANOTHER
	LDB	T,[POINT 6,AA,5];GET POSITION FIELD OF POINTER
	ADDI	T,7		;COVER LAST CHAR, TOO
	DPB	T,[POINT 12,AA,11]  ;SIZE GETS P+7, CLEAR P
	MOVEI	C,0
	DPB	C,AA		;CLEAR REST OF WORD
	ADDI	A,WINDEX	;A POINTS TO NEXT SCREEN LINE
	SOJG	D,WINFI5	;FILLED WINDOW YET?
	MOVEM	I,SCRNZ		;REMEMBER FIRST CHARACTER NOT DISPLAYED
WINFI8:	CAILE	A,WINTOP-1	;HAS WHOLE DISPLAY AREA BEEN UPDATED??
	POPJ	P,		;YES
	SETOM	WINDOW(A)	;NO, MARK REST OF SCREEN "BLANK"
	ADDI	A,WINDOW+1	;CONCOCT
	HRLI	A,-1(A)		; A BLT POINTER
	BLT	A,WINDOW+WINTOP-1  ;TO "BLANK" REST OF THE SCREEN
	POPJ	P,		;RETURN
;DISPLAY INITIALIZATION ROUTINE

DISINI:	MOVEM	I,DISCA		;PRESET LAST KNOWN LINE START
	SETZM	DISCAA		;AND COUNT OF LINES PAST THAT POINT
DISZER:	SETZM	TABFIL		;TAB FLAG
	SETZM	EOBFLG		;END OF BUFFER FLAG
	SETZM	DISPTF		;POINTER IN DISPLAY FLAG
	SETZM	DISCTF		;NON-ZERO MEANS CONTROL CHARACTER
	SETZM	SEOL		;END OF LINE SEEN FLAG
	SETZM	SEOL2		;CLEAR FREE <CR><LF> NEEDED FLAG
	SETZM	SEOL3		;CLEAR ^J FILLER DISPLAY
	TXZ	F2,TYMSGF!TYSPCL;CLEAR FUNNY TYO-MODE FLAGS
	POPJ	P,
;ROUTINE TO RETURN NEXT DISPLAY LINE CHARACTER IN T, TAKES
;TWO CALLS TO GET ^* FOR CONTROL-CHARACTER.  CARRIAGE RETURN
;AND LINEFEED ARE RETURNED AS ^J AND ^M UNLESS THEY APPEAR
;IN THE BUFFER AS CRLF.  THE CONTENTS OF TCOCH IS GIVEN
;IF LINE IS ABOUT TO GO OVER RIGHT MARGIN, AND TABS ARE CONVERTED
;TO THE PROVERBIAL "APPROPRIATE NUMBER OF SPACES", WITH THE CONTENTS
;OF TABSIZE USED TO SAYiOOST NUMBER OF SPACES EVER TO USE FOR TAB.
;POINTER IS DISPLAYED AS CHARACTER STRING THAT IS THE CONTENTS OF
;PTRCHR.  EVERY DISPLAY LINE
;ENDS WITH CRLF EITHER BECAUSE THE TEXT BUFFER HAD ONE, OR END OF
;DISPLAY LINE IS REACHED.

DISCHR:	CAIG	C,0		;START OF NEW LINE?
	SETZM	TABUNF		;YES, THEN CHARACTER POSITION IS IN PHASE
				; WITH ITS PHYSICAL SCREEN POSITION
	SKIPE	SEOL		;NON-ZERO SEOL MEANS END OF DISPLAY LINE
	JRST	DISEOL		;END OF LINE
	CAML	C,SWIDTH	;BEGINNING OF END OF LINE ???
	JRST	DISCON		;HANDLE END OF LINE
	SKIPE	CH,DISCTF	;OUTPUTTING CONTROL CHARACTER ??
	JRST	DISCT2		;YES, GO FINISH SECOND HALF OF ^X
	AOSG	SEOL2		;NEED A FREE <CR><LF>?
	JRST	DISEOC		;YES
	SKIPLE	DISPTF		;DISPLAYING POINTER "PICTURE"
	JRST	DISPT2		;YES, CONTINUE POINTER SEQUENCE
	MOVEI	CH," "		;SPACE FILLER CHARACTER
	SOSGE	SEOL3		;DOING ^J (NEXT LINE) FILL?
	SOSL	TABFIL		;OR TAB FILL?
	POPJ	P,		;YES
	SKIPE	EOBFLG		;END OF BUFFER ??
	JRST	EOBCHR		;YES, JUST SEND CRLFS
	CAMN	I,PT		;ARE WE AT "."?
	JRST	DISPTR		;YES, START UP POINTER SEQUENCE
DISCH2:	CAME	I,SCRNVZ	;HIT FORCED END OF SCREEN?
	CAML	I,Z		;OR END OF TEXT?
	JRST	EOBCH4		;YES, FILL WITH <CF><LF>S THEN

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PRECEDING PAGE

DISCH3:	PUSHJ	P,GETINC	;GET THE NEXT TEXT CHARACTER
	CAIN	CH,.CHTAB	;TAB ??
	JRST	DISTAB		;YES, START GIVING SOME SPACES
	CAIN	CH,.CHESC	;ALTMODE ??
	MOVEI	CH,"$"		;ALTMODE REGULAR NON-CONTROL CHARACTER
	CAIN	CH,.CHCRT	;CR ??
	JRST	SCR		;YES, MAYBE END OF LINE (IF LINEFEED NEXT)
	CAIN	CH,.CHLFD	;LF ??
	JRST	SLF		;YES, PART OF END OF LINE ??
	CAIN	CH,.CHDEL	;A RUBOUT?
	JRST	DISDEL		;YES, TREAT SORT OF LIKE CONTROL CHARACTER
	CAIE	CH,.CHVTB	;<VT>?
	CAIN	CH,.CHFFD	;OR <FF>?
	CAIA			;YES - NEEDS A FREE <CR><LF>
	JRST	DISCH8		;NO, CHECK FOR OTHER CONTROL CHARACTER
DISCH5:	SETOM	SEOL2		;YES, GIVE A FREE <CR><LF> FOLLOWING
	MOVEM	I,DISCA		;SAVE LAST KNOWN LEFT MARGIN ADDRESS
	SETOM	DISCAA		;AND SKIP LINES FOR VUNXT
DISCH8:	CAIGE	CH," "		;OTHER CONTROL CHARACTER ??
	JRST	DISCTL		;YES, GO DISPLAY IT
	PUSHJ	P,SFLAGC	;FLAG THIS CHARACTER ??
	POPJ	P,		;NO
	MOVEM	CH,DISCTF	;REMEMBER WHAT CH WAS FLAGGED
	AOS	TABUNF		;COUNT SCREEN SPACE USED UP
	MOVEI	CH,CFLAG	;GET FLAG CHARACTER
	POPJ	P,
;HERE TO DISPLAY CONTROL CHARACTER IN ^X FORMAT (<DEL> AS ^?)

DISCTL:	TROA	CH,100		;MAKE X PART OF ^X
DISDEL:	MOVEI	CH,"?"		;MARK A <DEL>
	MOVEM	CH,DISCTF	;FLAG IT FOR NEXT CALL TO DISCHR
	MOVEI	CH,"^"		;PRINT UPARROW FIRST
DISCT0:	AOS	TABUNF		;WE JUST SWIPPED A SCREEN SPACE
	POPJ	P,

DISCT2:	SETZM	DISCTF		;END OF CONTROL CHARACTER SEQUENCE
	POPJ	P,		;RETURN WITH SECOND HALF (X OF ^X)



;HERE TO HANDLE TABS (FILL WITH SPACES FOR DISPLA)

DISTAB:	MOVE	CH,C		;GET COLUMN COUNT SO FAR
	SUB	CH,TABUNF	;CH:=WHERE WE OUGHT TO BE ON SCREEN
	IDIV	CH,TABSIZ	;SEE HOW MANY TAB STOPS OVER WE ARE
	IMUL	CH,TABSIZ	;CHANGE TO COLUMNS AGAIN
	ADD	CH,TABSIZ	;GET TO NEXT TAB STOP
	SUBI	CH,1(C)		;CH:=SPACE FILL FOR REST OF TAB
	MOVEM	CH,TABFIL	;FLAG SPACE FILL NEEDED (MAYBE)
	CAIL	CH,0		;ARE WE BACK IN PHASE WITH THE SCREEN POSITION?
	SETZ	CH,		;YES!
	MOVNM	CH,TABUNF	;NOT CAUGHT UP, BUT CLOSER!
	MOVEI	CH," "		;START TAB SEQUENCE
	POPJ	P,
EOBCHR:	SKIPL	EOBFLG		;EOBFLG NEGATIVE IF JUST REACHED END OF LINE
	JRST	EOBCH6		;DIDN'T JUST, SO OSCILLATE BETWEEN CR AND LF
EOBCH4:	MOVEI	CH,.CHLFD	;SO CR BEFORE LF IN OSCILLATION
	MOVEM	CH,EOBFLG
EOBCH6:	MOVEI	CH,.CHCRT+.CHLFD;CR+LF
	SUBB	CH,EOBFLG	;CHANGE CR TO LF AND LF TO CR
	POPJ	P,		;T HAS CR OR LF BECAUSE NO MORE BUFFER



DISEOC:	MOVEI	CH,.CHCRT	;<CR> OF FREE <CR><LF> PAIR
	MOVEM	CH,SEOL		;REMEMBER TO DO THE <LF>
	POPJ	P,		;RETURN WITH <CR>

DISEOL:	MOVEI	CH,.CHCRT+.CHLFD;CR + LF
	SUBB	CH,SEOL		;CHANGE ONE TO THE OTHER
	CAIE	CH,.CHLFD	;SEE IF WE'VE PRINTED ONE SET YET
	POPJ	P,		;NO
	SETZM	SEOL		;YES, CLEAR FLAG
	AOS	DISCAA		;AND COUNT DISPLAY LINES SEEN
	POPJ	P,		;RETURN WITH <LF>




DISPTR:	SKIPLE	DISPTF		;HAVE WE STARTED POINTER PICTURE YET?
	JRST	DISPT2		;YES, JUST CONTINUE IT
	SKIPE	DISPTF		;HAVE WE ALREADY FINISHED IT?
	JRST	DISCH2		;YES ("." AT END OF TEXT)
	MOVE	CH,DISCA	;LAST LINE BASE
	MOVEM	CH,DIPTA	;SAVE CURSOR BASE
	MOVE	CH,DISCAA	;LAST LINE SKIP COUNT
	MOVEM	CH,DIPTAA	;SAVE CURSOR SKIP
	MOVEM	C,DIPTC		;SAVE SCREEN POSITION OF START OF CURSOR
	MOVEM	I,DIPTI		;SAVE ACTUAL CURRENT VALUE OF "."
	MOVE	CH,[POINT 7,PTRCHR]  ;POINTER TO POINTER PICTURE
	MOVEM	CH,DISPTF	;NOTE IN POINTER SEQUENCE
				; (DISPT2'S ILDB ENSURES DISPTF .GT. 0
				;  WHICH FLAGS POINTER IN PROGRESS)
DISPT2:	ILDB	CH,DISPTF	;NEXT CHARACTER IN PICTURE
	MOVE	T,DISPTF	;SCRATCH COPY OF BYTE POINTER
	ILDB	T,T		;PEEK AT NEXT CHARACTER
	CAIN	T,0		;CURRENT POINTER CHAR THE LAST ONE?
	SETOM	DISPTF		;YES, FLAG POINTER COMPLETELY IN DISPLAY WINDOW
	JRST	DISCT0		;RETURN BOGUS CHARACTER
SCR:	CAME	I,SCRNVZ	;FORCED TO BREAK HERE?
	CAMN	I,PT		;CURSOR AFTER <CR>?
	JRST	DISCTL		;CURSOR AFTER <CR> = ^M
	PUSHJ	P,GET		;GET CHARACTER AFTER <CR>
	CAIN	CH,.CHLFD	;LF ??
	JRST	SCR1		;YES
	MOVEI	CH,.CHCRT	;NO, ^M
	JRST	DISCTL		;GO DO CONTROL CHARACTER SEQUENCE

SCR1:	MOVEI	CH,.CHCRT	;CRLF, SO CARRIAGE RETURN NOT HACKED
	POPJ	P,

SLF:	SUBI	I,1		;CHARACTER ADDRESS OF <LF>
	CAMG	I,BEG		;<LF> FIRST IN BUFFER?
	AOJA	I,SLF2		;YES, DISPLAY AS ^J
	SUBI	I,1		;CHARACTER IN FRONT OF <LF>
	PUSHJ	P,GETINC	;GET IT
	CAIE	CH,.CHCRT	;A <CR><LF> PAIR?
	AOJA	I,SLF2		;NO, THEN GETS DISPLAYED AS ^J
	MOVEI	CH,.CHLFD	;GET BACK THE <LF> CHARACTER
	CAMN	I,PT		;YES, IS CURSOR SANDWICHED INBETWEEN?
	AOJA	I,DISCH5	;YES, DISPLAY AS ^J WITH FREE CRLF
	ADDI	I,1		;NO, NORMAL <CR><LF>
	MOVEM	I,DISCA		;SAVE LAST KNOWN LEFT MARGIN ADDRESS
	SETZM	DISCAA		;AND SKIP LINES FOR VUNXT
	POPJ	P,		;RETURN WITH THE <LF>

;HERE FOR A STANDALONE LINE FEED, GIVE ^J THEN "ECHO" A <LF>

SLF2:	SETOM	SEOL2		;FLAG A FREE <CR><LF> NEEDED
	MOVEI	CH,2(C)		;CURRENT LINE POSITION (COUNTING ^J)
	CAML	CH,SWIDTH	;JUST HAPPEN TO HAVE A FULL LINE WITH THE ^J?
	SETZ	CH,		;YES, START NEW LINE THEN
	MOVEM	CH,SEOL3	;NEED LEADING SPACE FILL ON NEXT LINE
	MOVEI	CH,.CHLFD	;THE LINE FEED CHARACTER AGAIN
	JRST	DISCTL		;DISPLAY IT AS ^J
DISCON:	SETZM	TABFIL		;NO MORE TAB FILLING ON THIS LINE
	SETZM	TABUNF		;ALSO NO MORE SPACE TO RECLAIM
	MOVEM	I,DISCI		;SAVE I ACROSS OUR MUNGING BELOW
	CAMN	I,PT		;ARE WE [POSSIBLY FRESHLY] AT "."?
	SKIPGE	DISPTF		;YES, BUT ARE WE DONE WITH THE POINTER?
	SKIPE	DISCTF		;POINTER PICTURE OK - IN MIDDLE OF CTL CHR?
	JRST	DISCO9		;INCOMPLETE POINTER OR CONTROL CHARACTER
	CAME	I,SCRNVZ	;JUST HIT FORCED END OF SCREEN?
	CAML	I,Z		;OR END OF TEXT BUFFER?
	JRST	EOBCH4		;YES, CAP OFF WITH <CR><LF>'S THEN
	PUSHJ	P,GETINC	;PEEK AT NEXT TEXT CHARACTER
	CAMN	I,PT		;IF POINTER HERE
	JRST	DISCO9		;THEN CONTINUATION LINE
	CAIN	CH,.CHCRT	;IF <CR>
	JRST	DISCO4		;CHECK FOR <CR><LF>
	CAIE	CH,.CHTAB	;NOT <CR>, HOW ABOUT A <TAB>
	CAIN	CH,.CHESC	;OR AN <ESC>?
	JRST	DISCO2		;YEAH, COUNT AS NORMAL CHARACTERS
	CAIE	CH,.CHDEL	;HOW ABOUT A <DEL>
	CAIGE	CH," "		;OR RANDOM CONTROL CHARACTER?
	JRST	DISCO9		;YES, THEN A CONTINUATION LINE
DISCO2:	PUSHJ	P,SFLAGC	;IS THIS CHARACTER FLAGGED?
	CAIA			;NO, NORMAL PRINTING CHARACTER
	JRST	DISCO9		;YES, THEN CONTINUATION LINE
	CAME	I,SCRNVZ	;FORCED END OF DISPLAY HERE?
	CAML	I,Z		;OR END OF TEXT BUFFER?
	JRST	DISCO6		;YES, THEN NO CONTINUATION NEEDED
	PUSHJ	P,GETINC	;PEEK AT NEXT CHARACTER
	CAIN	CH,.CHCRT	;<CR> IS THE ONLY POSSIBILITY ALLOWED
	CAMN	I,PT		;BUT EVEN THEN ONLY IF NOT FOLLOWED BY "."
	JRST	DISCO9		;<CR> AS ^M, CONTINUATION NEEDED
DISCO4:	CAME	I,SCRNVZ	;FORCED END OF DISPLAY AFTER <CR>?
	CAML	I,Z		;OR END OF TEXT?
	JRST	DISCO9		;YES, <CR> AS ^M, CONTINUATION NEEDED
	PUSHJ	P,GETINC	;ONE MORE CHARACTER
	CAIE	CH,.CHLFD	;<LF> OR NOTHING!
	JRST	DISCO9		;NOTHING, NEED CONTINUATION
DISCO6:	MOVE	I,DISCI		;CONTINUATION NOT NEEDED AFTER ALL
	JRST	DISCH2		;SO PROCESS CHARACTER NORMALLY

DISCO9:	MOVE	I,DISCI		;CONTINUATION NEEDED, RESTORE CHARACTER
	MOVEI	CH,.CHLFD	;PRESET SEOL
	MOVEM	CH,SEOL		;TO RETURN <CR><LF> ON NEXT DISCHR CALL
	MOVE	CH,TCOCH	;PICKUP AND
	POPJ	P,		;RETURN CONTINUATION LINE FLAG
;ROUTINE TO DISPLAY NEW WINDOW

REPEAT	0,<

DISPLA:	PUSHJ	P,WINFIL	;FILL WINEW WITH NEW DISPLAYFUL
DISPLX:	SKIPE	CMFTYO		;SUPPRESSING OUTPUT DUE TO COMMAND FILE?
	POPJ	P,		;YES, RETURN NOW IN THAT CASE
	SETZB	B,AA		;B IS BUFFER POINTER, AA IS LINE COUNTER
DISPL1:	MOVE	T,B		;BASE OF LINE COMPARE
	CAML	AA,SLENTH	;IF SCREENFUL DONE, QUIT
	POPJ	P,		;YES, SO QUIT
DISCOM:	MOVE	C,WINDOW(T)	;GET SOME FROM CURRENT DISPLAY
	CAME	C,WINEW(T)	;SAME AS DESIRED?
	JRST	DISDIF		;NO, SO LINES ARE DIFFERENT
	TRNE	C,177_1		;END OF ASCIZ LINE?
	AOJA	T,DISCOM	;NO, LOOK AT NEXT WORD
DISPL2:	ADDI	B,WINDEX	;LINES THE SAME, NEEDN'T DISPLAY
	AOJA	AA,DISPL1
DISDIF:	MOVEI	T,.TOTTC	;TOTAL MONITOR-HELD INPUT CHARACTERS
	MOVE	TT,TTYUDX	;UDX OF TERMINAL
	MOVE	C,[2,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	C,		;SKIP IF THERE IS ANY TYPEIN
	  JRST	DISPL7		;NO, OUTPUT THIS LINE
	JUMPE	C,DISPL7	;IS THERE ANY TYPEIN AVAILABLE?
	SETOM	WINDOW(B)	;YES, ECHO LIKELY CLOBBERED LAST LINE
	POPJ	P,		;AND GO PROCESS TYPEIN

DISPL7:	MOVEI	CH,(AA)		;FIND WHAT DISPLAY LINE POSITION TO
	PUSHJ	P,LINECH	;GO TO AND GO THERE
	PUSHJ	P,CLREOL	;CLEAR TO END OF LINE (WIPE OUT OLD LINE)
	MOVEI	C,WINEW(B)	;ADDRESS OF NEW LINE OF TEXT
	PUSHJ	P,VTSTR		;OUTPUT ASCIZ STRING
	MOVE	T,B		;GET COPY OF POINTER TO DISPLAY AREA
	HRL	T,T		;COPY IT TO LEFT HALF
	ADD	T,[WINEW,,WINDOW]  ;MAKE BLT POINTER
	BLT	T,WINDOW+WINDEX-1(B)  ;AND MOVE LINE FROM WINEW TO WINDOW AREA
	JRST	DISPL2		;GO BACK FOR REST

> ;END REPEAT 0
;NEW VERSION OF DISPLAY

REPEAT	1,<

DISPLA:	PUSHJ	P,WINFIL	;GENERATE NEW SCREEN IMAGE (INTO WINEW)
DISPLX:	SKIPE	CMFTYO		;SUPPRESSING OUTPUT DUE TO COMMAND FILE?
	POPJ	P,		;YES, RETURN NOW
	SETZ	C,		;INIT LINE COUNTER

;LOOP OVER EACH LINE LOOKING FOR ANY DIFFERENCES BETWEEN NEW AND OLD SCREEN

DISPL0:	CAML	C,SLENTH	;DONE FULL SCREEN YET?
	JRST	DISPLZ		;YES, ALL DONE HERE
	MOVE	A,C		;COPY OF LINE COUNTER
	IMULI	A,WINDEX	;A:=OFFSET INTO WINDOW AREA OF LINE
	ADD	A,[POINT 7,WINDOW]  ;A:=BYTE POINTER TO OLD SCREEN LINE
	MOVE	T,A		;COPY OF BYTE POINTER
	HRRI	T,WINEW-WINDOW(T)  ;T:=BYTE POINTER TO NEW LINE
	SETZ	B,		;NO DIFFERENCES YET THIS LINE

;LOOP OVER EACH CHARACTER WITHIN THE LINE

DISPL2:	ILDB	AA,A		;GET NEXT OLD CHARACTER
	ILDB	TT,T		;AND NEXT NEW CHARACTER
	CAME	AA,TT		;ANY CHANGES?
	JRST	DISPL4		;YES, MUST UPDATE VIDEO SCREEN
	JUMPN	TT,DISPL2	;NO, LOOP BACK FOR REST OF NEW LINE
	JUMPN	AA,DISPL7	;NEW LINE ENDED, BUT OLD HASN'T, MUST ERASE
				; THIS MAY ACTUALLY SUPERFLUOUSLY ERASE,
				; BUT IT WON'T HURT THE SCREEN
	JUMPN	B,DISPL8	;BOTH ENDED TOGETHER, BUT THERE WAS A
				; DIFFERENCE, UPDATE WINDOW FROM WINEW
	AOJA	C,DISPL0	;GO CHECK NEXT LINE
;STILL IN REPEAT 1

;HERE WHEN A CHANGE IN THE SCREEN IS NEEDED

DISPL4:	JUMPN	B,DISPL5	;FIRST DIFFERENCE THIS LINE?
	MOVE	AA,T		;YES, SAVE T A MOMENT
	MOVEI	T,.TOTTC	;TOTAL MONITOR-HELD INPUTTABLE CHARACTERS
;	MOVEI	T,.TOSIP	;***SKIP IF TYPEIN AVAILABLE
	MOVE	TT,TTYUDX	;FOR APPROPRIATE TTY
	MOVE	B,[2,,T]	;TRMOP. ARG POINTER TO
	TRMOP.	B,		;SEE IF USER HAS TYPED AHEAD
	 SETZ	B,		;ASSUME NO TYPEAHEAD
;	TDZA	B,B		;***
;	MOVEI	B,1		;***
	JUMPN	B,DISPLZ	;IF TYPEAHEAD GET OUT NOW
	MOVE	T,AA		;RESTORE T
	MOVE	CH,C		;GET LINE NUMBER
	PUSHJ	P,LINECH	;AND POSITION TO IT
	MOVE	B,C		;LINE NUMBER AGAIN
	IMULI	B,WINDEX	;B:=OFFSET INTO WINDOW REGION
	ADD	B,[POINT 7,WINEW]  ;B:=BYTE POINTER TO NEW LINE

;NOW POSITION TO CHANGED CHARACTER ON LINE

DISPL5:	ILDB	CH,B		;NEXT NEW LINE CHARACTER
	JUMPE	CH,DISPL7	;NULL MEANS SHORTER NEW LINE
	PUSHJ	P,TYOCH		;OUTPUT CHARACTER
	CAME	B,T		;CAUGHT UP TO DIFFERENCE YET?
	JRST	DISPL5		;NO, KEEP GOING
	JRST	DISPL2		;YES, CHECK REST OF LINE

;HERE WHEN NEW LINE IS SHORTER THAN OLD LINE, ERASE REST OF OLD LINE

DISPL7:	MOVE	B,COLUMN	;LAST SCREEN COLUMN POSITION
	CAMG	B,SWIDTH	;AT RIGHT EDGE OF SCREEN?
				; SOME TERMINALS WILL ERASE THE LAST
				; CHARACTER ON EOL IF AT RIGHT MARGIN
	PUSHJ	P,CLREOL	;NO - ERASE SCREEN TO END OF LINE

;UPDATE WINDOW FROM WINEW TO REFLECT CHANGED LINE

DISPL8:	MOVE	B,C		;LINE NUMBER
	IMULI	B,WINDEX	;B:=OFFSET INTO WINDOW REGION
	ADDI	B,WINDOW	;B:=ADDRESS OF OLD LINE
	MOVE	T,B		;COPY
	HRLI	T,WINEW-WINDOW(T)  ;T:=BLT POINTER TO
	BLT	T,WINDEX-1(B)	;COPY NEW LINE TO OLD LINE
	AOJA	C,DISPL0	;NOW GO CHECK NEXT LINE

DISPLZ:	MOVE	CH,DLENTH	;GET BOTTOM OF DISPLAY WINDOW
	PJRST	LINECH		;AND POSITION THERE

> ;END OF REPEAT 1
ZAPSCN:	SETZM	MESFLG		;SCREEN AND MEMORY AGREE
	SETOM	 WINDOW		;TRASH THE WINDOW BUFFER
	MOVE	TT,[WINDOW,,WINDOW+1]  ;BLT POINTER TO
	BLT	TT,WINDOW+WINTOP-1  ;TRASH THE ENTIRE BUFFER AREA
				;SO THAT DISPLA WILL RE-WRITE IT
	SKIPN	SCTYPE		;DISPLAY MODE?
	PJRST	CRR		;NO, JUST TYPE A <CR><LF>
	PJRST	HOMEUP		;YES, POSITION TO TOP OF SCREEN

CLRSCN:	SETZM	MESFLG		;SCREEN AND MEMORY AGREE
	MOVE	TT,[WINDOW,,WINDOW+1]  ;BLT POINTER FOR FIRST HALF
	MOVE	TT1,DLENTH	;DISPLAY WINDOW LENGTH
	IMULI	TT1,WINDEX	;FIRST LOC PAST WINDOW IN BUFFER
	ADDI	TT1,WINDOW	;RELOCATE INTO WINDOW REGION
	SETZM	WINDOW		;CLEAR WINDOW PICTURE
	BLT	TT,-1(TT1)	;AS FAR AS WE KNOW ABOUT IT
	SETOM	(TT1)		;AND ZAP REST OF THE IMAGE
	HRLI	TT1,1(TT1)	;CONCOCT BLT POINTER
	MOVS	TT1,TT1		; . . .
	BLT	TT1,WINDOW+WINTOP-1  ;AND ZAP BUFFER OUTSIDE OF THE WINDOW
	SKIPN	SCTYPE		;CLEAR SCREEN UNLESS NOT IN DISPLAY MODE
	JRST	CRR		;IN WHICH CASE JUST TYPE A <CR><LF>
	PUSHJ	P,HOMEUP	;GET TO TOP OF SCREEN
				;AND CLEAR FROM THERE DOWN
CLREOS:	SKIPA	CH,TEREOS	;ERASE TO EOS CODES
CLREOL:	MOVE	CH,TEREOL	;ERASE TO EOL CODES
	PJRST	VT5CD		;OUTPUT CODES

CUP:	SOSGE	CURLIN		;DISPLAY CURSOR MOVES UP
	SETZM	CURLIN		;OOPS - HIT TOP OF SCREEN
	MOVE	CH,TCUP		;CURSOR UP CODES
	PJRST	VT5CD		;OUTPUT CODES

CBACK:	PUSH	P,CH
	MOVEI	CH,10		;BACKSPACE (CONTROL H)
	PUSHJ	P,TYOA		;TYPE MAGIC CHARACTER AND MAKE SURE IT HAPPENS NOW
	SOSGE	COLUMN		;NOTE BACKWARDS CURSOR MOVEMENT
	SETZM	COLUMN		;OOPS - HIT LEFT MARGIN
	POP	P,CH
	POPJ	P,

HOMEUP:	SETZM	CURLIN		;CURSOR MOVES TO LINE 0
	SETZM	COLUMN		;AND COLUMN 0
	MOVE	CH,THOME	;CURSOR TO HOME CODES
	PJRST	VT5CD		;OUTPUT CODES
;ROUTINE TO PUT CURSOR ON LINE SPECIFIED BY CONTENTS OF CH

LINECH:	SETZM	COLUMN		;ALWAYS LEAVES US IN COLUMN 0
	PUSH	P,CH		;SAVE CH
	SUB	CH,CURLIN	;HOW FAR IS THAT?
	JUMPE	CH,[PUSHJ P,VTCR	;OUTPUT A <CR>
		POP	P,CH
		POPJ	P,]
	JUMPL	CH,LINEUP
	CAILE	CH,4		;CLOSE ENOUGH SO LINE FEEDS PAY?
	JRST	CHDCA		;NO, USE DIRECT CURSOR ADDRESSING
	PUSHJ	P,VTCR		;GET TO LEFT MARGIN
	PUSHJ	P,VTLF		;GO DOWN A LINE
	SOJG	CH,.-1		;LOOP ENOUGH
	POP	P,CURLIN
	POPJ	P,

LINEUP:	AOJL	CH,CHDCA	;IF MORE THAN ONE UP, USE DCA
	PUSHJ	P,VTCR		;IF JUST ONE, GET TO LEFT MARGIN
	POP	P,CH
	PJRST	CUP		;GO UP ONE LINE

CHDCA:	MOVE	CH,0(P)
	MOVEM	CH,CURLIN	;SET POSITION
	PJRST	@TDCAD		;GO TO APPROPRIATE ROUTINE
;VT05-STYLE CURSOR ADDRESSING PROCESSOR

VT05LN:	MOVEI	CH,16		;CONTROL N IS MAGIC CURSOR ADDRESSING CHARACTER
	PUSHJ	P,TYOA		;TYPE IT
	POP	P,CH		;RECOVER LINE NUMBER DESIRED
	ADDI	CH,40		;FIRST ON SCREEN
	PUSHJ	P,TYOA		;OUTPUT IT
	MOVE	CH,[BYTE(7) 040,177,177,177,177] ;LEFT MARGIN WITH FILLERS
	PJRST	VT5CD		;OUTPUT SPECIAL CODES



;VT50-STYLE CURSOR ADDRESSING PROCESSOR

VT50LN:	MOVE	CH,THOME	;HOME UP SEQUENCE
	PUSHJ	P,VT5CD		;GET TO UPPER LEFT
	POP	P,CH		;GET DESIRED LINE #
	JUMPE	CH,CPOPJ	;WE'RE ALREADY AT ZERO
	PUSHJ	P,VTLF		;USE LINE FEEDS TO GET THERE
	SOJG	CH,.-1
	POPJ	P,



;VT52-STYLE CURSOR ADDRESSING PROCESSOR

VT52LN:	MOVE	CH,[BYTE(7) 033,"Y",000,000,000] ;CURSOR ADDRESS STARTER
	PUSHJ	P,VT5CD		;START UP DCA SEQUENCE
	POP	P,CH		;DESIRED LINE #
	ADDI	CH,40
	PUSHJ	P,TYOA		;OUTPUT LINE INDEX
	MOVEI	CH,40		;LEFT MARGIN
	PJRST	TYOA		;OUTPUT CHARACTER INDEX



;ANSI (VT100) SYTLE CURSOR ADDRESSING PROCESSOR

VTANLN:	MOVE	CH,[BYTE(7) 033,"[",000,000,000] ;CURSOR ADDRESS STARTER
	PUSHJ	P,VT5CD		;START UP ESCAPE SEQUENCE
	POP	P,CH		;RESTORE LINE NUMBER
	ADDI	CH,1		;ANSI STARTS WITH LINE 1, DT WITH LINE 0
	PUSHJ	P,VTAPN		;OUTPUT NUMERIC ANSI PARAMETER
	MOVE	CH,[BYTE(7) ";","0","H",000,000] ;END OF DCA
	PJRST	VT5CD		;FINISH OFF CURSOR ADDRESS
;SUPPORT ROUTINES FOR SCREEN ROUTINES ABOVE

VT5CD:	ROT	CH,7		;POSITION NEXT CHARACTER
	PUSHJ	P,TYOA		;OUTPUT IT
	ANDCMI	CH,177		;TOSS IT OUT
	JUMPN	CH,VT5CD	;MORE CHARACTERS?
	POPJ	P,		;NO, ALL DONE



;VTSTR - OUTPUT ASCIZ STRING

VTSTR:	TLOA	C,(POINT 7,)	;MAKE 7-BIT BYTE POINTER
VTSTR0:	PUSHJ	P,TYOA		;OUTPUT THE CHARACTER
	ILDB	CH,C		;NEXT CHARACTER
	JUMPN	CH,VTSTR0	;OUTPUT IT
	POPJ	P,		;END OF STRING, DONE



;VTAPN - OUTPUT NUMERIC ANSI PARAMETER

VTAPN:	PUSH	P,CH-1		;NEED A SCRATCH AC
	PUSHJ	P,VTAPN0	;OUTPUT IT
	POP	P,CH-1		;RESTORE AC
	POPJ	P,		;AND RETURN

VTAPN0:	MOVE	CH-1,CH		;POSITION FOR IDIVI
VTAPN2:	IDIVI	CH-1,^D10	;GET A DECIMAL DIGIT
	JUMPE	CH-1,VTAPN5	;DONE?
	PUSH	P,CH		;NO, MORE PARAMETER LEFT
	PUSHJ	P,VTAPN2	;OUTPUT REST OF NUMBER
	POP	P,CH		;GET BACK LAST DECIMAL DIGIT
VTAPN5:	ADDI	CH,"0"		;ASCIIZE IT
	PJRST	TYOA		;AND OUTPUT IT



;OUTPUT <CR>, PRESERVING AC CH

VTCR:	PUSH	P,CH		;SAVE AC
	MOVEI	CH,.CHCRT	;A CARRIAGE RETURN CHARACTER
	PUSHJ	P,TYOA		;OUTPUT IT
	SETZM	COLUMN		;NOW IN COLUMN 0
	POP	P,CH		;RESTORE CH
	POPJ	P,		;DONE

;OUTPUT <LF>, PRESERVING AC CH

VTLF:	PUSH	P,CH		;SAVE AN AC
	MOVEI	CH,.CHLFD	;A LINE FEED CHARACTER
	PUSHJ	P,TYOA		;OUTPUT IT
	POP	P,CH		;RESTORE CH
	POPJ	P,		;DONE
;TABLE OF SCREEN POINTERS TO BE RELOCATED BY NROOMC

SCRNRP:	IFIW	@SCRNRT(AA)	;POINTER INTO TABLE OF POINTERS

SCRNRT:	IFIW	SCRNA		;SCREEN BASE
	IFIW	SCRNB		;START OF SCREEN
	IFIW	SCRNZ		;END OF SCREEN (+1)
	IFIW	DISCA		;NEXT SCREEN'S SCRNA
	IFIW	DIPTA		;CURSOR BASE/SKIP

	SCRNRL==.-SCRNRT	;LENGTH OF RELOCATION TABLE
;DISPLAY ROUTINE VARIABLE AREA

U SCRNA,1	;ABSOLUTE BASE OF SCREEN (CHARACTER ADDRESS)
U SCRNAA,1	;LINE OFFSET BETWEEN SCRNA AND SCRNB
U SCRNB,1	;FIRST CHARACTER ON SCREEN (CHARACTER ADDRESS)
U SCRNVZ,1	;FORCED END OF SCREEN (CHARACTER ADDRESS)
U SCRNZ,1 	;FIRST CHARACTER PAST SCREEN (CHARACTER ADDRESS)
U DISCA,1	;DISCHR'S UPDATED SCRNA FOR VUNXT
U DISCAA,1	;DITTO FOR SCRNAA
U DIPTA,1	;CURSOR BASE AND
U DIPTAA,1	;SKIP COUNT TO START OF SCREEN LINE
U DIPTC,1	;POSITION WITH SCREEN LINE OF CURSOR
U DIPTI,1	;TEXT ADDRESS OF "." FOR DIPT?? ABOVE
U MESFLG,1 	;SET TO -1 TO MEAN DISPLAY IS MESSED UP
U SWIDTH,1 	;SCREEN PRINTING COLUMN QUANTITY, NOT COUNTING CONTINUATION CHARACTER
U SSIZE,1	;HOLDS SCREEN LENGTH
U SLENTH,1 	;HOLDS NUMBER OF SCREEN LINES TO DISPLAY
U DLENTH,1
U CLENTH,1	;HOW FAR DOWN WE LIKE THE CURSOR
U TABSIZ,1 	;MAXIMUM SPACES PRINTED FOR TAB
U PTRCHR,2	;ASCII STRING TO REPRESENT POINTER

;SCREEN STORAGE

U WINDOW,WINTOP	;STORAGE OF WHAT IS SHOWING ON SCREEN NOW
U WINEW,WINTOP	;NEW SCREENFUL ABOUT TO BE DISPLAYED
U WINFLG,1 	;SET TO -1 BY COMMAND ROUTINES LIKE = AND ^A
		; THAT DON'T WANT SCREEN WRITTEN OVER THEIR OUTPUT
U VFREEZ,1	;.NE. 0 THEN "V" COMMAND HAS FROZEN THE SCREEN
U EOBFLG,1 	;END OF BUFFER FLAG
U TABFIL,1 	;.GT. 0 THEN TAB FILLER COUNTER
U TABUNF,1	;.GT. 0 THEN TAB UNFILLER (RECLAIM BOGUS SPACE)
U SEOL,1 	;END OF DISPLAY LINE FLAG
U SEOL2,1	;.LT. 0 THEN WANT TO DO A <CR><LF> AT NEXT DISCHR
U SEOL3,1	;.GT. 0 THEN ^J FILLER COUNTER
U DISCTF,1 	;CONTROL CHARACTER FLAG
U DISPTF,1 	;POINTER ON SCREEN FLAG
U DISCI,1	;SCRATCH FOR DISCON
U SCTYPE,1	;TERMINAL TYPE:
		; 0 UNKNOWN OR HARDCOPY TERMINALS
		; 1 DEC VT05
		; 2 DEC-STANDARD ESCAPE SEQUENCE, NO CURSOR ADDRESSING (VT50)
		; 3 DEC-STANDARD ESCAPE SEQUENCE, CURSOR ADDRESSING (VT52)
		; 4 ANSI-STANDARD ESCAPE SEQUENCE, CURSOR ADDRESSING (VT100)
	SUBTTL	LOCAL UUO HANDLER

UUOINI:	SKIPE	SECTN		;ARE WE RUNNING EXTENDED SECTIONS?
	JRST	UUOIN3		;YES, DIFFERENT TRAP THEN
	MOVE	T,[PUSHJ P,UUOH];DISPATCH TO UUO HANDLER
	MOVEM	T,.JB41		;SETUP UUO TRAP SERVICE
	JRST	CPOPJ1		;SECTION 0 UUO SERVICE ENABLED.

UUOIN3:	XMOVEI	TT1,XUUOB	;EXTEDNED-ADDRESS UUO TRAP HANDLER BLOCK
	MOVEI	TT,0		;WHICH IS "TRAP 0"
	MOVEI	T,1		;WHICH IS ONLY ONE TRAP PAIR
	MOVE	A,[.UTSET,,T]	;UTPR. ARG POINTER TO
	UTRP.	A,		;ENABLE FOR UUO TRAPS
	 POPJ	P,		;THIS IS AWFUL
	XMOVEI	A,XUUOH		;ADDRESS OF SECTION-N TRAP HANDLER
	MOVEM	A,XUUOB+3	;STASH IN UUO BLOCK
	JRST	CPOPJ1		;SECTION N UUO SERVICE ENABLED



U XUUOB,4			;SECTION-N UUO TRAP BLOCK

U UUOCD,1			;UUO OPCODE
U UUOAC,1			;UUO AC
U UUOEF,1			;UUO EFFECTIVE ADDRESS

U UUORA,1			;UUO [NEW] RETURN ADDRESS
;HERE ON SECTION-0 UUOS

UUOH:	MOVEM	B,ARGSTO	;SAVE POSSIBLE ARG
	HRRZ	B,.JBUUO	;EFFECTIVE ADDRESS OF UUO
	MOVEM	B,UUOEF		;SET EFFECTIVE ADDRESS
	LDB	B,[POINT 4,.JBUUO,12]  ;GET UUO AC FIELD
	MOVEM	B,UUOAC		;SET AC FIELD
	LDB	B,[POINT 9,.JBUUO,8]	;GET UUO TYPE
	MOVEM	B,UUOCD		;SAVE UUO OPCODE
	PUSHJ	P,UUOSR		;DISPATCH TO UUO SERVICE ROUTINE
	SKIPE	B,UUORA		;WANT NEW ADDRESS FOR UUO?
	HRRM	B,0(P)		;YES, SET NEW PC
	MOVE	B,ARGSTO	;RESTORE TRASHED AC
	POPJ	P,		;RETURN FROM UUO




;HERE ON SECTION-N UUOS

XUUOH:	MOVEM	B,ARGSTO	;SAVE POSSIBLE ARG
	MOVE	B,XUUOB+2	;UUO EFFECTIVE ADDRESS
	MOVEM	B,UUOEF		;SET EFFECTIVE ADDRESS
	LDB	B,[POINT 4,XUUOB+0,12+18]  ;UUO AC FIELD
	MOVEM	B,UUOAC		;SET AC FIELD
	LDB	B,[POINT 9,XUUOB+0,8+18]  ;UUO OPCODE
	MOVEM	B,UUOCD		;SET OPCODE
	PUSHJ	P,UUOSR		;DISPATCH TO UUO SERVICE
	SKIPE	B,UUORA		;WANT NEW ADDRESS?
	HRRM	B,XUUOB+1	;YES, SET NEW PC
	MOVE	B,ARGSTO	;RESTORE TRASHED AC
	XJRSTF	XUUOB		;RETURN FROM UUO



;DISPATCH TO SELECTED UUO SERVICE ROUTINE

UUOSR:	SETZM	UUORA		;INITIALIZE NEW RETURN ADDRESS
	CAIN	B,20		;CHKEO?
	PJRST	CEO		;YES
	CAIN	B,1		;MESSAGE UUO?
	PJRST	MSGUUO		;YES
	$FATAL	(UUO,,<Illegal UUO>)
	SUBTTL	MSG. UUO (INFORMATIONAL/WARNING/ERROR MESSAGES)

MSGUUO:	PUSHJ	P,TEBURB	;Checkpoint the TEB file
	SETOM	WINFLG		;Messages screw up the screen
	PUSHJ	P,SCNCTX	;Switch to SCAN's context
	MOVE	T1,COMMAX	;Get # of characters in command buffer
	SUB	T1,COMCNT	;- # of characters to be processed
	MOVEM	T1,ERR1		;Store for command echo
	DMOVE	T1,COMPTR	;Get byte pointer to command buffer
	DMOVEM	T1,ERR2		;Store for command echo
	MOVE	T1,UUOEF	;Get address of argument block
	DMOVE	T2,(T1)		;Copy arguments
	DMOVEM	T2,MSGARG	;Store for easy reference
	MOVEM	T3,UUORA	;Store new return address
	PUSHJ	P,.VERBO##	;Get our verbosity bits
	MOVEM	T1,MSGBIT	;Store them
	SKIPE	COLUMN		;If not at the left margin, then
	PUSHJ	P,.TCRLF##	;Start with a new line
	MOVE	T1,UUOAC	;Pick up AC field
	MOVEM	T1,MSGSEV	;Store severity level
	MOVE	T1,[EXP	"["	;Comment message
		    EXP	"%"	;Warning message
		    EXP	"?"](T1);Fatal message
	PUSHJ	P,.TCHAR##	;Type severity character
	HLRZ	T1,MSGARG	;Get the 3 character prefix
	HRLI	T1,'TEC'	;Include our identifier
	MOVE	T2,MSGBIT	;Get verbosity bits
	TXNE	T2,JWW.PR	;Want a prefix ?
	PUSHJ	P,.TSIXN##	;Yes - type prefix
	PUSHJ	P,.TSPAC##	;Type a space for cleanliness
	HRRZ	T1,MSGARG	;Get address of text
	HRLI	T1,(POINT 7)	;Make a byte pointer
	MOVEM	T1,MSGPTR	;Store it
	MOVE	T1,MSGBIT	;Get our verbosity bits
	TXNE	T1,JWW.FL	;Want a first line ?
	PUSHJ	P,ERRPRN	;Yes - type it
	MOVE	T1,MSGBIT	;Get our verbosity bits
	TXNE	T1,JWW.CN	;Want continuation text ?
	PUSHJ	P,ERRTYP	;Yes - type it
	MOVEI	T1,"]"		;Incase we're typeing a comment
	SKIPN	MSGSEV		;Zero severity level means a comment
	PUSHJ	P,.TCHAR##	;Finish it properly
	PUSHJ	P,.TCRLF##	;Type a new line to finish the message
	PUSHJ	P,TECCTX	;Switch to TECO's context
	MOVE	B,ARGSTO	;Restore real "B" from UUOH
	SOSLE	MSGSEV		;Return on comments or warnings
	TXZN	FF,CCLFLG	;MAKE or TECO command produce error ?
	POPJ	P,		;Return somewhere

	POPJ	P,	;*** TEMP ***
	LDB	CH,[POINT 15,XEXT,35]  ;CHECK FOR ?FNF-00
	JUMPN	CH,CPOPJ	;IT'S NOT
	MOVE	CH,UUOEF	;MAYBE
	CAIE	CH,(SIXBIT /FNF/)  ;..
	POPJ	P,
	CLOSE	OUTCHN,CL.RST	;YES -  DON'T SUPERCEDE OLD FILE.
	JRST	FINISZ		;YES, POP UP TO MONITOR

U MSGARG,2			;MSG. UUO arguments
U MSGSEV,1			;MSG. UUO severity level
U MSGBIT,1			;MSG. UUO verbosity bits
U MSGPTR,1			;MSG. UUO byte pointer
U ARGSTO,1			;STORE FOR ARGUMENT (IF ANY)
ERRPRN:	PUSHJ	P,ERRCHR	;Get a character
	  POPJ	P,		;End of line
	CAXE	CH,.CHCNN	;Check for the special flag character
	JRST	ERRPR1		;Not the one
	PUSHJ	P,ERRCHR	;Get the next character
	  POPJ	P,		;End of line
	MOVEI	T1,-"0"(CH)	;Convert ASCII to octal
	IMULI	T1,12		;Shift T1 by a power of 10
	PUSHJ	P,ERRCHR	;Get second digit
	  POPJ	P,		;End of line
	ADDI	T1,-"0"(CH)	;Add it in
	CAILE	T1,ETABLN	;Does it fit?
	 HALT	ERRPRN		;No???^%$#$#(*%$#&^)&%$#!
	PUSHJ	P,@ETABL(T1)	;Dispatch to typeout routine
	JRST	ERRPRN		;Loop back for rest of message

ERRPR1:	MOVE	T1,CH		;Put character in a better place
	PUSHJ	P,.TCHAR##	;Type it
	JRST	ERRPRN		;Loop back


;Get a character from the error text

ERRCHR:	ILDB	CH,MSGPTR	;Load a byte
	SKIPE	CH		;End of line ?
	AOS	(P)		;Skip
	POPJ	P,		;Return
ERRT.1:	ILDB	T1,P1		;Get a character
	CAMG	T4,ERR1		;Was it in the command buffer ?
	PUSHJ	P,SCNTYS	;Type possible funny character
	CAMN	P1,ERR2		;Reached the bad command yet ?
	CAME	P1+1,ERR2+1	; . . .
	SOJA	T4,ERRT.1	;No - loop
	MOVEI	T1,[ASCIZ | <---|]  ;Arrow marking the end
	PJRST	.TSTRG##	;Type it and return

ERRTYP:	PUSHJ	P,.SAVE2##	;Need a coupla PEAs too
	PUSHJ	P,.TCRLF##	;Type a CRLF
	MOVEI	T1,[ASCIZ |	---> |]	;Arrow marking the begining
	PUSHJ	P,.TSTRG##	;Type it
	MOVNI	P1,12		;Backup
	ADJBP	P1,ERR2		;COMPTR before the error
	MOVEI	T4,12		;Count of characters
	JRST	ERRT.1		;Match angle brackets



;Routine to output a 6 digit octal quantity with leading zeros
; Call:	MOVE	T1,word to output
;	PUSHJ	P,HLFWRD
;	<return>

HLFWRD:	PUSH	P,T1		;Save argument
	HRLOS	T1		;T1:= xxx,,-1
	JFFO	T1,.+1		;Get number of leading one bits
	IDIVI	T2,3		;Get number of digits to pad
	SKIPA	T1,["0"]	;Load a leading zero
	PUSHJ	P,.TCHAR##	;Type it
	SOJG	T2,.-1		;Loop
	POP	P,T1		;Restore original argument
	PJRST	.TOCTW##	;Type number in octal and return

U ERR1,1			;
U ERR2,2			;
;DISPATCH TABLE FOR SPECIAL INFORMATION TYPEOUT
;BASED ON CHARACTER AFTER CONTROL-N

ETABL:	IFIW	ECOMCH		;00  -  LAST COMMAND CHARACTER (COMPTR)
	IFIW	EOUTFL		;01  -  OUTPUT FILE SPECIFICATION (OUNAM)
	IFIW	EFILEN		;02  -  LAST FILE SPECIFICATION (XNAM)
	IFIW	EERNUM		;03  -  LAST FILE UUO ERROR (XEXT)
	IFIW	EDEVNM		;04  -  DEVICE NAME (OPNBLK)
	IFIW	EPROJN		;05  -  FILE PATH (PTHBLK)
	IFIW	EARG1		;06  -  DECIMAL COMMAND ARGUMENT (ARGSTO)
	IFIW	EPROTC		;07  -  FILE PROTECTION (XPRV)
	IFIW	EEBFN		;08  -  EB FILENAME (EBNAM)
	IFIW	EINFIL		;09  -  INPUT FILE SPEC (INFIL)
	IFIW	EEBFIL		;10  -  EB FILE SPEC (EBNAM)
	IFIW	EIOFLG		;11  -  I/O STATUS (ARGSTO)
	IFIW	ESTAB		;12  -  TAG (STAB)
	IFIW	ESKIP		;13  -  UNUSED
	IFIW	EISKIP		;14  -  UNUSED
	IFIW	EFILSP		;15  -  LAST FILE SPEC (XNAM)
	IFIW	EEOVAL		;16  -  "EO" FLAG VALUE (EOVAL)
	IFIW	EESCH		;17  -  SEARCH STRING (SCHARG)
	IFIW	EECTRL		;18  -  CHARACTER (ARGSTO)
	IFIW	EESWIT		;19  -  FILE SWITCH (SWITHL)
	IFIW	EEBPTH		;20  -  EB PATH (EBPTH)
	IFIW	EINFSP		;21  -  INPUT FILE SPEC (INNAM)
	IFIW	EOUFSP		;22  -  OUTPUT FILE SPEC (OUNAM)
	IFIW	EPATH		;23  -  PATH (PTHBLK)

	ETABLN==.-ETABL		;MAX TYPEOUT ROUTINE
;SPECIAL INFORMATION TYPEOUT ROUTINES

EECTRL:	SKIPA	T1,ARGSTO	;GET BAD CHAR FROM TEXT STRING
ECOMCH:	LDB	T1,COMPTR	;GET LAST COMMAND STRING CHAR.
	PJRST	SCNTYS		;AND TYPE IT OUT IN A READABLE MANNER

EOUTFL:	MOVEI	TT1,OUNAM	;AIM AT OUTPUT FILENAME
EOUTF2:	PJRST	EFILE		;TYPE THE FILE

;HERE TO TYPE A FILENAME.EXTENSION

EFILE:	MOVE	T1,(TT1)	;PICK UP FILE NAME
	PUSHJ	P,.TSIXN##
	HLLZ	T1,1(TT1)
	JUMPE	T1,.POPJ##	;SKIP REST IF NO EXTENSION
	MOVEI	T1,"."
	PUSHJ	P,.TCHAR##
	HLLZ	T1,1(TT1)
	PUSHJ	P,.TSIXN##
	POPJ	P,

EFILEN:	MOVEI	TT1,XNAM	;GET FILENAME REF'D BY UUO
	PJRST	EFILE

EERNUM:	LDB	T1,[POINT 15,XEXT,35]  ;GET 2-DIGIT ERROR CODE
EERNU1:	PJRST	.TOCTW##	;TYPE IT

EDEVNM:	MOVE	T1,OPNDEV	;GET DEVICE NAME
EDEVN1:	PJRST	.TSIXN##	;PRINT THE DEVICE NAME

EPROJN:	SKIPE	PTHPPN		;LOOKUP/ENTER ON DEFAULT PATH?
	SKIPN	T1,PTHBLK+.PTSTR;NO, GET ACTUAL PATH STRUCTURE (IF ANY)
	JRST	EPROJP		;NO STRUCTURE TO TYPE
	PUSHJ	P,.TSIXN##	;TYPE DEVICE/STRUCTURE
	PUSHJ	P,.TCOLN##	;AND THE SEPARATING ":"
	SKIPA	T1,[PTHBLK+.PTPPN]  ;NO, GET PATH WE USED
EPROJP:	MOVEI	T1,.MYPTH##+.PTPPN  ;YES, POINT TO DEFAULT PATH
	TLO	T1,1		;FLAG PATH SPEC
	PJRST	.TDIRB##	;AND TYPE DIRECTORY PATH

EESWIT:	MOVE	T1,SWITHL	;GET I/O SWITCH NAME
	PJRST	.TSIXN##

EARG1:	MOVE	T1,ARGSTO	;GET ARG BACK
EARG1A:	PJRST	.TDECW##	;PRINT IT
EPROTC:	LDB	T1,[POINT 9,XPRV,8]  ;GET FILE PROTECTION
	PJRST	.TOCTW##	;TYPE IT

EEBFN:	MOVE	T1,EBNAM	;EB FILENAME
	PJRST	.TSIXN##

EINFIL:	MOVEI	TT1,INNAM	;AIM AT INPUT FILENAME
	PJRST	EFILE		;TYPE THE FILE

EEBFIL:	MOVEI	TT1,EBNAM	;AIM AT EB ORIGINAL FILENAME
	PJRST	EFILE

EIOFLG:	HRRZ	T1,ARGSTO	;GET I/O STATUS
	PJRST	HLFWRD		;TYPE IT

ESTAB:	MOVEI	T2,STAB		;INDEX STAB WHERE TAG RESIDES
ESTAB1:	SKIPN	T1,(T2)
	POPJ	P,
	PUSHJ	P,SCNTYS
	AOJA	T2,ESTAB1

EISKIP:
ESKIP:	HALT	.+1
	POPJ	P,

EEOVAL:	MOVEI	T1,EOVAL	;GET MAXIMUM EOFLAG FOR THIS VERSION
	PJRST	.TDECW##

EESCH:	MOVE	T3,[POINT 7,SCHARG]  ;GET PTR TO SEARCH STRING
	MOVM	T4,SCHCTR	;[MHK] & STRING CTR
EESCH2:	ILDB	T1,T3		;GET STRING CHAR
	PUSHJ	P,SCNTYS	;TYPE IT
	SOJG	T4,EESCH2	;LOOP FOR REST OF STRING
	POPJ	P,		;RETURN TO ERRPRN
EFILSP:	MOVEI	TT1,XNAM	;POINT TO FILE NAME
	MOVEI	C,PTHBLK	;AND DEVICE, CHR'S, PATH
	JRST	ETSPEC		;JOIN COMMON ROUTINE

EPATH:	SKIPA	C,[PTHBLK]	;POINT TO PTHBLK
EEBPTH:	MOVEI	C,EBPTH		;POINT TO EB PATH
	JRST	EDSPTH		;GO DISPLAY IT

EINFSP:	MOVEI	TT1,INNAM	;SETUP INPUT FILE NAME
	MOVEI	C,INPTH		;AND INPUT PATH
	JRST	ETSPEC		;MERGE WITH COMMON CODE

EOUFSP:	MOVEI	TT1,OUNAM	;OUTPUT FILE NAME
	MOVEI	C,OUPTH		;OUTPUT PATH
	JRST	ETSPEC		;COMMON CODE

;HERE TO TYPE PATH C POINTS TO IF FROM A DISK.

EDSPTH:	MOVE	E,-1(C)		;GET DEVCHR WORD
	TXNN	E,DV.DSK	;A DISK?
	POPJ	P,		;NO, DONE
	SKIPE	2(C)		;THIS PATH BLOCK SET UP?
	JRST	EDSPT1		;YES, PROCEED
	MOVE	E,-3(C)		;NO, PICKUP DEVICE
	MOVEM	E,0(C)		;STORE IN PATH BLOCK
	MOVSI	E,10		;ASSUME 10 WORDS LONG
	HRRI	E,0(C)		;NOW SET UP FOR PATH UUO
	PATH.	E,		;FIND OUT DEVICE'S PATH
	 POPJ	P,		;NOT A DISK, FORGET IT
EDSPT1:	MOVEI	T1,(C)		;POINT TO THE PATH BLOCK
	PJRST	.TDIRB##	;TYPE IT

ETSPEC:	MOVE	T1,-3(C)	;Get device name
	PUSHJ	P,.TSIXN##	;Type it
	PUSHJ	P,.TCOLN##	;Type a colon
	MOVE	T1,(TT1)	;Get file name
	PUSHJ	P,.TSIXN##	;Type it
	MOVEI	T1,"."		;Get a dot
	PUSHJ	P,.TCHAR##	;Type it
	HLLZ	T1,1(TT1)	;Get extension
	PUSHJ	P,.TSIXN##	;Type it
	MOVEI	T1,2(C)		;Point to path block
	PJRST	.TDIRB##	;Type it
;CHKEO EO#,ADDR
;IF EOFLAG GT EO#, RETURN AT CALL+1 (FEATURE IS LEFT ON)
;OTHERWISE GO TO ADDR (FEATURE IS TURNED OFF)

CEO:	PUSH	P,A		;SAVE AC
	MOVE	B,UUOAC		;GET EO TEST VALUE
	MOVE	A,EOFLAG	;GET LAST SETTING OF EOFLAG
	CAIG	A,(B)		;EOFLAG GT TEST VALUE?
	JRST	CEO1		;NO
CEO2:	POP	P,A		;RESTORE AC A
	MOVE	B,ARGSTO	;RESTORE AC B
	POPJ	P,		;RETURN

CEO1:	MOVE	A,UUOEF		;GET DISPATCH ADDR
	MOVEM	A,UUORA		;SET AS NEW RETURN ADDRESS
	JRST	CEO2
	SUBTTL	MISCELLANEOUS SUBROUTINES

;ROUTINE TO RETURN STRING OPERATION STRING ARGUMENTS.
;ARGUMENTS ARE CHARACTER ADDRESSES IN THE DATA BUFFER.
;TRANSFORMS M,N OR N, WHERE THE LATTER SPECIFIES A NUMBER OF LINES,
;TO ARGUMENTS.
;CALL	PUSHJ P,GETARG
;	RETURN WITH FIRST ARGUMENT ADDRESS IN C, SECOND IN B.
;IF THE EO VALUE HAS BEEN SET TO 1, THE ONLY EOL CHAR IS LINE FEED.
;IF EO GT 1, THE EOL CHARS ARE LF, VT, AND FF (& END OF BUFFER IF
;LAST CHAR IN BUFR IS NOT AN EOL)

GETARG:	TXNE	FF,ARG2		;IS THERE A SECOND ARGUMENT?
	JRST	GETAG6		;YES

;N	SIGN INDICATES DIRECTION RELATIVE TO PT.
GETNAG:	PUSHJ	P,CHK2		;NO, GET 1ST ARG (+ OR - 1 IF NONE THERE)
	MOVE	I,PT		;IN:=PT
GETAG4:	JUMPLE	B,GETAG2	;WAS LAST ARGUMENT FUNCTION -?
	CAMN	I,Z		;NO. ARGUMENT IS LOCATION OF NTH EOL FORWARD FROM PT.
				;IS PT AT END OF BUFFER?
	JRST	GETAG1		;YES.
	PUSHJ	P,GETINC	;NO. CH:=NEXT DATA BUFFER CHARACTER, IN:=IN+1
	PUSHJ	P,CKEOL		;IS IT AN EOL?
	JRST	GETAG4		;NO. TRY AGAIN.
	SOJG	B,GETAG4	;YES. NTH EOL?

GETAG1:	MOVE	B,I		;YES. RETURN FIRST ARGUMENT IN C
	MOVE	C,PT		;SECOND IN B.
	POPJ	P,

;M,N
GETAG6:	ADD	B,BEG		;C:=M+BEG
	ADD	C,BEG		;B:=N+BEG
	POPJ	P,

GETAG2:	SOS	I		;SET I FOR CHAR BEFORE PT
	CAMGE	I,BEG		;PASSED BEGINNING OF BUFFER?
	JRST	GETAG3		;YES. IN:=BEG
	PUSHJ	P,GETINC	;NO. CH:=NEXT DATA BUFFER CHARACTER. IN:=IN+1
	PUSHJ	P,CKEOL		;IS IT AN EOL?
	SOJA	I,GETAG2	;NO. BACK UP ONE POSITION AND TRY AGAIN.
	AOJLE	B,.-1		;YES. NTH EOL?

GETAG3:	CAMGE	I,BEG		;YES. PASSED BEGINNING OF BUFFER?
	MOVE	I,BEG		;YES. RESET TO BEGINNING.
	MOVE	C,I		;NO. RETURN FIRST ARGUMENT IN C.
	MOVE	B,PT		;SECOND IN B
	POPJ	P,
;GET - GET CHARACTER FROM TEXT STRING
;GETINC - GET ADDRESSED CHARACTER, INCREMENT ADDRESS
;Call is:
;
;	MOVX	I,<ADR>
;	PUSHJ	P,GET/GETINC
;	normal return
;
;<ADR> is absolute text address of desired character.
;
;On normal return, the addressed character is in CH.
;
;Uses TT, TT1

GET:	MOVE	TT,I		;TEXT ADDRESS OF DESIRED CHARACTER
	IDIVI	TT,5		;WORD ADDRESS . . .
	LDB	CH,BTAB(TT1)	;GET ADDRESSED CHARACTER
	POPJ	P,		;RETURN WITH CHARACTER IN CH

GETINC:	MOVE	TT,I		;TEXT ADDRESS OF DESIRED CHARACTER
	IDIVI	TT,5		;WORD ADDRESS . . .
	LDB	CH,BTAB(TT1)	;GET ADDRESSED CHARACTER
	ADDI	I,1		;ADVANCE "INPUT" (OR "GET") POINTER
	POPJ	P,		;RETURN WITH CHARACTER IN CH



;PUT - PUT/STORE CHARACTER AS ADDRESSED
;PUTINC - PUT CHARACTER AS ADDRESSED, INCREMENT ADDRESS
;Call is:
;
;	MOVX	I,<ADR>
;	PUSHJ	P,PUT/PUTINC
;	normal return
;
;<ADR> is absolute text address to receive <CHR>.
;
;On normal return, the character in CH has been stored as directed
;by <ADR>.
;
;Uses TT, TT1

PUT:	MOVE	TT,OU		;TEXT ADDRESS FOR PENDING CHARACTER
	IDIVI	TT,5		;WORD ADDRESS . . .
	DPB	CH,BTAB(TT1)	;PUT CHARACTER IN MEMORY
	POPJ	P,		;RETURN WITH CHARACTER STORED

PUTINC:	MOVE	TT,OU		;TEXT ADDRESS FOR PENDING CHARACTER
	IDIVI	TT,5		;WORD ADDRESS . . .
	DPB	CH,BTAB(TT1)	;PUT CHARACTER IN MEMORY
	ADDI	OU,1		;ADVANCE "OUTPUT" (OR "PUT") POINTER
	POPJ	P,		;RETURN WITH CHARACTER STORED
;FILL OUT WORD POINTED AT BY I WITH NULLS

TRAIL0:	SUBI	I,1		;POINT AT LAST REAL CHARACTER
	MOVE	TT,I		;TEXT ADDRESS OF DESIRED CHARACTER
	IDIVI	TT,5		;WORD ADDRESS . . .
	SETZ	CH,		;LOTS OF ZERO BITS
	DPB	CH,BT0TAB(TT1)	;CLEAR OUT TRAILING BITS IN WORD
	POPJ	P,		;AND RETURN



;CHARACTER TRANSLATION BYTE POINTER TABLE
;TRANSLATES 1 CHARACTER POSITION TO THE RIGHT OF A CHARACTER ADDRESS POINTER

	POINT	07,0(TT),-1	;PRECEDING BYTE
BTAB:	POINT	07,0(TT),06	;FIRST BYTE WITHIN WORD
	POINT	07,0(TT),13	;SECOND BYTE WITHIN WORD
	POINT	07,0(TT),20	;THIRD BYTE WITHIN WORD
	POINT	07,0(TT),27	;FOURTH BYTE WITHIN WORD
	POINT	07,0(TT),34	;FIFTH BYTE WITHIN WORD

;DITTO FOR TRAILING BITS

BT0TAB:	POINT	29,0(TT),35	;FOUR TRAILING BYTES WITHIN WORD
	POINT	22,0(TT),35	;THREE TRAILING BYTES WITHIN WORD
	POINT	15,0(TT),35	;TWO TRAILING BYTES WITHIN WORD
	POINT	08,0(TT),35	;ONE TRAILING BYTE WITHIN WORD
	POINT	01,0(TT),35	;ONE DANGLING BIT WITHIN WORD



;CHECK IF CH = EOL CHARACTER
;CALL:	PUSHJ	P,CKEOL
;	RETURN IF CH NOT = EOL
;	RETURN IF CH IS EOL CHAR

CKEOL:	CAIN	CH,.CHLFD	;LINE FEED?
	JRST	CPOPJ1		;YES, IT IS AN EOL!
	CHKEO	EO21,CPOPJ	;IF EO=1, LF IS ONLY POSSIBLE EOL
	CAIE	CH,.CHVTB	;VERTICAL TAB?
	CAIN	CH,.CHFFD	;FORM FEED?
	AOS	(P)		;YES, SKIP RETURN
	POPJ	P,		;NO
	SUBTTL	MEMORY MANAGEMENT - TEXT EXPANSION/CONTRACTION

;*** THIS CODE NEEDS TO BE INTERLOCKED WRT ^C TRAPPING . . .

;NROOMQ - ALLOCATE ROOM FOR A Q-REGISTER

NROOMQ:	SETOM	NRQFLG		;FLAG REQUEST IS FOR A Q-REGISTER
	JRST	NROOM0		;JOIN COMMON CODE

;NROOMC - ALLOCATE ROOM FOR REGULAR TEXT CHARACTERS

NROOMC:	MOVEM	C,VVAL		;SAVE LENGTH OF STRING
NROOM:	SETZM	NRQFLG		;NOTE REGULAR TEXT EXPANSION/CONTRACTION

;FIRST SAVE ALL THE REGISTERS. THIS IS LARGELY HISTORICAL, AS THE "BYTE-BLT"
;ROUTINE NO LONGER RUNS IN THE ACS.

NROOM0:	MOVEM	16,AC0+16	;SAVE A REGISTER
	MOVEI	16,AC0		;BLT POINTER TO
	BLT	16,AC0+15	;SAVE ACS 0-15
	CAIN	C,0		;REQUEST A NO-OP?
	HALT	.+1		;HMMM
	CAIGE	C,0		;EXPANSION OR DELETION?
	SKIPN	NRQFLG		;DELETION - FOR REQULAR TEXT?
	CAIA			;OK
	HALT	.+1		;DELETION OF A Q-REGISTER?
	SETZM	CRREL
	SETZM	RREL
	JUMPL	C,NRMDL0	;IF DELETE, GO SHRINK THE TEXT BUFFER
	MOVE	T,PT
	CAMN	T,Z		;PT=Z? I.E., DATA BUFFER EXPANSION?
	SKIPE	NRQFLG		;YES, UNLESS Q-REG REQUEST
	JRST	NRMIN0		;Q-REG OR TEXT INSERT (THE HARD WAY)

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;TEXT INSERTION (EXPANSION) THE EASY WAY, WHERE PT=Z.

NROOM1:	ADD	T,C		;TOTAL SPACE REQUIREMENT
	CAMGE	T,MEMSIZ	;IS THERE ENOUGH?
	JRST	NROOMZ		;YES, JUST ADVANCE Z AND RETURN

;THE EASY INSERTION/EXPANSION CASE, BUT NOT ENOUGH ROOM IMMEDIATELY AVAILABLE.

NROOM3:	PUSHJ	P,GC		;GARBAGE COLLECT Q-REG/TEXT AREA
	 JFCL			;ERROR?
	MOVE	T,Z		;GET TOTAL SO FAR
	ADD	T,C		;ADD IN THE REQUEST
	CAMGE	T,MEMSIZ	;STILL IN NEED OF CORE?
	JRST	NROOMZ		;NO, ALL SET, JUST ADVANCE "Z"
	PUSHJ	P,GRABAK	;YES, GET THE REQUIRED CORE FROM THE MONITOR
	 JRST	GCRERR		;CAN'T EXPAND, INSUFFICIENT MEMORY

;COMMON EXIT FOR NROOM1, NRMIN?, NRMDL? (I.E., ALL THE HAIRY CASES)

NROOMZ:	ADDM	C,Z		;UPDATE END-OF-BUFFER ("Z") POINTER
NROOMA:	SETZM	NRMGCZ		;CLEAR YANK6'S "Z" ADDRESS
	MOVSI	16,AC0		;BLT POINTER TO
	BLT	16,16		;RESTORE ACS 0-16
	POPJ	P,		;AND RETURN


;INSUFFICIENT MEMORY FOR EXPANSION

GCRERR:	PUSHJ	P,NROOMA	;RESTORE THE BY-NOW-THOROUGHLY-TRASHED ACS
CORERR:	$FATAL	(COR,,<Storage capacity exceeded>)


U NRQFLG,1			;.NE. 0 IF NROOM REQUEST IS FOR Q-REGISTER
U NRMGCZ,1			;.NE. 0 THEN "Z" ADDRESS FOR GC
U NRMPTR,1			;TO-BE-PRESERVED-BITS BYTE POINTER FOR BYTE-BLT
U NRMPTX,1			; (DOUBLE-WORD POINTER ADDRESS)
;TEXT INSERTION (EXPANSION) THE HARD WAY

NRMIN0:	MOVE	T,Z		;CURRENT END TEXT ADDRESS
	ADD	T,C		;DESIRED NEW END TEXT ADDRESS
	CAMGE	T,MEMSIZ	;WILL REQUEST OVERFLOW MEMORY?
	JRST	NRMIN2		;NO, ALL SET, JUST MOVE STRING TO MAKE ROOM

;INSUFFICIENT ROOM REMAINING FOR EXPANSION, MUST MAKE MORE ROOM

	PUSHJ	P,GC		;FIRST TRY FOR GARBAGE COLLECTION
	 JFCL			;ERROR?
	MOVE	T,Z		;CURRENT END TEXT ADDRESS
	ADD	T,C		;DESIRED NEW END TEXT ADDRESS
	CAMGE	T,MEMSIZ	;WILL REQUEST FIT NOW?
	JRST	NRMIN2		;YES, ALL SET, JUST MOVE STRING TO MAKE ROOM
	PUSHJ	P,GRABAK	;NO, TRY TO EXPAND MEMORY
	 JRST	GCRERR		;INSUFFICIENT MEMORY, ERROR

;RELOCATE SCREEN POINTERS AFFECTED BY THE INSERTION. THIS CODE DOESN'T
;HANDLE THE REALLY BAD CASES (INSERT BETWEEN SCRNA AND SCRNB FOR EX-
;AMPLE), BUT WORKS FOR "REASONABLE" TEXT FILES. THIS NEEDS TO BE DONE
;IN ORDER TO ALLOW THE "V" COMMAND TO WORK AS PART OF A "LONG AND COM-
;PLICATED" COMMAND WHICH FIRST CAUSES THE EDIT BUFFER TO MOVE AND THEN
;DOES THE "V" COMMAND. THE ALTERNATIVE WOULD BE TO RELOCATE THE SCREEN
;POINTERS AT BOTH GOSC AND VCMD.

NRMIN2:	PUSH	P,C		;SAVE COPY OF INSERTION/EXPANSION COUNT
	MOVE	A,PT		;STARTING POINT OF EXPANSION
	MOVSI	AA,-SCRNRL	;INDEX INTO TABLE OF POINTERS
	SKIPN	NRQFLG		;REGULAR OR Q-REGISTER REQUEST?
	SKIPA	TT,[CAMGE A,@SCRNRP]  ;REGULAR - ONLY RELOCATE SOME OF 'EM
	MOVSI	TT,(JFCL)	;Q-REGISTER - RELOCATE ALL SCREEN PARAMETERS
NRMIN3:	XCT	TT		;GROWTH IN FRONT OF THIS POINTER?
	ADDM	C,@SCRNRP	;YES, RELOCATE THE POINTER
	AOBJN	AA,NRMIN3	;RELOCATE REST OF POINTERS

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;MOVE FROM PT THROUGH Z UP C POSITIONS

NRMIN4:	MOVE	A,PT		;TEXT ADDRESS OF START OF INSERTION/EXPANSION
	IDIVI	A,5		;WORD ADDRESS OF . . .
	MOVNI	AA,-5(AA)	;COUNT OF BYTES PAST "." MODULO WORD
	IMULI	AA,7		;COUNT OF [DATA] BITS . . .
	MOVE	T,[POINT 0,@AA,34]  ;PROTOTYPE LAST PARTIAL WORD POINTER
	DPB	AA,[POINT 6,T,11]  ;SIZE FIELD OF LAST PARTIAL WORD POINTER
	MOVEM	T,NRMPTR	;HOLD ONTO LAST PARTIAL WORD POINTER
	MOVE	AA,C		;TEXT SIZE OF EXPANSION
	IDIVI	AA,5		;WORD SIZE OF . . .
	ADD	AA,A		;AA := INITIAL "DESTINATION" POINTER (WORD ADR)
	ADDI	AA,1		; . . .
	IMULI	B,7		;[DATA] BIT SIZE OF EXPANSION MODULO WORDS
	MOVN	C,B		;C := BYTE-BLT COMBINING LSHC VALUE
	MOVEI	D,-43(B)	;D := BYTE-BLT REMAINDER LSH VALUE
	MOVE	T,Z		;TEXT END ADDRESS
	IDIVI	T,5		;WORD END ADDRESS
	AOS	B,T
	SUB	B,A		;B := POSITIVE NUMBER OF BYTE-BLT'ED WORDS
	MOVSI	T,((B))		;IFIW INDEXING OFF OF AC "B"
	SKIPE	SECTN		;PC IN EXTENDED SECTION?
	LSH	T,IFX2EF	;YES, SELECT EFIW INDEXING THEN
	IOR	A,T		;INDEX "SOURCE" POINTER
	IOR	AA,T		;INDEX "DESTINATION" POINTER
	SOJL	B,NRMIN9	;SKIP LOOP IF NULL, ELSE ENTER BYTE-BLT LOOP

;LOOP "BLT"ING THE BYTES A WORD-AT-A-TIME
;
;	A/	"SOURCE" POINTER (WORD ADDRESS, INDEXED OFF OF "B")
;	AA/	"DESTINATION" POINTER (WORD ADDRESS, INDEXED OFF OF "B")

NRMIN7:	MOVE	T,@A		;FETCH NEXT SOURCE WORD
	LSH	T,-1		;RIGHT JUSTIFY FOR LSHC CONCATENATION
	LSHC	T,(C)		;COMBINE WITH PREVIOUS LEFTOVERS
	MOVEM	TT,@AA		;STORE THIS DESTINATION WORD
	LSHC	T,(D)		;REMAINDER OF THIS SOURCE WORD (LEFT JUSTIFIED)
	SOJGE	B,NRMIN7	;LOOP FOR ENTIRE SOURCE STRING

NRMIN9:	CAME	B,[-1]		;*** DEBUGGING (NRMPTR DEPENDS ON @AA)
	HALT	.+1		;*** (REPLACE WITH SETO . . .)
	ROTC	T,43(C)		;POSITION LAST PARTIAL WORD.
	DPB	T,NRMPTR	;AND STORE IT IN MEMORY
	POP	P,C		;RESTORE INSERT/EXPANSION COUNT
	JRST	NROOMZ		;RETURN, UPDATING "Z" AND RESTORING THE ACS
;TEXT DELETION

NRMDL0:	PUSH	P,C		;SAFE COPY OF DELETION COUNT
	MOVE	A,PT		;STARTING POINT OF DELETION
	MOVE	B,A		;COPY
	SUB	B,C		;B:=ENDING POINT OF DELETION
	MOVSI	AA,-SCRNRL	;INDEX INTO TABLE OF POINTERS
NRMDL3:	CAMGE	A,@SCRNRP	;POINTER IN AREA BEING DELETED?
	CAMG	B,@SCRNRP	; . . .
	CAIA			;NO, RELATIVELY SAFE THEN
	MOVEM	B,@SCRNRP	;YES, THEN WILL SOON CEASE TO EXIST
	CAMGE	A,@SCRNRP	;WILL THIS POINTER BE AFFECTED BY DELETION?
	ADDM	C,@SCRNRP	;YES, RELOCATE IT
	AOBJN	AA,NRMDL3	;RELOCATE REST OF POINTERS
	MOVNI	B,3		;COMMAND EXECUTION COUNT
	MOVEM	B,TOOBIG	;TO TRY TO RECLAIM MEMORY PAGES

;MOVE FROM PT+ABS(C) THROUGH Z DOWN ABS(C) POSITIONS

NRMDL4:	MOVE	T,PT		;TEXT ADDRESS OF START OF DELETEION
	IDIVI	T,5		;WORD ADDRESS OF . . .
	MOVEM	T,NRMPTX	;INITIAL DESTINATION ADDRESS
	SKIPE	SECTN		;RUNNING EXTENDED?
	MOVSI	T,(1B12)	;YES, DOUBLE-WORD BYTE POINTER
	IMULI	TT,7		;[DATA] BITS PRECEDING "." MODULO WORD
	DPB	TT,[POINT 6,T,11]  ;SIZE FIELD OF TO-BE-PRESERVED-BITS POINTER
	MOVNI	TT,-44(TT)	;[DATA] BITS PAST "." MODULO WORD
	DPB	TT,[POINT 6,T,5]  ;POS FIELD OF TO-BE-PRESERVED-BITS POINTER
	MOVEM	T,NRMPTR	;SET TO-BE-PRESERVED-BITS BYTE POINTER
	MOVE	A,Z		;TEXT ADDRESS OF END OF TEXT
	IDIVI	A,5		;WORD ADDRESS OF . . .
	ADDI	A,1		;INITIAL "SOURCE" POINTER (WORD ADR)
	MOVE	AA,C		;TEXT SIZE OF DELETION
	IDIVI	AA,5		;WORD SIZE OF . . .
	ADD	AA,A		;INITIAL "DESTINATION" POINTER (WORD ADR)
	SUBI	AA,1		; . . .
	IMULI	B,7		;[DATA] BIT SIZE OF DELETION MODULO WORDS
	MOVN	C,B		;C := BYTE-BLT COMBINING LSHC VALUE
	MOVNI	D,-43(C)	;D := BYTE-BLT REMAINDER LSH VALUE
	MOVE	B,NRMPTX	;FIRST DESTINATION WORD ADDRESS
	SUB	B,AA		;B := NEGATIVE NUMBER OF BYTE-BLT'ED WORDS
	SUBI	B,1		; . . .
	MOVSI	T,((B))		;IFIW INDEXING OFF OF AC "B"
	SKIPE	SECTN		;PC IN EXTENDED SECTION?
	LSH	T,IFX2EF	;YES, SELECT EFIW INDEXING
	IOR	A,T		;INDEX "SOURCE" POINTER
	IOR	AA,T		;INDEX "DESTINATION" POINTER
	LDB	T,NRMPTR	;PRESERVED PORTION OF FIRST "DESTINATION" WORD
	PUSH	P,T		;SAVE TO-BE-PRESERVED SOURCE BITS
	MOVE	T,@A		;PRELOAD FIRST "SOURCE" WORD
	ROT	T,-1		; (RIGHT JUSTIFIED)
	AOJG	B,NRMDL9	;SKIP LOOP IF NULL, ELSE ENTER BYTE-BLT LOOP

;LOOP "BLT"ING THE BYTES A WORD-AT-A-TIME
;
;	A/	"SOURCE" POINTER (WORD ADDRESS, INDEXED OFF OF "B")
;	AA/	"DESTINATION" POINTER (WORD ADDRESS, INDEXED OFF OF "B")

NRMDL7:	MOVE	TT,@A		;FETCH NEXT SOURCE WORD
	LSHC	T,(C)		;COMBINE WITH PREVIOUS LEFTOVERS
	LSH	T,1		;LEFT-JUSTIFY (CLEARING BIT 35)
	MOVEM	T,@AA		;STORE THIS DESTINATION WORD
	LSHC	T,(D)		;REMAINDER OF THIS SOURCE WORD (RIGHT JUSTIFIED)
	AOJLE	B,NRMDL7	;LOOP FOR ENTIRE SOURCE STRING

NRMDL9:	POP	P,T		;RETRIEVE TO-BE-PRESERVED INITIAL BITS
	DPB	T,NRMPTR	;AND RESTORE THEM INTO INITIAL DESTINATION WORD
	POP	P,C		;RETRIEVE DELETION COUNT
	JRST	NROOMZ		;RETURN, UPDATING "Z" AND RESTORING THE ACS
	SUBTTL	MEMORY MANAGEMENT - GARBAGE COLLECTION

GC:	SETOM	GCPTR		;GCPTR:=-1
	SETZM	TAGSYM		;CLEAR "O" COMMAND TAG SYMBOL TABLE
	MOVE	T,[XWD TAGSYM,TAGSYM+1]  ;IT WILL BE REBUILT AS NEEDED
	BLT	T,SYMEND-1	;BY SUBSEQUENT "O" COMMANDS
	MOVEI	T,COMPTR	;COMMAND BUFFER
	PUSHJ	P,GCMBP		;GARBAGE-COLLECT IT AS A BYTE POINTER
	MOVEI	T,-1(P)		;PROGRAM STACK
	PUSHJ	P,GCMBP		;GARBAGE COLLECT ALL BYTE POINTERS ON IT.
	CAILE	T,PDLST
	SOJA	T,.-2
	HRRZ	T,AC0+PF	;GARBAGE COLLECT Q-REG PUSHDOWN LIST.
	CAIL	T,PFL
	PUSHJ	P,GCMQR
	CAILE	T,PFL
	SOJA	T,.-2
	MOVE	T,[XWD -QTBLEN,QTAB]	;GARBAGE COLLECT Q-REGISTERS.
	PUSHJ	P,GCMQR
	AOBJN	T,.-1
	MOVE	I,BEG		;MAKE SURE STUFF BEFORE BEG IS COLLECTED
	MOVEI	T,0		;MARK THIS AS LAST COLLECTION
	PUSHJ	P,GCMQR3	;STORE IT ON THE GC LIST

;COMPACT QREG STRING STORAGE AREA

	MOVE	I,QRBUF		;I: NEXT FREE ADDR. TO USE

;FIND STRING WITH LOWEST ADDRESS IN AREA

GCS10:	MOVSI	TT,200000	;TT GT MAX. NO. CHARACTERS IN WORLD
	MOVE	OU,GCPTR	;GO BACKWARDS THROUGH GCTAB
GCS11:	MOVE	A,GCTABC(OU)	;GET CHARACTER ADDRESS OF STRING FOUND ABOVE
	CAMGE	A,I		;PTR ABOVE AREA ALREADY DONE?
	JRST	GCS12		;NO, NOT INTERESTED
	CAMGE	A,TT		;THIS LOWEST PTR IN GC AREA?
	MOVE	TT,A		;YES, REMEMBER IT
GCS12:	SOJGE	OU,GCS11
	CAMN	TT,[1B1]	;ANYTHING IN GCTAB?
	JRST	GCS40		;NO, DON'T SAVE INFINITY

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;HAVE FOUND A STRING, MOVE IT AND EVERYTHING AFTER IT DOWN TO
;LOWEST FREE ADDRESS.

GCS20:	SKIPG	A,NRMGCZ	;CALLED FROM YANK6?
	MOVE	A,Z		;NO, USE "NORMAL Z" ADDRESS
	IDIVI	A,5		;WORD ADDRESS . . .
	MOVE	AA,TT		;HIGHEST CHARACTER.
	IDIVI	AA,5		;LENGTH OF STRING
	MOVE	B,I		;TEXT ADDRESS TO BLT TO
	IDIVI	B,5		;WORDS TO OFFSET
	CAIE	E,0		;FRACTIONATED WORD?
	AOS	B		;YES, ROUND UP
	MOVE	T,AA		;SOURCE ADDRESS
	SUB	T,B		;COMPUTE DISTANCE OF MOVE
	JUMPLE	T,GCS40		;ANYTHING TO GET?
	SUB	A,T		;FINAL DESTINATION (SOURCE MINUS DISTANCE)
	SKIPE	SECTN		;NORMAL OR EXTENDED BLT NEEDED?
	JRST	GCS24		;EXTENDED

;SECTION-0 BLT NEEDED

GCS23:	HRL	B,AA		;GENERATE SOURCE,,DEST ADDRESS POINTER TO
	BLT	B,(A)		;MOVE STRING(S) DOWN
	JRST	GCS25		;GO RELOCATE THINGS

;EXTENDED SECTION BLT NEEDED

GCS24:	SUB	A,B		;NUMBER OF WORDS TO BE BLT'ED
	ADDI	A,1		;DON'T FORGET THE LAST WORD
	EXTEND	A,[XBLT]	;MOVE STRING(S) DOWN

GCS25:	MOVNS	OU,T		;GET NEG DISTANCE
	IMULI	OU,5		;IN TERMS OF CHARACTERS

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;NOW RELOCATE MOST OF THE WORLD'S POINTERS
;	T/	WORD COUNT
;	OU/	BYTE COUNT

GCS30:	ADDM	OU,BEG		;BEG:=C(BEG)-5*NREG
	ADDM	OU,PT		;PT:=C(PT)-5*NREG
	ADDM	OU,Z		;Z:=C(Z)-5*NREG
	ADDM	OU,RREL		;RREL:=C(RREL)-5*NREG
	MOVSI	AA,-SCRNRL	;INDEX INTO TABLE OF SCREEN POINTERS
GCS32:	ADDM	OU,@SCRNRP	;RELOCATE SCREEN
	AOBJN	AA,.-1		;RELOCATE REST OF POINTERS
	MOVE	CH,GCPTR	;UPDATE INSERTER
GCS33:	MOVE	A,GCTABC(CH)	;CHARACTER ADDRESS OF STRING
	CAMGE	A,TT
	JRST	GCS39
	ADDM	OU,GCTABC(CH)	;RELOCATE PTR
	HRRZ	A,GCTABA(CH)	;GET ADDRESS OF CHARACTER ADDRESS
	JUMPE	A,GCS39		;NO PTR TO BEG
	CAIN	A,COMPTR	;IN COMMAND BUFFER?
	ADDM	T,CRREL		;YES. UPDATE COMMAND POINTER RELOCATION
	SKIPGE	(A)		;Q-REG?
	JRST	GCS37		;YES, RELOCATE TEXT ADDRESS
	SKIPE	SECTN		;NO, BYTE POINTER.  PC IN EXTENDED SECTION?
	ADDI	A,1		;YES, FULL WORD ADDRESS FOLLOWS POINTER
	ADDM	T,(A)		;RELOCATE WORD ADDRESS
	JRST	GCS39		;CHECK OUT REST OF GCTAB?

GCS37:	ADDM	OU,(A)		;YES. RELOCATE BASE POINTER.
GCS39:	SOJGE	CH,GCS33	;DONE?
	ADD	TT,OU		;YES. IN:=C(TT)-5*NREG
GCS40:	CAML	TT,BEG		;LAST COLLECTION?
	POPJ	P,		;YES, RETURN
	MOVE	I,TT
	PUSH	P,C
	PUSHJ	P,GTQCNT
	ADD	I,C
	POP	P,C
	JRST	GCS10
;IF T POINTS TO AN ASCII BYTE POINTER, IN:=CHARACTER ADDRESS OF TOP
;OF STRING - NO. OF CHARACTERS.

GCMBP:	HLRZ	TT,(T)		;LEFT HALF OF PTR
	TRC	TT,700		;DOES T POINT TO A TEXT BYTE POINTER?
	TRNE	TT,7700
	POPJ	P,		;NO
	MOVE	I,-1(T)		;MAYBE. GET WORD BEFORE POINTER. (MAX)
	SUB	I,2(T)		;MAX-CT
	LSH	TT,-14		;BYTE POSITION
	IDIVI	TT,7		;NO. OF CHARACTERS
	MOVEI	TT1,4-3+1	;2
	SUB	TT1,TT		;2-NO. OF CHARACTERS
	SKIPE	SECTN		;PC IN EXTENDED SECTION?
	SKIPA	TT,1(T)		;YES, FETCH DOUBLE-WORD POINTER ADDRESS
	HRRZ	TT,(T)		;NO, POINTER WORD ADDRESS (UNRELOCATED)
	IMULI	TT,5		;5*ADDRESS
	ADD	TT,TT1
	SUBM	TT,I		;5*ADDRESS-NO. CHARS+2+CT-MAX
	JRST	GCMQR2



;MARK ACTIVE QREG STRING
; T: ADDRESS OF QREG STRING PTR

GCMQR:	MOVE	I,(T)
	TLZE	I,400000	;DOES Q-REG CONTAIN TEXT?
	TLZE	I,300000
	POPJ	P,		;NO
	ADD	I,QRBUF		;YES. ENTER POINTER IN GCTAB
GCMQR2:	CAML	I,BEG		;REGION BEFORE TEXT BUFFER?
	POPJ	P,		;NO. FORGET IT.
	CAMGE	I,QRBUF		;IN Q-REG STORAGE AREA?
	POPJ	P,		;NO, FORGET IT.
GCMQR3:	AOS	TT,GCPTR	;YES. TO BE GRABBED.
	CAIL	TT,GCTBLN	;AM I WINNING?
	$FATAL	(GCE,,<Garbage collector error>)
	HRRZM	T,GCTABA(TT)	;SAVE ADDRESS OF STRING POINTER
	MOVEM	I,GCTABC(TT)	;SAVE CHARACTER ADDRESS OF STRING
	POPJ	P,		;DONE THIS POINTER
;SHRINK - TRY TO SHRINK DOWN ACTIVE PHYSICAL MEMORY USAGE IF FEASIBLE

SHRINK:	MOVE	T,Z		;LAST ACTIVE TEXT ADDRESS
	ADDI	T,<XSPGMX*PAGSIZ*5>  ;"EXCESS" ALLOCATION (MODULO CHARACTERS)
	CAML	T,MEMSIZ	;GOT TOO MUCH EXCESS MEMORY ALLOCATED?
	POPJ	P,		;NO, ALL SET

;QUERY:	IS IT WORTHWHILE TO DO A GARBAGE COLLECT HERE?

	MOVE	T,MEMSIZ	;CURRENT MEMORY LIMIT (TEXT)
	IDIVI	T,5		;CURRENT MEMORY LIMIT (WORDS)
	LSH	T,WRD2PG	;TRUNCATE TO CURRENT LAST PAGE
	MOVE	TT,Z		;CURRENT END OF TEXT (TEXT)
	IDIVI	TT,5		;CURRENT END OF TEXT (WORDS)
	MOVE	TT1,TT		; (COPY)
	IORI	TT1,PAGSIZ-1	;ROUND UP TO LAST WORD WITHIN NEW LAST PAGE
;FF	MOVEM	TT1,.JBFF	;SET NEW FIRST FREE POINTER
	IMULI	TT1,5		;A:=LAST BYTE ADDRESS IN NEW LAST PAGE
	MOVEM	TT1,MEMSIZ	;SET NEW SIZE OF MEMORY
	LSH	TT,WRD2PG	;TRUNCATE TO NEW LAST MEMORY PAGE
	SUB	T,TT		;T:=COUNT OF PAGES TO BE DELETED
	ADDI	TT,1		;TT:=FIRST PAGE TO BE DELETED
	PUSHJ	P,PGDES		;FREE UP THE EXCESS MEMORY PAGES
	 HALT	.+1		;DUH?
	POPJ	P,		;ALL DONE HERE
	SUBTTL	MEMORY MANAGEMENT - MEMORY ALLOCATION

;MEMORY WILL BE EXPANDED UNDER ONE OF THESE CONDITIONS.

;	1.AN INTERNAL BUFFER EXPANSION CANNOT BE PERFORMED,
;	  TO DO SO WOULD OVERFLOW THE PRESENT MEMORY
;	  CAPACITY. THE INTERNAL OPERATIONS WHICH DESCOVER
;	  THE NEED FOR EXPANSION ARE:

;	  A.COMMAND BUFFER EXPANDING
;	  B.THE Q-REG GET (GI)
;	  C.THE Q-REG LOAD (NXI)
;	  D.ANY OF THE INSERTS
;	  E.COMMAND ACCEPTANCE ROUTINE


;	2.THE DATA BUFFER WILL BE MAINTAINED AT A MINIMUM
;	  NUMBER OF 5000 CHARACTERS BEFORE NEW DATA IS LOADED
;	  FROM AN INPUT DEVICE OTHER THAN THE CONSOLE. Q-REG
;	  USAGE SHORTENS THE NUMBER OF AVAILABLE CHARACTERS
;	  DIRECTLY, AND NORMAL TECO COMMANDS ARE GREATLY IMPARED
;	  OTHERWISE.
GRABAK:	PUSHJ	P,GRABAC	;SAVE SOME ACS
	IDIVI	T,5		;T:=DESIRED HIGHEST WORD ADDRESS
	ADDI	T,1		;(MEMSIZ ITSELF IS A BUFFER WORD)
	LSH	T,WRD2PG	;T:=DESIRED HIGHEST PAGE ADDRESS
	MOVE	TT1,T		;(COPY)
	MOVE	TT,MEMSIZ	;CURRENT Q-REG/TEXT AREA LIMIT
	MOVEM	TT,OJBFF	;(SAVE IN CASE OF ERROR)
	IDIVI	TT,5		;TT:=CURRENT HIGHEST WORD ADDRESS
	LSH	TT,WRD2PG	;TT:=CURRENT HIGHEST PAGE ADDRESS
	SUB	T,TT		;T:=COUNT OF PAGES NEEDED
	ADDI	TT,1		;TT:=FIRST PAGE TO ALLOCATE
	CAIL	TT,DSECTN*1000	;ALLOCATING IN EXTENDED DATA SECTIONS?
	JRST	GRABK4		;YES, GO FOR IT!

;VERIFY THAT PAGE WON'T RUN INTO RANDOM PAGES OR HISEG

	MOVE	TT1,T		;COUNT OF PAGES TO ALLOCATE
	ADD	TT1,TT		;TT1:=PROPOSED NEW FIRST NON-EX PAGE
	CAIL	TT1,HIORGP	;REQUEST RUN INTO HIGH SEGMENT?
	JRST	GRABKF		;YES, THEN DEFINITELY WON'T FIT
	SKIPN	IOFIR		;IOFIR BEEN SET YET?
	JRST	GRABK4		;NO, THEN WE'RE OK
	CAML	TT1,IOFIR	;WILL EXPANSION RUN INTO I/O BUFFERS
				; (NOTE THAT A NON-EX PAGE MUST BE KEPT
				;  BETWEEN LOW SEGMENT AND I/O BUFFERS IN
				;  ORDER TO PROTECT .JBREL!)
	JRST	GRABKF		;YES, NO ROOM

;HERE WITH ENOUGH ROOM AVAILABLE TO EXPAND THE LOW SEGMENT.

GRABK4:	PUSHJ	P,PGCRE		;ALLOCATE NEW PAGES
	 JRST	GRABKE		;CAN'T EVEN GET VIRTUAL MEMORY!
GRABK6:	ADD	T,TT		;FIRST NEW NON-EX PAGE
	SUBI	T,1		;NEW LAST Q-REG/TEXT AREA PAGE
	LSH	T,PG2WRD	;WORD ADDRESS
	IORI	T,PAGSIZ-1	;LAST WORD IN NEW LAST PAGE
	IMULI	T,5		;LAST CHAR IN NEW LAST PAGE
	MOVEM	T,MEMSIZ	;SET NEW Q-REG/TEXT AREA LIMIT
	JRST	CPOPJ1		;EXIT SUCCESSFULLY
;NO CORE AVAILABLE (OR NOT ENOUGH)

GRABKE:	DMOVE	T,OJBFFT	;RETRIEVE CREATION QUANTITY (FROM PGCRE)
	PUSHJ	P,PGZAP		;MAKE SURE DOESN'T PLAGUE US
	 JFCL			;SIGH
GRABKF:	MOVE	T,OJBFF		;GET LAST FIGURE OF CORE BOUND
	MOVEM	T,MEMSIZ	;RESTORE IT
	POPJ	P,		; AND RETURN ERROR



;GRABAC - AC-SAVE COROUTINE FOR GRABAK

GRABAC:	PUSH	P,T		; . . .
	PUSH	P,TT		; . . .
	PUSH	P,TT1		; . . .
	PUSHJ	P,@-3(P)	;COROUTINE BACK TO GRAB?? (OR WHOMEVER)
	 CAIA			;ERROR RETURN
	AOS	-4(P)		;SUCCESSFUL (SKIP) RETURN
	POP	P,TT1		; . . .
	POP	P,TT		; . . .
	POP	P,T		; . . .
	ADJSP	P,-1		;DISCARD NOW-USELESS COROUTINE CALLER PC
	POPJ	P,		;RETURN AS DIRECTED



U OJBFF,1			;HOLD .JBFF IN CASE OF GROWTH PAINS
U OJBFFT,2			;T AND TT TO RECOVER FOR PARTIAL GROWTH
U TOOBIG,1			;WHEN AOS'ED TO 0 TRY TO SHRINK MEMORY
	SUBTTL	MEMORY MANAGEMENT - PAGE MANIPULATION

;GETPG  --  FIND AND ALLOCATE SOME FREE PAGES
;GETPW  --  SAME, BUT WITH WORD ARGUMENTS
;CALL IS:
;
;	MOVX	A,<COUNT>
;	PUSHJ	P,GETPG/GETPW
;	 ERROR RETURN
;	NORMAL RETURN
;
;WHERE <COUNT> IS A COUNT OF WORDS NEEDED IF CALL TO GETPW OR A COUNT
;OF THE PAGES NEEDED IF A CALL TO GETPG.
;
;ON ERROR RETURN NO FREE PAGES ARE AVAILABLE (OR NOT ENOUGH TO SATISFY
;REQUEST).
;
;ON NORMAL RETURN <COUNT> PAGES HAVE BEEN FOUND AND ALLOCATED. THE PAGE
;ADDRESS IS RETURNED IN AA.
;
;USES T, TT, TT1.

GETPW:	ADDI	A,PAGSIZ-1	;ROUND UP AND
	LSH	A,WRD2PG	;TRUNCATE TO PAGE COUNT
GETPG:	PUSHJ	P,FNDPG		;SEE IF ANY PAGES AVAILABLE
	 POPJ	P,		;NOPE, ERROR RETURN
	DMOVE	T,A		;YES, POSITION COUNT AND PAGE ADDRESS
	PUSHJ	P,PGCRE		;GRAB THE FREE PAGES
	 POPJ	P,		;MONITOR BEING STINGY
	SKIPE	IOFIR		;THIS THE FIRST I/O AREA IN USE?
	CAMGE	AA,IOFIR	; OR IS THIS AREA ABOVE PREVIOUS BUFFER AREA?
	MOVEM	AA,IOFIR	;YES, SET NEW FIRST I/O AREA
	JRST	CPOPJ1		;TAKE SUCCESSFUL RETURN
;FREPG  --  FREE UP PAGES
;PREPW  --  SAME AS FREPG BUT WITH WORD ARGUMENTS
;CALL IS:
;
;	MOVX	A,<COUNT>
;	MOVX	AA,<ADDR>
;	PUSHJ	P,FREPG/FREPW
;	 ERROR RETURN
;	NORMAL RETURN
;
;WHERE <COUNT> IS THE WORD COUNT IF CALL TO FREPW OR THE PAGE COUNT IF CALL
;TO FREPG OF THE PAGES TO BE FREED; <ADDR> IS THE WORD ADDRESS IF CALL TO
;FREPW OR PAGE ADDRESS IF CALL TO FREPG OF THE FIRST PAGE TO BE FREED.
;
;ERROR RETURN CANNOT OCCUR.
;
;ON NORMAL RETURN THE SPECIFIED PAGES HAVE BEEN DEALLOCATED.
;
;USES T, TT, TT1.

FREPW:	ADDI	A,PAGSIZ-1	;ROUND UP AND
	LSH	A,WRD2PG	;TRUNCATE TO PAGE COUNT
	LSH	AA,WRD2PG	;TRUNCATE TO PAGE ADDRESS
FREPG:	DMOVE	T,A		;POSITION COUNT AND ADDRESS
	PUSHJ	P,PGDES		;DESTROY THE PAGES
	 HALT	.+1		;BLETCH
	CAME	AA,IOFIR	;WAS THIS FIRST I/O AREA?
	JRST	CPOPJ1		;NO
	MOVE	TT,AA		;YES, IT WAS
	ADD	T,A		;SKIP PAST JUST-DEALLOCATED AREA
FREPG3:	AOS	T,TT		;ADVANCE TO NEXT PAGE
	HRLI	T,.PAGCA	;MAKE PAGE. ARG BLOCK TO
	PAGE.	T,		;ASK MONITOR ABOUT THE PAGE
	 CAIA			;DUH?
	JUMPL	TT1,FREPG3	;IF PAGE DOESN'T EXIST KEEP LOOKING
		.CREF	PA.GNE	;THE APPROPRIATE SYMBOL
	MOVEM	TT,IOFIR	;PAGE EXISTS, MARK FIRST PAGE IN USE
				; NOTE THIS MAY WELL BE THE HIGH SEGMENT!
	JRST	CPOPJ1		;RETURN
;FNDPG  --  FIND FREE PAGES
;CALL IS:
;
;	MOVX	A,<COUNT>
;	PUSHJ	P,FNDPG
;	 ERROR RETURN
;	NORMAL RETURN
;
;WHERE <COUNT> IS THE NEEDED COUNT OF CONTIGUOUS FREE PAGES.
;
;ON ERROR RETURN THERE ARE NOT ENOUGH CONTIGUOUS FREE PAGES AVAILABLE.
;
;ON NORMAL RETURN A HAS THE COUNT AND AA HAS THE PAGE ADDRESS OF THE
;FIRST FREE PAGE WHICH MATCHS.
;
;USES T, TT, TT1.

FNDPG:	MOVE	TT,.JBREL	;LAST ADDRESS IN LOW SEGMENT
	ADDI	TT,PAGSIZ	;ROUND UP AND
	LSH	TT,WRD2PG	;TRUNCATE TO FIRST FREE PAGE PAST LOW SEGMENT
	ADD	TT,SECTNP	;RELOCATE TO PC SECTION
	MOVEI	AA,HIORGP	;WHERE TO START THE PAGE SEARCH
	ADD	AA,SECTNP	;RELOCATE TO PC SECTION
FNDPG2:	MOVE	T,A		;[P]RESET THE PAGE COUNT NEEDED
FNDPG3:	SOS	TT1,AA		;NEXT PAGE TO TRY
	CAMG	TT1,TT		;HIT LOW SEGMENT YET?
				; (MUST ALWAYS KEEP ONE FREE PAGE AFTER .JBREL
				;  IN ORDER TO PROTECT .JBREL)
	POPJ	P,		;YES, NO FREE PAGES THEN
	HRLI	TT1,.PAGCA	;NO, MAKE PAGE. ARG BLOCK TO
	PAGE.	TT1,		;SEE IF PAGE EXISTS
	 POPJ	P,		;DUH?
	JUMPGE	TT1,FNDPG2	;IF PAGE EXISTS RESTART SEARCH
		.CREF	PA.GNE	;CREF REFERENCE TO APPROPRIATE SYMBOL
	SOJG	T,FNDPG3	;PAGE IS AVAILABLE - FOUND ENOUGH YET?
	JRST	CPOPJ1		;YES - ALL SET THEN
;PGCRE  --  CREATE [ALLOCATE] MEMORY PAGES
;PGCRP  --  CREATE [ALLOCATE] MEMORY PAGES, PHYSICAL
;PGCRV  --  CREATE [ALLOCATE] MEMORY PAGES, VIRTUAL
;PGDES  --  DESTROY [DEALLOCATE] MEMORY PAGES
;PGZAP  --  DESTROY [OK IF NON-EXISTENT] MEMORY PAGES
;PSZAP  --  DESTROY [OK IF NON-EXISTENT] MEMORY SECTIONS (512 PAGES)
;PGMDN  --  MOVE PAGES DOWN [TOWARDS HIGH SEGMENT]
;PGMUP  --  MOVE PAGES UP [TOWARDS 0]
;PGPIN  --  PAGE IN [FROM SWAPPING SPACE] MEMORY PAGES
;PGPOU  --  PAGE OUT [TO SWAPPING SPACE] MEMORY PAGES
;CALL IS:
;
;	MOVX	T,<COUNT>
;	MOVX	TT,<PAGE>
;	PUSHJ	P,P1XXX/PGXXX
;	 ERROR RETURN
;	NORMAL RETURN
;
;WHERE <PAGE> IS THE PAGE NUMBER OF THE FIRST PAGE TO BE AFFECTED
;(CREATED, MOVED, ETC.) AND <COUNT> IS THE COUNT OF CONSECUTIVE PAGES
;AFFECTED. CALL AT P1XXX WITHOUT SETTING UP T IF THE COUNT IS ONE.
;
;ON ERROR RETURN A FATAL ERROR (PAGING I/O ERROR, ETC.) HAS OCCURRED.
;THE ERROR CODE (PAG??%) IS IN AC T.
;
;ON NORMAL RETURN, THE APPROPRIATE PAGES HAVE BEEN WHATEVERED.
;
;USES T, TT, TT1
;CREATE [ALLOCATE] PAGES

P1CRE:	MOVEI	T,1		;COUNT OF ONE
PGCRE:	DMOVEM	T,OJBFFT	;HANG ONTO ALLOCATION QUANTITIES
	PUSHJ	P,PGCRP		;TRY FOR PHYSICAL ALLOCATION
	 CAIA			;CAN'T ALLOCATE PHYSICALLY
	JRST	PGCRE7		;GOT 'EM, SUCCESSFUL RETURN
	CAIE	T,PAGLE%	;[PHYSICAL] LIMIT EXCEEDED?
	POPJ	P,		;NO, FATAL ERROR, ABORT
	DMOVE	T,OJBFFT	;YES, TRY AGAIN, BUT THIS TIME
	PUSHJ	P,PGCRV		;TRY FOR VIRTUAL ALLOCATION
	 POPJ	P,		;NO GO
PGCRE7:	DMOVE	T,OJBFFT	;RESTORE CALLER'S ARGS
	JRST	CPOPJ1		;AND RETURN SUCCESSFULLY



;CREATE [ALLOCATE] PAGES (PHYSICALLY IN MEMORY)

P1CRP:	MOVEI	T,1		;COUNT OF ONE
PGCRP:	MOVSI	TT1,.PAGCD	;CREATE FUNCTION
	PUSH	P,.		;NO IGNORABLE ERROR
	PJRST	PGUUO		;GO DO PAGE.(S)



;CREATE [ALLOCATE] PAGES (VIRTUALLY ON DISK, "ALLOCATED BUT ZERO")

P1CRV:	MOVEI	T,1		;COUNT OF ONE
PGCRV:	MOVSI	TT1,.PAGCD	;CREATE FUNCTION
	TXO	TT,PA.GCD	;"ALLOCATED BUT ZERO"
	PUSH	P,.		;NO IGNORABLE ERROR
	PJRST	PGUUO		;GO DO PAGE.(S)
;DESTROY [DEALLOCATE] PAGES

P1DES:	MOVEI	T,1		;COUNT OF 1
PGDES:	MOVSI	TT1,.PAGCD	;DESTROY FUNCTION
	TXO	TT,PA.GAF	; (OTHER HALF OF DESTROY FUNCTION)
	PUSH	P,.		;NO IGNORABLE ERROR
	PJRST	PGUUO		;GO DO PAGE.(S)



;ZAP [DEALLOCATE] PAGES, OK IF NONE

P1ZAP:	MOVEI	T,1		;COUNT OF 1
PGZAP:	MOVSI	TT1,.PAGCD	;DESTROY FUNCTION
	TXO	TT,PA.GAF	; (OTHER HALF OF DESTROY FUNCTION)
	PUSH	P,[PAGME%]	;IGNORABLE ERROR
	PJRST	PGUUO		;GO DO PAGE.(S)



;ZAP [DEALLOCATE] SECTIONS, OK IF NONE

PSZAP:	MOVSI	TT1,.PAGSC	;DESTROY (SECTIONS) FUNCTION
	TXO	TT,PA.GAF	; (OTHER HALF OF DESTROY FUNCTION)
	PUSH	P,[PAGSM%]	;IGNORABLE ERROR
	PJRST	PGUUO		;GO DO PAGE.(S)
;MOVE PAGES DOWN IN ADDRESSING SPACE

P1MDN:	MOVEI	T,1		;COUNT OF 1
PGMDN:	PUSH	P,T		;SAVE COUNT
	HRL	T,T		;PAGE ADDRESS IN BOTH HALVES
	ADD	TT,T		;POINT TO LAST PAGE TO BE MOVED
PGMDN2:	MOVEI	T,1		;MOVE ONE PAGE AT A TIME
	MOVE	TT1,[.PAGEM,,T]	;MOVE PAGE FUNCTION
	PAGE.	TT1,		;MOVE ONE PAGE DOWN IN MEMORY
	 JRST	PGMDN9		;ANY ERROR IS FATAL
	SUB	TT,[1,,1]	;MOVE BACKWARDS ONE PAGE
	SOSLE	0(P)		;NEED TO MOVE IT TOO?
	JRST	PGMDN2		;YES
	AOS	-1(P)		;NO, ALL PAGES SUCCESSFULLY MOVED
PGMDN9:	POP	P,T		;ADJUST STACK
	POPJ	P,		;RETURN AS APPROPRIATE


;MOVE PAGES UP IN ADDRESSING SPACE

P1MUP:	MOVEI	T,1		;COUNT OF 1
PGMUP:	MOVSI	TT1,.PAGEM	;MOVE FUNCTION
	PUSH	P,[-1]		;ALL ERRORS FATAL
	PJRST	PGUUO		;GO DO PAGE.(S)


;PAGE IN [FROM SWAPPING SPACE] MEMORY PAGES

P1PIN:	MOVEI	T,1		;COUNT OF 1
PGPIN:	MOVSI	TT1,.PAGIO	;PAGEIN FUNCTION
	PUSH	P,[PAGCI%]	;IGNORABLE ERROR
	PJRST	PGUUO		;GO DO PAGE.(S)


;PAGE OUT [TO SWAPPING SPACE] MEMORY PAGES

P1POU:	MOVEI	T,1		;COUNT OF 1
PGPOU:	MOVSI	TT1,.PAGIO	;PAGEOUT FUNCTION
	TXO	TT,PA.GAF	; (OTHER HALF OF PAGEOUT FUNCTION CODE)
	PUSH	P,[PAGMI%]	;IGNOREABLE ERROR
	PJRST	PGUUO		;GO DO PAGE.(S)
;PGUUO  --  DO REAL WORK OF PGXXX ROUTINES

PGUUO:	PUSH	P,TT1		;SAVE FUNCTION CODE
	PUSH	P,T		;SAVE REPEAT COUNT IN CASE NEEDED LATER
	HRRI	TT1,T		;ADDRESS OF PAGE. ARG BLOCK
	MOVNS	T		;NEGATIVE COUNT = REPEAT COUNT
	PAGE.	TT1,		;TRY OUR BEST SHOT
	  CAIA			;BUTTS, MUST NOT BE IMPLEMENTED
	JRST	PGUUO5		;SUCCESS - RETURN NOW

IFN	RUN603,<		;6.03 RETURNS YET A DIFFERENT ERROR
	CAIN	TT1,PAGIA%	;"ILLEGAL ARGUMENT"?
	MOVEI	TT1,PAGIP%	;YES, FAKE OUT CODE BELOW
> ;END IFN RUN603

	CAIE	TT1,PAGIP%	;STUPID MONITOR'S ERROR CODES
	CAMN	TT1,-2(P)	;THIS ERROR RECOVERABLE?
	CAIA			; . . .
	JRST	PGUUO9		;NOPE, FATAL, GO AWAY NOW

;TRY IT THE HARD WAY - ONE PAGE AT A TIME

PGUUO2:	MOVE	TT1,-1(P)	;RETRIEVE  FUNCTION CODE
	HRRI	TT1,T		;ADDRESS OF PAGE. ARG BLOCK
	MOVEI	T,1		;ONE PAGE AT A TIME
	PAGE.	TT1,		;FUNCTIONIZE JUST THIS ONE PAGE
	  JRST	PGUUO8		;CHECK OUT THE ERROR
PGUUO3:	TLNE	TT,77777	;MOVE-TYPE FUNCTION CODE?
	ADD	TT,[1,,0]	;YES, ADJUST LEFT HALF TOO
	SOSLE	0(P)		;COUNT DOWN REPEAT COUNTER
	AOJA	TT,PGUUO2	;GO DO ANOTHER PAGE
PGUUO5:	ADJSP	P,-3		;ADJUST THE STACK
	JRST	CPOPJ1		;SUCCESSFUL (USUALLY) RETURN

;CHECK OUT PAGE. ERROR

PGUUO8:	CAMN	TT1,-2(P)	;EXPECTING THIS TYPE OF ERROR?
	JRST	PGUUO3		;YEAH, JUST IGNORE THIS PAGE
PGUUO9:	MOVE	T,TT1		;NO, FATAL, PUT ERROR CODE IN T
	ADJSP	P,-3		;CLEAN UP THE STACK
	POPJ	P,		;AND PROPAGATE THE ERROR
	SUBTTL	COMMAND DISPATCH TABLE

DEFINE	DSP (C1,A1,C2,A2)<
	XWD	<<C1>B20+<A1-<HIORGP_PG2WRD>>>,<<C2>B20+<A2-<HIORGP_PG2WRD>>>>

;CODES INDICATE TYPE OF DISPATCH
JR==0	;FOR SIMPLE JRST DISPATCH
HR==1	;FOR DISPATCH TO A COMMAND PERFORMED BY A SUBROUTINE
MV==2	;FOR JRST DISPATCH AFTER PROCESSING PRECEDING NUMERIC ARGUMENTS

DTB:	DSP(JR,ERRA,JR,COMMEN)		;^@	^A
	DSP(JR,ERRA,JR,ERRA)		;^B	^C
	DSP(JR,TDDT,JR,FFEED)		;^D	^E
	DSP(JR,LAT,JR,BELDMP)		;^F	^G
	DSP(JR,GTIME,HR,TAB)		;^H	TAB
	DSP(JR,CD5,JR,ERRA)		;LF	VT
	DSP(HR,TYO,JR,CD5)		;FF	CR
	DSP(JR,EOF,JR,OCTIN)		;^N	^O
	DSP(JR,ERRA,JR,ERRA)		;^P	^Q
	DSP(JR,ERRA,JR,ERRA)		;^R	^S
	DSP(MV,CMCCT,JR,ERRA)		;^T	^U
	DSP(MV,LOWCAS,MV,STDCAS)	;^V	^W
	DSP(MV,SETMCH,JR,ERRA)		;^X	^Y
	DSP(JR,FINISZ,JR,ALTMOD)	;^Z	^[
	DSP(JR,ERRA,JR,ERRA)		;^BKSLH	^]
	DSP(JR,CNTRUP,JR,ERRA)		;^^	^LFTARR
	DSP(MV,PLUS,JR,EXCLAM)		;SPACE	!
	DSP(MV,DQUOTE,MV,COR)		;"	#
	DSP(JR,ERRA,MV,PCNT)		;$	%
	DSP(MV,CAND,JR,CD)		;&	'
	DSP(JR,OPENP,MV,CLOSEP)		;(	)
	DSP(MV,TIMES,MV,PLUS)		;*	+
	DSP(MV,COMMA,MV,MINUS)		;,	-
	DSP(JR,PNT,MV,SLASH)		;.	/
	DSP(JR,CDNUM,JR,CDNUM)		;0	1
	DSP(JR,CDNUM,JR,CDNUM)		;2	3
	DSP(JR,CDNUM,JR,CDNUM)		;4	5
	DSP(JR,CDNUM,JR,CDNUM)		;6	7
	DSP(JR,CDNUM,JR,CDNUM)		;8	9
	DSP(MV,COLON,MV,SEMICL)		;:	;
	DSP(MV,LSSTH,HR,PRNT)		;<	=
	DSP(JR,GRTH,JR,QUESTN)		;>	?
	DSP(MV,ATSIGN,JR,ACMD)		;@	A
	DSP(JR,BEGIN,MV,CHARAC)		;B	C
	DSP(MV,DELETE,HR,ECMD)		;D	E
	DSP(MV,FCMD,JR,QGET)		;F	G
	DSP(JR,HOLE,HR,INSERT)		;H	I
	DSP(MV,JMP,MV,KILL)		;J	K
	DSP(MV,LCMD,JR,MAC)		;L	M
	DSP(MV,SERCHP,JR,OCMD)		;N	O
	DSP(HR,PUNCHA,JR,QREG)		;P	Q
	DSP(MV,REVERS,MV,SERCH)		;R	S
	DSP(HR,TYPE,MV,USE)		;T	U
	DSP(HR,VCMD,JR,ERRA)		;V	W
	DSP(MV,XCMD,HR,YANK)		;X	Y
	DSP(JR,END1,MV,OPENB)		;Z	[
	DSP(MV,BAKSL,MV,CLOSEB)		;BKSLH	]
	DSP(JR,UAR,MV,LARR)		;^	LFTARR
	XLIST			;THE LITERALS
	LIT
	LIST
	SUBTTL	GENERAL IMPURE STORAGE

U PDLST0,1			;"TOP" OF STACK (FLAG 0, SEE "GO")
U PDLST,PDLEN			;PROGRAM STACK

U PSIVEC,4			;BASE OF PSI VECTORS
U PSICCV,4			;CONTROL-C INTERUPT VECTOR
;GENERAL MEMORY CONTROL AND RELATED STUFF

U SECTN,1			;SECTION,,0 IN WHICH DTECO IS RUNNING
U SECTNP,1			;PAGE OFFSET FOR SECTN

U RMWBAS,1			;RANDOM MEMORY BASE ADDRESS (WORDS)
U RMWEND,1			;RANDOM MEMORY END ADDRESS (WORDS)

U CMDBAS,1			;COMMAND BUFFER BASE ADDRESS (WORDS)
U CMDEND,1			;COMMAND BUFFER END ADDRESS (WORDS)
U CMDPTR,1			;COMMAND BUFFER BYTE POINTER (MASTER COPY)
U CMDPTX,1			; (DOUBLE-WORD POINTER ADDRESS)

;*** DO NOT SEPARATE *** SEE GC ROUTINE***
U COMMAX,1			;TOTAL CHARACTERS AT CURRENT COMMAND LEVEL
U COMPTR,1			;EXECUTION-TIME COMMAND STRING BYTE POINTER
U COMPTX,1			; (DOUBLE-WORD POINTER ADDRESS)
U COMCNT,1			;CHARACTERS REMAINING AT CURRENT COMMAND LEVEL

U QRBUF,1			;Q-REG/TEXT AREA BASE ADDRESS (CHARACTERS)
				; (THE Q-REGS FIT 'TWEEN QRBUF AND BEG)

;*** DO NOT SEPARATE ***
U BEG,1				;EDITING TEXT BASE ("B") ADDRESS (CHARACTERS)
U PT,1				;EDITING TEXT POINT (".") ADDRESS (CHARACTERS)
U Z,1				;EDITING TEXT END ("Z") ADDRESS (CHARACTERS)

U MEMSIZ,1			;Q-REG/TEXT AREA END ADDRESS (CHARACTERS)


;GARBAGE COLLECTION (GC) DATA

U GCPTR,1			;INDEX INTO GCTABA/GCTABC
U GCTABA,GCTBLN			;ADDRESS OF STRING POINTER FOR GC
U GCTABC,GCTBLN			;CHARACTER ADDRESS OF STRING FOR GC
U CRREL,1			;
U RREL,1			;


;CORRECT FOR 2/3 BUFFER FILLING ERROR.M23 IS 2/3'S AND M23PL IS 2/3
;PLUS THE OTHER THIRD-128 CHARACTERS.

U M23,1				;
U M23PL,1			;
;SWITCH STORAGE FOR SWITCH.INI SWITCHES

U S.CRDI,1			;.LT. 0 IGNORE
				;.EQ. 1 THEN NO CRASH RECOVERY FILE
				;.EQ. 2 THEN DELETE FILE ON EXIT
				;.EQ. 3 THEN PRESERVE FILE ON EXIT
U S.CRPR,1			;.GE. 0 THEN CRASH RECOVERY FILE PROTECTION
U S.CRSA,1			;.GE. 0 THEN TEBSAV VALUE
U S.EAMO,1			;.LT. 0 IGNORE
				;.EQ. 0 DEFAULT NO EA ON ER
				;.GT. 0 DEFAULT EA ON ER
U S.EOMO,1			;.GE. 0 THEN EO VALUE IF TIMESHARING
U S.EOBA,1			;.GE. 0 THEN EO VALUE IF BATCH
U S.OKLS,1			;.LT. 0 IGNORE
				;.EQ. 0 THEN SUPPRESS LSNS ON INPUT
				;.GT. 0 THEN LSNS ARE "OK" ON INPUT
U S.OKNU,1			;.LT. 0 THEN IGNORE
				;.EQ. 0 THEN SUPPRESS NULLS IN INPUT
				;.GT. 0 THEN NULLS ARE OK IN INPUT FILE
U S.SFT,1			;.NE. 0 THEN NO [TECSFT ...] MESSAGES

	BOSWT==S.CRDI		;START OF SWITCHES AREA
	EOSWT==S.SFT		;END OF SWITCHES AREA

U S.CRFI,.FXLEN			;CRASH FILE SPEC SCAN BLOCK
U S.INIT,.FXLEN			;INIT FILE SPEC SCAN BLOCK
U CCLSW,1
U LISTF5,1			;OUTPUT DISPATCH
U ERRLEN,1			;TYPE OF ERROR MESSAGES WANTED BY DEFAULT
U AC0,20-1			;SAVE AC0-AC16 IN NROOM ROUTINE

U CHTB,1		;CONTROL CHARACTER DISPATCH TABLE

;Search stuff

U SCHCTR,1		;# OF CHARS IN SEARCH ARGUMENT (MUST PRECEDE SCHARG)
U SCHARG,<<SRCHMX/5>+1>	;STORE FOR SEARCH ARGUMENT
U SCHPT,1		;SAVED START OF SEARCH POINT
U SCHCNT,1		;SEARCH COUNT STORE
U SCHPTR,1		;SLOW-SEARCH'S "STATIC" BYTE POINTER
U SCHPTX,1		;SLOW-SEARCH'S "STATIC" BYTE POINTER EXTENDED ADDRESS

U FSNTRM,1		;FS, FN 2ND ARG TERMINATOR
U FSNCNT,1		;STORE FOR COMCNT DURING FS, FN
U FSNPTR,1		;DITTO COMPTR
U FSNPTX,1		;DITTO COMPTX

; *** Do not separate vvv
U SMATRX,SMATXN		;The old TECO search bit table
U BITMAT,BITMLN*^D36	;The new rotated search bit table
U DELTA2,^D36		;The table which knows what the pattern looks like
SCLRLN==SMATXN+<BITMLN*^D36>+^D36
; *** Do not separate ^^^

U DELTA0,SMATXN		;The tables which know where characters are
U DELTA1,SMATXN		; in the pattern
U INDMAT,^D36		;A table of indicies into the pattern
U PATLEN,1		;Number of positions in pattern
U ROTLEN,1		;Current distance from the right end of the pattern
U SCNEST,1		;Nest level counter during searches, 0 if none
U SCHTYP,1		;0 if old TECO search, -1 if new search
U SCTLGA,1		;0 if pattern source has no ^Gi, -1 if it does
U CTGLEV,1		;SEARCH FOR TEXT IN Q-REG NEST COUNTER
U STAB,STABLN		;SEARCH MATRIX
COMZR==STAB			;BEGINNING OF AREA TO ZERO
				;WHEN ENTERING COMMAND SCANNER
COMBLK==COMZR			;COMMAND BLOCK (FOR FILE SPEC)
COMDEV=STAB			;DEVICE USER TYPED
COMNAM=COMDEV+1			;FILENAME  "    "
COMEXT=COMNAM+1			;EXTENSION "    "
COMPPN=COMEXT+1			;PPN       "    "
COMSFD=COMPPN+1			;SFD'S     "    "
SWITC=COMSFD+5			;SWITCHES  "    "
SWITHL=SWITC+1			;LAST SWITCH TYPED, IN SIXBIT
	COMBLN==SWITHL-COMBLK+1	;LENGTH OF COM??? AREA

OPNBLK=<OPNSTS=SWITHL+1>	;STATUS TO DO OPEN WITH
OPNDEV=OPNSTS+1			;DEVICE TO OPEN
OPNBUF=OPNDEV+1			;BUFFER ADDRESS

OPNCHR=OPNBUF+1			;DEVCHR OF DEVICE IN OPNDEV

PTHBLK=OPNCHR+1			;1ST WORD OF PATH BLOCK
PTHFLG=PTHBLK+1			;SCAN SWITCH & OTHER FLAGS
PTHPPN=PTHFLG+1			;PROJ-PROG PAIR
PTHSFD=PTHPPN+1			;FIRST SFD
PTHLEN==PTHSFD+5-PTHBLK+1	;LENGTH OF PATH BLOCK

XFIBLK=PTHBLK+PTHLEN		;EXTENDED OPEN BLOCK
XFILNM==XFIBLK			;EXTENDED OPEN BLOCK
XCNT=XFILNM+.RBCNT		;COUNT OF ARGS FOLLOWING
XPPN=XFILNM+.RBPPN		;POINTER TO PATH BLOCK
XNAM=XFILNM+.RBNAM		;FILE NAME
XEXT=XFILNM+.RBEXT		;EXTENSION
XPRV=XFILNM+.RBPRV		;PROT. & DATES
XSIZ=XFILNM+.RBSIZ		;FILE SIZE (WORDS)
XVER=XFILNM+.RBVER		;VERSION
XSPL=XFILNM+.RBSPL		;SPOOLING NAME
XEST=XFILNM+.RBEST		;ESTIMATED SIZE
XALC=XFILNM+.RBALC		;BLOCKS ALLOCATED TO FILE
XPOS=XFILNM+.RBPOS		;POSITION OF FILE ON DISK
XNCA=XFILNM+.RBNCA		;NON-PRIVED CUST. ARG.
XDEV=XFILNM+.RBDEV		;UNIT OF STR THAT FILE CAME FROM
XFILEN==XDEV-XFILNM+1		;LENGTH OF LOOKUP BLOCK

SFILNM==XNAM			;ALTERNATE NAME FOR DTA LOOKUPS
CPATH=XFILNM+XFILEN		;SECOND PATH BLOCK FOR CHKPTH
CFLG=CPATH+1			;SCAN SWITCH
CPPN=CFLG+1			;PPN
CSFD=CPPN+1			;1ST SFD
CPTLEN==CSFD+5-CPATH+1		;LENGTH OF PATH BLOCK

DCBLK=CPATH+CPTLEN		;DSKCHR BLOCK FOR EB OPEN
DCSNM=DCBLK+.DCSNM		;STRUCTURE NAME FILE IS ON
DCLEN==DCSNM-DCBLK+1		;LENGTH OF DSKCHR BLOCK

COMEZR==DCBLK+DCLEN-1		;LAST LOCATION TO ZERO IN SCANNER
IFL <STABLN-<COMEZR-COMZR+1>>,<PRINTX ? MOVE X??? BLOCKS TO BIGGER AREA>

U BCOUNT,1			;BEGPAG MATCH FLAG FOR SLOSCH

;TAG SYMBOL TABLE USED BY "O" COMMAND FOR FAST EXECUTION

U TAGSYM,22			;PSEUDO-POINTER USED TO IDENTIFY "O" COMMAND
U TAGPTR,22			;COPY OF COMPTR FOR THIS "O" COMMAND
U TAGPTX,22			;COPY OF COMPTX FOR THIS "O" COMMAND
U TAGCNT,22			;COPY OF COMCNT FOR THIS "O" COMMAND
U SYMEND,0			;END OF TAG SYMBOL TABLE (FOR BLT)

U EQM,1				;LEVEL OF MACRO NESTING
U PFL,LPF			;Q-REGISTER STACK

U QTAB,QRGMAX			;Q-REGISTER TABLE
U COMSAV,1			;SAVED Q-REG VALUE FOR *I
	QTBLEN==QRGMAX+1	;FOR GARBAGE COLLECTION (INCLUDES COMSAV
				;AS A "HIDDEN" Q-REGISTER).
U COMLEN,1			;LENGTH OF BASIC COMMAND STRING

U LOWERB,1			;BOUNDED-SEARCH LOWER BOUND
U UPPERB,1			;BOUNDED-SEARCH UPPER BOUND

U LOWEND,0			;END OF THE IMPURE/LOWSEG
	END	TECO