Google
 

Trailing-Edge - PDP-10 Archives - decus_20tap5_198111 - decus/20-0148/spell.mac
There are 5 other files named spell.mac in the archive. Click here to see a list.
;<DECUS.10-184>SPELL.WCC.2, 27-Feb-81 19:17:10, EDIT BY SST.D-BIGELOW
;
; Wesleyan University Edit History
;
;[W1]	Correct a bug that causes SPELL to require a dictionary to be loaded
;	even when you're running an EXE file with one built in.  Areas
;	affected: BEGIN0:.	[DHB 25-Feb-81]
;
; End WCC edit history
;
;SPELL.MAC[510,51]	Installed at NBS by MDA 790112
;	Previous TENEX mods made compatable with 6.03 monitor.
;	Changes made in TOPS-10 version only: 
;	Default dictionary changed to WORDS.DIC because extension LST 
;	has special meaning pertaining to line printer.
;	Default dictionary is automatically read in at beginning;
;	option given to dump it at end.
;	Code placed in sharable high segment.
;	Option to rename input file with extension BAK and output file
;	to take name of input file on completion (like TECO).
;<RICHARDSON>NSPELL.MAC;7002	29-OCT-76 13:05:57	Edit by RICHARDSON
; added SOS code (indicated by [SOS]) at RDDATA, WRCORR.
;<RICHARDSON>NSPELL.MAC;7001	28-OCT-76 19:20:00	Edit by RICHARDSON
; minor Tops20 changes:
;	eliminate all PBOUTs of EOL (use PSOUT of CRLF)
;	if non-0 Tops20, assemble searching MONSYM
;<SPELL>NSPELL.MAC;70    22-OCT-75 09:40:28    EDIT BY WOLF
;  MINOR CHANGE TO STATS TYPEOUT FORMAT
;<SPELL>NSPELL.MAC;69    21-OCT-75 13:48:32    EDIT BY WOLF
;  CHANGED OPNFIL TO DO THE DVCHR BEFORE THE OPENF, RATHER THAN
;    AFTERWARDS;  THIS WAY, LPT: LOOKS NON-PMAPPABLE, AS WE NEED.
;  CHANGED HELMSG TO OUTPUT "C" OR "S" LINE ONLY IF THE NUMBER OF
;    CANDIDATE WORDS IS APPROPRIATE.
;<SPELL>NSPELL.MAC;67    17-JUL-75 09:28:23    EDIT BY WOLF
;<SPELL>NSPELL.MAC;66    10-JUL-75 16:39:33    EDIT BY WOLF
;  FIXED A SMALL GLITCH IN THE ENDTST DOCUMENTATION.
;<SPELL>NSPELL.MAC;65     9-JUL-75 12:44:37    EDIT BY WOLF
;  MOVED A ">" IN MACRO DEFINITION OF PRE() TO ELIMINATE "Q"
;    WARNINGS IN LATEST VERSION OF MACRO.
;<SPELL>NSPELL.MAC;64    16-JUN-75 09:51:10    EDIT BY WOLF
;  ADDED ENDTST DOCUMENTATION
;<SPELL>NSPELL.MAC;63    10-JUN-75 12:34:13    EDIT BY WOLF
;<SPELL>NSPELL.MAC;61     5-JUN-75 22:59:48    EDIT BY WOLF
;  MOVED QUESTIONS ABOUT SWITCHES (UPPERCASE DIR, PICKUP PAGE/LINE,
;    TRAINING DIR) FROM RDDATA TO RSWIT, SO THAT THEY GET ASKED AFTER
;    THE SWITCHES ARE SPECIFIED, NOT AT SOME ODD TIME AFTER SPELL
;    STARTS "WORKING".
;  FIXED TENEX FILCLO: USED TO BE THAT IF AN OUTPUT FILE HAD
;    NOTHING IN IT, A FULL PAGE OF ZEROS GOT WRITTEN.
;  FIXED UP THE LOOPING IN TRYFIX SO THE WORD IN QUESTION
;    GETS RETYPED ALONG WITH THE NUMBER OF GUESSES.
;<SPELL>NSPELL.MAC;52    22-MAY-75 17:50:00    EDIT BY WOLF
;  FIXED LENGTH TO PUT OUT ITS DATA IN 6-SPACE COLUMNS, RATHER THAN
;    WITH TABS, SO IT FITS A 72-COLUMN PAGE.
;<SPELL>NSPELL.MAC;43    10-MAY-75 14:06:38    EDIT BY WOLF
;  MODIFIED LDWORD SO THAT IT NO LONGER ACCEPTS APOSTROPHE
;    IF IT IS WORD-INITIAL OR -FINAL.
;  ADDED COUNTERS TO KEEP TRACK OF THE NUMBER OF WORDS AND MISSPELLINGS
;    IN EACH DICTIONARY.  ADDED COUNTERS TO COUNT
;    WORDS ACCEPTED, CORRECTED, INSERTED, MATCHED VIA AFFIX-STRIPPING,
;    MATCHED EXACTLY.  ADDED "N" (FOR "NUMBERS") AT END TO GIVE A
;    TYPEOUT OF ALL THESE STATISTICS, PLUS RUNTIMES.
;  ADDED TO TRAINING/QTRAINING THE ABILITY TO SPECIFY A DICTIONARY
;    TO BE USED FOR THE TRAINING SET.  WHEN DONE THE FILE, TELLS YOU
;    HOW MANY WORDS IT ADDED TO THAT DICTIONARY.
;<SPELL>NSPELL.MAC;37     6-MAY-75 22:05:32    EDIT BY WOLF
;  BECAUSE SEARCH AND RDICTW USE SKIP RETURNS TO SIGNIFY
;    MISSPELLINGS, NO NEED FOR MOST USES OF THE MISSPL BIT IN FL.
;    IT IS STILL USED, HOWEVER, IN INSERM.
;  AUGMENTED LOADEX TO BE A LITTLE MORE COMPLETE IN CHECKING
;    CONSISTENCY OF WORDS INPUT FROM A DICTIONARY FILE.
;<SPELL>NSPELL.MAC;32     3-MAY-75 20:16:07    EDIT BY WOLF
;  REARRANGED TRYRCM SO THAT IT HANDLES THE CASE WHERE THE TYPED
;    REPLACEMENT CORRESPONDS TO A KNOWN MISSPELLING.  ALSO, THE
;    REPLACEMENT GETS TYPED INTO WORDIX, WHENCE IT GETS COPIED
;    INTO THE OUTPUT AND INTO THE EXCEPTION FILE.
;  IN TENEX VERSION OF GETFIL, NOW REQUIRES CONFIRMATION ON INPUT
;    FILES AS WELL AS OUTPUT FILES.
;  BYPASSES DOMISS IN TRAINING MODES.
;<SPELL>NSPELL.MAC;30     1-MAY-75 20:59:20    EDIT BY WOLF
;  MISC. BUG FIXES.
;<SPELL>NSPELL.MAC;28    24-APR-75 09:20:27    EDIT BY WOLF
;  FIXED BUG IN RECONS, CHANGED PREFIX STACK PTR FROM L TO N.
;  ALSO CHANGED HELMSG FOR "L" COMMAND.
;<SPELL>NSPELL.MAC;24    20-APR-75 22:24:37    EDIT BY WOLF
;  ADDED A ROUTINE RECONS, AND MADE CHANGES TO ENDTST AND PREFIX
;    SO THAT IF THEY RECOGNIZE A "STEM" AS A MISSPELLING,
;    THEY CAN CALL RECONS TO RECONSTRUCT THE WORD FROM THE AFFIXES
;    (SAVED ON THEIR RESPECTIVE STACKS) AND THE MISSPELLING CORRECTION.
;    THIS ALSO AFFORDS AN OPPORTUNITY FOR ENDTST TO PROPOSE
;    CORRECTION OF CERTAIN SPECIFIC ERRORS IT CHECKS FOR (SUCH AS
;    MISSING DOUBLED CONSONANT, PROPER PLURAL ENDING, ETC.)
;    THE RECONSTRUCTED WORD IS PUT ON THE CANDBF LIST.
;<SPELL>NSPELL.MAC;17    16-APR-75 20:57:05    EDIT BY WOLF
;  FIXED BUG IN SEARCH:  IF THE WORD BEING SEARCHED FOR CONTAINED
;    EXACTLY 14 (21, 28, ...) CHARACTERS, THEN THE 11+ CHARS LIST
;    GETS SEARCHED.  IF IT MATCHES THE 1ST 14 CHARS OF A 14+
;    CHAR WORD, HAS NO WAY OF KNOWING THERE'S MORE.  NOW CHECKS
;    TO INSURE THAT 1ST CHAR OF NEXT MACHINE WORD IS 0.
;<SPELL>NSPELL.MAC;16    15-APR-75 22:54:16    EDIT BY WOLF
;  1. ADDED "-BLE" -> "-BLY" ("ABLY", "POSSIBLY") CASE TO ENDTST.
;  2. ADDED A STEM-VALIDITY TEST TO ENDTST AND PREFIX: STEM MUST HAVE
;     AT LEAST 3 LETTERS, AND IF EXACTLY 3, MUST HAVE AT LEAST 1 VOWEL
;     OR Y.
;  3. FIXED UP SUFFIX DERIVATION PRINTOUT FOR THE CASE OF ZAPPED LETTERS
;  4. CHANGED THE DICTIONARY-NUMBER HANDLING OF MISSPELLING-CORRECTIONS
;     GENERATED BY "R" AND "C" COMMANDS.  THEY ALWAYS GET CREATED
;     (IF POSSIBLE), AND GET PUT IN DICT. #0 UNLESS A DICT# IS TYPED
;     IN THE "R" OR "C" COMMAND ITSELF.
;  5. THE ROUTINE SETNUM IS CHANGED TO SETNM0 OR SETNM1, WHICH
;     DEFAULT IDNUM TO 0 OR 1 RESPECTIVELY.
;<SPELL>NSPELL.MAC;15    13-APR-75 23:24:43    EDIT BY WOLF
;  FIXED FILE OPENING IN TENEX VERSION OF LENGTH.
;<SPELL>NSPELL.MAC;14    13-APR-75 22:30:10    EDIT BY WOLF
;  CHANGED SEARCH ROUTINE SO THAT SKIP RETURNS DISTINGUISH BETWEEN
;    NOT FOUND, MISSPELLING FOUND, REAL SPELLING FOUND.  MATCH
;    ROUTINE WORKS SAME WAY TOO, OF COURSE.
;  CHANGED DICTIONARY READING ROUTINE SO THAT SKIP RETURNS DISTINGUISH
;    BETWEEN EOF, WORD IS MISSPELLING, WORD IS SPELLING.
;<SPELL>NSPELL.MAC;13     9-APR-75 11:22:04    EDIT BY WOLF
;  CHANGED SUFFIX-STACK POINTER FROM K TO M, SINCE K IS USED IN
;    TENEX I/O.  ALSO CLEANED UP SOME BUGS IN MODIFIED PREFIX.
;    ALSO ADDED A JSYS ERROR STRING PRINTER FOR OPENING TENEX
;    FILE ERRORS.
;<SPELL>NSPELL.MAC;6     7-APR-75 21:54:05    EDIT BY WOLF
;  1. MADE MANY CHANGES TO THE DETAILS OF ENDTST, MOSTLY TO TIGHTEN
;     IT UP.  ALSO MODIFIED ZLAST AND SETLST TO SAVE ON A STACK THE
;     LETTERS STRIPPED OFF THE WORD, SO THAT THE WORD COULD BE
;     BUILT UP AGAIN.
;  2. IN EXCEPTION FILE, WORDS WHICH MATCHED VIA AFFIX-STRIPPING GET
;     THEIR DERIVATIONS PRINTED OUT.
;  3. SMARTENED UP THE OVERFLOW CHECKS ON LIBUF AND LOBUF.  OVERFLOW
;     SHOULD NOW CAUSE A GRACEFUL FAILURE.
;  4. MISSPELLINGS ARE NO LONGER MARKED AS DICT. #31.  INSTEAD, A BIT
;     IN THE FLAGS WORD (MISSPL) IS SET.
;  5. REMOVED THE "TYPE S,A,R,..." TYPEOUT EACH TIME.  INSTEAD, IT
;     TYPES THE NUMBER OF GUESSES (CANDIDATE CORRECTIONS) IT HAS
;     FIGURED OUT.  IF 1, STILL SAYS "I GUESS ..." AS BEFORE.
;  6. FIXED A BUG IN THE TENEX FILE-CLOSING ROUTINE.
;  7. CHANGED PREFIX TO TRY STRIPPING ANOTHER PREFIX, IF STRIPPING ONE
;     DOESN'T MAKE A MATCH ("UNRECONSTRUCTED").  ALSO A PREFIX STACK.
;  8. DICTIONARY DUMPS ALWAYS DUMP MISSPELLINGS.
;<SPELL>NSPELL.MAC;1    24-MAR-75 22:58:28    EDIT BY WOLF
;  THIS IS THE VERSION OF SPELL[S,REG] FTP'D FROM SU-AI ON 3/18/75,
;    CONTAINING FIXES TO THE 3 BUGS I TOLD GORIN I FOUND IN THE TENEX
;    CODE OF HIS NEW PROGRAM.  HE HAD ALSO MADE SOME CHANGES TO LDWORD.
COMMENT    VALID 00045 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00005 00002		TITLE	SPELL	I HAVE YOU UNDER MY SPELL
C00007 00003		SUBTTL	DEFINITIONS
C00016 00004		SUBTTL	Documentation
C00060 00005		SUBTTL	INITIALIZATION - OUTER LOOP
C00000 00000		SUBTTL	SETBAK	INPUT FILE TO BECOME .BAK ON EXIT
C00068 00006		SUBTTL	RSWIT	READ MODE SWITCHES FROM USER TERMINAL
C00071 00007		SUBTTL	THE LOOP WHERE ALL THE WORK GETS DONE.
C00075 00008		SUBTTL	GETLIN	READ A LINE OF DATA INTO LIBUF
C00079 00009		SUBTTL	CHKLIN	CHECK EACH WORD FROM THE LINE
C00085 00010		SUBTTL	PUTLIN	WRITE LINE TO CORRECTION FILE.  CONVRT,CONVRZ,PPAGE
C00090 00011		SUBTTL	LDWORD	LOAD WORD FROM INPUT LINE
C00099 00012		SUBTTL	RDDATA THE READING ROUTINE
C00104 00013		SUBTTL	DESCRIPTION OF ENDTST
C00116 00014		SUBTTL	ENDTST	TEST THE SUSPECT WORD BY REMOVING THE ENDINGS
C00128 00015		SUBTTL	ROUTINES USED BY ENDTST
C00131 00016		SUBTTL  PREFIX - TRY TO REMOVE PREFIXES
C00135 00017		SUBTTL	CHANNEL INITIALIZATION	- DEC AND STANFORD
C00139 00018		SUBTTL	CHANNEL INITIALIZATION	- TENEX
C00148 00019		SUBTTL	DICTIONARY MANIPULATION - DUMPD - DUMP ROUTINE
C00160 00020		SUBTTL	DICTIONARY MANIPULATION - LOADER - LOAD A DICTIONARY FILE.
C00166 00021		SUBTTL	DICTIONARY MANIPULATION - RDDICT - READ DICTIONARY FILE
C00168 00022		SUBTTL	DICTIONARY MANIPULATION - RDICTW - READ A DICTIONARY WORD
C00171 00023		SUBTTL	GETFIL	SCAN TERMINAL FOR A FILE NAME.
C00180 00024		SUBTTL	ERROR MESSAGES
C00184 00025		SUBTTL	HASHCP	THE HASH COMPUTATION.
C00187 00026		SUBTTL	SEARCH	LOOK IN DICTIONARY FOR A WORD.
C00190 00027		SUBTTL	INSERT
C00194 00028		SUBTTL	CORE ROUTINES
C00195 00029		SUBTTL	TRYFIX	OUR HUMBLE ATTEMPT TO CORRECT THE WORD.
C00204 00030		SUBTTL	REPLACE AND SELECT COMMANDS
C00214 00031		SUBTTL	STANFORD DISPLAY ROUTINES
C00221 00032		SUBTTL	STANFORD DISPLAY ROUTINES
C00225 00033		SUBTTL	STANFORD DISPLAY ROUTINES
C00232 00034		SUBTTL	THE HELP MESSAGE
C00234 00035		SUBTTL	REPCHK, SETNUM
C00236 00036		SUBTTL	X1SRCH	TRY TO CORRECT ONE MISSPELLED LETTER
C00240 00037		SUBTTL	X1EXL	MAYBE HE TYPED ONE EXTRA LETTER
C00242 00038		SUBTTL	XTRNP	ONE PAIR TRANSPOSITION
C00244 00039		SUBTTL	ONE LETTER MISSING
C00247 00040		SUBTTL	SAVEME  WRITE OUT CORE IMAGE USING SWAP UUO.
C00250 00041		SUBTTL	TENEX UUO HANDLER
C00256 00042		SUBTTL	LENGTH	COUNT THE LENGTH OF THE HASH CHAINS.
C00260 00043		SUBTTL	THE DEBUG QUEUE
C00262 00044		SUBTTL	DTRACE,DTRACY  TRACE DUMP ROUTINE
C00264 00045		SUBTTL	SOME OF THE STORAGE STUFF
C00269 ENDMK
C;
	TITLE	SPELL	I HAVE YOU UNDER MY SPELL
;		SPELLING CHECK  & CORRECTION.

;		R. E. Gorin 20 February, 1971
;		Revised July 23, 1972 III displays
;		TENEX version 1/12/74 Wiiliam W. Plummer, mod REG 11/19/74
;		Additional features, October 1974, Jerry Wolf, mod REG 11/23/74

COMMENT $

Acknowledgements:

	The work reported here was supported in part by the  Advanced
Research  Projects Agency of the Department of Defense under contract
SD-183,  and  in  part by  the  National  Science  Foundation,  which
supported the author as a Fellow. 


Report Problems with this program to:
			Ralph E. Gorin
			Artificial Intelligence Laboratory
			Stanford University
			Stanford, California 94305
$
	SUBTTL	DEFINITIONS
	PAGE

IFDEF FOR,<MACRO__0;>MACRO==1		;SELECT ASSEMBLER.  MACRO OR FAIL

COMMENT/  ASSEMBLY SWITCHES.

    DISCLAIMER: COUNTS AND XCNT ARE INTENDED FOR GATHERING
    INFORMATION THAT IS NOT OF INTEREST TO THE CASUAL USER.
    USERS ARE INFORMED THAT THOSE FEATURES ARE NOT SUPPORTED
    IN ANY FASHION.   THE DRD SWITCH IS ALSO UNSUPPORTED.

STANSW	GIVES SIXBIT PPN AND STANFORD SWAP UUO

TENEX	GIVES TENEX VERSION.

COUNTS	GIVES THE EXECUTION COUNTS AND DEBUGGING TRACE OF THE
	LAST 100 AREAS EXECUTED. (not recommended - reg)

XCNT	ADDS CODE TO WRITE A FILE CONTAINING THE HASH CHAIN LENGTHS

DRD	DEPARTMENT OF REDUNDANCY DEPARTMENT - ADDS CODE TO BOUNDS-CHECK
	CERTAIN IDPB INSTRUCTIONS.

IF STANSW IS 0 THEN IF SANSW IS 1 YOU GET DECIMAL PPN, ELSE OCTAL PPN

/

;SWITCH SETTINGS:

;ON THE BASIS OF WHAT ASSEMBLER YOU USE, YOU GET DIFFERENT VERSIONS
;IFDEF JSYS,<TENEX==1>		; NBS is not TENEX. MDA 790112
IFDEF SPCWAR,<STANSW==1>

tenex==1			;[decus] added for tops-20 version
tops20==1			;[decus]

IFNDEF STANSW,<STANSW==0>
IFNDEF TENEX,<TENEX==0>
IFNDEF TOPS20,<TOPS20==0>	; assume using non-Dec system for assembly
IFNDEF SANSW,<SANSW==0>
IFNDEF COUNTS,<COUNTS==0>	;THIS IS HIGHLY NON-RECOMMENDED  REG.
XCNT=1
IFNDEF XCNT,<XCNT==0>		;SPECIAL COUNT CODE - LENGTH OF CHAINS
IFNDEF DRD,<DRD==0>		;BOUNDS CHECK ON IDPB INSTRUCTIONS

IFN SANSW,<SANSW==1>		;NORMALIZE
IFE STANSW,<PPNMUL==10+SANSW+SANSW>

IFN STANSW,<	PRINTX	STANFORD VERSION	>
IFN TENEX,<	PRINTX	TENEX VERSION	>
IFE TENEX!STANSW,<	PRINTX	TOPS-10 VERSION	>



;AC DEFINITIONS:


	FL=0
	A=1
	B=2
	C=3
	D=4
	W=5
	X=6	;X MUST FOLLOW W
	Y=7
	Z=10
	K=11
	L=12
	M=13
	N=14

IFN COUNTS,<	DEBA=15
		DEBX=16	>
	P=17

LF==12
FF==14
CR==15
ESC==33
IFN TENEX,<EOL==15>	;[Tops20] TENEX EOL CONCEPT FLUSHED FOR TOPS20

;DEFINE SYMBOLS FOR 5BIT CHARACTERS A5, B5, ...
	DEFINE DEF5(CH) 
	<IRPC CH,<CH'5=="CH"&37>>

	DEF5 ABCDEFGHIJKLMNOPQRSTUVWXYZ
	APOS==Z5+1		;5BIT CODE FOR APOSTROPHE

	EXTERN	.JBFF,.JBSA,.JBREL,.JBHRL

;DEFINE I-O CHANNELS:
	DICT==14	;FOR DICTIONARY READIN AND DICTIONARY DUMPS
	DATA==15	;FOR FILE TO CORRECT
	CORR==16	;CORRECTED FILE.
	EXCP==17	;EXCEPTIONS

IFE TENEX,<
;COMMON DEC CALLIS
OPDEF	RESET	[CALLI	0]
OPDEF	EXIT	[CALLI	12]
OPDEF	CORE	[CALLI	11]
IFE STANSW,<	OPDEF	DEVSIZ	[CALLI 101]	>

;STANFORD-DEC TTY CALLS 
OPDEF	TTCALL	[51B8]
OPDEF	INCHRW	[TTCALL 0,]
OPDEF	OUTCHR	[TTCALL 1,]
OPDEF	INCHRS	[TTCALL 2,]
OPDEF	OUTSTR	[TTCALL 3,]
OPDEF	INCHWL	[TTCALL 4,]
OPDEF	GETLCH	[TTCALL 6,]
OPDEF	CLRBFI	[TTCALL 11,]

>;END IFE TENEX

IFN TENEX,<
		PURGE	RESET
IFE TOPS20,<
		SEARCH	STENEX
>
IFN TOPS20,<	SEARCH MONSYM>	;the Tops20 symbols
		DICTPG==600		;PMAP DICTIONARY FILE HERE
		DATAPG==601
		EXCPPG==602
		CORRPG==603
		OPDEF	ENTER	[1B8]
		OPDEF	LOOKUP	[2B8]
		OPDEF	CLOSE	[3B8]
		OPDEF	RELEAS	[4B8]
		OPDEF	INCHRW	[5B8]
		OPDEF	OUTCHR	[6B8]
		OPDEF	INCHRS	[7B8]
		OPDEF	OUTSTR	[10B8]
		OPDEF	INCHWL	[11B8]
		OPDEF	GETLCH	[12B8]
		OPDEF	CLRBFI	[13B8]
		OPDEF	EXIT	[HALTF]
		DEFINE HALT(ADR) <
		%ADR==ADR
		HALTF
		IFB <ADR>,< JRST .-1>
		IFNB <ADR>,< JRST %ADR>>
>;IFN TENEX


;	RIGHT HALF FLAGS

	FRSTOP==1		;FIRST I/O OPERATION ON DATA CHANNEL
	TECO==2			;FOUND A TECO FILE ON DATA CHANNEL
	LEFT==4			;HASH ON LEFT, NOT ON RIGHT
	ERRLIN==10		;THERE IS AN ERROR IN THIS LINE
	MISSPL==40		;LAST DICTIONARY SEARCH FOUND A MISSPELLED WORD
				;ALSO, IN LH FLAGS WORD, THIS ENTRY IS
				; A MISSPELLING
	NOCORR==100		;CHECK ONLY, NO CORRECT
	NOEXCP==200		;DON'T WRITE EXCEPTION FILE
	IDUMP==400		;DO INCREMENTAL DUMP, OR INCREMENTAL INSERT
	SUFWIN==1000		;SUFFIX REMOVAL WON
	PREWIN==2000		;PREFIX REMOVAL WON
	NOTRAC==4000		;DON'T ADD TO TRACE WHILE DUMPING TRACE
	NOSUFF==10000		;DON'T PERFORM SUFFIX REMOVAL
	NOPREF==20000		;DON'T PERFORM PREFIX REMOVAL
	PICKUP==40000		;ALLOW A PICKUP IN THE MIDDLE OF FILE
	SHUTUP==100000		;NO CORRECTIONS, BUT WRITE EXECPTIONS
	TRAIN==200000		;T MODES. ADD ALL EXCEPTIONS TO DICTIONARY (TRDNUM).
	QTRAIN==400000		;TRAIN AND MARK CLOSE WORDS IN EXCEPTION FILE

;LEFT HALF FLAGS
	UPPER==1		;INPUT WORD IS ALL UPPER CASE
	MIXED==2		;FIRST LETTER UPPER CASE, REST LOWER
	LOWER==4		;ALL LETTERS LOWER CASE
	ODD==10			;ODD CASE E.G., McCarthy
IFN STANSW,<
	IIIINI==20		;DISPLAY HAS BEEN INITIALIZED
	DDDSW==40		;WE'RE REALLY ON A STANFORD DATA DISC
	IIISW==100		;WE ARE ON A STANFORD III
>
	ADDBIT==200		;SUFSTK: THIS LETTER WAS ADDED TO WORD
	ZAPBIT==400		;SUFSTK: THIS LETTER ZAPPED OFF THE WORD

	DEFINE	BCHECK	(BYP,BOUND)<
IFG DRD,<
	PUSH	P,A
	MOVEI	A,@BYP	;GET ADDRESS OF BYTE.
	CAILE	A,BOUND
	PUSHJ	P,INTCFN
	POP	P,A
>>


	DEFINE	ICOUNT<
IFG COUNTS,<
	%QXX==%QXX+1
	AOS	ICTAB+%QXX
	MOVEI	DEBA,%QXX
	PUSHJ	P,DEBQUE
>>

IFG COUNTS,<	%QXX==-1
		LALL>

IFN STANSW,<				;COMPILE FOR STANFORD FEATURES
OPDEF	SWAP	[CALLI	400004]		;STANFORD SWAP UUO.
OPDEF	BUFLEN	[CALLI	400042]		;GET BUFFER SIZE.
OPDEF	DPYCLR	[701B8]			;CLEAR DISPLAY
OPDEF	PPIOT	[702B8]			;
OPDEF	DPYPOS	[PPIOT	2,]		;SET Y POSITION OF PAGE PRINTER
OPDEF	DPYSIZ	[PPIOT	3,]		;SET SIZE OF PAGE PRINTER.
OPDEF	UPGIOT	[703B8]
OPDEF	PTYUUO	[711B8]
OPDEF	PTLOAD	[PTYUUO 15,]
	VBRT==4000			;LVW BRIGHTNESS FIELD
	VSIZ==1000			;LVW SIZE FIELD
	VABS==100			;LVW ABSOLUTE FIELD
	VENDP==20			;LVW ENDPOINT FIELD
	VINVIS==40			;LVW INVISIBLE FIELD
		DEFINE	LVW(X,Y,TYPE,MODE,BRT,SIZ)<
		IFIDN <MODE><A>,<MD==1;>MD==0
		IFIDN <TYPE><I>,<TT==2;>TT==0
		IFIDN <BRT><>,<BQ==0;>BQ==BRT
		IFIDN <SIZ><>,<SQ==0;>SQ==SIZ
		BYTE(11)<X>,<Y>(3)BQ,SQ(2)MD,TT(4)6
		>


COMMENT/
A LONG VECTOR WORD (LVW) FOR THE III DISPLAY HAS THE FOLLOWING FORMAT

BITS  0-10	X	COORDINATE
BITS 11-21	Y	COORDINATE
BITS 22-24	BRT	BRIGHTNESS. 0=NO CHANGE, 1-7 INCREASING BRIGHTNESS
BITS 25-27	SIZ	SIZE. 0=NO CHANGE, 1-7 INCREASING SIZE
BIT     29	M	MODE. 0=RELATIVE TO LAST, 1=ABSOLUTE FROM CENTER
BITS 30-31	T	TYPE. 0=VISIBLE, 1=ENDPOINT, 2=INVISIBLE
BITS 32-35		6.  DENOTES LVW IN DISPLAY PROCESSOR

/

;COMMAND WORD FOR THE DATA DISC (DD) DISPLAYS

DEFINE CW(C1,D1,C2,D2,C3,D3)<BYTE(8)D1,D2,D3(3)C1,C2,C3,4>


>;IFN STANSW

	LOC 137
	400701000007	;mda 790112
	RELOC 0
IFE TENEX,<	TWOSEG			;MDA 790112
		RELOC	400000	>	;TOPS-10 REENTRANCY

	SUBTTL	Documentation
	PAGE

COMMENT %

The text of this comment is intended to  provide most of the external
documentation for this program.  Since this program operates slightly
differently under TENEX, some  of the documentation has been  labeled
TENEX or TOPS-10 as appropriate. 


				Ralph E. Gorin
				Artificial Intelligence Laboratory
				Computer Science Department
				Stanford University
				Stanford, California 94305

				4 March 1971
				11 March 1974 revision
				Tenex Mods: March-October 1974
				   William Plummer, Jerry Wolf
				14 December 1974 revision

---------------------------------------------------------------------



             SPELL: Spelling Check and Correction Program



1.0  INTRODUCTION

SPELL is a program designed to read text  files  and  check  them  for
correctness  of  spelling.   In  addition  to  the spelling check, the
program provides a means for  correcting  words  that  it  thinks  are
misspelled.   This  program was written by Ralph E.  Gorin of Stanford
University Artificial Intelligence Laboratory.  It has been  augmented
by William Plummer and Jerry Wolf of BBN and Marshall Abrams of NBS.  

In its normal mode of usage, SPELL reads through an input  text  file,
asks  the  user  about each word it does not recognize, and creates an
output file in which corrections have  been  made.   Provisions  exist
for:

     1.  Loading,  incrementally  augmenting,  and   dumping   special
         dictionaries.   Such dictionary files are ordinary text files
         which  may  be   listed   and   edited.    Arbitrarily   many
         dictionaries  may  be loaded, subject only to availability of
         (virtual) main memory.  

     2.  Training modes where SPELL scans an input file  and  makes  a
         list  of all words it does not recognize.  Such a list can be
         used as an auxiliary dictionary.

     3.  Termination of spelling checking part way through a file  and
         a way of picking up where you left off in a later session.

Other features of the program are:

     4.  SPELL  will  read  either  SOS,  TECO  or  E/TV  files.   The
         corrected  output  will  be  written in the same mode, except
         E/TV directories must be deleted.  Dictionary  files  may  be
         SOS, TECO or E/TV format.

     5.  An exception file may also produced.  This file contains  all
         words  SPELL  did  not  recognize  (and  their contexts), all
         corrections,  plus  all  words  which  SPELL  recognized   by
         stripping  off  prefixes and/or suffixes.  This last class of
         words appears marked with "[" or "]"  to  denote  prefix-  or
         suffix-    removal.     E.g.,    FOOING]    [PREFOOED]    The
         affix-stripping algorithms are not foolproof  (e.g.,  CHOSES]
         ), so this gives a quick way to scan for the exceptions which
         may slip through.

     6.  SPELL keeps track of all word spellings which were  corrected
         by   the   user.    Subsequent   occurrences   of   such  are
         automatically corrected by the program.  This is reported  to
         the user by a typeout of "MISSPELLING ==> CORRECTION".

     7.  When a word is corrected, the output file will  be  rewritten
         with  either  upper  case, lower case, or mixed (first letter
         upper, the remainder in lower), depending on the cases of the
         first  two letters in the original word.  Note:  this will be
         incorrect in some cases (e.g., McCarthy).





2.0  USING SPELL

2.1  Starting SPELL

Type the command R SPELL (under TENEX, type "SPELL" to the EXEC).  All
typeins to SPELL must be terminated by carriage return.  (In the TENEX
version, editing by ^A, ^Q, and ^R may be done.) (TOPS-10 accepts  ^U,
DEL, and, depending on MONGEN parameters, BS.)



2.2  Augmenting The Built-in Dictionary

The non-TENEX version will first attempt to load the  default  private
dictionary file WORDS.DIC into dictionary 1 with incremental insertion
set (see Incremental Insertion below).

Next, SPELL will ask:  "Do you want to augment the dictionary?" If you
wish  to  use  only  the main dictionary (plus WORDS.DIC) presently in
memory, type <cr>.  You can then skip the next paragraph.  



2.2.1  Private Auxiliary Dictionary - If   in   fact   you   have   an
additional  auxiliary dictionary (of specific terms, infrequently used
words, etc.) you wish to use, type "Y" <cr>.  You will then  be  asked
for the name of the dictionary file.



2.2.1.1  Incremental Insertions - After typing the file name you  will
be  given  the  option  of  marking  the  new  entries  as incremental
insertions.  If the new entries are marked as  incremental  then  they
will  be  included  in an incremental dump of the dictionary.  To have
the new entries marked as incremental, type "I" <cr>;  otherwise, type
<cr>.   (If  any of the words in your auxiliary dictionary are already
in the main dictionary then no second copy of the word will  be  made.
Hence,  if  your  words are marked as incremental then in a subsequent
incremental dump, any words that were already in the  dictionary  will
not be dumped.)



2.2.1.2  Additional Dictionaries - After    loading    an    auxiliary
dictionary  the program will type the new total number of words in the
dictionary (and, except under TENEX, the amount of  core  used).   You
will then have an opportunity to save the new core image (normally you
won't do this).  You will again be asked, "Do you want to augment  the
dictionary?",  thus  allowing  you  to  enter  a  number  of auxiliary
dictionaries (limited only by the availability of {virtual} core).  



2.2.1.3  Dictionary Format - The format of the file is one  dictionary
entry  (word)  on  a  line;   words  must  be  composed  of alphabetic
characters  or  apostrophe  and  less  than  40  letters  long.    The
dictionary   entries   need   not   be   in   alphabetical  order.   A
misspelling-correction  pair  may  occur  one   line   in   the   form
"MISSPELLING>CORRECTION".



2.3  Switches

You will then be given an opportunity to specify zero or  more  switch
options.  The meanings of the switches are:

     T    Training mode.   SPELL  will  treat  the  input  file  as  a
          training  set rather than a file to be corrected.  All words
          in the file which are unfamiliar to SPELL will be entered in
          the  dictionary  as  incremental  insertions.   After  SPELL
          finishes reading the file, the user has  an  opportunity  to
          dump  all  the words that were inserted in this manner.  The
          resulting list of words may be edited, and any  words  which
          are incorrect may be deleted.  Then this file can be used as
          an auxiliary dictionary while correcting the original source
          file.

          This feature is provided  for  the  purpose  of  easing  the
          problem  of  creating a specialized dictionary of jargon and
          infrequently used words.

     Q    Q-Training mode.  In this mode, all words in the source file
          that   are   unfamiliar  to  SPELL  will  be  added  to  the
          dictionary;  the difference is, if any "new" word is  "close
          to"  some  old  word,  the  new  word  will be output to the
          exception file.  The exception file will contain  only  such
          words.   In  this  way,  the  spelling checker calls to your
          attention the fact that these words may be misspelled.

     N    No suffix removal.  This switch suppresses  the  attempt  to
          remove  suffixes to recognize a correctly spelled root word.
          SPELL will then find many more questionable  words,  but  it
          will work more correctly than the heuristic affix removal.  

     A    No prefix removal.  This switch suppresses  the  attempt  to
          remove prefixes to recognize a correctly spelled root word.

     U    Accept Upper case mode.  In this mode, all  words  that  are
          written  entirely  in  upper  case  will  be inserted in the
          dictionary.  This is useful when a manuscript file  contains
          jargon   terms   that   are   written  in  upper  case,  and
          text-processor (e.g., PUB, TJ6, or RUNOFF) commands in upper
          case.   Before  reading the input file, SPELL will ask for a
          dictionary number to use for all  words  inserted  this  way
          (see "How to Use Multiple Dictionaries").  

     P    Pickup mode.  After specifying input and output file  names,
          you  will  be  asked  to  specify a page and line number for
          pickup.  The effect is to suspend  spelling  checking  until
          the  page  and  line specified.  When a user has a partially
          corrected file, this mode will enable him to skip  over  the
          portion  of  the  file that has already been corrected.  The
          input file will be copied without  checking  to  the  output
          until  the  page and line specified, at which point spelling
          checking begins.



2.4  File To Be Corrected

Next you will be asked for the name of the file that you want to check
for  spelling errors.  File names are specified in the usual format of
"name.ext[prj,prg]" where name  is  the  filename,  ext  is  the  file
extension,  and  [prj,prg] is the name of the file owner, which may be
omitted if the file is on the present user's disk area.  If  you  omit
the  file  name then you will immediately enter the exit sequence (see
below).




2.5  Output File

You will be next asked to name the output file.  Enter a file name, or
just a <cr> if you wish to use the default (see next paragraph).



2.5.1  Default Output File(s) - In the TENEX version there are  always
output  and exception files;  by default the output file will have the
same name and extension as the input, and the exception file will have
the  extension "EXCEPTIONS".  In non-TENEX versions the default output
is to rename the input file with  extension  .BAK  and  to  place  the
corrected  text in the (previous) input file name.  The exception file
may be omitted.  



2.5.2  Exception File - The exception file, should you chose  to  make
one,  will  contain  each  line  on  which  an  error  was  found, the
indication of the page and line number, and the suspect  word.   Words
accepted  via  the  affix  removal  heuristics will also appear in the
exception file.  



2.6  Checking And Correcting

After you have specified all the files, the program will respond  with
"Working..." and start checking the input file for spelling errors.  



2.6.1  Choices When An Unknown Word Is Found - When    the    spelling
checker  encounters  a word that isn't in the dictionary, it will type
the page and line number, the line in which the word occurs,  and  the
word itself.

In general, when a word is found that is  not  in  the  dictionary,  a
brief message will be typed to remind you of the possible choices.  In
the special case  where  the  program  finds  precisely  one  possible
correction  for  the word, you will be given the choice of typing C to
accept the "guess" or any other option.  The options are:

     C    The "guess" is correct.   Correct  the  word  in  the  text.
          Enter misspelling in dictionary so that it will be corrected
          if it appears again.

     A    Accept this word, this one time.  

     I    Accept this word and insert it in  the  dictionary  so  that
          subsequent  occurrences  of this word will be recognized and
          accepted.  Words that are inserted this way  are  marked  as
          incremental  insertions  and  they  may be dumped to form an
          auxiliary dictionary.

     R    Replace this word.  Type "R" <cr> and the program  will  ask
          you  for  the  replacement word.  If the replacement word is
          not already in the dictionary, the program will give you  an
          opportunity to insert it.

          If the misspelling is due to an omitted space between words,
          use the "R" command to retype the words with the space.

          If the  replacement  word  contains  no  spaces  or  illegal
          characters,  you  will  be  asked  if  you  wish to add this
          replacement to the list of misspelling-correction pairs.  If
          you  do  add  the  replaced  word  as a misspelling then all
          subsequent occurrences of that word will  be  replaced  with
          the replacement string.  

     X    Accept this word and finish.  The  word  will  be  accepted.
          Then  the remainder of the input file will be copied without
          checking to the output file.

     W    Save my incremental insertions.  After you type "W" <cr> you
          will  be asked for a file name.  Then an incremental dump of
          the dictionary will be written into  the  file.   After  the
          dump  is  complete  you  may then decide what to do with the
          excepted word.

     L    Load an auxiliary dictionary.  The present word is  accepted
          and you will be asked for the name of the dictionary file to
          load.  This is useful if you encounter  a  jargon  term  but
          forgot to load the appropriate dictionary.  

     D    Display the line and offending word again.  The line that is
          displayed  will  not have any corrections shown in it.  If a
          line has more than one error the line  will  only  be  typed
          once.   Subsequent  errors  on that line will cause only the
          particular word to be typed, unless this command is used.

     S    If this choice is offered  then  the  spelling  checker  has
          discovered  several words that could be possible corrections
          of this word.  If you type "S" <cr> then you  will  enter  a
          mode  where you can look at the words that were found by the
          program and (optionally) select one of the  words  from  the
          list.

          When you enter this selection submode, the first word in the
          list  of  possible  corrections will be typed followed by an
          asterisk.  Then you have the following choices:

          C<cr>  Use this word as the Correction.

          <cr>   Show the next possible choice.  When you exhaust  the
                 choices you are returned to the outer mode, and asked
                 again.

          ^<cr>  Back up in the list.

          <esc>  Escape from this submode  and  return  to  the  outer
                 command mode.

Note that when you make a correction via the C command or by selection
from  the  list presented by the S command, that correction is entered
in the misspelling-correction list and subsequent occurrences  of  the
same misspelling will be corrected automatically.  



2.7  Finished Processing The File

When the input file is exhausted, all files are  closed,  the  program
types "Finished.", and the exit sequence is entered.  Except on TENEX,
you will be asked if you want the default dictionary WORDS.DIC dumped.
Answer  "yes"  or  "no"  (actually  only  a  single  letter  answer is
required).  The user then has several options:

E    Exit now.

S    Save this core image.

C    Go back and correct another file.

A    Augment the dictionary, set new  switches,  and  correct  another
     file.

D    Complete dump of the dictionary.  This will create a  very  large
     file, and it is not usually recommended.

I    Incremental dump of the dictionary.  All the words that were read
     in  from  a  private  dictionary  and marked with an I plus those
     inserted while running the program are dumped  to  a  file.   The
     user  specifies  a  file  name  (the default is WORDS.DIC).  This
     incremental file is in a format suitable for editing or  for  use
     as  an  auxiliary  dictionary.   The  words  in  this file are in
     alphabetical order.  

X    This command is used to get a trace count of the program.  It  is
     for  diagnostic  purposes  only,  and  is displayed as a possible
     choice only if the program has  been  assembled  as  a  debugging
     program.




3.0  HOW TO USE MULTIPLE DICTIONARIES


SPELL has a set of features whereby the user can cause the creation of
several  disjoint incremental dictionaries.  In this way, the user may
collect  several  dictionaries  of  special  terms.   Internally,  all
dictionary entries are considered equivalent as regards word searches.
The distinction  between  dictionaries  becomes  relevant  when  doing
incremental  dumps  (the  I  command during the exit sequence or the W
command while in the middle of execution).  When an  incremental  dump
is  requested,  the user may specify a number, e.g., W9, which selects
the particular incremental dictionary to be dumped.  In this  example,
dictionary 9 will be dumped.  



3.1  Dictionaries 0 And 1

Dictionary 0 is the main dictionary.  Words cannot be  added  to  this
dictionary,  except  by  reading an auxiliary file.  In general, words
that are inserted incrementally are marked as being in  dictionary  1.
All  words  that  are incremental insertions in the dictionary will be
marked in dictionary 1, unless the user specifies otherwise.  



3.2  Specifying A Dictionary

The following places are where the user may specify  which  dictionary
to add to:

     1.  When loading an auxiliary dictionary, if  the  user  responds
         with  "In"  to  the  question  about  marking  new entries as
         incremental,  then  the  new  entries  will  be   marked   in
         dictionary  number  n  (where n is interpreted as decimal and
         should be less than 31).

     2.  After a word has been rejected, type "In" to insert the  word
         in dictionary number n.

     3.  After replacing a word, if the  replacement  is  not  in  the
         dictionary,  then  type  "In"  to insert the replacement into
         dictionary n.


When  requesting  an  incremental  dump,  the  user  may  specify  the
particular dictionary to dump.  This is allowed in two cases:

     1.  After some word has been  rejected,  the  command  "Wn"  will
         cause dictionary number n to be dumped.

     2.  During  the  exit  sequence,  the  command  "In"  will  cause
         dictionary number n to be dumped.


In all five cases above, if n is either 0 or omitted, then it will  be
taken as being 1.  




3.3  Caution!

There is no  provision  in  SPELL  for  remembering  which  dictionary
numbers  have  been used.  Therefore, it remains the individual user's
responsibility to remember the numbers of all the dictionaries that he
creates.    (Forgetting  the  number  will  mean  that  the  forgotten
dictionary can not be dumped incrementally.  The words in a  forgotten
dictionary  will  still be available, but the only way to actually get
them dumped out is to dump the entire dictionary).  




3.4  Hint:

In the course of correcting a file, it is  likely  that  you  will  be
asked  about  words  which you wish to have accepted during this file,
but  which  you  don't  wish  to  have  saved  in   your   incremental
dictionary(s).   In  these  cases, simply insert them in a "throwaway"
incremental dictionary which you don't  bother  to  dump  when  you're
finished.  




4.0  ABNORMAL CONDITIONS


While the program is running it  is  possible  that  certain  abnormal
conditions  may  obtain.  The usual response of the program is to type
some sort of error message.  The following is  a  list  of  the  error
messages in SPELL, with an indication of the severity of the error.  

     Illegal dictionary entry:  <word>
          This error occurs if an entry in a dictionary  file  exceeds
          40 (decimal) characters.  The word is ignored.
     0 LENGTH WORD AT HASHCP
          Somebody just asked to compute the hash address of an  empty
          word.   The program continues, but there is a possibility of
          error.
     HASHING ERROR
          Somebody asked for the hash address of a word  that  doesn't
          begin   with   letters   or  apostrophe  as  the  first  two
          characters.  This is a fatal error;  the program halts.
     DEVICE DATA ERROR (OUTPUT)
          This message means that  while  writing  a  file,  something
          screwed up.  The program halts.
     DEVICE ERROR (INPUT)
          The input file is screwed  up  in  some  way.   The  program
          halts.
     Internal confusion in the spelling checker.
     Called from location <loc>.
          The spelling checker has  discovered  a  (possible)  bug  in
          itself.   The program halts, but the user may type CONTINUE.
          Please note the location  mentioned  and  the  circumstances
          that evoked the message.
     Dictionary number too large, Maximum is 30.
          This message means that the user  attempted  to  select  for
          insertion  or  dumping  a  dictionary  beyond  the  range of
          allowed numbers.  The user will get another chance to do the
          right thing.
     Unrecognized switch.
          The user asked for an unknown switch.  He  must  repeat  the
          entire switch specification again.  

The following messages occur only in the non-TENEX version:

     Illegal Character in Scan.
          This is a message from the routine that  reads  file  names.
          You will be asked to try retyping the name.
     File not Found.  <filename>
          The indicated file could not be found.   The  user  gets  to
          specify some other file.  
     Enter failed on:  <file name>
          An enter uuo failed while trying  to  select  the  indicated
          file for output.  The user may specify another name.  
     Open Failed on Device <dev>:
          You asked for a device that doesn't exist or isn't available
          to  the program.  You will get a chance to ask for something
          else.  
     Insufficient Core Available.
          SPELL requires more core while expanding the dictionary  but
          none is available.  The program exits.  




5.0  INTERNAL WORKINGS

5.1  Data Structures - Hashing Function


The data structure is the heart of the program, and any efficiency  in
the  program  operation  is  due  primarily  to  this  choice  of data
structure.  The data structure is basically a hash coding scheme where
dictionary  entries are accessed by both their alphabetic order and by
their length.  There is a base table  that  contains  26  *  26  *  10
halfwords;   this  table  gives  anchors  for 6760 chains.  Each chain
contains exactly all words with the same two first  letters  and  some
given   length.    To   be   precise,   the   hashing   function   is:
(L1*26+L2)*10+min(WL-2,9), where L1 and L2 are numeric representations
of  the  first and second letters (A=0, B=1, ...  Z=25, and apostrophe
also is 25), and WL is the length of the word in characters.

This scheme was chosen since it provides  both  an  efficient  way  to
probe  the  dictionary and a quick way to select a small subset of all
words that are close to a given input word.




5.2  Data Structures - Dictionary Entry Format


Entries are  added  to  the  appropriate  hash  chain  by  the  INSERT
subroutine.   Entries  are  added to the head of the chain, saving the
time and effort of searching to the end of  the  chain.   This  scheme
means  that the last item entered on a chain is the first item seen by
a search.  The format of the entry is given by:

Word 0: xwd flags,nextlk
Word 1: 5 bit representation
Word 2: 5 bit representation
        ...

There are  precisely  1+ceiling(WL/7)  machine  words  used  for  each
dictionary  entry.   WL  is  the  length  of  the entry in characters.
Nextlk is the pointer to the next entry in the list, or zero  if  this
is  the  last in the chain.  The left side contains flags;  bits 13-17
specify the incremental  dictionary  number  (0  for  main,  1-30  for
incremental  dictionaries,  and 31 for misspellings).  One can imagine
that bits 5-12 could be used to store semantic information  about  the
entry.   The  unused  bytes in the last word of an entry must be zero,
since they are used to stop the routine that converts the five bit  to
7 bit.  

Misspellings are entered in the main dictionary with  the  incremental
dictionary  number  set  to  decimal  31.   If  a  word is marked as a
misspelling then the word preceding the  flags  and  link  contains  a
pointer to the flag and link word of the correction.  Misspellings may
be deleted before the full dictionary is  dumped,  or  whenever  SPELL
asks  about  saving  the  core  image.  The space obtained by deleting
misspellings is not reutilized at present, although that feature could
be added without great difficulty.  



5.3  Spelling Correction Heuristics


There are four kinds of errors that the program attempts to correct:

     1. one wrong letter.
     2. one missing letter.
     3. one extra letter.
     4. two transposed letters.

For a wrong letter in the third or  subsequent  character,  all  words
that are candidates must exist on the same chain that the suspect word
hashes to.  Hence, each entry on that chain is inspected to  determine
if  the suspect differs from the entry by exactly one character.  This
is accomplished by an exclusive-or (XOR) between the suspect  and  the
dictionary.   Then  a JFFO instruction selects the first non zero byte
in the XOR.  This byte is zeroed and if the result is  all  zero  then
the  dictionary word differs from the suspect in only one letter.  All
such words are listed at CANDBF, where they can be inspected later.  

For a wrong letter in the first or second character, the program tries
varying  the  second  letter through all 26 possible values, searching
for an exact match.  Then all 26 possible values of the  first  letter
are  tried,  after  setting  the  second letter to its original value.
This means that 52 more chains are searched for possible matches.  

To correct transposed letters, all combinations of transposed  letters
are  tried.   There  are  only WL-1 such combinations, so it is fairly
cheap to do that.  

To correct one extra letter, wl copies of the word are made, each with
some  letter  removed.   Each of these is looked up in the dictionary.
This takes WL searches.  

To correct one missing letter, WL+1 copies of the word are made,  each
time inserting a null character in a new position in the suspect.  The
null character is  never  part  of  any  word,  so  the  suspect  word
augmented  by  an  embedded  null can be thought of as a word with one
wrong letter (the null) then the  algorithm  for  matching  one  wrong
letter  is  used.   If the first character is omitted, all 26 possible
first characters are tried.  Also, 26 more words are formed by varying
the second character in case that had been omitted.  




6.0  ASSEMBLY & LOADING INSTRUCTIONS


There are three assembly time switches, TENEX, STANSW and  SANSW.   If
STANSW is set then there are SIXBIT ppn's and the SWAP UUO;  if STANSW
is zero, then normally there are octal ppn's except if SANSW  is  set,
in which case, there are decimal ppn's.  If the TENEX switch is set it
overrides the others and TENEX style file names are used.  Compile the
program  using MACRO or FAIL and load it.  The non-TENEX versions will
produce a sharable high segment and a non-sharable low segment.   When
you  start  the program the first time after loading, it will demand a
dictionary.  This dictionary will be read in as dictionary zero, which
is  the built-in dictionary for future use.  In the non-TENEX versions
dictionary zero is read into  the  sharable  high  segment.   Use  the
largest dictionary you have which meets your storage limitations.  The
file SPELLD.ALL is recommended.

When dictionary zero is loaded, SPELL will ask "Do you  wish  to  save
this  core image?" Answer "Yes" and save the resulting core image.  On
non-TENEX systems, do an SSAVE to  produce  a  sharable  high  segment
containing dictionary zero.

There are  various  other  assembly  switches,  but  they  default  to
reasonable settings, and you meddle with them at your peril.  



7.0  POSSIBLE EXPANSIONS


No program that is still in use is complete.  The following paragraphs
include suggestions of possible future work in this area.  

For non-paged systems, the  main  dictionary  (0)  should  be  in  the
sharable  segment  and  the  private  additions  in  the  non-sharable
segment.  This would require adjusting the hash chains to point across
the gap.

The dictionary should be expanded to include all  suffixes  for  every
word.   There  is  a  feature  that strips suffixes for the purpose of
finding the stem of the word in the dictionary, but this heuristic  is
error  prone and incompatible with later attempts to correct the word.

If semantic information were included in the dictionary, it could help
guide the selection of a correction.  

Either of these would require a major restructuring  of  the  program,
since  the  dictionary  would  no  longer  fit in core.  Probably, the
dictionary should be kept on the disk, with a data  structure  similar
to  the  one used in core, but arranged to keep each hash chain in the
minimum number of disk pages, so that searches through the  dictionary
can be made efficient.  


%
	SUBTTL	INITIALIZATION - OUTER LOOP
	PAGE

CRLF:	BYTE(7)15,12

START:	JFCL
	RESET				;BBN OR TOPS-10 RESET
IFN TENEX,<			;[Tops20] SEE IF RUNNING UNDER TOPS20
	CLEARB	3,4
	HRROI	1,3
	HRLOI	2,600015	; NOTHING DEVICE DESIGNATOR
	DEVST
	 CLEAR	3,3		; ASSUME TENEX IF FAILS
	CAME	3,[ASCII\NUL\]	; IS IT SPELLED ALA TOPS20?
	 SETCMI	4,37		; NO, MUST BE TENEX
	SETCAM	4,TNXEOL	; SAVE RESULT
	 >
	SETZM	NWA			;ZERO STATISTICS COUNTERS
	MOVE	A,[NWA,,NWA+1]
	BLT	A,NWEX
IFN TENEX,<	MOVEI	1,400000	;GET INITIAL RUNTIMES
		RUNTM
		IDIV	3,2		;CONVERT TO SECONDS
		MOVEM	3,REALTM
		IDIV	1,2
		MOVEM	1,CPUTIM >
ASTART:	MOVEI	FL,0			;FLAGS
	MOVE	P,[IOWD PDLEN,PDLIST]	;STACK

IFN TENEX,<	PUSHJ	P,INITX	>	;SPECIAL INITIALIZATION FOR TENEX
IFN STANSW,<	PUSHJ	P,INITST >	;SPECIAL INITIALIZATION FOR STANFORD DPYS

IFG COUNTS,<	MOVE	A,[XWD ICTAB,ICTAB+1]
		SETZM	ICTAB
		BLT	A,ICTABX
		MOVE	DEBX,[IOWD 2*%DTL,%DBT]	>

	MOVE	A,.JBFF	
	SKIPN	NDICT			;NOT REDEFINED IF DICT LOADED
	MOVEM	A,LISTFF		;SET FIRST FREE LOC FOR DICTIONARY
	SKIPN	NDICT			;IF EMPTRY, DON'T
	PUSHJ	P,LOADER		;NO DICTIONARY
IFE TENEX,<	SKIPN	NDICTI+1	;IF DEFAULT DICTIONARY (1) EMPTY
		PUSHJ	P,LOAD1A	;LOAD IT (FROM WORDS.DIC). MDA 790112
		MOVE	A,NDICTI+1	;SAVE NUMBER OF WORD IN DIC 1
		MOVEM	A,NDICT1	;FOR COMPARISON ON COMPLETION
		SKIPA >

;**;[W1] Remove one line at BEGIN0: + 0L
BEGIN0:	OUTSTR	[ASCIZ/Do you want to augment the dictionary? /]
	INCHWL	A			;WAIT FOR ANSWER
	PUSHJ	P,FLUTTY		;FLUSH TO NEXT DELIM
	TRZ	A,40			;MAKE SURE OF UPPER CASE

;**;[W1] Change one line and add one line at BEGIN0: + 4L
	CAIE	A,"Y"			;[W1]
	 JRST	BGIN02			;[W1] Answer is no, continue on
	PUSHJ	P,LOADER		;LOADING AUX
	JRST	BEGIN0			;OFF TO LOAD MORE.

BGIN02:	PUSHJ	P,RSWIT			;READ SWITCHES

BEGIN1:	OUTSTR	[ASCIZ/Name of the file to check and correct: /]
	TRO	FL,NOCORR!NOEXCP	;ASSUME NO OUTPUT.

IFN TENEX,<	PUSHJ	P,INDATA	;INITIALIZE DATA CHANNEL
		MOVEI	K,DATABF
		SETZB	L,M	>	;NO DEFAULTS

	PUSHJ	P,GETFIL		;GET A FILE NAME IN SOME WAY.
	JRST	ENDIT

IFE TENEX,<	PUSHJ	P,INDATA
		JRST	BEGIN1>

	LOOKUP	DATA,K
	JRST	[PUSHJ	P,FNOTFM
		JRST	BEGIN1]
IFE TENEX,<			;[decus] added conditional
		MOVEM	K,INBLK		;SAVE LOOKUP BLOCK
		MOVEM	L,INBLK+1	;IN CASE OUTPUT SPECIFIES
		MOVEM	M,INBLK+2	;CREATION OF A .BAK FILE
		MOVEM	N,INBLK+3>	;MDA 790112
	TRNE	FL,TRAIN
	JRST	BEGIN5			;NO OUTPUT OR EXCEPTIONS IF TRAINING

IFN TENEX,<	HRROI	1,LIBUF		;FIND NAME.EXT OF INPUT FILE
		MOVE	L,1		; AND USE FOR DEFAULT FOR OUTPUT
		HRRZ	2,DATABF+3	; AND EXCEPTION FILE
		HRLZI	3,(1B8)
		JFNS
		HRROI	1,LOBUF
		MOVE	M,1
		HRLZI	3,(1B11)
		JFNS		>

	TRNE	FL,QTRAIN		;OR SPECIAL TRAINING
	JRST	BEGIN3			;EXCEPTION IS NEEDED AND NO CORRECTIONS
BEGIN2:	OUTSTR	[ASCIZ /File name for correction output: /]

IFN TENEX,<	PUSHJ	P,INCORR
		MOVEI	K,CORRBF	;DEFAULT TO SAME AS INPUT FILE >
IFE TENEX,<	OUTSTR	[ASCIZ/ (CR for .BAK) /] >

	PUSHJ	P,GETFIL

IFN TENEX, <	JRST	[OUTSTR	[ASCIZ/No corrections.
/]
		JRST	BEGIN3] >
IFE TENEX,<	JRST	SETBAK		;NO NAME MEANS CREATE .BAK  MDA 790112
		PUSHJ	P,INCORR
		JRST	BEGIN2	>

	ENTER	CORR,K
	JRST	[PUSHJ	P,ENTFAI
		JRST	BEGIN2]
BEGN3A:	TRZ	FL,NOCORR		;THERE ARE CORRECTIONS
BEGIN3:	TRNE	FL,QTRAIN		;SPECIAL TRAINING?
	OUTSTR	[ASCIZ/
An exception file is needed.  /]
	OUTSTR	[ASCIZ/File for exceptions (or CR): /]

IFN TENEX,<	PUSHJ	P,INEXCP
		MOVEI	K,EXCPBF
		HRROI	M,[ASCIZ/EXCEPTIONS/]	;DEFAULT TO NAME.EXCEPTIONS >

	PUSHJ	P,GETFIL
	JRST	[TRNE	FL,QTRAIN
		JRST	BEGIN3			;OVER AND OVER.
		OUTSTR	[ASCIZ/No exception file.
/]
		JRST	BEGIN5]

IFE TENEX,<	PUSHJ	P,INEXCP
		JRST	BEGIN3	>

	ENTER	EXCP,K
	JRST	[PUSHJ	P,ENTFAI
		JRST	BEGIN3]
	TRZ	FL,NOEXCP			;THERE ARE EXCEPTIONS
BEGIN5:

IFN STANSW,<	MOVEM	FL,SAVEFL		;SAVE III AND DD FLAGS
		TRC	FL,NOCORR!NOEXCP
		TRCN	FL,NOCORR!NOEXCP	;SKIP IF EITHER CORR OR EXCP
		TLZN	FL,IIISW!DDDSW		;NO OUTPUT FILES. ACT LIKE TTY.
		JRST	.+2			;WE WERE A TTY, OR OUTPUT FILES.
		PUSHJ	P,DPYPOP		;SET DPY TO LARGER SIZE >

	OUTSTR	[ASCIZ/Working...
/]
	TRZ	FL,TECO!SHUTUP
	TRO	FL,FRSTOP		;FLAG UP FOR FIRST I/O ON DATA
	PUSHJ	P,LOOP			;GO OFF AND DO ALL THE WORK

IFN STANSW,<	MOVSI	A,IIISW!DDDSW
		AND	A,SAVEFL	;GET ORIGINAL STATE OF DISPLAY.
		IOR	FL,A		;AND SET FL FROM THAT>

	OUTSTR	[ASCIZ/Finished.
/]
IFE TENEX,<	MOVE	A,NDICT1	;HOW MANY WORDS AT START
		CAMGE	A,NDICTI+1	;COMPARED WITH NOW?
		JRST	DMPDEF	
		OUTSTR	[ASCIZ/No additions made to default dictionary.
/]
		JRST	ENDIT		;NONE ADDED
DMPDEF:		OUTSTR	[ASCIZ/Do you want to dump the default dictionary WORDS.DIC? /]
		INCHWL	A		;WAIT FOR ANSWER
		PUSHJ	P,FLUTTY	;FLUSH TO NEXT DELIM
		TRZ	A,40		;MAKE SURE OF UPPER CASE
		CAIE	A,"Y"
		JRST	ENDIT		;NO DEFAULT DUMP
		MOVE	K,[SIXBIT/WORDS/]
		MOVSI	L,'DIC'
		MOVEI	A,1		;DEFAULT DICTIONARY
		MOVEM	A,IDNUM		;NUMERO UNO
		SETZB	M,N
		PUSHJ	P,IDMPD1 >	;MDA 790112
ENDIT:	OUTSTR	[ASCIZ/Type E,S,C,A,D,I,N,/]
IFN COUNTS,<	OUTSTR	[ASCIZ/X,/]	>
	OUTSTR	[ASCIZ/ or ? /]
	TRZ	FL,TRAIN!QTRAIN		;EXIT TRAINING MODE
	INCHWL	A
	CAIL	A,"A"+40
	TRZ	A,40			;CONVERT TO UPPERCASE
	CAIE	A,"I"
	PUSHJ	P,FLUTTY		;FLUSH TTY EXCEPT FOR I COMMAND
	MOVSI	B,-NENDC
	LDB	C,[POINT 7,ENDCMD(B),35]
	CAIE	A,(C)
	AOBJN	B,.-2
	HLRZ	C,ENDCMD(B)
	PUSH	P,C			;SET JUMP ADDRESS ON STACK.
	LDB	A,[POINT 1,ENDCMD(B),18]
	JUMPE	A,CPOPJ			;JUMP UNLESS DISPLAY RESET REQUIRED
IFN STANSW,<	TLNE	FL,IIISW!DDDSW	;ON STANFORD DISPLAY?
		PUSHJ	P,DPYRST	;YES. RESET THE DISPLAY>
	POPJ	P,			;JUMP TO APPROPRIATE DISPATCH


ENDCMD:	ENDHLP,,"?"
	DOEXIT,,400000+"E"		;RESET DISPLAY
	SAVET,,400000+"S"
	XBEG.1,,400000+"C"
	ASTART,,400000+"A"
	D.END,,"D"
	I.END,,"I"
	N.END,,"N"
IFN COUNTS,<	DTRACE,,"X"	>
NENDC==.-ENDCMD
	ENDIT,,0			;HERE TO CATCH ERRORS


ENDHLP:	OUTSTR	ENDHM1
IFG COUNTS,<	OUTSTR	[ASCIZ/X	Dump the trace counts (for debugging only)
/]>
	OUTSTR	ENDHM2
IFE TENEX,<	OUTSTR [ASCIZ/ (Rewrites a file!)/] >
	OUTSTR	ENDHM3
	JRST	ENDIT

ENDHM1:	ASCIZ	/
Options are:
E	Exit
S	Save this core image
C	Correct another file
/

ENDHM2:	ASCIZ/A	Augment the dictionary and correct another file
D	Dump the dictionary to disk (writes a big, big file)
I	Write out user's dictionary with incremental insertions./

ENDHM3: ASCIZ /
N	Numbers (usage statistics) typeout
/

DOEXIT:	EXIT
	JRST	ENDIT		;IN CASE USER TYPES CONTINUE

I.END:	PUSHJ	P,SETNM1
	PUSHJ	P,IDMPD
	JRST	ENDIT

SAVET:	PUSHJ	P,SAVEME
	JRST	ENDIT

D.END:	PUSHJ	P,DUMPD
	JRST	ENDIT

N.END:	PUSHJ	P,STATS
	JRST	ENDIT

XBEG.1:	RESET
IFN TENEX,<	PUSHJ	P,INITX >
IFN STANSW,<	PUSHJ	P,INITST >
	JRST	BGIN02

	SUBTTL	SETBAK	INPUT FILE TO BECOME .BAK ON EXIT
	PAGE
IFE TENEX, <
DUM==11

SETBAK:	LDB	A,[POINT 3,INBLK+2,2]	;OWNERS' PROTECTION
	SUBI	A,2		;SHOULD PERMIT RENAME
	JUMPLE	A,STBK1		;IT DOES
	OUTSTR	[ASCIZ/Protection prevents input file rename!
/]
	JRST	BEGIN2		;GO ASK AGAIN
STBK1:	MOVE	K,['SPELLQ']	;TEMPORARY OUTPUT FILE
	MOVSI	L,'TMP'
	MOVEI	A,DATA		;DETERMINE DISK STRUCTURE
	HRRZM	A,DEVBLK	;OF INPUT FILE
	MOVE	A,[XWD 4,DEVBLK]
	PATH.	A,
	JRST	SETBK2
	MOVE	M,DEVBLK	;PUT OUTPUT ON SAME
	MOVEI	N,0
	PUSHJ	P,INCORR	;INITALIZE CORRECTION FILE
	JRST	SETBK2		;FAILURE
	MOVEM	K,BAKFLG	;LEAVE A FLAG THAT THIS IS A .BAK
	ENTER	CORR,K
	JRST	[PUSHJ	P,ENTFAI
		JRST	BEGIN2]
	MOVEM	K,CORBLK	;SAVE ENTER BLOCK FOR CORRECTION
	MOVEM	L,CORBLK+1	;OUTPUT FOR FUTURE RENAME
	MOVEM	M,CORBLK+2
	MOVEM	N,CORBLK+3
	JRST	BEGN3A

SETBK2:	OUTSTR	[ASCIZ/Unable to open SPELLQ.TMP on input structure.
/]
	JRST	BEGIN2		;GO ASK WHERE OUTPUT SHOULD BE PUT

DOBAK:	MOVE	K,INBLK		;INPUT FILE INFO
	MOVEM	K,CORBLK	;WILL BE USED TO RENAME
	MOVE	L,INBLK+1	;CORRECTION FILE
	HLLM	L,CORBLK+1
	MOVE	M,INBLK+2	;INPUT FILE PROTECTION
	LDB	A,[POINT 9,M,8]
	DPB	A,[POINT 9,CORBLK+2,8]
	MOVEI	N,0
	MOVEI	A,0		;PROTECTION OF .BAK FILE
	DPB	A,[POINT 3,M,2]	;CHANGED TO 0XX
	RENAME	DATA,K
	JRST	BAKERR
	MOVSI	A,'BAK'		;EXTENSION CHANGED 
	HLL	L,A		;TO BAK
	OPEN	DUM,DUMBLK
	JRST	BAKERR
	HLLM	L,INBLK+1	;EXISTING BAK FILE
	SETZM	,INBLK+2	;HAS TO BE DELETED
	SETZM	,INBLK+3
	LOOKUP	DUM,INBLK	;IS THERE ONE?
	JRST	RENAM1		;ASSUME NOT FOUND
	SETZM	,INBLK		;WIPE OUT NAME
	SETZM	,INBLK+1
	RENAME	DUM,INBLK	;DELETE IT
	JRST	BAKERR
RENAM1:	RENAME	DATA,K
	JRST	BAKERR
	CLOSE	DATA,
	RELEAS	DATA,
	RENAME	CORR,CORBLK	;ALL SET UP
	CLOSE	CORR,
	STATZ	CORR,740000	;CHECK FOR DEVICE ERROR
	JRST	BAKERR
	RELEAS	CORR
	JRST	FLOOP1		;GO REJOIN MAIN STREAM
BAKERR:	OUTSTR	[ASCIZ'Error renaming/closing files.
Enter .CLOSE and examine SPELLQ.TMP plus input file.
']
	EXIT
			>	;END IFE TENEX. MDA 790112


	SUBTTL	RSWIT	READ MODE SWITCHES FROM USER TERMINAL
	PAGE

RSWIT:
RSWIT0:	OUTSTR	[ASCIZ /Mode switches (zero or more of T,Q,N,U,P,A, or ?):  /]
	SETZM	UCASE			;ASSUME UPPERCASE IS NORMAL
	TRZ	FL,PICKUP!TRAIN!QTRAIN!NOSUFF!NOPREF
RSWIT1:	INCHWL	A
	CAIL	A,"A"+40
	TRZ	A,40
	MOVSI	B,-NSWCH
	CAME	A,SWTAB(B)
	AOBJN	B,.-1
	XCT	SWTAB1(B)		;IF SEARCH LOSES, XCT LOSE MESSAGE
	JRST	RSWIT1

SWTAB:	"P"
	"T"
	"Q"
	"N"
	"U"
	"A"
	"?"
IFN TENEX,<	CR	;[Tops20]
		LF	;[Tops20]
		33>	;[Tops20]
IFE TENEX,<	CR
		LF	>		;IFE TENEX
NSWCH==.-SWTAB

;ACTIONS TO BE XCTD FOR SWITCHES
SWTAB1:	TRO	FL,PICKUP		;P
	TRO	FL,TRAIN		;T
	TRO	FL,QTRAIN		;Q
	TRO	FL,NOSUFF		;N
	SETOM	UCASE			;U
	TRO	FL,NOPREF		;A FOR AFFIX?
	PUSHJ	P,SWHELP		;?
IFN TENEX,<	JRST	RSWRET		;[Tops20]
		JRST	RSWRET		;[Tops20]
		JRST	RSWRET>		;[Tops20]
IFE TENEX,<	JFCL			;CR - IGNORE
		JRST	RSWRET		;LF > ;IFE TENEX
	JRST	SWLOSE			;CATCH ERRORS HERE.

SWHELP: OUTSTR	SWHLPM			;TYPE HELP MESSAGE
	JRST	FLUTTY			;FLUSH LINE. RETURN TO GET A NEW LINE

SWLOSE:	OUTSTR	[ASCIZ /Unrecognized switch: /]
	OUTCHR	A
	OUTSTR	[ASCIZ/.  Try again!
/]
	PUSHJ	P,FLUTTY
	JRST	RSWIT0

RSWRET:	SETCM	A,FL			;CHECK IF BOTH T AND Q
	TRNE	A,TRAIN!QTRAIN	
	JRST	ASKU			;OK
	OUTSTR	[ASCIZ /Can't do both Training and Q-Training!  Try again!
/]
	JRST	RSWIT0			;TO DO IT RIGHT

ASKU:	SKIPN	UCASE		;UPPER CASE HACK?
	JRST	ASKP
	OUTSTR	[ASCIZ/  Dictionary number for uppercase words: /]
	PUSHJ	P,SETNM1
	MOVEM	B,UCASE		;SET DICTIONARY NUMBER FOR INSERTION
ASKP:	TRNN	FL,PICKUP
	JRST	ASKQT
	OUTSTR	[ASCIZ/  On what page do you want to pickup?  /]
	PUSHJ	P,INDEC		;READ DECIMAL FROM TERMINAL
	JUMPG	B,SETPG1
	OUTSTR	[ASCIZ/  Default is page 1
/]
	MOVEI	B,1
SETPG1:	MOVEM	B,PICKPG
	PUSHJ	P,FLUTTY
	OUTSTR	[ASCIZ/  and on what line do you want to start?  /]
	PUSHJ	P,INDEC		;READ DECIMAL LINE NUMBER
	JUMPG	B,SETLO2
	OUTSTR	[ASCIZ/  Default is line 1
/]
	MOVEI	B,1
SETLO2:	MOVEM	B,PICKLN
	PUSHJ	P,FLUTTY
ASKQT:	TRNN	FL,TRAIN!QTRAIN
	POPJ	P,
	OUTSTR	[ASCIZ/  Dictionary number for unrecognized words: /]
	PUSHJ	P,SETNM1
	MOVEM	B,TRDNUM		;DICT. # FOR TRAINING SET
	MOVE	A,NDICTI(B)		;NUMBER OF WORDS IN TRAINING
	MOVEM	A,NTRDCT		; DICT AT BEGINNING
	SETZM	NQTRN
	POPJ	P,

SWHLPM:	ASCIZ /
T  Training mode
Q  Q-Training mode
N  No Suffix removal
A  No Prefix removal
U  Upper case words are special
P  Pickup mode

Switches:  /
	SUBTTL	THE LOOP WHERE ALL THE WORK GETS DONE.
	PAGE

COMMENT %

	This file depicts what happens to a word as it is checked
and corrected by the spelling checker.

			 <begin>
			    I
			    V
			    O_--------------------------------------_O
			    I					     ^
			    V					     I
		----------------------------			     I
		I			   I			     I
O_-(if eof)_----I	read next word	   I			     I
I		I			   I			     I
I		I    lookup in dictionary  I--(if success: win)----->O
I		I			   I			     ^
I		I	(failure)	   I			     I
I		I			   I			     I
I		I   lookup as misspelling  I--(if success: correct)->O
I		I			   I			     ^
I		I	(failure)	   I			     I
I		I			   I			     I
I		I	call endtst	   I--(if success: win)----->O
I		I			   I			     ^
I		I	(failure)	   I			     I
I		I			   I			     I
I		I	call prefix	   I--(if success: win)----->O
I		I			   I			     ^
I		I	(failure)	   I			     I
I		I			   I			     I
I		I	call tryfix	   I			     I
I		I			   I			     I
I		I    (correct/accept word) I			     I
I		----------------------------			     I
I			    I					     I
I			    V					     I
I			    O--------------------------------------->O
I
V
O-------------------------->O
			    I
			    V
		----------------------------
		I			   I
		I	end sequence	   I
		I			   I
		----------------------------

%

LOOP:	ICOUNT
	PUSHJ	P,GETLIN
	JRST	FLOOP		;EOF ON DATA
	PUSHJ	P,CHKLIN	;CHECK/CORRECT LINE
	PUSHJ	P,PUTLIN	;OUTPUT LINE
	JRST	LOOP

FLOOP:
IFE TENEX, <	SKIPE	BAKFLG		;CREATING .BAK?
		JRST	DOBAK  >	;YES. MDA 790112
	CLOSE	DATA,		;YOU KNOW WHAT TO DO
	RELEAS	DATA,

	TRNE	FL,NOCORR
	JRST	FLOOP1		;JUMP IF NO CORRECTION FILE
	CLOSE	CORR,		;CLOSE OUTPUT CHANNEL
IFE TENEX,<	STATZ	CORR,740000	;CHECK IT
		JRST	DDE		;DEVICE DATA ERROR (OUTPUT) >
	RELEAS	CORR,

FLOOP1:	TRNE	FL,NOEXCP
	JRST FLOOP2
	CLOSE	EXCP,			;CLOSE EXCEPTIONS
IFE TENEX,<	STATZ	EXCP,740000	;CHECK IT
		JRST	DDE		;ERROR  >
	RELEAS	EXCP,
FLOOP2:	TRNN	FL,TRAIN!QTRAIN
	JRST	FLOOP4			;NOT EITHER TRAINING
	MOVE	B,TRDNUM		;TELL HIM HOW MANY WORDS WERE
	MOVE	A,NDICTI(B)		; ADDED TO THE TRAINING
	SUB	A,NTRDCT		; DICTIONARY
	PUSHJ	P,DECPTR
	OUTSTR	[ASCIZ/ words were added to dictionary #/]
	MOVE	A,TRDNUM
	PUSHJ	P,DECPTR
	SKIPE	A,NQTRN
	TRNN	FL,QTRAIN
	JRST	FLOOP3
	OUTSTR	[ASCIZ/, of which,
/]
	PUSHJ	P,DECPTR		;IF QTRAINING, TELL HIM HOW MANY
	OUTSTR	[ASCIZ/ possible misspellings were written in the exception file/]
FLOOP3:	OUTSTR	[ASCIZ/.
/]
FLOOP4:	POPJ	P,

	SUBTTL	GETLIN	READ A LINE OF DATA INTO LIBUF
	PAGE

GETLIN:	ICOUNT
	SETZM	LIBUF
	MOVE	A,[XWD LIBUF,LIBUF+1]
	BLT	A,LOBUF+LINSIZ-1	;CLEAR BOTH INPUT AND OUTPUT LINES
	PUSHJ	P,RDDATA
	POPJ	P,		;NON-SKIP AT EOF.
	AOS	LINENO		;COUNT LINES
	TRNE	FL,TECO		;ARE WE A TECO FILE?
	JRST	GETLTC		;GET A TECO LINE
	MOVE	B,[POINT 36,LIBUF]	;SET FOR WORD BY WORD
	JRST	GETLN2		;A IS SET WITH FIRST DATA
GETLN1:	ICOUNT
	HRRZ	A,B
	CAIL	A,LIBUF+LINSIZ	;IS LIBUF FULL?
	JRST	LOVFLW		;YES: COMPLAIN
	PUSHJ	P,RDDATA	;READ DATA (SKIP RETURN)
	POPJ	P,		;NOT GOOD MANNERS TO EOF 
				;IN THE MIDDLE OF A LINE
GETLN2:	ICOUNT
	IDPB	A,B		;SAVE THE DATA IN THE LINE
	ANDI	A,377		;MASK ALL BUT THE LAST 8 BITS
	LSH	A,-1		;A_THE FIFTH ASCIZ CHARACTER THAT HAD BEEN IN A,
				;RIGHT JUSTIFIED IN A.
	JUMPE	A,GETLN3	;END OF A LINE IN SOS FORMAT
	CAIE	A,LF		;OR LF WILL END A LINE
	JRST	GETLN1		;BACK FOR MORE OF THIS LINE
GETLN3:	ICOUNT
	MOVE	A,[XWD LIBUF,LOBUF]
	BLT	A,LOBUF+1	;COPY FIRST TWO MACHINE WORDS TO OUTPUT
				;WE WILL USE ONLY THE FIRST 6 CHARACTERS
				;THE LINE NUMBER AND THE TAB.
	MOVE	A,[POINT 7,LIBUF+1,6]	;SET TO GRAB THE FIRST REAL 
					;CHARACTER BY ILDB.
	MOVEM	A,INPTR			;SAVE AS THE "IN POINTER"
	HRRI	A,LOBUF+1		;FIX ADDRESS
	MOVEM	A,OUTPTR		;SAVE THE OUT POINTER
	TRNN	FL,PICKUP
	JRST	CPOPJ1			;AND GIVE A SKIP RETURN
	MOVE	A,PAGENO
	CAMGE	A,PICKPG
	JRST	CPOPJ1
	CAME	A,PICKPG
	JRST	[TRZ	FL,PICKUP
		JRST	CPOPJ1]
	MOVE	A,LIBUF
	TRZ	A,1
	CAML	A,PICKLN
	TRZ	FL,PICKUP
	JRST	CPOPJ1

;FOR TECO LINES
GETLTC:	ICOUNT
	MOVE	B,[POINT 7,LIBUF]
	JRST	GETEC1
GETTEC:	ICOUNT
	HRRZ	A,B
	CAIL	A,LIBUF+LINSIZ	;IS LIBUF FULL?
	JRST	LOVFLW		;YES: COMPLAIN
	PUSHJ	P,RDDATA
	POPJ	P,
GETEC1:	ICOUNT
	IDPB	A,B
	CAIE	A,LF
	CAIN	A,FF
	JRST	.+2
	JRST	GETTEC
	MOVE	A,[POINT 7,LIBUF]
	MOVEM	A,INPTR
	HRRI	A,LOBUF
	MOVEM	A,OUTPTR
	TRNN	FL,PICKUP		;PICKUP IN PROGRESS?
	JRST	CPOPJ1			;NOPE. RETURN NOW
	MOVE	A,PAGENO
	CAMGE	A,PICKPG
	JRST	CPOPJ1			;NOT YET TO THE RIGHT PAGE
	CAME	A,PICKPG
	JRST	GETEC2			;BEYOND PICKUP PAGE.  CLEAR PICKUP.
	MOVE	A,LINENO
	CAML	A,PICKLN
GETEC2:	TRZ	FL,PICKUP
	JRST	CPOPJ1
	SUBTTL	CHKLIN	CHECK EACH WORD FROM THE LINE
	PAGE
CHKLIN:	ICOUNT
	TRZ	FL,ERRLIN		;NO ERROR YET

IFN STANSW,<	TLNE	FL,IIISW	;DD IS TOO SLOW FOR THIS?
		PUSHJ	P,DPGL		;DISPLAY PAGE/LINE NUMBER >

CHKLN1:	ICOUNT
	PUSHJ	P,LDWORD		;GET A WORD
	JRST	CHKLN2			;NOT A WORD
	TRNE	FL,SHUTUP+PICKUP
	JRST	CHKL1A			;DON'T BOTHER
	PUSHJ	P,MATCH			;LOOK FOR IT
	JRST	CHKLN3			;WASN'T THERE
	JRST	DOMISS			;FOUND AS A MISSPELLING
	AOS	NWEX			;COUNT EXACT MATCH
CHKL1A:	ICOUNT
	PUSHJ	P,COPYIO		;COPY TO OUTPUT
	JRST	CHKLN1			;BACK FOR THE REST

CHKLN2:	ICOUNT
	PUSHJ	P,COPYIO
	JUMPE	A,CPOPJ			;SUPER NULL, EO LINE
	CAIN	A,14			;CHECK FOR FF
	JRST	[AOS	PAGENO		;COUNT ANOTHER PAGE.
		SETZM	LINENO
		POPJ	P,]
	CAIN	A,12	
	POPJ	P,			;LF - RETURN TO LOOP FOR CALL TO PUTLIN
	JRST	CHKLN1			;BACK FOR THE REST OF THE LINE

;HERE WHEN WORD LOOKUP FAILED.
CHKLN3:	ICOUNT
	PUSHJ	P,CONVRT		;MAKE ASCII APPEAR IN WORDIX, WE'LL NEED IT
	SKIPE	UCASE			;UPPER CASE ACCEPTANCE?
	TLNN	FL,UPPER		;YES. WAS IT REALLY UPPERCASE?
	JRST	CHKL3A			;NOT UPPERCASE OR NOT ACCEPTING UC (NORMAL)
	SKIPA	K,UCASE
CHKL3B:	MOVE	K,TRDNUM		;TRAINING DICTIONARY NUMBER
	MOVEM	K,IDNUM			;SET DICTIONARY NUMBER
	PUSHJ	P,HASHCP
	PUSHJ	P,INSERT		;ADD WORD TO TRAINING SET OR UC SET
	AOS	NWI			;COUNT WORD INSERTED
	JRST	CHKL1A
	

CHKL3A:	SETZM	CANDID			;ZERO THE CANDIDATE COUNT
	TRZ	FL,PREWIN!SUFWIN
	PUSHJ	P,ENDTST		;TRY REMOVING ENDINGS
	JRST	CHKL3E			;FAILED TO FIND WORD
	JRST	CHKL3D			;RECONSTRUCTED CANDIDATE FORMED
	JRST	CHKL3C			;ACCEPT WORD - ANNOUNCE WON VIA AFFIX HEUR.

CHKL3E:	PUSHJ	P,PREFIX		;TRY REMOVING PREFIXES AND ENDINGS TOO.
	JRST	CHKL3D			;NO THERE'S NO SIMPLE ANSWER
	JRST	CHKL3D			;RECONSTRUCTED CANDIDATE FORMED
CHKL3C:	AOS	NWAF			;COUNT AFFIX-MATCH
	TRNE	FL,TRAIN!QTRAIN!NOEXCP
	JRST	CHKL1A			;IF TRAINING, DON'T WRITE EXCEPTIONS
;HERE WE WRITE IN THE EXCEPTION FILE EACH WORD THAT MATCHED VIA
;AFFIX-STRIPPING.  WE WRITE THE WORD ITSELF AND ITS DERIVATION, WHICH
;INFORMATION IS CONTAINED IN STEM AND THE PREFIX/SUFFIX STACKS.
	MOVEI	B,[ASCIZ/  /]		;A COUPLE OF SPACES FOR READABILITY
	PUSHJ	P,WRSEXC
	MOVEI	B,WORDIX
	PUSHJ	P,WRSEXC
	MOVEI	B,14			;SPACE OUT TO COLUMN 16
	SUB	B,W
	JUMPLE	B,SPDONE
	MOVEI	A," "
	PUSHJ	P,WREXCP
	SOJG	B,.-1
SPDONE:	MOVEI	B,[ASCIZ/ = /]
	PUSHJ	P,WRSEXC
	MOVEI	B,PRESTK		;COPY OUT ANY PREFIXES
	TRZE	FL,PREWIN		;SKIP PREFIX-PRINTING IF NONE
PLOOP:	SKIPN	(B)
	JRST	PDONE			;NO MORE PREFIXES
	MOVE	C,[POINT 5,(B)]
PCOPY:	ILDB	A,C
	JUMPE	A,[	MOVEI	A,"+"
			PUSHJ	P,WREXCP
			AOJA	B,PLOOP]
	PUSHJ	P,COPY5
	JRST	PCOPY

PDONE:	MOVSI	B,(POINT 5,0)
	HRR	B,STEM			;BYTE PTR TO STEM
STEMLP:	ILDB	A,B
	JUMPE	A,STEMDN
	PUSHJ	P,COPY5
	JRST	STEMLP

STEMDN:	TRZN	FL,SUFWIN	;SKIP SUFFIX-PRINTING IF NO SUFFIX
	JRST	SUFDON
CLRZA:	TLZ	FL,ADDBIT!ZAPBIT	;CLEAR ADD/ZAP BITS
SUFPOP:	POP	M,B			;POP LETTER FROM SUFFIX STACK
	JUMPL	B,SUFDON		;END OF STACK MARKED WITH -1
	JUMPE	B,CLRZA			;0 MEANS A BREAK
	TRZN	B,40			;SKIP IF AN ADDED LETTER
	JRST	ADDING
	TLZ	FL,ADDBIT		;RESET ADDING-BIT
	TLOE	FL,ZAPBIT		;AND SET ZAPPING-BIT
	JRST	WRLET
	MOVEI	A,"-"			;NEED TO WRITE A "-" FIRST
	PUSHJ	P,WREXCP
	PUSH	P,[0]		;NEED TO REVERSE ORDER OF ZAPPED LETTERS
	PUSH	P,B		;BY MOVING THEM FROM M-STACK TO P-STACK
	POP	M,B		;THEN COPYING FROM P-STACK TO EXCP FILE
	TRZE	B,40
	JRST	.-3
	PUSH	M,B
	POP	P,A
	JUMPE	A,CLRZA
	PUSHJ	P,COPY5
	JRST	.-3

ADDING:	TLZ	FL,ZAPBIT
	TLOE	FL,ADDBIT
	JRST	WRLET
	MOVEI	A,"+"
	PUSHJ	P,WREXCP
WRLET:	MOVE	A,B
	PUSHJ	P,COPY5
	JRST	SUFPOP			;BACK FOR ANOTHER

COPY5:	CAIN	A,APOS
	SKIPA	A,["'"]
	ADDI	A,"A"-1
	PUSHJ	P,WREXCP
	POPJ	P,

SUFDON:	MOVEI	B,CRLF
	PUSHJ	P,WRSEXC
	JRST	CHKL1A

CHKL3D:	TRNE	FL,TRAIN		;SKIP UNLESS WE ARE TRAINING
	JRST	CHKL3B			;INSERT IN TRAINING SET
	TRNE	FL,QTRAIN
	JRST	CHKLN5			;OMIT EXCEPTION FILE IN Q-TRAIN
	PUSHJ	P,PERLIN		;PUBLISH ERROR LINE (INCL III CASE)
	MOVEI	B,WORDIX
IFN STANSW,<	TLNN FL,IIISW!DDDSW>
	OUTSTR	(B)
	PUSHJ	P,WRSEXC
	MOVEI	B,[ASCIZ /  /]
IFN STANSW,<	TLNN FL,IIISW!DDDSW>
	OUTSTR	(B)
	MOVEI	B,CRLF
	PUSHJ	P,WRSEXC
	TRNN	FL,NOCORR+SHUTUP	;SKIP IF HE DOESN'T WANT IT
CHKLN5:	PUSHJ	P,TRYFIX		;TRY TO FIX IT
	PUSHJ	P,COPYIO		;WORD WAS ACCEPTED (A, I, X)
	JRST	CHKLN1		;WORD WAS CHANGED (R,C) OR NEW DICT (L)

;PUBLISH ERROR LINE (TO TTY AND TO EXCEPTIONS)

PERLIN:	TROE	FL,ERRLIN		;LINE DONE BEFORE?
	JRST	PERLN1			;YES.
	PUSHJ	P,PPAGE			;PUBLISH PAGE
IFN STANSW,<	TLNN	FL,IIISW!DDDSW>
	OUTSTR	LIBUF			;PUBLISH LINE
	MOVEI	B,LIBUF
	PUSHJ	P,WRSEXC		;IN EXCEPTION FILE TOO
PERLN1:
IFN STANSW,<	TLNE	FL,DDDSW	;DISPLAY PAGE/LINE ON DD
		PUSHJ	P,DPGL
		TLNE	FL,IIISW!DDDSW
		PUSHJ	P,DPYLIN	;DISPLAY SPECIAL IF ON III>
	POPJ	P,


;HERE WHEN WE'VE FOUND A MISSPELLING AND KNOW THE CORRECTION
DOMISS:	TRNE	FL,QTRAIN!TRAIN		;SKIP IF NOT TRAINING
	JRST	CHKLN3
	PUSHJ	P,CONVRT	;5BIT FROM WORDIN TO 7BIT IN WORDIX
	HRRZ	X,-2(X)			;GET POINTER TO THE CORRECTION.
	ADDI	X,1			;POINT DIRECTLY AT THE TEXT
	MOVEM	X,CANDBX
	PUSHJ	P,PERLIN		;PRINT ERROR LINE
	MOVEI	B,WORDIX
	OUTSTR	(B)
	PUSHJ	P,WRSEXC
	MOVEI	B,[ASCIZ / ==> /]
	OUTSTR	(B)
	PUSHJ	P,WRSEXC
	MOVSI	Z,440500
	HRR	Z,CANDBX
	PUSHJ	P,CONVRZ		;(CANDBX) TO WORDIX, 5BIT TO 7BIT
	MOVEI	B,WORDIX
	OUTSTR	(B)
	PUSHJ	P,WRSEXC
	TLNN	FL,ODD
	JRST	DOMIS1
	MOVEI	B,[ASCIZ / Corrected word may have some letters in the wrong case /]
	OUTSTR	(B)
	PUSHJ	P,WRSEXC
DOMIS1:	MOVEI	B,CRLF
	OUTSTR	(B)
	PUSHJ	P,WRSEXC
	PUSHJ	P,TRFXR2		;SUBSTITUTE THE CORRECTION
	JFCL				;ALWAYS SKIPS
	JRST	CHKLN1

	SUBTTL	PUTLIN	WRITE LINE TO CORRECTION FILE.  CONVRT,CONVRZ,PPAGE
	PAGE
PUTLIN:	TRNE	FL,NOCORR
	POPJ	P,			;AVOID NEEDLESS HASSLE
	TRNE	FL,TECO
	JRST	PUTLN2			;CHARACTER AT A TIME FOR NON-SOS
	MOVE	B,[POINT 36,LOBUF]
PUTLN1:	ILDB	A,B
	PUSHJ	P,WCORR0
	ANDI	A,376			;NULL CHARACTER AT END OF WORD?
	JUMPE	A,CPOPJ
	CAIE	A,12*2			;OR LF AT END OF WORD? (SHIFTED 1 BIT)
	JRST	PUTLN1
	POPJ	P,

;FOR TECO LINES
PUTLN2:	MOVE	B,[POINT 7,LOBUF]
PUTLN3:	ILDB	A,B
	PUSHJ	P,WCORR0
	CAIE	A,LF
	CAIN	A,FF
	POPJ	P,
	JRST	PUTLN3


;WRITE A BYTE IN THE CORRECTION FILE
WRCORR:	TRNE	FL,NOCORR
	POPJ	P,
WCORR0:					;[SOS]{
IFN TENEX,<	TRNE	FL,TECO
		 JRST	WCORR2		; NON-SOS
		PUSH	P,A
		MOVNI	A,4		; SPECIAL ACCOUNTING FOR SOS FILES
		ADDM	A,CORRBF+2
		POP	P,A
WCORR2:	>
	SOSLE	CORRBF+2		;[SOS]}
	JRST	WCORR1

IFE TENEX,<	OUTPUT	CORR,
		STATZ	CORR,740000
		JRST	DDE	>

IFN TENEX,<	MOVEI	K,CORRBF
		PUSHJ	P,@7(K)	>
IFN TENEX,<				;[SOS]{
		TRNE	FL,TECO		; HAVE WE AN SOS FILE?
		 JRST	WCORR1		; NO
		PUSH	P,A
		MOVSI	A,(<POINT 36,>)	; YES, SETUP WORD POINTER
		HLLM	A,CORRBF+1
		POP	P,A>		;[SOS]}

WCORR1:	IDPB	A,CORRBF+1
	POPJ	P,



;WRITE A STRING (PTR IN B) IN THE EXCEPTION FILE
WRSEXC:	HRLI	B,(<POINT 7,0>)
	TRNE	FL,NOEXCP
	POPJ	P,
WRSEX0:	ILDB	A,B
	JUMPE	A,CPOPJ
	PUSHJ	P,WEXCP0
	JRST	WRSEX0

;WRITE A BYTE IN THE EXCEPTION FILE
WREXCP:	TRNE	FL,NOEXCP
	POPJ	P,
WEXCP0:	SOSLE	EXCPBF+2
	JRST	WEXCP1

IFE TENEX,<	OUTPUT	EXCP,
		STATZ	EXCP,740000
		JRST	DDE	>

IFN TENEX,<	MOVEI	K,EXCPBF
		PUSHJ	P,@7(K)	>

WEXCP1:	IDPB	A,EXCPBF+1
	POPJ	P,

;WRITE A BYTE IN THE DICTIONARY FILE
WDICT:	ICOUNT
	SOSLE	DICTBF+2
	JRST	WDICT1

IFE TENEX,<	OUTPUT	DICT,
		STATZ	DICT,740000
		JRST	DDE	>

IFN TENEX,<	MOVEI	K,DICTBF
		PUSHJ	P,@7(K)	>

WDICT1:	IDPB	A,DICTBF+1
	POPJ	P,

;COPY FROM LIBUF (INPTR) TO LOBUF (OUTPTR) TIL INPTR=INPTR1
COPYIO:	ICOUNT
	MOVE	Z,INPTR
COPYI1:	ICOUNT
	HRRZ	A,OUTPTR
	CAIL	A,LOBUF+LINSIZ	;IS LOBUF FULL?
	JRST	LOVFLW		;YES: COMPLAIN
	ILDB	A,Z
	IDPB	A,OUTPTR
	CAME	Z,INPTR1
	JRST	COPYI1
	MOVEM	Z,INPTR
	POPJ	P,

;COPY 5-BIT IN WORDIN TO ASCIZ IN WORDIX, USING THE CASE INFO IN CASEBT
CONVRT:	ICOUNT
	MOVE	Z,[POINT 5,WORDIN]
CONVRZ:	MOVE	Y,[POINT 7,WORDIX]	;ENTER HERE WITH Z SETUP.
	TLNN	FL,ODD			;ODD CASE?
	JRST	CONVRA			;NO. USE SIMPLE RULES FOR DISPLAY
	PUSH	P,B
	PUSH	P,C
	MOVE	B,[POINT 1,CASEBT]
CONVR1:	ILDB	A,Z
	JUMPE	A,CONVR2
	ILDB	C,B		;GET CASE BIT FOR THIS CHAR
	CAIN	A,APOS
	JRST	[MOVEI	A,"'"
		JRST	CONVR2]
	ADDI	A,"A"-1
	JUMPE	C,CONVR2
	ADDI	A," " 		;SET LOWERCASE
CONVR2:	IDPB	A,Y
	JUMPN	A,CONVR1
	POP	P,C
	POP	P,B
	POPJ	P,

CONVRA:	PUSH	P,FL
CONVA1:	ILDB	A,Z
	JUMPE	A,CONVA2
	CAIN	A,APOS
	JRST	[MOVEI	A,"'"
		JRST	CONVA2]
	ADDI	A,"A"-1
	TLNE	FL,LOWER	;LOWERCASE?
	ADDI	A," " 		;YES. SET LOWERCASE
	TLZE	FL,MIXED	;MIXED CASE?
	TLO	FL,LOWER	;YES. AFTER FIRST CHARACTER SET LOWER
CONVA2:	IDPB	A,Y
	JUMPN	A,CONVA1
	POP	P,FL
	POPJ	P,


;PRINT PAGE AND LINE NUMBER ON TTY AND IN EXCEPTION FILE
PPAGE:	MOVEI	B,[ASCIZ/Page /]
IFN STANSW,<	TLNN FL,IIISW!DDDSW>
	OUTSTR	(B)
	PUSHJ	P,WRSEXC
	MOVE	A,PAGENO
	PUSHJ	P,DECPB
	TRNN	FL,TECO
	JRST	PPAGE1			;JUMP IF SOS FILE
	MOVEI	B,[ASCIZ/:/]
IFN STANSW,<	TLNN	FL,IIISW!DDDSW>
	OUTSTR	(B)
	PUSHJ	P,WRSEXC
	MOVE	A,LINENO		;GET LINE NUMBER
	PUSHJ	P,DECPB
PPAGE1:	MOVEI	B,CRLF
IFN STANSW,<	TLNN	FL,IIISW!DDDSW>
	OUTSTR	(B)
	JRST	WRSEXC			;WRITE IN EXCEPTION FILE AND RETURN

DECPB:	ICOUNT
	IDIVI	A,12
	PUSH	P,B
	SKIPE	A
	PUSHJ	P,DECPB
	POP	P,A
	ADDI	A,"0"
IFN STANSW,<	TLNN FL,IIISW!DDDSW>
	OUTCHR	A
	JRST	WREXCP
	SUBTTL	LDWORD	LOAD WORD FROM INPUT LINE
	PAGE
;THIS VERSION DOESN'T ALLOW WORD-INITIAL OR WORD-FINAL APOSTROPHES.
;MAKES A TABLE, CASEBT, OF THE CASE OF EACH CHARACTER, TO ALLOW
;REASONABLE DISPLAYS LATER.  ALSO, SETS A FLAG, ODD, IF WORD IS NOT
;UPPER,LOWER OR MIXED
;SKIP RETURN IF IT HAS GOBBLED A REAL WORD, NONSKIP RETURN IF
;NOT A WORD.  (STRINGS OF LETTERS AND NUMBERS, LIKE "K9", ARE CONSIDERED
;NONWORDS.)

LDWORD:	ICOUNT
	TLZ	FL,ODD!UPPER!LOWER!MIXED	;ASSUME NOTHING ABOUT CASE
	SETZM	WORDIN
	MOVE	Z,[XWD WORDIN,WORDIN+1]
	BLT	Z,WORDIN+5
	SETZM	CASEBT				;CASE BITS
	SETZM	CASEBT+1			;ZERO = UPPER CASE, 1=LOWER
	MOVE	Z,[POINT 1,CASEBT]		;POINTER TO CASEBT
	MOVEM	Z,CASEPT			;SAVE IT.
	MOVE	Z,INPTR
	MOVE	Y,[POINT 5,WORDIN]
	SETZB	W,LETCNT			;CHARACTER COUNT.
LDWRD1:	MOVEI	B,0				;ASSUME UPPERCASE
	ILDB	A,Z				;READ A CHARACTER
	CAIL	A,"A"+40
	CAILE	A,"Z"+40
	JRST	.+2				;NOT LOWERCASE
	AOJA	B,LDWRD2			;ACCEPT LOWERCASE
	CAIL	A,"A"
	CAILE	A,"Z"
	JRST	.+2		;NOT A LETTER.
	JRST	LDWRD2		;UPPERCASE LETTER
	CAIE	A,"'"		;APOSTROPHE?
	JRST	LDWRD6		;NOT A LETTER AT ALL. END OF A WORD?
	TLNN	FL,ODD!UPPER!LOWER!MIXED	;IS "'", AT BEGINNING?
	JRST	LDWRD7		;YES - WE DON'T ALLOW THAT
	MOVE	A,Z
	ILDB	A,A		;GET NEXT CHR - IS IT A LETTER?
	CAIL	A,"A"
	CAILE	A,"Z"
	JRST	.+2
	JRST	LDWR1A		;YES, MEANING "'" IS INSIDE A WORD
	CAIL	A,"A"+40
	CAILE	A,"Z"+40
	JRST	LDWR6A		;WE DON'T ALLOW WORD-FINAL EITHER
LDWR1A:	MOVEI	A,APOS		;SET CODE FOR APOSTROPHE.
LDWRD2:	IDPB	A,Y
	BCHECK(Y,WORDIN+10)
	IDPB	B,CASEPT	;STUFF CASE BIT
	MOVEM	Z,INPTR1	;BYTE POINTER TO LAST BYTE (SO FAR) OF WORD.
	ADDI	W,1		;COUNT CHARACTER SEEN.
	CAILE	W,50		;CAN'T EXCEED 40 (DECIMAL) CHARACTERS
	JRST	LDWRDX		;TELL USER.
	TLNN	FL,ODD		;CASE HOPELESS ALREADY?
	CAIN	A,APOS		;NO. APOSTROPHE?
	JRST	LDWRD1		;APOSTROPHE OR WORD CASE ALREADY SCREWED UP.
	TRNN	A,40		;SKIP IF LOWERCASE.
	JRST	LDWRD4		;UPPER
	TLNE	FL,LOWER!MIXED	;LOWER SEEN.  LOWER OR MIXED SET?
	JRST	LDWRD1		;YES.  NO CHANGE NEEDED.
	TLNN	FL,UPPER	;
	JRST	LDWRD3		;FIRST LETTER SEEN IN WORD.  SET LOWER
	SOSE	LETCNT
LDWRD5:	TLOA	FL,ODD		;LOWERCASE SEEN AFTER MORE THAN 1 UPPERCASE.
	TLC	FL,UPPER!MIXED	;LOWER SEEN AFTER PRECISELY 1 UPPER. MIXED_1 UPPER_0
	JRST	LDWRD1		;DONE.

LDWRD3:	TLO	FL,LOWER	;SET LOWERCASE
	JRST	LDWRD1

LDWRD4:	AOS	LETCNT		;COUNT UPPERCASE CHARACTERS.
	TLNE	MIXED!LOWER	;SKIP UNLESS SCREWED
	JRST	LDWRD5		;UPPER SEEN AFTER LOWER OR MIXED
	TLO	FL,UPPER	;SET UPPERCASE SEEN
	JRST	LDWRD1

LDWRD6:	TLNN	FL,ODD!UPPER!LOWER!MIXED
	JRST	LDWRD7		;JUMP IF THIS IS NON-LETTER AT BEGINNING OF A WORD
LDWR6A:	TLNE	FL,ODD		;IF CASE IS STRANGE,
	TLZ	FL,MIXED!UPPER!LOWER	;MUST CLEAR BITS WHICH MAY HAVE BEEN LEFT ON
	CAIL	A,"0"		;DIGITS MEAN NOT-WORDS BUT ARE NOT DELIMITERS.
	CAILE	A,"9"
	JRST	CPOPJ1		;WE HAVE A DELIM.  WE HAVE SEEN A WORD.
LDWRD7:	MOVEM	Z,INPTR1	;WHATEVER WE HAVE, IT'S NOT A WORD
				;SO PUT THE POINTER PAST IT.
	CAIL	A,"A"		;TEST FOR A DELIMITER
	CAILE	A,"z"
	JRST	LDWRD8		;MAYBE A DELIM
	CAILE	A,"Z"
	CAIL	A,"a"
	JRST	LDWRD9		;NOT A DELIM
LDWRD8:	CAIL	A,"0"
	CAILE	A,"9"
	POPJ	P,		;THIS IS A DELIM BUT NOT A WORD
LDWRD9:	ILDB	A,Z		;NOT A DELIM
	JRST	LDWRD7		;FLUSH TO A DELIMITER

LDWRDX:	MOVEI	B,[ASCIZ/Error - input word too long - will be ignored
/]
	OUTSTR	(B)
	TRNN	FL,TRAIN!QTRAIN
	PUSHJ	P,WRSEXC	;WRITE IN EXCEPTIONS.
LDWRX1:	PUSHJ	P,CONVRT	;MAKE THE OFFENDING WORD ASCII
	MOVEI	B,WORDIX
	OUTSTR	(B)
	TRNN	FL,TRAIN!QTRAIN
	PUSHJ	P,WRSEXC
	MOVE	Z,INPTR1
LDWRX2:	ILDB	A,Z		;NOT A DELIM
	MOVEM	Z,INPTR1
	OUTCHR	A
	TRNN	FL,TRAIN!QTRAIN
	PUSHJ	P,WREXCP
	CAIL	A,"A"		;TEST FOR A DELIMITER
	CAILE	A,"z"
	JRST	LDWRX3		;MAYBE A DELIM
	CAILE	A,"Z"
	CAIL	A,"a"
	JRST	LDWRX2		;NOT A DELIM
LDWRX3:	CAIL	A,"0"
	CAILE	A,"9"
	SKIPA	B,[CRLF]	;THIS IS A DELIM BUT NOT A WORD
	JRST	LDWRX2
	OUTSTR	(B)
	TRNN	FL,TRAIN!QTRAIN
	PUSHJ	P,WRSEXC
	POPJ	P,
	SUBTTL	RDDATA THE READING ROUTINE
	PAGE

RDDATA:					;[SOS]{
IFN TENEX,<	MOVNI	A,4		; SPECIAL ACCOUNTING FOR SOS
		TRNN	FL,TECO
		 ADDM	A,DATABF+2>
	SOSLE	DATABF+2		;[SOS]}
	JRST	RDATA1
IFE TENEX,<	INPUT	DATA,
		STATZ	DATA,740000
		JRST	DIE
		STATZ	DATA,20000
		POPJ	P,		>;IFE TENEX

IFN TENEX,<	MOVEI	K,DATABF
		PUSHJ	P,@7(K)
		POPJ	P,		>;IFN TENEX

	TRZE	FL,FRSTOP
	JRST	CKTECO		;CHECK FOR A TECO FILE.
RDATA1:	ICOUNT
IFN TENEX,<	MOVSI	A,(<POINT 36,>)	;[SOS]{
		TRNN	FL,TECO
		 HLLM	A,DATABF+1>	;[SOS]}
	ILDB	A,DATABF+1
	JUMPE	A,RDDATA	;BACK FOR MORE IF NULL
	JRST	CPOPJ1

CKTECO:	MOVEI	A,1		;SINCE WE ARE AT FIRSTOP, WE MIGHT AS
	MOVEM	A,PAGENO	;WELL INITIALIZE THE PAGE COUNT
	SETZM	LINENO		;AND ZERO THE LINE NUMBER

IFN TENEX,<	MOVE	A,@DATABF+1
		TRNN	A,1
		TRO	FL,TECO	>

IFE TENEX,<	PUSH	P,B
		MOVE	B,DATABF+1
		ILDB	A,B
		TRNE	A,1
		JRST	CKTEC8		;SOS FILE. PRESERVE LINE NUMBERS
		SETZM	TVE		;ASSUME NOT TV/E FORMAT
		CAME	A,[ASCII/COMME/]
		JRST	CKTEC9
		ILDB	A,B
		CAMN	A,[ASCII/NT  /]
		SETOM	TVE
CKTEC9:		TRO	FL,TECO		;UNNUMBERED FILE. TECO OR TV/E FORMAT
		MOVEI	A,5
		IMULM	A,DATABF+2	;MAKE WORD COUNT INTO CHAR COUNT
		MOVSI	A,000700	;WHEN ILDB HITS THIS YOU GET THE
					;RIGHT BYTE, (FROM THE NEXT WD)
		HLLM	A,DATABF+1	;UPSET THE BYTE POINTERS
		SETSTS	DATA,1		;CHANGE MODES 
;WE ALSO HAVE TO CHANGE THE MODE OF THE CORR CHANNEL
;SO THAT IT WILL ACCEPT CHARACTER AT A TIME BYTE POINTERS.
		TRNN	FL,NOCORR	;SKIP IF NO CORRECTION FILE.
		SETSTS	CORR,1		;HAVE TO SCREW AROUND WITH BYTE POINTERS
		HLLM	A,CORRBF+1 	;SINCE OUTBUF HAS ALREADY SET THEM
		SKIPN	TVE		;TVE FILE?
		JRST	CKTEC8		;NO.
		OUTSTR	[ASCIZ ?TV/E directory page will be deleted.
Page 2
?]
		AOS	PAGENO
		AOS	DATABF+2	;MAKE THE COUNT BE 1 TOO BIG FOR RDDATA
CKTEC0:		PUSHJ	P,RDDATA	;CALL MAIN READER AGAIN
		JRST	[OUTSTR [ASCIZ/Unexpected end of file while skipping the directory.
/]
			POP P,B
			POPJ P,]
		CAIE	A,14		;FF YET?
		JRST	CKTEC0		;NO. READ MORE
CKTEC8:		POP	P,B
>;IFE TENEX

	TRNE	FL,PICKUP		;IF PICKUP
	TRNE	FL,TECO			;AND NON-TECO (MEANING SOS) FILE
	JRST	CKTEC4
	MOVE	A,PICKLN		;NEED TO CONVERT PICKLN TO
	MOVE	C,[ASCIZ /00000/]	;SOS-STYLE LINE NUMBER
	PUSHJ	P,SOSCVT
	MOVEM	C,PICKLN
CKTEC4:	SKIPN	TVE		;SKIP IF TV/E FILE
	JRST	RDATA1
	SETZM	TVE
	JRST	RDDATA		;FOR TV/E WE HAVE TO SOS THE COUNT AGAIN

INDEC:	MOVEI	B,0
INDEC1:	INCHWL	A
	CAIL	A,"0"
	CAILE	A,"9"
	POPJ	P,
	IMULI	B,12
	ADDI	B,-"0"(A)
	JRST	INDEC1

SOSCVT:	IDIVI	A,12		;CONVERT LINE NUMBER (IN A) TO
	HRLM	B,(P)		;SOS-STYLE (IN C)
	JUMPE	A,.+2
	PUSHJ	P,SOSCVT
	HLRZ	A,(P)
	ADDI	A,"0"
	LSH	C,7
	LSH	A,1
	OR	C,A
	POPJ	P,
	SUBTTL	DESCRIPTION OF ENDTST
	PAGE
COMMENT/

SKIP  RETURN  SIGNIFIES  THAT  THE  WORD  IS ACCEPTED; NON SKIP MEANS
REJECTION.  IN  EITHER  CASE,  THE  RETURN  WILL  BE MADE SO THAT THE  
ORIGINAL WORD IS RESTORED (IN FIVEBIT) TO WORDIN.

These are the cases ENDTST aspires to handle.  Lower
case letters are literal, V means vowel, C means consonant, and C2
means a consonant which may double before a suffix that begins with
a vowel (see ISC2).  Once a stem is found, it is rejected if it is less
than 3 characters long, or if 3 characters, contains no vowel (or Y).

					ENDFIXes
EDT.S:	-s		craps		Cys -> Cies		*candys
					invalid -s plural	*hashs
	-'s		John's
	-es		wrenches	invalid -es plural
	-Cy -> -Cies	candies

EDT.G:	-e -> -ing	liking
	-ing		doing		Ceing -> Cing		*takeing
					C2 doubling needed
	-C2 -> -C2C2ing	winning

EDT.T:	(-est, -er, and -ed behave identically)
EDT.R:
EDT.D:	-e -> -ed	liked
	-ed		knocked		Cyed -> Cied		*relyed
					C2 doubling needed
	-Cy -> -Cied	candied
	-C2 -> -C2C2ed	fitted

EDT.E:	-ive		restive
	-e -> -ive	abusive

EDT.H:	-th		sixth
	-y -> -ieth	twentieth

EDT.N:	-e -> -en	spoken
	-en		dampen
	-C2 -> -C2C2en	redden
	-Ct -> -Ction	rejection
	-Vte -> -Vtion	ignition
	-y -> -ication	magnification

EDT.Y:	-ty		loyalty, chatty
	-e -> -ity	activity
	-ity		formality
	-ble -> -bility	possibility

EDT.LY:	-ble -> -bly	probably
	-ly		lovely
	-c -> -cally	basically

EDT.SS:	-ness		kindness
	-less		heartless
	-y -> -iness	happiness
	-y -> -iless	penniless

/
	SUBTTL	ENDTST	TEST THE SUSPECT WORD BY REMOVING THE ENDINGS
	PAGE

;RETURNS TO CALL+1 IF NO MATCH COULD BE ACHIEVED BY SUFFIX-STRIPPING
;		+2 IF A RECONSTRUCTED WORD HAS BEEN PUT IN CANDBF
;		   (THIS CAN HAPPEN 2 WAYS: A STEM WAS RECOGNIZED AS A
;		    MISSPELLING, AND THE CORRECTION HAD THE PREFIXES
;		    AND SUFFIXES PUT BACK ON, OR A SPECIFIC ERROR WAS
;		    RECOGNIZED (E.G., DOUBLED-CONSONANT MISSING), AND
;		    THE SAME SORT OF THING WAS DONE.)
;		+3 IF SUFFIX-STRIPPING ALLOWED A MATCH
;SETS UP M AS SUFFIX STACK POINTER

DEFINE GETLST(N) <LDB A,GETLBT+N(W)>  ;LOAD A WITH LAST+NTH BYTE OF WORD

ENDSRT:	ICOUNT
	PUSHJ	P,ISSTEM	;MAKE SURE LEFT WITH VALID STEM
	JRST	ENDFRT		;STEM NOT VALID!
	AOS	(P)		;SET +3 RETURN
	TRO	FL,SUFWIN	;FLAG SUFFIX REMOVAL WON
	JRST	ENDSR1

ENDFIX:	MOVE	A,[WORDIN,,RECON]	;MOVE THE "FIXED" WORD FROM
	BLT	A,RECON+5		;WORDIN TO RECON, AND FIX STEM
	MOVEI	A,[RECON-1]+2		;TO MAKE RECON LOOK LIKE A
	MOVEM	A,STEM			;CORRECTION STRING
ENDMSP:	TRO	FL,SUFWIN
	PUSHJ	P,RECONS		;GO MAKE A RECONSTRUCTED WORD
ENDSR1:	AOS	(P)			;SET +2 RETURN
ENDFRT:	ICOUNT			;ON FAILURE, NO SKIP RETURN.
	JRST	UNSVWD		;RESTORE WORD AND SIZE, RETURN

;ENTRY FOR SUFFIX REMOVAL

ENDTST:	ICOUNT
	TRNN	FL,NOSUFF	;SKIP SUFFIX TEST IF REQUESTED.
	CAIG	W,3		;IF TOO SMALL THEN
	POPJ	P,		;RETURN QUICK WITH FAILURE
	PUSHJ	P,SAVWD		;SAVE WORDIN AND W,(IN A PLACE KNOWN
				;TO BUT A FEW).
	MOVE	M,[IOWD SUFLEN,SUFSTK]	;INITIALIZE SUFFIX STACK
	PUSH	M,[-1]		;MARK TOP OF STACK WITH -1
ENDTG.:	GETLST			;GET LAST LETTER INTO A.
	CAIN	A,S5		;IS IT S?
	JRST	EDT.S		;YES: GO CHECK FOR PLURAL/POSSESSIVE
ENDTGO:	ICOUNT
	PUSH	M,[0]		;PUT A BREAK ON THE SUFFIX STACK
	GETLST
	CAIN	A,G5		;MAYBE AN "ING"
	JRST	EDT.G
	CAIN	A,D5		;"ED"
	JRST	EDT.D
	CAIN	A,R5		;"ER"
	JRST	EDT.R
	CAIN	A,E5		;"IVE"
	JRST	END.E
	CAIN	A,T5		;"EST"
	JRST	EDT.T
	CAIN	A,H5		;"TH"
	JRST	EDT.H
	CAIN	A,N5		;"EN", "TION", AND "ICATION"
	JRST	EDT.N
	CAIN	A,Y5		;"LY", "TY", "ITY", "BILITY"
	JRST	EDT.Y
	CAIN	A,S5		;"NESS" AND "LESS"
	JRST	EDT.SS
	JRST	ENDFRT		;LAST LETTER DOESN'T SUGGEST ANY SUFFIXES

EDT.S:	ICOUNT
	PUSHJ	P,ZLAST		;TRY SINGULAR FORM
	PUSHJ	P,MATCH
	JRST	.+3		;FAILURE
	JRST	ENDMSP		;MISSPELLING
	JRST	EDT.S1		;SUCCESS - VERIFY WE DID A GOOD THING.
	GETLST
	CAIN	A,APOS			;"'S" ?
	JRST	[PUSHJ	P,ZLAST		;YES. FLUSH APOSTROPHE AND SEARCH AGAIN
		PUSHJ	P,MATCH
		JRST	ENDTGO		;TRY SUFFIX REMOVAL ON REDUCED WORD
		JRST	ENDMSP		;MISSPELLING
		JRST	ENDSRT]		;SUCCESS.

	CAIE	A,E5
	JRST	[CAIE	A,S5	;MAYBE ...NESS?
		JRST	ENDTGO	;NO BACK THRU LIST
		JRST	ENDSS]	;OFF TO TRY IT

	PUSHJ	P,ZLAST		;WIPE OUT THE E
	PUSHJ	P,MATCH
	JRST	ITOY1
	JRST	ENDMSP		;MISSPELLING
	JRST	EDT.ES		;CHECK THAT "-ES" PLURAL IS OK
ITOY1:	GETLST
	CAIE	A,I5
	JRST	ENDFRT		;QUIT
;HAVE FOUND A FINAL "I".  TRY CHANGING IT TO "Y" AND MATCHING.
ITOY:	PUSH	M,[0]
	MOVEI 	A,Y5		;CHANGE THE -I TO -Y
	PUSHJ	P,SETLST
	PUSHJ 	P,MATCH		;DOES IT MATCH NOW?
	JRST	EDT.Y		;NO, BUT -Y IS A POSSIBLE -LY
	JRST	ENDMSP		;MISSPELLING
	GETLST	-1		;YES: CHECK IF -<CONS>Y
	PUSHJ	P,ISCONS
	JRST	ENDFRT		;NO: ERROR LIKE "*PLAIED"
	JRST	ENDSRT		;YES, LIKE "SPIED"

;HAVE FOUND A "-S" PLURAL.  THE "S" HAS BEEN REMOVED.
EDT.S1:	GETLST
	CAIE	A,Y5
	JRST	EDT.S2
	GETLST	-1		;"YS" SHOULD BE PRECEDED BY A VOWEL
	PUSHJ	P,ISVOWL
	JRST	.+2		;LOSE. *"CRYS"
	JRST	ENDSRT		;WIN. "DAYS", "PREYS", "TOYS", "GUYS"
	PUSH	M,[E5]		;RECONSTRUCT WORD WITH "-YS" REPLACED
	PUSH	M,[I5]		;BY "-IES", BY DINT OF PUSHING THE
	PUSH	M,[Y5+40]	;APPROPRIATE MODS ONTO THE SUFFIX
	JRST	ENDFIX		;STACK

EDT.S2:	PUSHJ	P,ESPLUR	;MAKE SURE "-S" PLURAL IS LEGAL
	JRST	ENDSRT		;IT IS
	PUSH	M,[E5]		;NO, "-ES" IS NEEDED FOR PLURAL!
	JRST	ENDFIX		;RECONSTRUCT WORD WITH THE "-ES"

;HAVE FOUND A "-ES" PLURAL.  THE "ES" HAS BEEN REMOVED.
EDT.ES:	PUSHJ	P,ESPLUR
	JRST	.+2
	JRST	ENDSRT
	POP	M,A		;TRY RECONSTRUCTING WITH JUST
	JRST	ENDFIX		;AN "-S" PLURAL

;SKIP IF A "-ES" PLURAL IS REQUIRED (-S, -X, -Z, -CH, -SH)
ESPLUR:	GETLST
	CAIE	A,S5		;"GRASSES"
	CAIN	A,X5		;"TAXES"
	JRST	CPOPJ1
	CAIN	A,Z5		;"BUZZES"
	JRST	CPOPJ1
	CAIE	A,H5
	POPJ	P,		;ALL OTHERS BUT  "...HS" TAKE "-S".
	GETLST	-1
	CAIE	A,C5		;"WRENCHES" (BUT "EPOCHS")
	CAIN	A,S5		;"HASHES"
	AOS	(P)		;SKIP
	POPJ	P,

EDT.G:	ICOUNT
	PUSHJ	P,ZLAST
	CAIE	A,N5
	JRST	ENDFRT		;CAN'T DO ANYTHING ELSE
	PUSHJ	P,ZLAST
	CAIE	A,I5
	JRST	ENDFRT
	MOVEI	A,E5		;FOUND "ING".  TRY REPLACING THE "I"
	PUSHJ	P,SETLST	;WITH "E" SO "LIKING" WILL HAVE A CHANCE
	PUSHJ	P,MATCH
	JRST	.+3
	JRST	ENDMSP		;MISSPELLING
	JRST	ENDSRT
	PUSHJ	P,ZLAST		;TAKE BACK THE IRRELEVANT "E"
	POP	M,A		;REMOVE THE "+E-E" FROM SUFFIX STACK
	POP	M,A
	PUSHJ	P,MATCH
	JRST	EDT.CC		;GO CHECK FOR DOUBLED CONSONANT
	JRST	ENDMSP		;MISSPELLING
	GETLST
	CAIE	A,E5		;IS IT "-EING"?
	JRST	EDT.C		;NO, BUT GO CHECK IF A DOUBLED CONSONANT
				;WAS REQUIRED BUT MISSING
	GETLST	-1		;YES, THE ONE BEFORE THAT HAD BETTER
				; BE AN "E", "I", "O", OR "Y"
	CAIE	A,E5		;"SEEING"
	CAIN	A,O5		;"TOEING"
	JRST	ENDSRT
	CAIE	A,I5		;"TIEING" VAR. OF "TYING"
	CAIN	A,Y5		;"EYEING"
	JRST	ENDSRT
	PUSH	M,[E5+40]	;FIX WORDS LIKE *"TAKEING"
	JRST	ENDFIX

;"-ER", "-ED", AND "-EST" ALL ACT THE SAME
EDT.T:	ICOUNT
	PUSHJ	P,ZLAST		;ZAP THE "T"
	CAIE	A,S5		;IS IT "-ST"?
	JRST	ENDFRT		;NOPE
EDT.R:
EDT.D:	ICOUNT
	PUSHJ	P,ZLAST		;ZAP THE "D"
	CAIE	A,E5		;ENDS IN "-ED"?
	JRST	ENDFRT
	PUSHJ	P,MATCH		;YES: -E-D LIKE "LIKED"?
	JRST	.+3
	JRST	ENDMSP		;MISSPELLING
	JRST	ENDSRT		;YES, WIN
	PUSHJ	P,ZLAST		;FLUSH THE "E"
	PUSHJ	P,MATCH		;NOW DOES IT MATCH?
	JRST	.+3
	JRST	ENDMSP		;MISSPELLING
	JRST	EDT.ED		;YES: GO CHECK -Y/DOUBLED CONSONANT
	GETLST
	CAIN	A,I5		;NO: CAN WE TRY "-I" TO "-Y"?
	JRST	ITOY		;YES
;CHECK TO SEE IF STEM ENDS WITH A DOUBLED DOUBLABLE CONSONANT, AND IF
;  REMOVING ONE OF THEM MAKES IT MATCH
EDT.CC:	PUSH	M,[0]		;PUT A BREAK ON THE SUFFIX STACK
	GETLST
	PUSHJ	P,ISC2		;DOES IT END IN A DOUBLER?
	JRST	ENDFRT
	PUSHJ	P,ZLAST		;YES: GET THE NEXT ONE BACK
	CAME	A,(M)		;IS IT DOUBLED (SAME AS PREVIOUS)?
	JRST	ENDFRT		;NOT DOUBLED
	PUSHJ	P,MATCH		;YES: DOES STEM MATCH NOW?
	JRST	ENDFRT
	JRST	ENDMSP		;MISSPELLING
	GETLST	-1		;YES: CHECK IF DOUBLING VALID
	PUSHJ	P,ISVOWL	;NEXT ONE BACK MUST BE A VOWEL
	JRST	ENDFRT
	GETLST	-2
	PUSHJ	P,ISCONS	;AND THE NEXT ONE A CONSONANT
	JRST	ENDFRT
;THE SHORT VOWEL FOLLOWED BY A DOUBLABLE CONSONANT IS A NECESSARY
;CONDITION, BUT NOT SUFFICIENT, SINCE FOR POLYSYLLABIC STEMS, THE STRESS
;MUST ALSO BE ON THE LAST SYLLABLE.  WE HAVE NO WAY OF KNOWING THAT,
;OF COURSE, SO WE HAVE TO ACCEPT IT REGARDLESS.
	JRST	ENDSRT

;WE HAVE A MATCH AFTER STRIPPING "-ED" ("-ER", "-EST").  NOW CHECK
;FOR "-Y" ENDING OR IF A DOUBLED CONSONANT WAS REQUIRED BUT IS MISSING.
EDT.ED:	GETLST
	CAIE	A,Y5		;DOES STEM END IN -Y?
	JRST	EDT.C		;NO, BUT GO CHECK IF A DOUBLED CONSONANT
				;WAS REQUIRED BUT MISSING
	GETLST	-1		;YES: IS IT -<CONS>Y?
	PUSHJ	P,ISCONS
	JRST	ENDSRT		;NO ("PLAYED")
	PUSH	M,[I5]		;YES (*"SPYED")
	PUSH	M,[Y5+40]	;RECONSTRUCT WORD WITH "-Y" REPLACED
	JRST	ENDFIX		;BY "-I"

;CHECK IF CONSONANT DOUBLING WAS REQUIRED BUT MISSING
EDT.C:	PUSHJ	P,ISC2		;DOES STEM END WITH A DOUBLER?
	JRST	ENDSRT		;NO, SO NO FURTHER CHECKS NECESSARY
	GETLST	-1
	PUSHJ	P,ISVOWL	;PRECEDED BY A VOWEL?
	JRST	ENDSRT
	GETLST	-2
	PUSHJ	P,ISCONS	;AND THEN PRECEDED BY A CONSONANT?
	JRST	ENDSRT
;OK, HAD A SHORT VOWEL, FOLLOWED BY A DOUBLABLE CONSONANT.  IF STEM
;HAS ONLY ONE SYLLABLE, THEN CONSONANT DOUBLING WAS REQUIRED.  IF
;MORE THAN ONE SYLLABLE, DOUBLES ONLY IF STRESS IS ON LAST
;SYLLABLE, WHICH WE CAN'T KNOW.
	MOVEM	W,B		;TEMP. SAVE W
	SUBI	W,2
	SOJLE	W,EDT.C1	;FOUND NO VOWEL, SO SINGLE SYLLABLE
	GETLST
	PUSHJ	P,ISVOWL
	JRST	.-3		;KEEP LOOKING
	MOVE	W,B		;FOUND ANOTHER VOWEL, SO STEM HAS AT
	JRST	ENDSRT		;LEAST 2 SYLLABLES.

EDT.C1:	MOVE	W,B		;RESTORE W
	GETLST			;GET THE FINAL CONSONANT
	PUSH	M,A		;PUT A COPY OF IT ON THE STACK AND
	JRST	ENDFIX		;RECONSTRUCT A VERSION WITH 2 OF THEM

EDT.H:	ICOUNT
	PUSHJ	P,ZLAST		;"H" OFF
	CAIE	A,T5
	JRST	ENDFRT
	PUSHJ	P,ZLAST		;"TH" OFF
	PUSHJ	P,MATCH
	JRST	ITOY1		;"TWENTIETH", ETC.
	JRST	ENDMSP		;MISSPELLING
	JRST	ENDSRT		;"SIXTH", "SEVENTH", ETC.

EDT.N:	ICOUNT
	PUSHJ	P,ZLAST
	CAIN	A,E5
	JRST	EDT.EN
	CAIE	A,O5
	JRST	ENDFRT
	PUSHJ	P,ZLAST		;REMOVED "ON" THUS FAR
	CAIE	A,I5
	JRST	ENDFRT
	PUSHJ	P,ZLAST		;"ION" OFF
	CAIE	A,T5
	JRST	ENDFRT
	GETLST	-1		;FOUND "TION"
	PUSHJ	P,ISVOWL	;IS PREVIOUS LETTER A VOWEL?
	JRST	CTION		;NO: "REJECTION", "CONGESTION"?
	MOVEI	A,E5		;YES: ADD AN "E" FOR "IGNITION", ETC.
	PUSHJ	P,ADDLST
	PUSHJ	P,MATCH
	JRST	.+3		;TRY "Y" -> "-ICATION"
	JRST	ENDMSP		;MISSPELLING
	JRST	ENDSRT		;WIN
	PUSHJ	P,ZLAST		;TAKE BACK THE "E"
	POP	M,A		;REMOVE THE "+E-E" FROM SUFFIX STACK
	POP	M,A
	PUSHJ	P,ZLAST		;"TION" OFF
	CAIE	A,A5
	JRST	ENDFRT
	PUSHJ	P,ZLAST
	CAIE	A,C5
	JRST	ENDFRT
	PUSHJ	P,ZLAST
	CAIE	A,I5
	JRST	ENDFRT
	MOVEI	A,Y5		;FOUND "-ICATION"
	PUSHJ	P,SETLST	;TRY CHANGING THE "I" TO "Y"
CTION:	PUSHJ	P,MATCH
	JRST	ENDFRT
	JRST	ENDMSP		;MISSPELLING
	JRST	ENDSRT

EDT.EN:	ICOUNT
	PUSHJ	P,MATCH		;"SPOKEN"
	JRST	.+3
	JRST	ENDMSP		;MISSPELLING
	JRST	ENDSRT
	PUSHJ	P,ZLAST		;"-EN" OFF
	PUSHJ	P,MATCH
	JRST	EDT.CC		;GO CHECK FOR DOUBLED CONSONANT ("REDDEN")
	JRST	ENDMSP		;MISSPELLING
	JRST	ENDSRT

EDT.Y:	ICOUNT
	PUSHJ	P,ZLAST		;"Y" OFF
	CAIN	A,L5
	JRST	EDT.LY
	CAIE	A,T5
	JRST	ENDFRT
	PUSHJ	P,ZLAST		;"TY" OFF
	PUSHJ	P,MATCH
	JRST	.+3
	JRST	ENDMSP		;MISSPELLING
	JRST	ENDSRT		;"CHATTY", ETC.
	GETLST
	CAIE	A,I5
	JRST	ENDFRT
	MOVEI	A,E5
	PUSHJ	P,SETLST	;TRY "-E" -> "-ITY" ("ACTIVITY")
	PUSHJ	P,MATCH
	JRST	.+3
	JRST	ENDMSP		;MISSPELLING
	JRST	ENDSRT
	PUSHJ	P,ZLAST		;TRY WITHOUT THE "E"
	POP	M,A		;REMOVE THE "+E-E" FROM SUFFIX STACK
	POP	M,A
	PUSHJ	P,MATCH		;"FORMALITY", "SOLIDITY", ETC?
	JRST	.+3
	JRST	ENDMSP		;MISSPELLING
	JRST	ENDSRT
	GETLST			;LOOK FOR "-BILITY"
	CAIE	A,L5
	JRST	ENDFRT
	PUSHJ	P,ZLAST
	CAIE	A,I5
	JRST	ENDFRT
	PUSHJ	P,ZLAST
	CAIE	A,B5
	JRST	ENDFRT
	MOVEI	A,L5		;FOUND IT: ADD "LE"
	PUSHJ	P,ADDLST
	MOVEI	A,E5
	PUSHJ	P,ADDLST
	PUSHJ	P,MATCH
	JRST	ENDFRT
	JRST	ENDMSP		;MISSPELLING
	JRST	ENDSRT		;"ABILITY", "FEASIBILITY"

EDT.LY:	ICOUNT
	MOVEI	A,E5		;FIRST TRY ADDING "E" FOR WORDS LIKE
	PUSHJ	P,ADDLST	; "PROBABLY", "POSSIBLY"
	PUSHJ	P,MATCH
	JRST	ENDLY1		;NOPE
	JRST	ENDMSP
	GETLST	-2		;MAKE SURE IT'S "-BLE"
	CAIE	A,B5
	JRST	ENDFRT
	JRST	ENDSRT

ENDLY1:	PUSHJ	P,ZLAST		;TAKE BACK THE "E"
	POP	M,A		;AND REMOVE THE "+E-E"
	POP	M,A
	PUSHJ	P,ZLAST		;"LY" REMOVED
	PUSHJ	P,MATCH
	JRST	.+3
	JRST	ENDMSP		;MISSPELLING
	JRST	ENDSRT
	GETLST
	CAIE	A,L5
	JRST	ENDFRT
	PUSHJ	P,ZLAST
	CAIE	A,A5
	JRST	ENDFRT
	PUSHJ	P,ZLAST
	CAIE	A,C5
	JRST	ENDFRT
	PUSHJ	P,MATCH		;-C TO -CALLY? ("BASICALLY")
	JRST	ENDFRT
	JRST	ENDMSP		;MISSPELLING
	JRST	ENDSRT

EDT.SS:	PUSHJ	P,ZLAST		;"S" OFF
	CAIE	A,S5
	JRST	ENDFRT
ENDSS:	CAIGE	W,4
	JRST	ENDFRT		;SHORT WORDS NEED NOT APPLY
	PUSHJ	P,ZLAST		;"SS" OFF
	CAIE	A,E5		;THIS MUST BE AN "E"
	JRST	ENDFRT		;FAILURE
	PUSHJ	P,ZLAST		;WIPE OUT E
	CAIE	A,N5		;"-NESS"?
	CAIN	A,L5		;"-LESS"?
	JRST	.+2
	JRST	ENDFRT		;FAIL
	PUSHJ	P,ZLAST		;WIPE OUT THE N OR L
	PUSHJ	P,MATCH
	JRST	.+3		;NOPE, NOT YET
	JRST	ENDMSP		;MISSPELLING
	JRST	ENDSRT		;WIN
	PUSH	M,[0]		;PUT A BREAK ON SUFFIX STACK
	GETLST
	CAIE	A,I5		;COULD BE "-INESS"?
	JRST	ENDTGO		;NO, BUT TRY AGAIN ("BOUNDEDNESS")
	JRST	ITOY		;"HAPPINESS", "PENNILESS", ETC??

END.E:	PUSHJ	P,ZLAST
	CAIE	A,V5
	JRST	ENDFRT
	PUSHJ	P,ZLAST
	CAIE	A,I5
	JRST	ENDFRT
	PUSHJ	P,ZLAST		;TAKE OFF THE I FROM IVE
	PUSHJ	P,MATCH
	JRST	.+3
	JRST	ENDMSP		;MISSPELLING
	JRST	ENDSRT		;WIN
	MOVEI	A,E5
	PUSHJ	P,ADDLST	;TRY CHANGING "-IVE" TO "-E".
	PUSHJ	P,MATCH
	JRST	ENDFRT
	JRST	ENDMSP		;MISSPELLING
	JRST	ENDSRT
	SUBTTL	ROUTINES USED BY ENDTST
	PAGE

COMMENT/

SAVWD:	SAVES WORDIN AT A PLACE KNOWN TO BUT A FEW
UNSVWD:	RESTORE THE WORD FROM THE SAME PLACE

/

SAVWD:	ICOUNT
	MOVEM	W,SVWDLN	;SAVE WORD LENGTH
	MOVE	W,[XWD WORDIN,SVWDWX]
	BLT	W,SVWDWX+5
	MOVE	W,SVWDLN
	POPJ	P,

UNSVWD:	ICOUNT
	MOVE	W,[XWD SVWDWX,WORDIN]
	BLT	W,WORDIN+5
	MOVE	W,SVWDLN
	POPJ	P,

;TABLE OF BYTEPOINTERS INTO WORDIN.  IF W HOLDS THE NUMBER OF THE
;CHARACTER, THEN LDB AC,GETLBT(W) LOADS IT.
GETLBT:	POINT	5,[0],35	;LOADS A 0 IF YOU BACK OFF THE END
	POINT	5,WORDIN,4
	POINT	5,WORDIN,9
	POINT	5,WORDIN,14
	POINT	5,WORDIN,19
	POINT	5,WORDIN,24
	POINT	5,WORDIN,29
	POINT	5,WORDIN,34
	POINT	5,WORDIN+1,4
	POINT	5,WORDIN+1,9
	POINT	5,WORDIN+1,14
	POINT	5,WORDIN+1,19
	POINT	5,WORDIN+1,24
	POINT	5,WORDIN+1,29
	POINT	5,WORDIN+1,34
	POINT	5,WORDIN+2,4
	POINT	5,WORDIN+2,9
	POINT	5,WORDIN+2,14
	POINT	5,WORDIN+2,19
	POINT	5,WORDIN+2,24
	POINT	5,WORDIN+2,29
	POINT	5,WORDIN+2,34
	POINT	5,WORDIN+3,4
	POINT	5,WORDIN+3,9
	POINT	5,WORDIN+3,14
	POINT	5,WORDIN+3,19
	POINT	5,WORDIN+3,24
	POINT	5,WORDIN+3,29
	POINT	5,WORDIN+3,34
	POINT	5,WORDIN+4,4
	POINT	5,WORDIN+4,9
	POINT	5,WORDIN+4,14
	POINT	5,WORDIN+4,19
	POINT	5,WORDIN+4,24
	POINT	5,WORDIN+4,29
	POINT	5,WORDIN+4,34
	POINT	5,WORDIN+5,4
	POINT	5,WORDIN+5,9
	POINT	5,WORDIN+5,14
	POINT	5,WORDIN+5,19
	POINT	5,WORDIN+5,24
	POINT	5,WORDIN+5,29
	POINT	5,WORDIN+5,34

;ZLAST:	ZERO THE LAST LETTER OF A WORD, REDUCE ITS LENGTH BY
;  ONE, THEN RETURN WITH C(A) = NEW LAST LETTER.
ZLAST:	ICOUNT
	GETLST
	PUSH	M,A		;SAVE LAST LETTER ON AFFIX STACK
	SETZ	A,
	DPB	A,GETLBT(W)	;ZAP IT
	SUBI	W,1
	CAIG	W,1		;IF STEM GETS DOWN AS FAR AS 1 LETTER,
	JRST	ZFAIL		; THEN NOT A VALID SUFFIXATION
	GETLST
	POPJ	P,

ZFAIL:	POP	P,A		;NOTE THAT THIS REQUIRES THAT ZLAST CAN
	JRST	ENDFRT		;ONLY BE CALLED FROM ENDTST ITSELF, NOT
				;FROM A DEEPER SUBROUTINE.

;ADDLST:  ADD THE LETTER (5BIT) IN A TO THE WORD.
;SETLST:  CHANGE THE LAST LETTER OF THE WORD TO THE LETTER (5BIT) IN A.
ADDLST:	ADDI	W,1
	JRST	SET1

SETLST:	ICOUNT
	PUSH	P,A
	GETLST
	PUSH	M,A		;SAVE FORMER LAST LETTER
	POP	P,A
SET1:	DPB	A,GETLBT(W)
	TRO	A,40		;MARK THIS LETTER AS AN ADDITION
	PUSH	M,A		;AND SAVE IT TOO
	POPJ	P,


;ISCONS:  SKIPS IF C(A) = A CONSONANT (INCLUDING "Y")
ISCONS:	CAIE	A,E5
	CAIN	A,A5
	POPJ	P,
	CAIE	A,O5
	CAIN	A,I5
	POPJ	P,
	CAIE	A,U5
	CAIN	A,APOS
	POPJ	P,
	CAIE	A,0
	AOS	(P)		;SKIP
	POPJ	P,

;ISVOWL:  SKIPS IF C(A) = A VOWEL
ISVOWL:	PUSHJ	P,ISCONS
	CAIN	A,APOS
	POPJ	P,
	CAIE	A,0
	AOS	(P)
	POPJ	P,

;ISC2:	SKIPS IF C(A) = A DOUBLABLE CONSONANT (B,D,G,L,M,N,P,R,S,T)
;(GROK, TREK, REV, QUIZ, WHIZ ARE THE ONLY (K, V, Z) I CAN FIND,
; SO THEY SHOULD BE HANDLED EXPLICITLY IN THE DICTIONARY.)
ISC2:	CAIE	A,B5
	CAIN	A,D5
	JRST	CPOPJ1
	CAIE	A,G5
	CAIN	A,P5
	JRST	CPOPJ1
	CAIL	A,L5
	CAILE	A,N5
	JRST	.+2
	JRST	CPOPJ1
	CAIL	A,R5
	CAILE	A,T5
	POPJ	P,
	JRST	CPOPJ1

;ISSTEM: SKIPS IF THE STEM REMAINING IN WORDIN MEETS CERTAIN TESTS.
;  MUST HAVE AT LEAST 3 LETTERS, AND IF EXACTLY 3, MUST HAVE AT LEAST
;  ONE VOWEL (OR Y).  VERY FEW 2-LETTER WORDS TAKE AFFIXES, AND THOSE
;  THAT DO SHOULD PROBABLY BE IN THE DICT EXPLICITLY.  ALSO RULES OUT
;  THINGS LIKE "A'S".
ISSTEM:	CAILE	W,3
	JRST	CPOPJ1
	CAIE	W,3
	POPJ	P,
	LDB	A,GETLBT+1
	PUSHJ	P,ISVOWL
	CAIN	A,Y5
	JRST	CPOPJ1
	LDB	A,GETLBT+2
	PUSHJ	P,ISVOWL
	CAIN	A,Y5
	JRST	CPOPJ1
	LDB	A,GETLBT+3
	PUSHJ	P,ISVOWL
	CAIN	A,Y5
	AOS	(P)
	POPJ	P,
	SUBTTL  PREFIX - TRY TO REMOVE PREFIXES
	PAGE

;RETURNS TO CALL+1 IF UNSUCCESSFUL
;		+2 IF RECONSTRUCTION PUT IN CANDBF, DUE TO FINDING
;		   THE STEM AS A MISSPELLING.
;		+3 IF A MATCH WAS FOUND.

IFN MACRO,<	DEFINE PRE(X) <
..NCHRS==0
..MASK==0
..STR==0
..NSH==^D36
IRPC X,<
..NSH==..NSH-5
..NCHRS==..NCHRS+1
..MASK==..MASK!<37_..NSH>
..STR==..STR!<<X'5>_..NSH>>
	..NCHRS		;;# CHRS IN PREFIX
	..MASK		;;MASK
	..STR		;;5BIT STRING OF PREFIX
>
>

IFE MACRO,<	DEFINE PRE(Y) <
..NCHRS==0
..MASK==0
..STR==0
..NSH==44
FOR X<Y><
..NSH==..NSH-5
..NCHRS==..NCHRS+1
..MASK==..MASK!<37..NSH>
..STR==..STR!<<X'5>..NSH>>
	..NCHRS		;;# CHRS IN PREFIX
	..MASK		;;MASK
	..STR		;;5BIT STRING OF PREFIX
>
>


;OTHER COMMON PREFIXES ARE:  ANTI,DE,IN,INTER,MULTI,PRO,OVER,SEMI,SUPER,SUB,WELL
PRETAB:	PRE (NON)		;TABLE OF PREFIXES	NONAGENARIAN
	PRE (RE)		;			REPENT
	PRE (UN)		;			UNIVERSAL
	PRE (PRE)		;			PREVIOUS
	PRE (MIS)		;			MISSISSIPPI
NPRE==.-PRETAB

PREFIX:	TRNN	FL,NOPREF	;SKIP PREFIX REMOVAL IF "N" SWITCH
	CAIG	W,3		;OR IF WORD IS TOO SHORT
	POPJ	P,		;NONSKIP RETURN IMPLIES FAILURE
	MOVEM	W,PREW		;SAVE W AND THE WORD (IN A PLACE OTHER
	MOVE	A,[XWD WORDIN,PREWD]	;THAN WHAT ENDTST USES, SINCE
	BLT	A,PREWD+5		;WE WILL CALL ENDTST)
	MOVE	N,[IOWD PRELEN,PRESTK]	;SET UP A PREFIX STACK USING N
PREAGN:	MOVSI	C,-NPRE
PRLOOP:	MOVE	A,WORDIN		;WE NEED TEST ONLY 1ST 7 CHRS
	AND	A,PRETAB+1(C)
	CAME	A,PRETAB+2(C)		;DOES WORD BEGIN WITH PREFIX?
	JRST	NOPRE			;NO
	PUSH	N,PRETAB+2(C)		;SAVE PREFIX ON PREFIX STACK
	MOVEM	C,PREPTR		;SAVE POINTER
	MOVE	A,PRETAB(C)		;YES - STRIP THE PREFIX OFF
	MOVE	D,W
	SUBI	W,(A)			;UNPREFIXED WORD IS SHORTER!
	MOVE	A,GETLBT(A)		;BYTPTR INTO 1ST WORD
	MOVE	B,[POINT 5,WORDIN]
	ILDB	C,A
	IDPB	C,B
	SOJGE	D,.-2			;ASSUME ENOUGH ZEROS IN WORDIN AFTER WORD
	PUSHJ	P,MATCH			;NOW SEE IF WE RECOGNIZE THE WORD
	JRST	PRESUF			;NO - NOW TRY SUFFIX REMOVAL TOO
	JRST	PREMSP			;FOUND AS MISSPELLING
	PUSHJ	P,ISSTEM		;FOUND AS SPELLING - STEM OK?
	JRST	PRERES			;NO
PRESRT:	AOS	(P)			;SET SKIP RETURN
	JRST	PRESR1

PREMSP:	TRO	FL,PREWIN		;STEM RECOGNIZED AS MISSPELLING
	PUSHJ	P,RECONS
PRESR1:	TRO	FL,PREWIN		;WON BY PREFIX REMOVAL.
	AOS	(P)
	PUSH	N,[0]			;MARK END OF PREFIX STACK
PRERES:	MOVE	W,[XWD PREWD,WORDIN]	;RESTORE WORDIN AND W FROM
	BLT	W,WORDIN+5		;PREWD AND PREW
	MOVE	W,PREW
	POPJ	P,

PRESUF:	PUSHJ	P,ENDTST		;TRY SUFFIX REMOVAL ON UNPREFIXED WORD
	JRST	PREMOR			;NOPE
	JRST	PRESR1			;ENDTST DID A RECONS
	JRST	PRESRT			;YAY!

NOPRE:	ADD	C,[3,,3]		;WE SKIP THRU PRETAB BY 3'S
	JUMPL	C,PRLOOP		;JUMP IF MORE.
	JRST	PRERES			;FAILURE RETURN

PREMOR:	CAIG	W,3	;HAVE TAKEN OFF A PREFIX, BUT NO MATCH.  IF WORD
	JRST	PRERES	;IS LONG ENOUGH, SEE IF ANY MORE CAN COME OFF
	JRST	PREAGN	;("UNRECONSTRUCTED")
	SUBTTL	RECONS - RECONSTRUCT A WORD FROM AFFIXES AND STEM
	PAGE

;ENDTST OR PREFIX HAS RECOGNIZED A "STEM" AS A MISSPELLING.  RECONSTRUCT
;A CORRECTED VERSION OF THE WORD BY ADDING THE STRIPPED AFFIXES
;TO THE CORRECTION STRING.  IT'S CERTAINLY NOT SAFE TO USE THIS
;NEW STRING IN AN AUTOMATIC MISSPELLING ==> CORRECTION, SO THE NEXT
;BEST THING TO DO IS TO PROPOSE THIS AS A CANDIDATE GUESS FOR THE
;EXCEPTED WORD.
RECONS:	SETZB	W,WORDIN		;CLEAR WORDIN, WHERE WE'LL
	MOVE	A,[WORDIN,,WORDIN+1]	;DO THE RECONSTRUCTION
	BLT	A,WORDIN+5
	MOVEI	B,PRESTK		;START WITH THE PREFIXES
	TRZE	FL,PREWIN
RECON1:	SKIPN	(B)
	JRST	RECON3
	MOVE	C,[POINT 5,(B)]
RECON2:	ILDB	A,C
	JUMPE	A,[AOJA	B,RECON1]
	DPB	A,GETLBT+1(W)
	AOJA	W,RECON2

RECON3:	HRRZ	B,STEM			;PTR TO MISSPELLED STEM
	HRRZ	B,-2(B)			;PTR TO CORRECTION
	ADD	B,[POINT 5,1]		;BYTE PTR TO CORRECTION STRING
RECON4:	ILDB	A,B
	JUMPE	A,RECON5
	DPB	A,GETLBT+1(W)
	AOJA	W,RECON4

RECON5:	TRZN	FL,SUFWIN
	JRST	RECON7
RECON6:	POP	M,A			;POP ITEM FROM SUFFIX STACK
	JUMPL	A,RECON7		;-1 ENDS STACK
	JUMPE	A,RECON6		;IGNORE BREAK = 0
	TRZN	A,40			;40-BIT MEANS LETTER WAS ZAPPED
	JRST	[DPB	A,GETLBT+1(W)	;ADD IT BACK AGAIN
		 AOJA	W,RECON6]
	SETZ	A,			;REMOVE ADDED LETTER
	DPB	A,GETLBT(W)
	SOJA	W,RECON6

RECON7:	PUSHJ	P,MATCH			;SEE WHAT WE CAN MAKE OF NEW ONE
	JRST	RECON9			;NOT FOUND
	SKIPA	X,-2(X)			;MISSPELLING - USE CORRECTION
RECON8:	MOVEM	X,CANDBF		;FOUND IT - PUT IT IN CANDBF
	AOS	CANDID			;AND COUNT IT
	POPJ	P,

RECON9:	MOVE	A,[WORDIN,,RECON]	;NOT FOUND, SO MUST MOVE THE
	BLT	A,RECON+5		;RECONSTRUCTION TO SOME PLACE
	MOVEI	X,RECON			;LESS VOLATILE
	JRST	RECON8
	SUBTTL	CHANNEL INITIALIZATION	- DEC AND STANFORD
	PAGE
IFE TENEX,<

HDRSIZ==3	;SIZE OF BUFFER HEADERS (DIFFERENT FOR TENEX)
BUFFNO==2	;NUMBER OF I/O BUFFERS FOR DEVICES
MODE==14	;BUFFERD BINARY WORD AT A TIME MODE.
AMODE==1	;BUFFFERED CHARACTER AT A TIME
DBFSIZ==203	;MAX BUFFER SIZE.

INDICT:	SKIPA	C,[DICTBF]		;DICTIONARY INPUT
INDCTO:	MOVSI	C,DICTBF		;DICTIONARY OUTPUT
	MOVEI	A,AMODE
	MOVE	D,[DICT*40,,DICTFF]	;CHANNEL,,BUFFER LOCATION

;CALL WITH A=MODE, M=DEVICE, C=BUFFER HEADER ADDRESS, D=CHANNEL*40,,BUFFER ADDRESS
;SKIPS ON SUCCESS, OTHERWISE MAKES A MESSAGE
INIALL:	SKIPN	B,M
	MOVSI	B,'DSK'
	MOVEM	D,INITMP		;SAVE BUFFER ADDRESS HERE
	HLLZ	D,D
	IOR	D,[OPEN A]
	XCT	D
	JRST	NODEV
	MOVEI	M,0			;FOR SUBSEQUENT ENTERS, IN CASE.

IFE STANSW,<	MOVEI	D,A
		DEVSIZ	D,
		MOVEI	D,203	
		HRRZS	D,D	>	;CLEAR NUMBER OF BUFFERS. MDA 790112

IFN STANSW,<	MOVE	D,B
		BUFLEN	D,
		JUMPG	D,.+2
		MOVEI	D,201
		ADDI	D,2	>

	CAILE	D,DBFSIZ
	JRST	BUFTBG			;BUFFER TOO BIG
	HRRZ	D,INITMP
	EXCH	D,.JBFF
	HLLZ	A,INITMP
	IOR	A,[INBUF BUFFNO]
	TRNE	C,-1
	XCT	A			;INBUF IF THERE'S AN INPUT BUFFER HEADER
	HLLZ	A,INITMP
	IOR	A,[OUTBUF BUFFNO]
	TLNE	C,-1
	XCT	A			;IF THERE'S AN OUTPUT BUFFER HEADER
	MOVEM	D,.JBFF
	JRST	CPOPJ1

INDATA:	MOVEI	C,DATABF		;FILE INPUT
	MOVEI	A,MODE			;TRY BUFFERED WORD MODE
	MOVE	D,[DATA*40,,DATAFF]
	JRST	INIALL

INEXCP:	MOVSI	C,EXCPBF		;EXCEPTION OUTPUT
	MOVEI	A,AMODE			;BUFFERED CHARACTER MODE
	MOVE	D,[EXCP*40,,EXCPFF]
	JRST	INIALL

INCORR:	MOVSI	C,CORRBF		;CORRECTION OUTPUT
	MOVEI	A,MODE			;TRY BUFFERED WORD MODE
	MOVE	D,[CORR*40,,CORRFF]
	JRST	INIALL

>;IFE TENEX

	SUBTTL	CHANNEL INITIALIZATION	- TENEX
	PAGE
IFN TENEX,<
;TENEX VERSION USES A WHOLE PAGE PER FILE FOR "BUFFER", PMAP-ING FOR
; SPEED. THE "RING HEADER" LOOKS LIKE:
;  HEADER+0:	400000,,COREPAGE	;JUST RIGHT FOR PMAP
;  HEADER+1:	CURRENT BYTE POINTER
;  HEADER+2:	# BYTES LEFT IN WINDOW
;  HEADER+3:	FILE JFN
;  HEADER+4:	# BYTES LEFT IN FILE (INPUT),WRITTEN IN FILE (OUTPUT)
;  HEADER+5:	CURRENT FILE PAGE
;  HEADER+6:	0 FOR AN INPUT BUFFER, -1 FOR OUTPUT
;  HEADER+7:	ROUTINE ADDRESS TO CALL TO READ/WRITE CHR

HDRSIZ==10

INDICT:	MOVSI	A,400000		;DICTIONARY INPUT
	HRRI	A,DICTPG		;PAGE FOR PMAP
	MOVEM	A,DICTBF+0
	SETZM	DICTBF+6		;FLAG INPUT
	SETZM	DICTBF+7
	POPJ	P,

INDCTO:	MOVSI	A,400000		;DICTIONARY OUTPUT
	HRRI	A,DICTPG
	MOVEM	A,DICTBF+0
	SETOM	DICTBF+6		;FLAG OUTPUT
	SETZM	DICTBF+7
	POPJ	P,

INDATA:	MOVSI	A,400000		;INPUT FILE
	HRRI	A,DATAPG
	MOVEM	A,DATABF+0
	SETZM	DATABF+6		;INPUT
	SETZM	DATABF+7
	POPJ	P,

INEXCP:	MOVSI	A,400000		;EXCEPTION OUTPUT
	HRRI	A,EXCPPG
	MOVEM	A,EXCPBF+0
	SETOM	EXCPBF+6		;OUTPUT
	SETZM	EXCPBF+7
	POPJ	P,

INCORR:	MOVSI	A,400000		;CORRECTED OUTPUT
	HRRI	A,CORRPG
	MOVEM	A,CORRBF+0
	SETOM	CORRBF+6		;OUTPUT
	SETZM	CORRBF+7
	POPJ	P,


;SIMULATE LOOKUP OR ENTER
;DOING THE DVCHR AFTER THE GTJFN BUT BEFORE THE OPENF LETS US WIN
;  IN THE CASE OF LPT:.  BEFORE THE OPENF, IT LOOKS NON-PMAPPABLE, BUT
;  AFTER, IT'S A LPT-SPOOLER FILE, WHICH IS PMAPPABLE.

OPNFIL:	PUSH	P,A
	PUSH	P,B
	PUSH	P,C
	PUSH	P,D
	PUSH	P,W
	MOVE	A,3(K)			;JFN
	DVCHR
	SKIPGE	6(K)
	JRST	OPNFI6
OPNFI4:	MOVEI	A,RDSIN			;USE SIN IF NOT PMAPPABLE
	TLNE	B,(1B4)
	MOVEI	A,RDPMAP		;OR PMAP IF OK
	JRST	OPNFI8

OPNFI6:	MOVEI	A,WRSOUT		;USE SOUT IF NOT PMAPPABLE
	TLNE	B,(1B4)
	MOVEI	A,WRPMAP

OPNFI8:	MOVEM	A,7(K)			;PUT ROUTINE ADDR IN XXXXBF
	SETOM	5(K)			;PAGE 0 WILL BE NEXT (AT FIRST CALL)
	SETZM	2(K)			;NO HOLES/BYTES LEFT IN WINDOW
	MOVE	A,3(K)			;JFN
	MOVE	B,[7B5+1B19]		;7-BIT, READ
	SKIPGE	6(K)			;FOR OUTPUT?
	TRO	B,1B20			;R/W NEEDED FOR IDPB, BLT
	OPENF
	JRST	[PUSHJ	P,JSYSER
		MOVE	A,3(K)
		RLJFN
		JFCL
		JRST	OPNFIY]		;NO SKIP
OPNFI9:	MOVE	A,6(K)			;-1 FOR OUTPUT
	MOVEM	A,4(K)			;SIGNAL FIRST OUTPUT
	JUMPL	A,OPNFIX		;DONE IF OUTPUT
	MOVE	A,3(K)			;JFN
	MOVE	B,[2,,11]
	MOVEI	C,C
	GTFDB				;GET BYTE SIZE AND COUNT
	LDB	C,[POINT 6,C,11]	;BYTE SIZE
	CAIN	C,7
	JRST	OPNFIW			;NO CONVERSION NEEDED
	MOVEI	B,44			;ASSEMBLER INDEPENDENT 36.
	IDIVI	B,0(C)
	IDIVI	D,0(B)
	IMULI	D,5
OPNFIW:	MOVEM	D,4(K)			;INPUT BYTE COUNT

OPNFIX:	AOS	-5(P)			;SET SKIP RETURN
OPNFIY:	POP	P,W
	POP	P,D
	POP	P,C
	POP	P,B
	POP	P,A
	POPJ	P,

;WRITE OUT BUFFER USING SOUT -- DECTAPE, ETC.

WRSOUT:	PUSH	P,1
	PUSH	P,2
	PUSH	P,3
	SKIPL	4(K)		;ANYTHING WRITTEN SO FAR?
	JRST	WRSOU2		;YES.
	SETZM	4(K)		;NO. MAKE BUFFER LOOK EMPTY
	MOVEI	1,5000
	MOVEM	1,2(K)
WRSOU2:	MOVE	3,2(K)		;HOLES LEFT IN WINDOW
	SUBI	3,5000		;NEG NUMBER OF BYTES TO OUTPUT
	JUMPE	3,WRSOU4	;NO BYTES IN BUFFER, DON'T SOUT
	HRRZ	2,0(K)		;PAGE WHERE WINDOW IS
	LSH	2,9		;ADDR
	TLO	2,-1		;MAKE POINTER
	HRRZ	1,3(K)		;JFN
	SOUT			;WRITE ON FILE

WRSOU4:	HRRZ	1,0(K)		;PAGE
	LSH	1,9
	SETZM	(1)
	HRLS	1
	ADDI	1,1
	HLRZ	2,1
	BLT	1,777(2)	;SET PAGE TO ZEROS

WRSOU5:	HRRZ	2,0(K)		;PAGE
	LSH	2,9		;MAKE ADDR
	HRLI	2,440700	;OBVIOUSLY A 7 BIT BYTEPOINTER
	MOVEM	2,1(K)		;RESET BYTE POINTER
	MOVEI	1,5000
	SUB	1,2(K)		;NUMBER OF BYTES IN WINDOW
	ADDM	1,2(K)		;RESTORE BUFFER TO EMPTY
	ADDM	1,4(K)		;BYTES WRITTEN ON FILE
	POP	P,3
	POP	P,2
	POP	P,1
	POPJ	P,


;WRITE OUT BUFFER WITH PMAP -- DISK

WRPMAP:	PUSH	P,1
	PUSH	P,2
	PUSH	P,3
	SKIPL	4(K)		;FIRST OUTPUT?
	JRST	WRPMP1		;NO.
	SETZM	4(K)		;MAKE BUFFER LOOK EMPTY
	MOVEI	1,5000
	MOVEM	1,2(K)
WRPMP1:	AOS	1,5(K)		;GET NEXT PAGE OF FILE
	HRL	1,3(K)		;FORM JFN,,PAGE FOR FILE
	MOVE	2,0(K)		;GET FORK,,PAGE FOR FORK
	MOVSI	3,140000	;READ/WRITE (IDPB, BLT DO READS)
	PMAP
	JRST	WRSOU4


;READ USING SIN -- DECTAPE ETC

RDSIN:	PUSH	P,1
	PUSH	P,2
	PUSH	P,3
	MOVE	3,4(K)		;NUMBER OF BYTES REMAINING IN FILE
	CAIL	3,5000		;NUMBER WHICH WILL FIT IN WINDOW
	MOVEI	3,5000		;FILL WINDOW IF POSSIBLE
	MOVEM	3,2(K)		;SAY THAT'S HOW MANY ARE AVAILABLE
	JUMPE	3,RDSIN8	;NO MORE
	HRRZ	2,0(K)		;BUFFER PAGE
	LSH	2,9		;MAKE IT AN ADDRESS
	TLO	2,-1		;MAKE IT A POINTER
	HRRZ	1,3(K)		;JFN
	SIN

RDSIN4:	HRRZ	2,0(K)		;PAGE
	LSH	2,9		;MAKE ADDR
	HRLI	2,440700	;7 BIT BYTES
	MOVEM	2,1(K)		;CURRENT BYTE POINTER
	MOVN	3,2(K)
	ADDM	3,4(K)
	AOS	-3(P)		;NOT AT EOF MEANS SKIP

RDSIN8:	POP	P,3
	POP	P,2
	POP	P,1
	POPJ	P,


;READ WITH PMAP -- DISK

RDPMAP:	PUSH	P,1
	PUSH	P,2
	PUSH	P,3
	MOVE	3,4(K)
	CAIL	3,5000
	MOVEI	3,5000
	MOVEM	3,2(K)
	JUMPE	3,RDSIN8
	AOS	1,5(K)
	HRL	1,3(K)
	MOVE	2,0(K)
	MOVSI	3,100000
	PMAP
	JRST	RDSIN4


;FILE CLOSING ROUTINES - CALLED FROM THE UUO HANDLER WITH K SETUP.
FILCLS:	SKIPN	1,7(K)		;FIND OUT WHICH ROUTINE WROTE/READ IT
	POPJ	P,		;RETURN QUICK IF NOBODY HOME.
	CAIE	1,RDSIN
	CAIN	1,RDPMAP
	JRST	FILCLI

FILCLO:	SOS	2(K)		;FIX UP COUNT OF HOLES IN LAST WINDOW
	CAIE	1,WRPMAP
	JRST	FILCX
	HRRZ	1,3(K)		;JFN
	HRLI	1,11		;WORD 11 OF FDB
	MOVSI	2,(77B11)	;CHANGE MASK
	MOVSI	3,(07B11)	;7 COME 11
	CHFDB			;SET BYTE SIZE TO 7
	HRLI	1,12		;FDB INDEX
	SETO	2,		;CHANGE ALL BITS
	MOVEI	3,5000
	SUB	3,2(K)		;NUMBER OF BYTES IN LAST WINDOW
	CAIN	3,5001		;SKIP IF ANYTHING HAS BEEN WRITTEN
	JRST	FILCLI		;NOTHING IN FILE, SO LENGTH=0
	ADD	3,4(K)		;PLUS NUMBER IN BUFFERS ALREADY OUTPUT
	CHFDB			;IS FILE LENGTH
	JRST	FILCLI

FILCX:	PUSHJ	P,WRSOUT	;WRITE LAST PARTIAL BUFFER
FILCLI:	SETO	1,
	MOVE	2,0(K)		;FORK,,PAGE
	CLEAR	3,3		;[Tops20]
	PMAP			;UNMAP LAST PAGE
	HRRZ	1,3(K)		;JFN
	CLOSF
	JFCL
	POPJ	P,

JSYSER:	PUSH	P,1		;TENEX ERROR MESSAGE PRINTER
	PUSH	P,2
	PUSH	P,3
	MOVEI	1,101
	MOVE	2,[400000,,-1]
	SETZ	3,
	ERSTR
	JFCL
	JFCL
	HRROI	1,CRLF		;[Tops20]
	PSOUT			;[Tops20]
	POP	P,3
	POP	P,2
	POP	P,1
	POPJ	P,
>;END IFN TENEX
	SUBTTL	DICTIONARY MANIPULATION - DUMPD - DUMP ROUTINE
	PAGE

IDMPD1:	SKIPA	Z,NDICT1	;ENTRY FOR DUMPING DEFAULT DICT 1
IDMPD:	SETZ	Z,		;NORMAL DUMP FLAG. MDA 790117
	TROA	FL,IDUMP
DUMPD:	TRZ	FL,IDUMP
	JUMPN	Z,DMPD1A	;DON'T ASK NAME OF DEFULT DICT
DUMPD1:	OUTSTR	[ASCIZ/file name: /]

IFN TENEX,<
DMPD1A:		PUSHJ	P,INDCTO		;[decus] addded label here
		HRROI	L,[ASCIZ/WORDS/]	;SET DEFAULT NAME
		HRROI	M,[ASCIZ/LST/]
		MOVEI	K,DICTBF		;BUFFER HEADER ADDRESS
		PUSHJ	P,GETFIL
		JRST	.-1		>	;IFN TENEX


IFE TENEX,<	PUSHJ	P,GETFIL
		POPJ	P,		;NO NAME=NO DUMP. MDA 790112
DMPD1A:		PUSHJ	P,INDCTO	;PREPARE DICTIONARY OUTPUT CHANNEL
		JRST	DUMPD1	>	;IFE TENEX

	ENTER	DICT,K
	JRST	[PUSHJ	P,ENTFAI
		JRST	DUMPD1]

	MOVSI	Z,-HASHTL
	SETZM	TLET.1			;COUNT WORDS/PAGE OUTPUT
	PUSH	P,Z			;SAVE GLOBAL INDEX TO HASHTB
DODMP0:	MOVEM	Z,(P)			;SAVE FOR LATER
	HRLI	Z,-5			;COUNT FOR LOCAL REGION
	PUSH	P,[-1]			;INITIAL INDEX TO BTABLE
	PUSH	P,Z			;SAVE LOCAL AOBJN
DODMP1:	MOVEM	Z,(P)			;SAVE Z
	HLRZ	X,HASHTB(Z)
	JUMPE	X,DODM1A
	PUSHJ	P,LITSRT		;SORT LEFT SIDE
	MOVE	Z,(P)
	HRLM	X,HASHTB(Z)
	AOS	Y,-1(P)
	HRRZM	X,BTABLE(Y)
DODM1A:	HRRZ	X,HASHTB(Z)
	JUMPE	X,DODM1B
	PUSHJ	P,LITSRT		;SORT RIGHT SIDE
	MOVE	Z,(P)
	HRRM	X,HASHTB(Z)
	AOS	Y,-1(P)
	HRRZM	X,BTABLE(Y)
DODM1B:	AOBJN	Z,DODMP1		;LOOP
	SUB	P,[1,,1]		;ADJUST STACK. (FLUSH LOCAL AOBJN)
	POP	P,Y			;POP COUNT OF BTABLE ENTRIES.
	JUMPL	Y,DODMP8		;JUMP IF NOTHING TO DO FOR THESE 10 ENTRIES

	MOVEM	Y,HEAPSZ		;SAVE DEGREE OF MERGE, -1.
	JUMPE	Y,DODM2A		;JUMP IF EASY.
	MOVEI	Z,-1(Y)
	LSH	Z,-1
DODMP2:	PUSHJ	P,ENHEAP		;MAKE A HEAP
	SOJGE	Z,DODMP2
DODM2A:	MOVE	X,BTABLE		;GET CAR OF SMALLEST LIST
	MOVE	A,(X)
	HRRZM	A,BTABLE		;STUFF CDR OF FORMERLY THE FIRST LIST
	PUSHJ	P,PRNTON		;PRINT ONE WORD IN DICTIONARY
	MOVEI	Z,0			;ARG FOR REHEAPING
	SKIPE	BTABLE			;FIRST LIST NOW EMPTY?
	JRST	DODMP2			;NO. REHEAP IT.
	SOSGE	Y,HEAPSZ		;DECREMENT DEGREE OF MERGE
	JRST	DODMP8			;ALL DONE!
	MOVE	A,BTABLE+1(Y)		;GET THING FROM THE END OF THE HEAP
	MOVEM	A,BTABLE		;STUFF IT AT THE HEAD OF THE HEAP
	JRST	DODMP2			;REHEAP ELEMENT 0

DODMP8:	MOVE	Z,(P)			;RESTORE Z FROM STACK
	ADD	Z,[5,,5]
	JUMPL	Z,DODMP0		;LOOP DOING 5 WORDS (10 ENTRIES) EACH TIME
	SUB	P,[1,,1]		;ADJUST STACK

	CLOSE	DICT,0

IFE TENEX,<	STATZ	DICT,740000
		JRST	DDE	>	;IFE TENEX

	POPJ	P,

PRNTON:	LDB	Y,[POINT 5,(X),17]
	TRNE	FL,IDUMP		;SKIP IF FULL DUMP
	CAMN	Y,IDNUM			;INCR. DUMP - SEE IF THIS IS THE RIGHT KIND
PRNT0:	SKIPA	B,[POINT 5,1(X)]	;DUMP THIS WORD. SET INTIAL BYTE POINTER
	POPJ	P,
PRNT1:	ILDB	A,B
	JUMPE	A,PRNT2
	CAIN	A,APOS
	SKIPA	A,["'"]
	ADDI	A,"A"-1
	PUSHJ	P,WDICT
	JRST	PRNT1

PRNT2:	MOVE	Y,(X)		;WAS THIS A MISSPELLING?
	TLNN	Y,MISSPL
	JRST	PRNT3		;YES: LET'S OUTPUT THE CORRECTION TOO
	HRRZ	X,-1(X)			;POINT TO CORRECTION
	MOVEI	A,">"			;TO RECOGNIZE A MISSPELLING-CORRECTION
	PUSHJ	P,WDICT			;PAIR WHEN INPUT BY DICTIONARY LOADER
	JRST	PRNT0
PRNT3:	MOVEI	A,CR			;WRITE CRLF, MAYBE CRLFFF.
	PUSHJ	P,WDICT
	MOVEI	A,LF
	PUSHJ	P,WDICT
	AOS	A,TLET.1
	CAIG	A,400			;ENOUGH ON THIS PAGE?
	POPJ	P,			;NO. WE'RE DONE
	SETOM	TLET.1			;RESET COUNT/PAGE
	MOVEI	A,FF
	JRST	WDICT			;SEND AN FF TO KEEP EDITORS HAPPY

ENHEAP:	MOVEI	L,0(Z)
ENHEP1:	MOVEI	N,(L)
	LSH	N,1
	MOVEI	N,1(N)
	CAML	N,HEAPSZ
	JRST	ENHEP2
	MOVE	X,BTABLE(N)
	MOVE	W,BTABLE+1(N)
	PUSHJ	P,LCOMP0
	ADDI	N,1
	JRST	ENHEP3

ENHEP2:	CAME	N,HEAPSZ
	POPJ	P,			;DONE!
ENHEP3:	MOVE	X,BTABLE(N)
	MOVE	W,BTABLE(L)
	PUSHJ	P,LCOMP0
	POPJ	P,
	MOVEM	X,BTABLE(L)
	MOVEM	W,BTABLE(N)
	MOVEI	L,(N)
	JRST	ENHEP1

COMMENT $
FOR THOSE FOLKS WHO LIKE THEIR MACHINE CODE COMMENTS WRITTEN IN META-LISP:

SORT(X)_IF NULL(X) OR NULL CDR(X) THEN X ELSE
		 MERGE(SORT(ALT(X)),SORT(ALT(CDR(X))));

MERGE(X,Y)_IF NULL(X) THEN Y ELSE IF NULL(Y) THEN X ELSE
		IF CAR(X)<CAR(Y) THEN CAR(X) . MERGE(CDR(X),Y)
		ELSE CAR(Y) . MERGE(X,CDR(Y));

ALT(X)_IF NULL(X) OR NULL(CDR(X)) THEN X ELSE CAR(X).ALT(CDDR(X));

$

;SORT ONE HASH CHAIN.  RECURSIVE.  LIST HEADER IN X.  RETURNS SORTED LIST IN X.

LITSRT:	JUMPE	X,CPOPJ			;NO WORK FOR NO LIST
	HRRZ	W,(X)			;GET LINK TO NEXT
	JUMPE	W,CPOPJ			;JUMP IF NO NEXT. 1-ELEMENT LIST IS SORTED.
;X AND W WILL BE NEARLY-EQUAL LENGTH LISTS
	MOVE	Y,W			;TAIL OF THE W LIST
	MOVE	Z,X			;TAIL OF THE X LIST
LITSR1:	HRRZ	N,(Y)			;GET LINK-OUT OF W LIST
	HRRM	N,(Z)			;STORE AS LINK-OUT IN X LIST
	SKIPN	Z,N			;ADVANCE X-TAIL
	JRST	LITSR2			;NO NEXT
	HRRZ	N,(Z)			;GET LINK-OUT OF X-LIST
	HRRM	N,(Y)			;STORE AS LINK-OUT OF W-LIST
	SKIPE	Y,N			;ADVANCE W-TAIL
	JRST	LITSR1			;MAKE LISTS OF ALTERNATE ELEMENTS.
LITSR2:	PUSH	P,W			;SAVE W-LIST
	PUSHJ	P,LITSRT		;SORT THE X-LIST (RECUR UNTIL DONE)
	EXCH	X,(P)			;EXCH SORTED X-LIST WITH W-LIST
	PUSHJ	P,LITSRT		;AND SORT W-LIST
	POP	P,W			;(X AND W ARE INTERCHANGED, BUT WHO CARES)
;W AND X NOW (ASSUME) POINT TO SORTED LISTS.  MERGE THEM INTO ONE LIST.
	MOVEI	Z,Y			;MERGE LIST HEAD IN Z
	JUMPE	X,LITSR4		;NO MERGE IF X IS EMPTY. ADD W TO OUT-LIST
	EXCH	W,X			;SWAP THEM (WHO CARES?)
	JUMPE	X,LITSR4		;NO MERGE IF X IS EMPTY. ADD W TO OUT-LIST
LITSR3:	PUSHJ	P,LCOMP			;COMPARE CAR(W) AND CAR(X).
					;  RETURN SMALLEST IN X
	HRRM	X,(Z)			;X<W. ADD CAR(X) TO OUT-LIST
	MOVEI	Z,(X)			;ADVANCE END OF OUT-LIST.
	HRRZ	X,(X)			;FORM CDR(NA)
	JUMPN	X,LITSR3		;CONTINUE THE MERGE
LITSR4:	HRRM	W,(Z)			;STORE OTHER LIST IN THE OUT-LIST
	MOVE	X,Y			;GET THE ADDRESS OF THE LIST-HEAD
	POPJ	P,			;RETURN, POINTER TO SORTED LIST IN NA


;LCOMP - COMPARE CAR(X) AND CAR(W).
LCOMP:	PUSHJ	P,LCOMP0		;SKIP IF X<W
	EXCH	X,W			;X>W  EXCH THEM
	POPJ	P,			;RETURN X<W

LCOMP0:	MOVE	K,X
	MOVE	M,W
LCOMP1:	ADDI	K,1
	ADDI	M,1
	MOVE	A,(K)
	LSH	A,-1
	MOVE	B,(M)
	LSH	B,-1
	CAMN	A,B
	JRST	LCOMP1			;LOOP WHILE THEY'RE THE SAME
	TLNN	A,370000		;DID A RUN OUT?
	JRST	CPOPJ1			;YES. X<W.  SKIP RETURN
	TLNN	B,370000		;DID B RUN OUT?
	POPJ	P,			;YES. W<X  - DIRECT RETURN
	CAMGE	A,B			;SKIP IF X>W
	AOS	(P)			;X<W SKIP RETURN
	POPJ	P,


;FLUSH THE MISSPELLINGS FROM THE DICTIONARY. (CALLED BY SAVME)
MISFLU:	SKIPG	NMIS
	POPJ	P,
	SETZM	NMIS
	MOVSI	Z,-HASHTL
MISFL1:	HLRZ	X,HASHTB(Z)
	MOVE	Y,[HRLM X,HASHTB(Z)]
	PUSHJ	P,MISSUB		;DO LEFT SIDE
	HRRZ	X,HASHTB(Z)
	MOVE	Y,[HRRM X,HASHTB(Z)]
	PUSHJ	P,MISSUB		;DO RIGHT SIDE
	AOBJN	Z,MISFL1		;LOOP
	POPJ	P,

MISSUB:	JUMPE	X,CPOPJ
	MOVE	B,(X)
	TLNE	B,MISSPL		;MISSPELLING?
	JRST	MISSU1			;YES
	MOVE	Y,[HRRM X,(A)]		;NO.
	MOVEI	A,(X)			;SAVE "PREVIOUS ADDRESS"
	HRRZ	X,(X)
	JRST	MISSUB

MISSU1:	HRRZ	X,(X)			;GET FORWARD LINK
	XCT	Y			;STORE USING Y
	JRST	MISSUB			;LOOP.

	SUBTTL	DICTIONARY MANIPULATION - LOADER - LOAD A DICTIONARY FILE.
	PAGE

IFE TENEX,<
LOAD1A:		SKIPE	,NDICTI+1	;IS DICT 1 EMPTY
		JRST	LOAD.1		;NO
		OUTSTR	[ASCIZ/Loading default dictionary WORDS.DIC
/]
		MOVE	K,['WORDS ']	;YES, TRY
		MOVSI	L,'DIC'		;DEFAULT DICTIONARY
		MOVEI	M,0		;IN OWN PPN
		MOVEI	N,0
		PUSHJ	P,LOAD1B	;GET INTO NORMAL FLOW
		SKIPA >		;MDA 790112
LOADER:	PUSHJ	P,LOADEX
	OUTSTR	[ASCIZ/Do you want to save this core image?  /]
	INCHWL	A
	PUSHJ	P,FLUTTY
	CAIE	A,"Y"
	CAIN	A,"y"
	JRST	.+2
	POPJ	P,
	PUSHJ	P,SAVEME
	JRST	START		;HAVE TO REESTABLISH THE WORLD AFTER THE RESET

LOADEX:
IFE TENEX,<	SKIPE	NDICT
		JRST	LOAD.1 >	;MUST LOAD DICTIONARY ZERO
	OUTSTR	[ASCIZ/
You must load a dictionary file.
/]				;IN CASE THERE'S NO DICTIONARY
LOAD.1:	OUTSTR	[ASCIZ/Dictionary file name: /]

IFN TENEX,<	PUSHJ	P,INDICT
		MOVEI	K,DICTBF
		SETZB	L,M			;NO DEFAULTS
		PUSHJ	P,GETFIL
		JRST	LOAD.1	>		;TRY AGAIN.

IFE TENEX,<	PUSHJ	P,GETFIL		;PRESUMED TO RETURN IN K,L,M,N.
		POPJ	P,			;NO FILE SPECIFIED. MDA 790112
LOAD1B:		PUSHJ	P,INDICT
		JRST	LOAD.1	>

	LOOKUP	DICT,K
	JRST	[PUSHJ	P,FNOTFM
		JRST	LOAD.1]
	TRZ	FL,IDUMP
	SKIPE	NDICT
	JRST	LOAD.7				;ALREADY HAVE A DICTIONARY
	SETZM	HASHTB
	MOVE	A,[XWD HASHTB,HASHTB+1]
	BLT	A,HASHTB+HASHTL-1		;CLEAR HASH TABLE
	SETZM	NDICTI		;ZERO ALL DICTIONARY COUNTS
	MOVE	A,[NDICTI,,NDICTI+1]
	BLT	A,NMIS
	JRST	LOAD.5

LOAD.7:
IFE TENEX,<	SKIPE	,NDICTI+1		;FIRST LOAD OF A DICTIONARY?
		JRST	LOAD.0		;NO
		MOVEI	A,1		;YES. DICTIONARY 1 DEFAULT
		MOVEM	A,IDNUM
		JRST	LOAD.5 >	;MDA 790112
LOAD.0:	OUTSTR	[ASCIZ/Type "I" to mark these as incremental insertions: /]
	INCHWL	A
	CAIE	A,"I"
	CAIN	A,"i"
	PUSHJ	P,SETNM1
	PUSHJ	P,FLUTTY
LOAD.5:	PUSHJ	P,RDICTW		;READ FIRST WORD
	JRST	LOAD.6			;EOF
	JRST	LOAD.3			;MISSPELLING
	MOVE	A,WORDIN		;GET THE WORD WE READ
	CAIN	W,7			;PRECISELY 7 LETTERS IN THE WORD?
	CAME	A,[BYTE(5)"C","O","M","M","E","N","T"]	;YES. "COMMENT"?
	JRST	LOD.2A			;NOT "COMMENT"; GO LOAD THIS WORD
	OUTSTR	[ASCIZ/(TV-E format directory page being skipped)
/]
LOAD.4:	PUSHJ	P,RDDICT		;SKIP TO NEXT FORM-FEED.
	JRST	LOAD.6			;NONE THERE
	CAIE	A,FF
	JRST	LOAD.4

LOAD.2:	PUSHJ	P,RDICTW		;READ A DICTIONARY WORD
	JRST	LOAD.6			;EOF
	JRST	LOAD.3			;MISSPELLING
LOD.2A:	PUSHJ	P,MATCH			;LOOK UP WORD
	JRST	LOD.2B			;NOT THERE, SO INSERT IT
	JRST	LOD.2C			;MISSPELLED!
	JRST	LOAD.2			;WORD WAS THERE, DON'T ADD IT AGAIN
LOD.2B:	PUSHJ	P,INSERT		;ADD IT TO THE LIST
	JRST	LOAD.2			;BACK FOR MORE

LOD.2C:	OUTSTR	[ASCIZ/The word "/]
	MOVEI	A,WORDIN
	PUSHJ	P,TYPE5
	OUTSTR	[ASCIZ/" corresponds to a known misspelling.  Ignored.
/]
	JRST	LOAD.2

;HERE IS HOW WE READ MISSPELLINGS AND ADD THEM TO THE DICTIONARY
LOAD.3:	PUSHJ	P,MATCH			;CHECK IF WE ALREADY KNOW ABOUT IT
	JRST	LOAD3B			;NO, SO INSERT IT
	JRST	LOD.4A			;ALREADY HERE AS A MISSPELLING
	OUTSTR	[ASCIZ/The misspelling "/]
	MOVEI	A,WORDIN
	PUSHJ	P,TYPE5
	OUTSTR	[ASCIZ/" corresponds to a known word.  Ignored.
/]
LOD.4A:	PUSHJ	P,RDICTW		;READ ITS ALLEGED CORRECTION
	JRST	LOAD.6
	JRST	LOAD.2			;AND IGNORE IT
	JRST	LOAD.2

LOAD3B:	PUSH	P,HASHTB(Z)		;SAVE ENOUGH TO BACK OUT!
	PUSH	P,Z
	PUSH	P,LISTFF		;SAVE ADDRESS OF MISSPELLING
	PUSHJ	P,INSRTM		;INSERT MISSPELLING! CANDBX NOT SET!
	PUSHJ	P,RDICTW		;READ CORRECTION
	JRST	LOAD3Z
	JRST	LOAD3Y		;CORRECTION LOOKS LIKE A MISSPELLING
	PUSHJ	P,MATCH
	JRST	LOAD3C			;NOT THERE, SO INSERT IT
	JRST	LOAD3Y			;ALLEGED CORRECTION IS MISSPELLED
	SOJA	X,LOAD3A		;ALREADY THERE. SET X TO FLAGS, NOT TEXT
LOAD3C:	PUSH	P,LISTFF		;ADDRESS OF CORRECTION
	PUSHJ	P,INSERT		;INSERT CORRECTION
	POP	P,X			;POP ADDRESS OF CORRECTION (FLAGS NOT TEXT)
LOAD3A:	POP	P,Y			;POP ADDRESS OF MISSPELLING
	HRRZM	X,(Y)			;STORE CORRECTION WITH MISSPELLING
	SUB	P,[2,,2]		;ADJUST STACK
	JRST	LOAD.2

LOAD3Y:	OUTSTR	[ASCIZ/An alleged correction, "/]
	MOVEI	A,WORDIN
	PUSHJ	P,TYPE5
	OUTSTR	[ASCIZ/", corresponds to a known misspelling.
Both it and its misspelling were ignored.
/]
	POP	P,LISTFF		;BACK OUT OF THIS MISSPELLING
	POP	P,Z
	POP	P,HASHTB(Z)
	JRST	LOAD.2

LOAD3Z:	POP	P,LISTFF		;BACK OUT OF THIS MISSPELLING
	POP	P,Z
	POP	P,HASHTB(Z)
LOAD.6:	CLOSE	DICT,			;DESELECT FILE
	OUTSTR	[ASCIZ/There are now /]
	MOVE	A,NDICT
	PUSHJ	P,DECPTR
	OUTSTR	[ASCIZ/ words /]
	SKIPG	A,NMIS
	JRST	LOAD6A
	OUTSTR	[ASCIZ /
  and /]
	PUSHJ	P,DECPTR
	OUTSTR	[ASCIZ/ misspelling-corrections /]
LOAD6A:	OUTSTR	[ASCIZ /in the dictionary.
/]


IFE TENEX,<	MOVE	A,.JBREL
		LSH	A,-12
		ADDI	A,1
		PUSHJ	P,DECPTR
		OUTSTR	[ASCIZ/ + /]		;HIGH SEG ALSO
		HRRZ	A,.JBHRL
		SUBI	A,400000		;SUB HI SEG ORIG
		LSH	A,-12			;MDA 790112
		ADDI	A,1
		PUSHJ	P,DECPTR
		OUTSTR	[ASCIZ/ K Core used.
/]	>
	POPJ	P,

	SUBTTL	DICTIONARY MANIPULATION - RDDICT - READ DICTIONARY FILE
	PAGE

;SOS LINE NUMBERS ARE STRIPPED.
;CHARACTER RESULT IN A. SKIP RETURN IS NORMAL, NON SKIP FOR EOF.

RDDICT:	ICOUNT
	SOSLE	DICTBF+2
	JRST	RDICT1

IFE TENEX,<	INPUT	DICT,
		STATZ	DICT,740000
		JRST	DIE
		STATZ	DICT,20000
		POPJ	P,			;DIRECT RETURN MEANS EOF >

IFN TENEX,<	MOVEI	K,DICTBF
		PUSHJ	P,@7(K)
		POPJ	P,>

RDICT1:	ICOUNT
	ILDB	A,DICTBF+1
	JUMPE	A,RDDICT
	PUSH	P,A
	MOVE	A,@DICTBF+1
	TRNE	A,1
	JRST	RDICT2
	POP	P,A
CPOPJ1:	ICOUNT
	AOS	(P)
CPOPJ:	ICOUNT
	POPJ	P,			;NORMALLY A SKIP RETURN

RDICT2:	ICOUNT
	MOVE	A,DICTBF+2
	SUBI	A,5
	MOVEM	A,DICTBF+2		;FIX CHARACTER COUNT.
	AOS	DICTBF+1		;LIKEWISE FIX BYTE POINTER
	POP	P,A
	JRST	RDDICT			;BACK AND READ MORE.
	SUBTTL	DICTIONARY MANIPULATION - RDICTW - READ A DICTIONARY WORD
	PAGE

;RETURNS TO CALL+1 ON EOF
;		+2 IF WORD IS A MISSPELLING (TERMINATED BY ">")
;		+3 IF WORD IS A REAL SPELLING
;CHARACTER COUNT IN W. 5 BIT TEXT IN WORDIN. 7 BIT ASCIZ IN WORDIX

RDICTW:	ICOUNT
	SETZB	W,WORDIN
	MOVE	A,[XWD WORDIN,WORDIN+1]
	BLT	A,WORDIX+12
	MOVE	X,[POINT 5,WORDIN]
	MOVE	Y,[POINT 7,WORDIX]
RDCTW1:	ICOUNT
	PUSHJ	P,RDDICT
	JRST	CPOPJ		;EOF. RETURN +1
	IDPB	A,Y		;SAVE ASCII
	CAIGE	A,"A"
	JRST	RDCTW3		;A DELIMITER OR APOSTROPHE
RDCTW2:	ICOUNT
	TRZA	A,140		;MAKE 5BIT, SKIP
RDCTW6:	MOVEI	A,APOS		;SET CODE FOR APOSTROPHE
	IDPB	A,X		;SAVE 5BIT
	CAILE	W,50
	JRST	RDCTW4		;TOO LONG
	AOJA	W,RDCTW1	;BACK FOR MORE

RDCTW3:	ICOUNT
	CAIN	A,"'"
	JRST	RDCTW6		;CHANGE TO SPECIAL CODE FOR APOSTROPHE
	CAIN	A,">"		;IS THIS A MISSPELLING?
	JUMPN	W,CPOPJ1	;RETURN +2
RDCTW7:	ICOUNT
	CAIE	A,LF
	CAIN	A,FF			;LF AND FF STOP US.
	JRST	[JUMPN	W,CPOPJ2	;RETURN A WORD, IF PRESENT.
		JRST	RDICTW]		;IGNORE ZERO LENGTH WORDS
	PUSHJ	P,RDDICT	;OTHERWISE FLUSH TO END OF LINE OR PAGE
	JRST	CPOPJ		;EOF - RETURN +1
	JRST	RDCTW7

RDCTW4:	OUTSTR	[ASCIZ/Dictionary entry too long, or illegal: /]
	OUTSTR	WORDIX
	OUTSTR	CRLF
RDCTW5:	PUSHJ	P,RDDICT
	JRST	CPOPJ		;EOF - RETURN +1
	OUTCHR	A		;TYPE FURTHER OFFENDING CHARACTERS
	CAIE	A,LF
	CAIN	A,FF		;FF OR LF WILL STOP US
	JRST	RDICTW		;BACK FOR A WHOLE NEW WORD
	JRST	RDCTW5
	SUBTTL	GETFIL	SCAN TERMINAL FOR A FILE NAME.
	PAGE

IFE TENEX,<
;SCAN DEV:FILE.EXT[PRJ,PRG]<CRLF>.  RETURNS K,L,M,N = FILE,EXT,DEV,PPN.

GETFIL:
SCAN:	SETZB	K,L
SCAN4:	SETZB	M,N			;ENTRY WHEN WISHING TO REUSE NAME. MDA 790112
	PUSHJ	P,GETSIX		;GET SIXBIT TERM
	JUMPE	B,[CAIE A,12		;NULL TERM MUST END WITH LF
		JRST SCNERR		;NO.
		POPJ P,]		;DIRECT RETURN = NULL TERM
	CAIE	A,":"			;DEVICE NAME?
	JRST	SCAN1			;NO.  MUST BE A FILE NAME
	MOVE	M,B			;LOAD DEVICE NAME
	PUSHJ	P,GETSIX		;GET WHAT SHOULD BE THE FILE NAME
SCAN1:	MOVE	K,B
	CAIE	A,"."			;EXT NEXT?
	JRST	SCAN2			;NOPE.
	PUSHJ	P,GETSIX
	HLLZ	L,B
SCAN2:	CAIE	A,"["			;PPN NEXT?
	JRST	SCAN3			;NO.

IFN STANSW,<	PUSHJ	P,GETSIX
		CAIE	A,","
		JRST	SCNERR		;ERROR IN PPN
		JUMPE	B,SCNERR	;ERROR IN PPN
		PUSHJ	P,RADJ
		MOVSI	N,(B)
		PUSHJ	P,GETSIX
		JUMPE	B,SCNERR	;ERROR IN PPN
		PUSHJ	P,RADJ
		HRRI	N,(B)	>

IFE STANSW,<	PUSHJ	P,PPNSCN
		CAIE	A,","
		JRST	SCNERR
		MOVSI	N,(B)
		PUSHJ	P,PPNSCN
		HRRI	N,(B)	>

	MOVEI	B,0
	CAIN	A,"]"
	PUSHJ	P,GETSIX
	JUMPN	B,SCNERR		;ERROR IF NOT IMEDIATE DELIMITER
SCAN3:	CAIN	A,12			;LF IS THE USUAL END
	JRST	CPOPJ1			;RETURN HAPPY.
SCNERR:	JUMPL	A,.+2
	PUSHJ	P,ILLEG			;GO COMPLAIN AND TELL HIM THE CHARACTER
	PUSHJ	P,FLUTTY		;EMPTY TO NEXT CRLF
	OUTSTR	[ASCIZ/Try again: /]
	JRST	SCAN


IFE STANSW,<

PPNSCN:		MOVEI	B,0
PPNSC1:		INCHWL	A
		CAIL	A,"0"
		CAIL	A,"0"+PPNMUL
		POPJ	P,			;RETURN DELIMITER
		IMULI	B,PPNMUL
		ADDI	B,-"0"(A)
		JRST	PPNSC1		>

IFN STANSW,<
RADJ:		HLRZ	B,B
RADJ1:		TRNE	B,77		;RIGHT ADJUSTED YET?
		POPJ	P,		;YES.
		LSH	B,-6
		JRST	RADJ1		>


GETSIX:	SETZB	B,QMODE			;B ACCUMULATES TEXT. QMODE FOR QUOTING
	SKIPA	C,[POINT 6,B]
QSET:	SETCMM	QMODE			;HERE FOR CTRL A (DOWN ARROW)
GETSX1:	INCHWL	A			;READ A CHARACTER
	ANDI	A,177			;STRIP OFF ANY BUCKY BITS
	MOVE	D,CHRTAB(A)		;GET NORMAL DISPATCH
	SKIPE	QMODE			;SKIP IF NORMAL
	MOVS	D,D			;USE QUOTE MODE DISPATCH
	JRST	(D)

GETSX2:	TRZA	A,100			;HERE FOR LOWER CASE LETTER
GETSX3:	SUBI	A," "			;HERE FOR UPPER CASE LETTER, DIGIT
	TLNE	C,770000		;BYTE OVERFLOW?
	IDPB	A,C			;NOT OVERFLOW. DEPOSIT BYTE
	JRST	GETSX1			;LOOP

DELIM:	POPJ	P,

BLANK:	JUMPN	B,CPOPJ			;TRAILING BLANK IS A DELIMITER
	JRST	GETSX1			;LEADING BLANKS, TABS ARE FLUSHED

ILLEG:	OUTSTR	[ASCIZ/ILLEGAL CHARACTER "/]
	CAIE	A,15
	OUTCHR	A
	OUTSTR	[ASCIZ/" OCCURED IN SCAN/]
	SKIPE	QMODE
	OUTSTR	[ASCIZ/ WHILE IN QUOTE MODE/]
	SETZM	QMODE
	OUTSTR	CRLF
	MOVNI	A,1			;SET DELIMITER TO REDICULOUS
	POPJ	P,			;RETURN, HOPING SOMEONE'LL NOTICE

CHRTAB:	GETSX1,,GETSX1		;NULL
	QSET,,QSET		;CTRL A = DOWN ARROW. SETS QUOTE MODE
	ILLEG,,ILLEG		;2
	ILLEG,,ILLEG		;3
	ILLEG,,ILLEG		;4
	ILLEG,,ILLEG		;5
	ILLEG,,ILLEG		;6
	ILLEG,,ILLEG		;7
	ILLEG,,ILLEG		;10
	ILLEG,,BLANK		;11
	ILLEG,,DELIM		;12
	ILLEG,,ILLEG		;13
	ILLEG,,ILLEG		;14
	ILLEG,,GETSX1		;15 IGNORE
	ILLEG,,ILLEG		;16
	ILLEG,,ILLEG		;17
REPEAT 40-20,<ILLEG,,ILLEG>	;20-37 ARE ALL ILLEGAL
	GETSX3,,BLANK		;40 BLANK IS A DELIMITER
	GETSX3,,ILLEG		;41 !
	GETSX3,,ILLEG		;42 "
	GETSX3,,ILLEG		;43 #
	GETSX3,,GETSX3		;44 $ LEGAL IN FILE NAMES
	GETSX3,,ILLEG		;45 %
	GETSX3,,ILLEG		;46 &
	GETSX3,,ILLEG		;47 '
	GETSX3,,ILLEG		;50 (
	GETSX3,,ILLEG		;51 )
	GETSX3,,ILLEG		;52 *
	GETSX3,,ILLEG		;53 +
	GETSX3,,DELIM		;54 , COMMA
	GETSX3,,ILLEG		;55 -
	GETSX3,,DELIM		;56 . PERIOD
	GETSX3,,ILLEG		;57 /
REPEAT 72-60,<GETSX3,,GETSX3>	;60-71 (0-9) ARE LEGAL
	GETSX3,,DELIM		;72 : 
	GETSX3,,ILLEG		;73 ;
	GETSX3,,ILLEG		;74 <
	GETSX3,,ILLEG		;75 =
	GETSX3,,ILLEG		;76 >
	GETSX3,,ILLEG		;77 ?
	GETSX3,,ILLEG		;100 @
REPEAT 133-101,<GETSX3,,GETSX3>	;101-132 (A-Z) ARE LEGAL
	GETSX3,,DELIM		;133 [
	GETSX3,,ILLEG		;134 \
	GETSX3,,DELIM		;135 ]
	GETSX3,,ILLEG		;136 ^
	GETSX3,,ILLEG		;137 _
	ILLEG,,ILLEG		;140 `
REPEAT 173-141,<GETSX2,,GETSX2>	;141-172 (a-z) ARE LEGAL AND ALWAYS CONVERTED
	ILLEG,,ILLEG		;173
	ILLEG,,ILLEG		;174
	ILLEG,,ILLEG		;175
	ILLEG,,ILLEG		;176
	ILLEG,,ILLEG		;177
>;IFE TENEX


IFN TENEX,<
; K:	POINTER TO HEADER, PRIVATE TO THIS FILE
; L:	POINTER TO ASCIZ FOR DEFAULT NAME
; M:	POINTER TO ASCIZ FOR DEFAULT EXTENSION

GETFI4:	CAIN	1,GJFX33	;HERE ON ERROR.  NULL FILE NAME?
	POPJ	P,		;YES, DON'T SKIP
	MOVEI	1,100
	CFIBF
	OUTSTR	[ASCIZ/ ?
/]
	PUSHJ	P,JSYSER
	OUTSTR	[ASCIZ/Try again: /]
GETFIL:	MOVEM	L,DEFALT+4	;DEFAULT NAME
	MOVEM	M,DEFALT+5	;DEFAULT EXTENSION
	MOVSI	1,(1B2!1B3!1B4)	;OLD, CONFIRM, OLD/NEW
	SKIPGE	6(K)
	MOVSI	1,(1B0!1B3!1B4)	;OUTPUT, CONFIRM, OLD/NEW
	MOVEM	1,DEFALT+0
	MOVEI	1,DEFALT
	SETZ	2,
	GTJFN
	JRST	GETFI4		;ERROR.
	MOVEM	1,3(K)		;STASH THE JFN
	SKIPGE	6(K)		;SKIP ON INPUT
	JRST	CPOPJ1		;OUTPUT - EXIT WITH SKIP RETURN
	JRST	CPOPJ1

>;END IFN TENEX
	SUBTTL	ERROR MESSAGES
	PAGE

DDE:	OUTSTR	[ASCIZ/DEVICE DATA ERROR (OUTPUT)
/]
	HALT

FNOTFM:
IFN TENEX,<POPJ	P, >
	OUTSTR	[ASCIZ/FILE NOT FOUND. DSK:/]
	JRST	TYFILN			;ARGS IN K,L,M,N

NODEV:	OUTSTR	[ASCIZ/DEVICE /]
	PUSHJ	P,TYSIX			;NAME IN B
	OUTSTR	[ASCIZ/: COULD NOT BE OPENED.
/]
	POPJ	P,

BUFTBG:	OUTSTR	[ASCIZ/BUFFER SIZE FOR DEVICE /]
	PUSHJ	P,TYSIX
	OUTSTR	[ASCIZ/: EXCEEDS SPACE ALLOCATED.  CHANGE DBFSIZ AND REASSEMBLE
/]
	POPJ	P,
	

;TYPES DECIMAL NUMBER GIVEN IN A.
DECPTR:	PUSH	P,B
	PUSH	P,C
	SETZ	C,
	PUSHJ	P,DECPTX	;USES B. A IS ARGUMENT
	POP	P,C
	POP	P,B
	POPJ	P,

DECPTX:	IDIVI	A,12		;IF CALLED DIRECTLY, TYPES (A) 
	HRLM	B,(P)		; AS A DECIMAL NUMBER, RIGHT JUSTIFIED
	SOS	C		; IN (C) COLUMNS
	JUMPE	A,.+2
	PUSHJ	P,DECPTX
DECPT1:	SOSL	C
	JRST	[OUTCHR [" "]
		 JRST DECPT1]
	HLRZ	A,(P)
	ADDI	A,"0"
	OUTCHR	A
	POPJ	P,

IFE TENEX,<			;IN TENEX VERSION, FLUTTY IS IN TTCALL SIMULATION
FLUTTY:	ICOUNT
	PUSH	P,A
FLUTT1:	ICOUNT
	CAIE	A,12
	CAIN	A,175
	JRST	FLUTT2
	CAIE	A,33
	CAIN	A,176
	JRST	FLUTT2
	INCHRS	A		;INPUT CHARACTER AND SKIP
	JRST	FLUTT2
	JRST	FLUTT1

FLUTT2:	POP	P,A
	POPJ	P,
>;IFE TENEX


NOCORE:	OUTSTR	[ASCIZ/INSUFFICIENT CORE AVAILABLE. I GIVE UP
/]
	EXIT
NOWRIT:	OUTSTR	[ASCIZ/Unable to write in high segment
/]
	EXIT


ENTFAI:
IFN TENEX, <	POPJ	P,	>
	OUTSTR	[ASCIZ/Enter failed on: /]
	JRST	TYFILN

DIE:	OUTSTR	[ASCIZ/DEVICE ERROR (INPUT)
/]
	HALT	.

;LIBUF OR LOBUF OVERFLOW
LOVFLW:	PUSHJ	P,PPAGE
	OUTSTR	[ASCIZ /Line exceeds /]
	MOVEI	A,5*LINSIZ
	PUSHJ	P,DECPTR
	OUTSTR	[ASCIZ ! characters.
You should edit the input file.  Checking/correcting aborted.
!]
	PUSHJ	P,FLOOP		;CLOSE OPEN FILES
	JRST	ENDIT		;LET USER DO SOMETHING ELSE, IF HE WANTS

INTCFN:
IFN TENEX,<	POPJ	P,	>
	OUTSTR	[ASCIZ/
Internal confusion in the spelling checker.  Called from location:  /]
	PUSH	P,A
	HRRZ	A,-1(P)
	PUSH	P,B
	SUBI	A,1
	PUSHJ	P,OCTPTR
IFG COUNTS,<	PUSHJ	P,CRASH>
	POP	P,B
	POP	P,A
	OUTSTR	[ASCIZ/
You may continue, with doubtful results....
/]
	HALT	CPOPJ

;TYPES OCTAL NUMBER GIVEN IN A
OCTPTR:	IDIVI	A,10
	PUSH	P,B
	JUMPE	A,.+2
	PUSHJ	P,OCTPTR
	POP	P,B
	ADDI	B,60
	OUTCHR	B
	POPJ	P,

TYFILN:	PUSH	P,A		;TYPE FILE NAME FROM K,L,N
	PUSH	P,B
	MOVE	B,K
	PUSHJ	P,TYSIX
	HLLZ	B,L
	JUMPE	B,TYPPN
	OUTCHR	["."]
	PUSHJ	P,TYSIX
TYPPN:	JUMPE	N,TYFLRT	;RETURN IF NO PPN
	OUTCHR	["["]
	HLRZ	A,N		;GET PRJ
	PUSHJ	P,TYPPN1	;TYPE PART
	OUTCHR	[","]
	HRRZ	A,N		;GET PRG
	PUSHJ	P,TYPPN1	;TYPE PART
	OUTCHR	["]"]
TYFLRT:	OUTSTR	CRLF
	POP	P,B
	POP	P,A
	POPJ	P,

TYPPN1:
IFN STANSW,<	HRLZ	B,A	;GET ARGUMENT
		JRST	TYSIX	>

IFE STANSW,<	IDIVI	A,PPNMUL
		HRLM	B,(P)
		JUMPE	A,.+2
		PUSHJ	P,TYPPN1
		HLRZ	A,(P)
		ADDI	A,"0"
		OUTCHR	A
		POPJ	P,>

TYSIX:	JUMPE	B,CPOPJ
	MOVEI	A,0
	LSHC	A,6
	ADDI	A," "
	OUTCHR	A
	JRST	TYSIX
	SUBTTL	HASHCP	THE HASH COMPUTATION.
	PAGE
COMMENT/
HASHCP:	COMPUTES THE HASH INDEX TO THE TABLE HASHTB.
ARGUMENTS:	W. WORD LENGTH
		WORDIN	5 BIT WORD
RESULTS:	Z:	THE INDEX TO THE TABLE, EXCEPT
		Z=-1 IF W < 2.
		FLAG, LEFT (IN FL RIGHT) IS SET IF HASH CODE IS ON
		LEFT HALF, OTHERWISE, RIGHT HALF
/

;APOSTROPHE HASHES AS "Z", APOSTROPHE ISN'T LEGAL AS THE FIRST CHARACTER
;OF ANY INPUT OR DICTIONARY WORD, HOWEVER, IN THE PROCESS OF CORRECTION
;WE MAY BE ASKED TO HASH A LEADING APOSTROPHE

HASHCP:	ICOUNT
	SETO	Z,
	JUMPLE	W,[OUTSTR [ASCIZ/0 LENGTH WORD AT HASHCP/]
		POPJ	P,]
	CAIG	W,1
	POPJ	P,		;SIMPLE FOR WORDS OF LENGTH 1.

	LDB	Z,[POINT 5,WORDIN,4]
	CAILE	Z,Z5
	JRST	HSHER2		;ERROR (OR MAYBE APOSTROPHE)
	JUMPE	Z,HASHER
; RESTORE CALCULATION FROM 1972 VERSION. MDA 790112
HASHC0:	SUBI	Z,1
	IMULI	Z,Z5

	LDB	A,[POINT 5,WORDIN,9]
	CAILE	A,Z5
	JRST	HSHER1		;PROBABLY HASHING ERROR, BUT MAYBE APOSTROPHE
	JUMPE	A,HASHER
HASHC1:	ADDI	Z,-1(A)
	IMULI	Z,12
	MOVEI	X,-2(W)
	CAILE	X,11
	MOVEI	X,11
	ADD	Z,X
	TRNE	Z,1
	TRZA	FL,LEFT		;ODD. RIGHT HALF
	TRO	FL,LEFT		;EVEN, SET LEFT FLAG
	LSH	Z,-1		;HALVE Z.
	POPJ	P,

HSHER2:	CAIN	Z,APOS
	SOJA	Z,HASHC0
HSHER1:	CAIN	A,APOS
	SOJA	A,HASHC1	;FOR APOSTROPHE, SET A TO CODE FOR "Z"
HASHER:	OUTSTR	[ASCIZ/HASHING ERROR
/]
	HALT	CPOPJ
	SUBTTL	SEARCH	LOOK IN DICTIONARY FOR A WORD.
	PAGE

COMMENT/	THE SUBJECT OF THE SEARCH LIVES IN WORDIN.
	IT HAS W CHARACTERS.
	IT HAS HASH INDEX Z. (AND PERHAPS FLAG "LEFT" IN RH OF FL)
	IF Z<0 (MEANS W<2) THEN WE WILL ALWAYS FIND IT AS A WORD.
	RETURNS POINTER TO WORD IN X (AND IN STEM).
	RETURNS TO CALL +1 IF WORD NOT FOUND
			+2 IF FOUND AS MISSPELLING
			+3 IF FOUND AS A REAL SPELLING
	CLOBBERS Y, L.
/

;SUBROUTINE MATCH:  PERFORM HASH COMPUTATION, THEN SEARCH FOR
;  WORD.  SKIP RETURN IF FOUND.
MATCH:	PUSHJ	P,HASHCP
SEARCH:	ICOUNT
	JUMPL	Z,CPOPJ2	;EASY.

	MOVEM	W,1(P)		;SAVE W FOR A WHILE.
	IDIVI	W,7		;7 CHARS/WORD IN FIVEBIT
	JUMPE	X,.+2		;SKIP IF REMAINDER ZERO
	ADDI	W,1		;THIS IS ENGLISH WORD'S LENGTH IN MACHINE WORDS.
	MOVN	W,W
	HRLZM	W,WWLEN		;SAVE -WORD LENGTH,,0.  (AOBJN POINTER TO WORDIN)
	MOVE	W,1(P)		;RESTORE W.

	TRNN	FL,LEFT		;MUST WE USE LEFT SIDE?
	SKIPA	L,HASHTB(Z)	;NO. (RIGHT SIDE GETS RIGHT SIDE)
	HLRZ	L,HASHTB(Z)	;USE LEFT SIDE. SIMULATE AN ADVANCE.
SERCH3:	ICOUNT			;HERE FOR FAILURE
	MOVEI	X,(L)		;LINK FORWARD.
	JUMPE	X,CPOPJ		;SEARCH EXHAUSTED, A FAILURE.
	HRRZ	L,(X)		;THIS LOADS L WITH LINK TO THE NEXT.
				;X POINTS ONE BEFORE THE PRESENT ENTRY.
	MOVE	Y,WWLEN		;Y WILL INDEX WORDIN. AOBJN POINTER.
SERCH2:	ICOUNT
	MOVE	K,WORDIN(Y)
	CAME	K,1(X)		;(X IS LAGGING - STARTS AT WORD HEADER)
	JRST	SERCH3		;FAILED
	ADDI	X,1
	AOBJN	Y,SERCH2	;ADVANCE Y (AND X)
	LDB	K,[POINT 5,1(X),4]	;IF W=14,21,... MAY BE COMPARING
	JUMPN	K,SERCH3		;AGAINST A LONGER WORD
	SUBI	X,-1(Y)		;MAKE DIRECT POINTER IN X
	MOVEM	X,STEM		;ALSO SAVE IT IN STEM
	MOVE	Y,-1(X)		;FLAGS WORD OF ENTRY
	TLNN	Y,MISSPL	;SKIP IF THE WORD IS MISSPELLED
CPOPJ2:	AOS	(P)		;ARRANGE FOR RETURN TO CALL+3
	AOS	(P)
	POPJ	P,
	SUBTTL	INSERT
	PAGE
COMMENT/
INSERT THE WORD AT WORDIN. LENGTH IS IN W. HASH INDEX IS IN Z.
LISTFF CONTAINS THE ADDRESS OF THE FIRST FREE WORD OF CORE.
IDNUM CONTAINS THE DICTIONARY NUMBER (0 - 31)

INSRTM:  INSERT MISSPELLING (PTR TO CORRECTION IN CANDBX)
	DICTIONARY ZERO IN HIGH SEGMENT ON TOPS-10
INSERT:  INSERT A PROPER SPELLING
/

INSRTM:	MOVEI	A,1		;HERE TO ADD A MISSPELLING
	MOVEM	A,WWLEN
	PUSHJ	P,CORECK	;MAKE SURE WE HAVE ROOM TO INSERT
	MOVE	A,CANDBX
	SUBI	A,1		;ADJUST TO POINT TO FLAGS OF CORRECTION
INSRT5:	HRRZM	A,@LISTFF	;STORE THRU FIRST FREE ADDRESS IN DICT.
	AOS	LISTFF		;INCREMENT IT.
	TRO	FL,MISSPL	;SAY IT'S A MISSPELLING
	JRST	INSRT2

INSERT:	ICOUNT
	TRZ	FL,MISSPL	;NOT A MISSPELLING
INSRT2:	PUSH	P,W
	PUSH	P,X
	JUMPL	Z,.+2
	CAIL	Z,HASHTL
	PUSHJ	P,INTCFN
	JUMPL	W,.+2
	CAILE	W,62
	PUSHJ	P,INTCFN
	IDIVI	W,7		;7 CHARS/WORD IN FIVEBIT
	JUMPE	X,.+2
	ADDI	W,1
	ADDI	W,1		;TOTAL NUMBER OF WORDS WE NEED TO USE
	MOVEM	W,WWLEN
	POP	P,X
	POP	P,W
	PUSHJ	P,CORECK	;SEE IF WE HAVE ENOUGH SPACE /GET MORE
	TRNE	FL,LEFT		;SKIP IF LEFT CLEAR
	HLRZ	K,HASHTB(Z)	;USE LEFT
	TRNN	FL,LEFT		;SKIP IF LEFT SET
	HRRZ	K,HASHTB(Z)	;USE RIGHT
INSRT6:	MOVE	L,LISTFF	;ADDRESS OF FREE STORAGE
	CAMG	L,K		;OUGHT TO BE BEYOND CURRENT POINTER
	PUSHJ	P,INTCFN
	HRRZ	A,IDNUM
	HRL	K,A		;LH K CONTAINS THE DICTIONARY NUMBER
	TRZE	FL,MISSPL	;SKIP IF NOT A MISSPELLING
	JRST	INSRT3
	AOS	NDICT		;TOTAL NUMBER OF REAL WORDS
	AOS	NDICTI(A)	;AND NUMBER IN THIS DICTIONARY
	JRST	INSRT4

INSRT3:	AOS	NMIS		;TOTAL NUMBER OF MISSPELLINGS
	AOS	NMISI(A)	;AND NUMBER IN THIS DICTIONARY
	TLO	K,MISSPL	;SET MISSPELLING BIT IN LH FLAGWORD
INSRT4:	MOVEM	K,(L)
	MOVEI	K,(L)
	TRNE	FL,LEFT		;SKIP IF LEFT CLEAR
	HRLM	K,HASHTB(Z)	;DEPOSIT NEW LINK ON LEFT
	TRNN	FL,LEFT
	HRRM	K,HASHTB(Z)	;DEPOSIT ON RIGHT
	ADDI	L,1
	SOS	WWLEN
	SOS	WWLEN		;HACK, HACK. (STOP SMOKING)
;NOW THAT THE LIST LINKS ARE HONEST, ADD THE WORD BENEATH (ABOVE)
;THE NEWEST LINK.  L POINTS TO THE FREE CORE.
	SETZ	K,
INSRT1:	ICOUNT
	MOVE	M,WORDIN(K)
	MOVEM	M,(L)
	ADDI	L,1
	CAMGE	K,WWLEN
	AOJA	K,INSRT1
	MOVEM	L,LISTFF	;UPDATE FREE POINTER
	HRLM	L,.JBSA		;HACK SO SAVE WILL WORK
	SETZM	(L)		;SUSPENDERS  (THE BELT WAS DELETED)
	POPJ	P,
	SUBTTL	CORE ROUTINES
	PAGE
COMMENT/
CORECK:	ADD WWLEN TO LISTFF AND IF THE RESULT >JOBREL REQUEST MORE.
GETCOR:	EXPAND CORE BY 1 K.
/

CORECK:	ICOUNT
	PUSH	P,A
CORCK1:	MOVE	A,LISTFF
	ADD	A,WWLEN
	CAML	A,.JBREL
	PUSHJ	P,GETCOR
	POP	P,A
	POPJ	P,

GETCOR:	ICOUNT
	PUSH	P,A
	MOVE	A,.JBREL
	ADDI	A,2000
IFE TENEX,<	CORE	A,
		JRST	NOCORE	>
IFN TENEX,<	MOVEM	A,.JBREL >
	POP	P,A
	POPJ	P,

	SUBTTL	TRYFIX	OUR HUMBLE ATTEMPT TO CORRECT THE WORD.
	PAGE
COMMENT/

THE SUSPECT WORD IS IN WORDIN AS FIVEBIT TEXT.
IF WE FIND A BETTER CANDIDATE, WE WILL SLIP IT IN
AND SKIP RETURN.  IF WE PLAN TO SKIP RETURN, WE HAVE TO COPY
THE NEW WORD INTO THE OUTPUT BUFFER AND SCREW AROUND WITH
SOME POINTERS TO CONVINCE PEOPLE THAT 1. WE HAVE READ THE
INPUT WORD AND 2. THAT WE HAVE USED THE SPACE IN THE OUTPUT BUFFER
SO NO ONE ELSE WILL STEP THERE.  
	IT WOULD ALSO BE NICE IF I WERE TO COPY IN LOWER CASE
OR UPPER CASE, OR MIXED, DEPENDING ON THE ORIGINAL TEXT.
(CHOICES ARE ALL UPPER, ALL LOWER OR FIRST LETTER IN UPPER,
REMAINDER IN LOWER. McCarthy HAD BETTER SPELL HIS NAME RIGHT.)

/

TRYFIX:	ICOUNT
	PUSH	P,W
	PUSH	P,X
	IDIVI	W,7
	JUMPE	X,.+2
	ADDI	W,1
	MOVEM	W,WWLEN
	POP	P,X
	PUSH	P,WWLEN
	MOVE	W,-1(P)
	PUSHJ	P,X1SRCH		;TRY MAYBE ONE LETTER WRONG
	PUSHJ	P,XTRNP			;TRY SIMPLE TRANSPOSITION
	PUSHJ	P,X1EXL			;TRY MAYBE DELETE 1 EXTRA LETTER
	PUSHJ	P,X1LMS			;ADD ONE LETTER
	POP	P,WWLEN
	CAME	W,(P)
	PUSHJ	P,INTCFN		;OOPS W SHOULDN'T CHANGE 
	POP	P,W
	TRNE	FL,QTRAIN		;TRAINING MODE?
	JRST	TRFQDO			;YES.
	MOVE	A,CANDID		;PICKUP COUNT
	CAILE	A,1			;THE EASY WAY?
	PUSHJ	P,REPCK			;MORE THAN ONE. CHECK FOR REPEATS

IFN STANSW,<	TLON	FL,IIIINI
		PUSHJ	P,DOIIIN >	;INITIALIZE STANFORD DISPLAYS

TRYFBA:	MOVE	D,CANDID

IFN TENEX,<	MOVEI	A,100
		SIBE				;SKIP UNLESS TYPEAHEAD
		JUMPE	D,TRYFBD	>	;OMIT TYPEOUT IF NO CANDIDATES

IFN STANSW,<	TLNE	FL,IIISW!DDDSW		;DISPLAY?
		JUMPG	D,TRYIII	>	;JUMP IF CANDIDATES TO DISPLAY

	CAIE	D,1
	JRST	TRYFBB				;JUMP UNLESS EXACTLY 1 GUESS
	OUTSTR	[ASCIZ/I guess: /]
	MOVE	X,CANDBF
	MOVEM	X,CANDBX
	PUSHJ	P,CNVRTY			;CONVERT AND TYPEOUT CANDIDATE
	OUTSTR	CRLF
	JRST	TRYFBZ

TRYFBB:	

IFN STANSW,<	TLNE	FL,IIISW!DDDSW		;III MODE?
		JRST	TRYFBZ		>	;YES. AVOID TYPEOUT

	OUTSTR	[ASCIZ /(/]
	MOVE	A,CANDID
	PUSHJ	P,DECPTR
	OUTSTR	[ASCIZ/ guesses)
/]
TRYFBZ:	OUTSTR	[ASCIZ/*/]
TRYFBD:	INCHWL	A				;FIND SOMETHING
TRYFBX:	CAIL	A,"A"+40
	TRZ	A,40				;CONVERT TO UPPER CASE.
	MOVSI	B,-NTRYCM
TRYFBE:	HRRZ	C,TRYCMD(B)
	CAIE	A,(C)
	AOBJN	B,TRYFBE
	SKIPL	C,TRYCMD(B)
	PUSHJ	P,FLUTTY			;FLUSH REMAINDER OF LINE
	XCT	TRYXCT(B)			;EXECUTE DISPATCH
	JRST	TRYFBW				;IF WE COME BACK

TRYFBY:	OUTSTR	[ASCIZ/?
/]
TRYFBW:	OUTSTR	WORDIX			;RETYPE WORD IN QUESTION
	OUTSTR	[ASCIZ /  /]
	JRST	TRYFBA		;THEN LOOP

TRYCMD:	400000,,"I"	;BIT 0 SET MEANS DON'T FLUSH REST OF LINE
	400000,,"W"
	"?"
	"A"
	400000,,"R"
	"X"
	"D"
	"S"
	400000,,"C"
	"L"
IFG COUNTS,<	"$"	>
NTRYCM==.-TRYCMD
	0				;CATCH ERRRORS HERE

TRYXCT:	JRST	TRYICM			;I - INSERT
	PUSHJ	P,TRYWCM		;W - WRITE DICTIONARY.  LOOP.
	PUSHJ	P,HELMSZ		;? - TYPE HELP MESSAGE.  LOOP.
	JRST	TRYACM			;A - ACCEPT. RETURN TO GET NEXT
	JRST	TRYRCM			;R - REPLACE
	JRST	TRYXCM			;X - FLUSH TO END OF FILE
	OUTSTR	LIBUF			;D - DISPLAY THE LINE AGAIN
	JRST	TRYSCM			;S - SELECT FROM LIST OF CHOICES
	JRST	TRYCCM			;C - CORRECT FROM ONE CHOICE
	JRST	TRYLOD			;L - ACCEPT & LOAD A DICTIONARY.
IFG COUNTS,<	PUSHJ	P,DTRACEY	>;$ - DUMP THE TRACE COUNTS
	JRST	TRYFBY			;CATCH ERRORS

TRYACM:	AOS	NWA		;COUNT WORD ACCEPTED
	POPJ	P,

TRYLOD:	PUSHJ	P,LOADEX	;LOAD DICTIONARY, THEN CAUSE WORD TO
	JRST	CPOPJ1		;BE RETRIED

TRYXCM:	TRO	FL,SHUTUP		;X FLUSH TO END OF FILE
	POPJ	P,

TRYWCM:	PUSHJ	P,SETNM1		;READ DICTIONARY NUMBER
	PUSH	P,W
	PUSHJ	P,IDMPD			;DUMP DICTIONARY.
	POP	P,W
	POPJ	P,

TRYICM:	PUSHJ	P,HASHCP		;CALCULATE HASH ADDRESS
	PUSHJ	P,SETNM1		;SET DICTIONARY NUMBER
	AOS	NWI			;COUNT WORD INSERTED
	JRST	INSERT			;GO INSERT. RETURN UPLEVEL

TRYCCM:	PUSHJ	P,SETNM0		;GET DICT# FOR MISSPL INSERTION
	MOVE	A,CANDID		;MAKE SURE COMMAND IS LEGAL
	CAIE	A,1			;I.E., PRECISELY ONE CANDIDATE
	JRST	TRYFBY			;MAKE LOSE MESSAGE
	JRST	TRFXR1

TRFQDO:	MOVE	A,TRDNUM		;HERE FOR QTRAINING.
	MOVEM	A,IDNUM			;SET INCREMENTAL DICT. NUMBER
	PUSHJ	P,HASHCP
	PUSHJ	P,INSERT		;STUFF WORD IN DICTIONARY
	AOS	NWI			;COUNT INSERTED WORD
	SKIPG	CANDID			;ANY "CLOSE" WORDS?
	POPJ	P,			;NOPE.
;WE THINK THIS MIGHT BE SOME OTHER WORD SO WE WRITE IN EXCEPTION FILE
	PUSHJ	P,CONVRT		;5BIT TO ASCII IN WORDIX
	MOVEI	B,WORDIX
	PUSHJ	P,WRSEXC
	MOVEI	B,CRLF
	AOS	NQTRN			;COUNT Q-TRAINING EXCEPTION WORD
	JRST	WRSEXC
	SUBTTL	REPLACE AND SELECT COMMANDS
	PAGE

TRYRCM:	PUSHJ	P,SETNM0		;GET DICT# FOR MISSPL INSERTION
	TLNE	FL,ODD			;ODD CASE?
	OUTSTR	[ASCIZ/Type the case of each letter exactly as you want it.  /]
	OUTSTR	[ASCIZ/Replace with: /]
	MOVEM	W,REPLW			;SAVE W, WORDIN, WORDIX UNTIL WE
	MOVE	A,[WORDIN,,REPLIN]	; GET REPLACEMENT.
	BLT	A,REPLIN+20

IFN STANSW,<	MOVE	B,[POINT 7,WORDIX]
		ILDB	A,B
		JUMPN	A,.-1
		MOVEI	A,15
		DPB	A,B
		MOVE	C,B
		MOVEI	A,12
		IDPB	A,B
		TLNE	FL,IIISW!DDDSW	;ON A STANFORD DISPLAY?
		PTLOAD	[0		;YES. GIVE HIM THE WORD TO RE-EDIT
			WORDIX]	
		MOVEI	A,0
		DPB	A,C
		IDPB	A,C		>;PUT WORDIX BACK TO NORMAL

	MOVE	A,[XWD WORDIN,WORDIN+1]		;PREPARE TO GATHER TEXT
	SETZB	W,WORDIN
	BLT	A,WORDIN+20
	MOVE	A,[POINT 5,WORDIN]
	MOVEM	A,TLET.1
	MOVE	A,[POINT 7,WORDIX]
	MOVEM	A,TLET.2
	TLNE	FL,ODD			;ODD CASE?
	SKIPA	A,[JRST REPL1A]		;YES. USER GETS TO TYPE VERBATIM
	MOVE	A,[TRZ	A,40]		;MAKE IT UPPER CASE
	MOVEM	A,RPLXCT
	TLNN	FL,ODD			;JRST REPL1A IF ODD
	MOVE	A,[JRST	REPL1B]	
	MOVEM	A,RPLXC1
REPL.1:	INCHWL	A			;REPLACEMENT CHARACTERS

IFE TENEX,<	CAIE	A,175		;ALT MODE?
		CAIN	A,33		;ANOTHER ALT MODE?
		JRST	REPXIT		;YES. ABORT >

	CAIGE	A,40
	JRST	REPL.2			;TERMINATE ON ANY CONTROL CHR.
	CAIL	A,"A"+40		;HAVE WE GOT LOWER CASE INPUT?
	CAILE	A,"Z"+40		;SKIP IF LOWER CASE
	JRST	.+2			;NOT LOWER CASE
	XCT	RPLXCT			;TRZ A,40 OR JRST REPL1A
	CAIL	A,"A"			;IS THIS A LETTER?
	CAILE	A,"Z"
	JRST	.+2			;NO.
	XCT	RPLXC1			;JRST REPL1B OR JRST REPL1A

	CAIN	A,"'"			;APOSTROPHE?
	JUMPG	W,REPL1A		;JUMP IF APOSTROPHE AFTER FIRST CHARACTER
	MOVNI	W,1			;SET W<0 TO FLAG A NON-LETTER WAS TYPED.
	JRST	REPL1A

REPL1B:	TLNE	FL,LOWER		;IS RESULT SUPPOSED TO BE LOWER?
	TRO	A,40			;YES TURN ON THE BIT
	TLZE	FL,MIXED		;MIXED UPPER THEN LOWER?
	TLO	FL,LOWER		;YES. MUST NOW BE TIME FOR LOWER
REPL1A:	IDPB	A,TLET.2		;STUFF CHARACTER INTO WORDIX
	JUMPL	W,REPL.1		;JUMP IF NON-LETTER SEEN
	CAIN	A,"'"
	MOVEI	A,APOS
	IDPB	A,TLET.1		;STUFF FIVEBIT HERE FOR LATER INSERTION
	BCHECK  (TLET.1,WORDIN+6)
	AOJA	W,REPL.1		;COUNT CHARACTER AND LOOP

REPL.2:	ICOUNT
	CAIGE	W,2
	JRST	REPL.5		;REPLACEMENT TOO SHORT TO BOTHER WITH

	PUSHJ	P,MATCH
	JRST	REPL2A		;REPLACEMENT NOT IN THE DICTIONARY
	JRST	REPL.6		;REPLACEMENT IS A KNOWN MISSPELLING!
	JRST	REPL.4		;REPLACEMENT ALREADY IN DICTIONARY

REPL2A:	OUTSTR	[ASCIZ/Type "I" to insert this replacement in the dictionary: /]
	INCHWL	A
	CAIE	A,"I"
	CAIN	A,"i"
	JRST	REPL.3
	PUSHJ	P,FLUTTY
	JRST	REPL.5

REPL.3:	PUSH	P,IDNUM		;SAVE DICT# SPECIFIED IN "R" COMMAND
	PUSHJ	P,SETNM1
	PUSH	P,LISTFF	;STORE ADDRESS OF INSERTION = CORRECTION
	PUSHJ	P,INSERT
	AOS	NWRI		;COUNT WORD REPLACED AND INSERTED
	POP	P,X		;POP ADDRESS OF CORRECTION
	ADDI	X,1		;POINT AT TEXT INSTEAD OF FLAGS
	POP	P,IDNUM
REPL.4:	MOVEM	X,CANDBX	;SET UP ARGUMENT FOR INSRTM
	MOVE	W,REPLW
	MOVE	A,[REPLIN,,WORDIN]
	BLT	A,WORDIN+5		;RESTORE WORDIN, BUT NOT WORDIX
	PUSHJ	P,HASHCP
	PUSHJ	P,INSRTM		;INSERT THE MISSPELLING
REPL.5:	ICOUNT
	AOS	NWR			;COUNT WORD REPLACED
	MOVE	A,INPTR1
	MOVEM	A,INPTR
	MOVEI	B,[ASCIZ/Replaced by: /]
	PUSHJ	P,WRSEXC		;MAKE EXCEPTION FILE ENTRY
	MOVEI	B,WORDIX
	PUSHJ	P,WRSEXC
	MOVEI	B,CRLF
	PUSHJ	P,WRSEXC
	MOVE	C,[POINT 7,WORDIX]	;COPY WORDIX INTO OUTPUT
REPL5A:	HRRZ	B,OUTPTR
	CAIL	B,LOBUF+LINSIZ		;IS LOBUF FULL?
	JRST	LOVFLW			;YES: COMPLAIN
	ILDB	A,C
	JUMPE	A,CPOPJ1	;SKIP RTN TO SAY WE FIXED THE WORD
	IDPB	A,OUTPTR
	JRST	REPL5A

REPL.6:	OUTSTR	[ASCIZ/The word you typed is a misspelling of "/]
	HRRZ	A,-2(X)
	PUSHJ	P,TYPE5
	OUTSTR	[ASCIZ/".
Type "Y" if you really wish to use it as the replacement: /]
	INCHWL	A
	TRZ	A,40
	CAIN	A,"Y"
	JRST	REPL.5
REPXIT:	CLRBFI				;FLUSH TYPE AHEAD
	MOVE	W,REPLW			;RESTORE ORIGINAL WORD, COUNT
	MOVE	A,[REPLIN,,WORDIN]
	BLT	A,WORDIN+20
	JRST	TRYFBA			;AND LET HIM TRY AGAIN.

TYPE5:	HRLI	A,(POINT 5,0)		;TYPE 5BIT STRING POINTED
	PUSH	P,B			;TO BY A
TYPE5A:	ILDB	B,A
	JUMPE	B,TYPE5B
	CAIN	B,APOS
	SKIPA	B,["'"]
	ADDI	B,"A"-1
	OUTCHR	B
	JRST	TYPE5A

TYPE5B:	POP	P,B
	POPJ	P,

;SELECT COMMAND

TRYSCM:	MOVE	A,CANDID		;HOW MANY CANDIDATES HAVE WE?
	CAIGE	A,2
	JRST	TRYFBY			;EXACTLY ONE CANDIDATE. S WASN'T LEGAL!
	PUSHJ	P,CORRSL		;SELECT FROM CHOICES.
	JRST	TRYFBW			;HE COULDN'T DECIDE.
TRFXR1:	MOVE	X,CANDBX		;HERE FOR C COMMAND WITH CANDBX SETUP
	MOVE	Z,[POINT 5,(X)]
	PUSHJ	P,CONVRZ		;COPY FROM (X) TO WORDIX
	MOVEI	B,[ASCIZ/Corrected to: /]
	PUSHJ	P,WRSEXC
	MOVEI	B,WORDIX
	PUSHJ	P,WRSEXC
	MOVEI	B,CRLF
	PUSHJ	P,WRSEXC		;WRITE EXCEPTION FILE

;WORDIN HAS THE MISSPELLED WORD, CANDBX CONTAINS THE ADDRESS OF THE CORRECTION
	PUSHJ	P,HASHCP		;COMPUTE HASH OF MISSPELLING
	PUSHJ	P,INSRTM		;INSERT MISSPELLING.
;ENTER HERE FOR AUTO-CORRECTION
TRFXR2:	MOVE	D,[POINT 7,WORDIX]	;COPY TEXT FROM WORDIX TO LOBUF
	AOS	NWC			;COUNT WORD CORRECTED
TRFXR3:	ILDB	A,D
	JUMPE	A,TRFXR4
	IDPB	A,OUTPTR
	JRST	TRFXR3

TRFXR4:	MOVE	A,INPTR1
	MOVEM	A,INPTR
	JRST	CPOPJ1

;SELECT A CORRECTION

CORRSL:	MOVEI	D,0
	OUTSTR	[ASCIZ/Type C,^,<altmode>,<cr> or ?
/]
CORRS1:	MOVE	X,CANDBF(D)			;GET THE NEXT WORD
	MOVEM	X,CANDBX			;STORE IT
	PUSHJ	P,CNVRTY			;TYPE IT
CORRS2:	OUTSTR	[ASCIZ/
*/]
	INCHWL	A
	CAIL	A,"A"+40
	CAILE	A,"Z"+40
	JRST	.+2
	TRZ	A,40				;MAKE UPPER CASE
	MOVSI	B,-CORTLN
	HRRZ	C,CORRTB(B)
	CAIE	A,(C)
	AOBJN	B,.-2
	JUMPGE	B,CORR.X			;ERROR
	HLRZ	C,CORRTB(B)
	PUSH	P,C
	CAIN	C,CPOPJ1
	PUSHJ	P,SETNM0		;GET DICT# FOR "C" AND "Y"
	PUSHJ	P,FLUTTY
	POP	P,C
	JRST	(C)

CORRTB:	CPOPJ1,,"C"
	CPOPJ1,,"Y"				;FOR COMPATIBILITY W/ OLD USERS
	CORR.Q,,"?"
	CORR.N,,CR
IFN TENEX,<	CORR.N,,EOL	>
	CORR.U,,"^"
	CPOPJ,,33				;ALTMODE
	CPOPJ,,175				;ALTMODE
	CPOPJ,,176				;ALTMODE
CORTLN==.-CORRTB

CORR.U:	SOJGE	D,CORRS1
	OUTSTR	[ASCIZ/Can't get there from here.
/]
	AOJA	D,CORRS1

CORR.Q:	OUTSTR	HELMS2
	JRST	CORRS2

CORR.X:	OUTSTR	[ASCIZ/?/]
	JRST	CORRS2

CORR.N:	ADDI	D,1
	CAMGE	D,CANDID
	JRST	CORRS1
	OUTSTR	[ASCIZ/Those are all the choices.
/]
	POPJ	P,



; NOTE THAT THIS ROUTINE DEPENDS ON THE FACT THAT 
; BITS 0-4 INCLUSIVE OF A LINK WORD ARE ZERO.
CNVRTY:	HRLI	X,(<POINT 5,0>)
CVTY1:	ILDB	A,X
	JUMPE	A,CPOPJ
	CAIN	A,APOS
	SKIPA	A,["'"]
	ADDI	A,"A"-1
	OUTCHR	A
	JRST	CVTY1

HELMS2:	ASCIZ/
C<cr> or Y<cr> to select this word as the correction,
<cr> to see next word,
^<cr> to see previous word, or
<altmode> to escape from this mode.
/
	SUBTTL	STANFORD DISPLAY ROUTINES
	PAGE

IFN STANSW,<

DDERS:	<BYTE(7)40,15,12>+1		;ASCID SPACE CRLF. USED ALSO TO ERASE
DPCRLF:	<BYTE(7)15,12>+1		;CRLF

INITST:	MOVNI	A,1
	GETLCH	A
	CAMN	A,[-1]
	POPJ	P,		;RETURN IF DETACHED?
	TLNE	A,020000	;SKIP UNLESS DD
	TLO	FL,DDDSW	;SET FLAG FOR DATA DISC
	TLNE	A,400000	;SKIP UNLESS III
	TLO	FL,IIISW	;SET III FLAG
	TLNN	FL,IIISW!DDDSW	;ON A DPY NOW?
	POPJ	P,		;NOPE.
				;FALL INTO DPYINI
;INITIALIZE DISPLAY SCREEN.  SHOVE PAGE PRINTER TO THE BOTTOM
DPYINI:	DPYCLR				;CLEAR THE SCREEN
	PPSEL	1			;SELECT PIECE OF PAPER 1
	PUSHJ	P,DPYRST		;ERASE POP 1
	PPSEL	1			;RESELECT POP 1 - UNDONE BY DPYCLR
	DPYPOS	-200			;PUSH THE PAGE PRINTER TO THE BOTTOM
	DPYSIZ	4002			;SET GLITCHES ETC
	POPJ	P,			;THAT'S ALL FOR NOW.

DPYPOP:	DPYPOS	640			;HERE FOR TTY OUTPUT TO DPY PAGE PRINTER
	DPYSIZ	4010			;4 GLITCHES OF 8 LINES EACH
	POPJ	P,

;RESTORE DISPLAY TO NORMAL STATE
DPYRST:	TLNN	FL,DDDSW		;DATADISC?
	JRST	DPYRS1			;NO. III IS EASIER.
	PUSHJ	P,DPYSTT		;FOR DD WE RUN A PROGRAM TO ERASE THE SCREEN
	CW(1,46,2,0,4,1)		;USUAL FCN, NULL SELECT, LINE=24.
	CW(3,2,3,2,5,10)		;COLUMN=2, LINE=24 LOW LINE MUST BE LAST!
	MOVEI	A,46			;ERASE 38 LINES
	PUSH	Z,DDERS
	SOJG	A,.-1
	PUSH	Z,[0]
	UPGIOT	DPYHDR
DPYRS1:	DPYCLR				;NORMALIZE PAGE PRINTER.  CLEAR EACH POG.
	TLZ	FL,IIIINI		;NEED TO REDRAW OPTION MESSAGE IF RESTARTED.
	POPJ	P,

;HERE TO START A III OR DD BUFFER (USUAL CASE ONLY!)
DPYSTT:	MOVE	Z,[IOWD DPYLEN,DPYBUF]
	TLNE	FL,DDDSW			;REALLY DD?
	JRST	DPYST1				;YES. DO DD INITIALIZE
	PUSH	Z,[0]
CPOPJ2:	AOS	(P)			;ALWAYS DOUBLE SKIP
	JRST	CPOPJ1

DPYST1:	PUSH	Z,@(P)			;STUFF FIRST COMMAND
	AOS	(P)
	PUSH	Z,@(P)			;AND SECOND
	JRST	CPOPJ1			;DOUBLE SKIP RETURN


;DISPLAY THE CURRENT LINE THAT IS IN ERROR.
DPYLIN:	MOVE	B,OUTPTR		;GET THE OUTPUT POINTER
	SETZ	A,
	IDPB	A,B			;STUFF A ZERO IN BEYOND THE OUTPUT LINE.
	DPYPOS	-200			;PUSH THE PAGE PRINTER TO THE BOTTOM
	DPYSIZ	4002			;SET GLITCHES ETC
	TLNE	FL,DDDSW
	PUSHJ	P,DDLN0			;ON DD, ERASE PREVIOUS CRUD
	PUSHJ	P,DPYSTT
	CW(1,46,2,0,4,20)		;USUAL FCN, NULL SELECT, LINE= OCTAL 410
	CW(3,2,3,2,5,10)		;COLUMN=2, LINE=410 LOW LINE MUST BE LAST!!
	TLNN	FL,DDDSW		;SKIP LVW ON DDD
	PUSH	Z,[LVW(-1000,0,I,A,2,2)]	;SET TO LEFT MIDDLE OF SCREEN
	MOVEI	C,1
	MOVE	Y,[POINT 7,C]
	MOVE	X,[POINT 7,LOBUF]	;GET POINTER TO LINE OUTPUT BUFFER
	SETZM	CPXCHR			;ZERO NUMBER OF CHARACTERS XFERED BY COPX
	SETOM	DDDCOL
	PUSHJ	P,COPX
	SKIPN	WORDIX
	JRST	DPYL1
	PUSH	Z,C			;STORE DANGLING WORD
	MOVE	C,CPXCHR
	MOVEM	C,DDDCOL		;SAVE COLUMN NUMBER FOR LATER!
	TLNN	FL,DDDSW		;CAN'T DO NEXT ON DDD
	PUSH	Z,[LVW(20,0,I,,7,4)]	;SET BRIGHTNESS AND SIZE FOR OFFENDER
	MOVE	Y,[POINT 7,C]
	MOVEI	C,1
	MOVE	X,[POINT 7,WORDIX]
	PUSHJ	P,COPX
	PUSH	Z,C
	TLNN	FL,DDDSW		;SKIP LVW FOR DDD
	PUSH	Z,[LVW(20,0,I,,2,2)]	;RESTORE NORMAL BRIGHTNESS AND SIZE
	MOVEI	C,1
	MOVE	Y,[POINT 7,C]
DPYL1:	MOVE	X,INPTR1
	PUSHJ	P,COPX
	PUSH	Z,C
	PUSH	Z,[0]
	HLRE	A,Z
	ADDI	A,DPYLEN
	MOVEM	A,DPYSIZ
	UPGIOT	2,DPYHDR
	TLNE	FL,DDDSW		;SKIP IF III
	SKIPGE	DDDCOL			;DD - SKIP IF WE NEED TO DO BLACK ON GREEN
	POPJ	P,
	PUSHJ	P,DPYSTT
	CW(1,62,2,0,4,20)		;SPECIAL FCN, NULL SELECT, LINE= OCTAL 410
	CW(3,2,3,2,5,10)		;COLUMN=2, LINE=410 LOW LINE MUST BE LAST!!
	MOVE	C,DDDCOL
	ADDI	C,2			;OFFSET TO LEFT MARGIN
	DPB	C,[POINT 8,(Z),15]	;CLOBBER COLUMN NUMBER
	MOVE	Y,[POINT 7,C]
	MOVEI	C,1
	MOVE	X,[POINT 7,WORDIX]
	PUSHJ	P,COPX
	PUSH	Z,C
	PUSH	Z,DPCRLF
	PUSH	Z,[0]
	HLRE	A,Z
	ADDI	A,DPYLEN
	MOVEM	A,DPYSIZ
	UPGIOT	DPYHDR
	POPJ	P,

DDLN0:	PUSHJ	P,DPYSTT		;FIRST ERASE THE OLD CRUD
	CW(1,46,2,0,4,20)		;USUAL FCN, NULL SELECT, LINE= OCTAL 410
	CW(3,1,3,1,5,10)		;COLUMN=1 TO ERASE BLACK ON GREEN!
	PUSH	Z,DDERS			;ASCID CRLF
	PUSH	Z,[0]
	MOVEI	A,4
	MOVEM	A,DPYSIZ
	UPGIOT	DPYHDR
	POPJ	P,


	SUBTTL	STANFORD DISPLAY ROUTINES
	PAGE

DECDIS:	IDIVI	A,12				;DECIMAL PRINTER
	HRLM	B,(P)
	JUMPE	A,.+2
	PUSHJ	P,DECDIS
	HLRZ	A,(P)
	ADDI	A,"0"				;TURN DIGIT INTO A CHARACTER
						;FALL INTO PRINTER.
DISDEP:	AOS	CPXCHR				;COUNT CHARACTERS WE STUFF
	TLNN	Y,740000			;SKIP IF WE ARE WITHIN THE WORD.
	JRST	DISDP1				;WE ARE ABOUT TO OVERFLOW.
	IDPB	A,Y
	POPJ	P,
DISDP1:	PUSH	Z,C				;ADD THIS WORD TO THE OUTPUT
	MOVEI	C,1
	MOVE	Y,[POINT 7,C]
	IDPB	A,Y
	POPJ	P,

COPX:	ILDB	A,X
	JUMPE	A,CPOPJ
	CAIN	A,11
	MOVEI	A,40			;TABS CAN'T BE DISPLAYED
	PUSHJ	P,DISDEP
	JRST	COPX

;INITIALIZATION FOR III AND DDD DISPLAYS
DOIIIN:	TLNN	FL,IIISW!DDDSW
	POPJ	P,
	PUSHJ	P,DPYSTT	;START DISPLAY HEADER
	CW(1,46,2,0,4,2)	;USUAL FCN, NULL SELECT, LINE =36,
	CW(3,2,3,2,5,4)		;LINE=36., COLUMN=2, LOW LINE MUST BE LAST!!
	TLNN	FL,DDDSW	;NO LVW ON DD!
	PUSH	Z,[LVW(-1000,700,I,A,4,4)]
	MOVE	X,[POINT 7,HELMSG]
	MOVE	Y,[POINT 7,C]
	MOVEI	C,1
	PUSHJ	P,COPX
	PUSH	Z,C
	PUSH	Z,[0]		;EXTRA WORD NEEDED FOR DD
	HLRE	A,Z
	ADDI	A,DPYLEN
	MOVEM	A,DPYSIZ
	UPGIOT	0,DPYHDR	;WRITE USING THE POINTER
	POPJ	P,


;DISPLAY PAGE AND LINE NUMBER.
DPGL:	PUSHJ	P,DPYSTT
	CW(1,46,2,0,4,17)		;USUAL FCN, NULL SELECT, LINE= OCTAL 374
	CW(3,2,3,2,5,14)		;COLUMN=2, LINE=374 LOW LINE MUST BE LAST!!
	TLNN	FL,DDDSW
	PUSH	Z,[LVW(-1000,40,I,A,2,2)]	;POSITION III DISPLAY
	MOVEI	C,1
	MOVE	Y,[POINT 7,C]
	MOVE	X,[POINT 7,[ASCIZ/Page /]]
	PUSHJ	P,COPX
	MOVE	A,PAGENO
	PUSHJ	P,DECDIS
	MOVE	X,[POINT 7,[ASCIZ/  Line /]]
	PUSHJ	P,COPX
	TRNE	FL,TECO			;HAS THIS GOT LINE NUMBERS
	JRST	DPGL1			;NO.
	MOVE	X,LIBUF			;GET A LINE NUMBER
	TRNN	X,1			;REAL LINE NUMBER?
	JRST	DPGL1			;NOPE.
	PUSH	P,C
	MOVE	C,LIBUF
	JRST	DPGL2

DPGL1:	MOVE	A,LINENO
	PUSHJ	P,DECDIS
DPGL2:	PUSH	Z,C
	PUSH	Z,DPCRLF		;NEEDED TO EXECUTE THE DD DISPLAY
	PUSH	Z,[0]			;NEEDED TO END THE DD BUFFER
	HLRE	A,Z
	ADDI	A,DPYLEN
	MOVEM	A,DPYSIZ
	UPGIOT	3,DPYHDR
	POPJ	P,

	SUBTTL	STANFORD DISPLAY ROUTINES
	PAGE

;ON A DISPLAY AND THERE ARE GUESSES TO DISPLAY
TRYIII:	MOVE	D,CANDID
	CAIG	D,1
	JRST	IIONE		;ONLY ONE WORD TO TRY
	PUSHJ	P,DPYSTT
	CW(1,46,2,0,4,2)	;USUAL FCN, NULL SELECT, LINE =36,
	CW(3,2,3,50,5,4)	;LINE=36., COLUMN=50, LOW LINE MUST BE LAST!!
	MOVE	D,CANDID
	CAILE	D,22				;MORE THAN 18 LINES CLOBBERS STUFF
	MOVEI	D,22				;TRUNCATE TO WHAT WE CAN DISPLAY
	MOVEM	D,CANDID
TRII.0:	SETZ	D,				;INDEX TO CANDIDATES
TRII.1:	TLNE	FL,DDDSW
	JRST	TRDD.1
	PUSH	Z,[LVW(400,000,I,A,7,3)]	;LVW TO POSITION THE TEXT. Y SET BELOW
	MOVNI	X,40				;LOAD A DIDDLE FACTOR
	IMULI	X,(D)				;TIMES THE WORD INDEX
	ADDI	X,700				;PLUS THE OFFSET
	DPB	X,[POINT 11,(Z),21]		;STORE THE Y POSITION
	JRST	TRDD.2

TRDD.1:	PUSH	Z,[CW(3,50,3,50,3,50)]		;SET COLUMN.
TRDD.2:	MOVEI	C,1
	MOVE	Y,[POINT 7,C]			;DEPOSIT POINTER.
	MOVEI	A,1(D)				;GET THE INDEX+1. 
	PUSHJ	P,DECDIS			;DECIMAL DISPLAY
	MOVEI	A,"."				;AND
	PUSHJ	P,DISDEP
	MOVEI	A," "
	PUSHJ	P,DISDEP
	MOVE	X,CANDBF(D)			;GET ADDRESS OF A CANDIDATE
	HRLI	X,(<POINT 5,0>)			;MAKE A BYTE POINTER
TRII.2:	ILDB	A,X				;GET A BYTE
	JUMPE	A,TRII.3			;JUMP IF DONE.
	CAIN	A,APOS
	SKIPA	A,["'"]
	ADDI	A,"A"-1				;MAKE IT 7 BIT ASCII
	PUSHJ	P,DISDEP			;DISPLAY DEPOSIT.
	JRST	TRII.2

TRII.3:	PUSH	Z,C				;ADD THIS WORD TO THE OUTPUT
	PUSH	Z,DPCRLF			;FOLLOWED BY CRLF
	ADDI	D,1
	CAMGE	D,CANDID
	JRST	TRII.1
	TLNN	FL,DDDSW
	PUSH	Z,[LVW(-1000,140,I,A,7,4)]	;VECTOR OVER TO THE LEFT CENTER
	TLNE	FL,DDDSW
	PUSH	Z,[CW(3,50,3,50,3,50)]		;SET COLUMN.
	MOVEI	C,1
	MOVE	Y,[POINT 7,C]
	MOVE	X,[POINT 7,DIGMES]		;GET MESSAGE POINTER
	PUSHJ	P,COPX
	PUSH	Z,C
	PUSH	Z,[0]
	HLRE	A,Z				;GET THE SIZE FIELD
	ADDI	A,DPYLEN
	MOVEM	A,DPYSIZ
	UPGIOT	1,DPYHDR			;TURN ON THE TEXT
	TLNN	FL,DDDSW
	JRST	TRII5A			;NO EFFORT TO ERASE ON III

	PUSHJ	P,DPYSTT	;PREPARE PROGRAM TO ERASE DD
	CW(1,46,2,0,4,2)	;USUAL FCN, NULL SELECT, LINE =36,
	CW(3,2,3,50,5,4)	;LINE=36., COLUMN=50, LOW LINE MUST BE LAST!!
	MOVE	D,CANDID	;NUMBER OF CANDIDATES
TRDD.3:	PUSH	Z,[CW(3,50,3,50,3,50)]		;SET COLUMN.
	PUSH	Z,DDERS
	SOJGE	D,TRDD.3
	PUSH	Z,[0]
	HLRE	A,Z				;GET THE SIZE FIELD
	ADDI	A,DPYLEN
	MOVEM	A,DPYSIZ

TRII5A:	OUTSTR	[ASCIZ/*/]
	INCHWL	A				;WAIT FOR A CHARACTER
	CAIL	A,"0"
	CAILE	A,"9"				;DECIMAL DIGIT?
	JRST	TRIXIT				;NO. ALL THAT WORK FOR NOTHING.
	MOVEI	B,-"0"(A)			;OK
TRII.6:	INCHWL	A
	CAIL	A,"0"
	CAILE	A,"9"
	JRST	TRII.7
	IMULI	B,12
	ADDI	B,-"0"(A)
	JRST	TRII.6

TRII.7:	CLRBFI
	SUBI	B,1				;DECREASE TO MAKE INDEX
	CAML	B,CANDID			;LESS THAN CANDID?
	JRST	[OUTSTR [ASCIZ/NUMBER TOO BIG
/]
		JRST	TRII5A]			;LOSER
	TLNE	FL,DDDSW
	UPGIOT	DPYHDR				;ERASE SCREEN
	MOVE	A,CANDBF(B)
	MOVEM	A,CANDBX			;SAVE ADDRESS OF THIS STUFF
	JRST	TRFXR1				;AND CORRECT THE WORD, ETC.

TRIXIT:	UPGIOT	1,DPYHDR
	JRST	TRYFBX				;PROCESS COMMAND AS IF NORMAL.


;HERE TO DISPLAY THE ONE GUESS WE HAVE
IIONE:	PUSHJ	P,DPYSTT
	CW(1,46,2,0,4,17)	;USUAL FCN, NULL SELECT, LINE =360
	CW(3,2,3,2,5,00)	;LINE=360, COLUMN=2, LOW LINE MUST BE LAST!!
	TLNN	FL,DDDSW
	PUSH	Z,[LVW(-1000,140,I,A,7,4)]
	MOVEI	C,1
	MOVEI	Y,[POINT 7,C]
	MOVE	X,[POINT 7,[ASCIZ/C Correct this to "/]]
	PUSHJ	P,COPX
	MOVE	X,CANDBF
	HRLI	X,(<POINT 5,0>)
IIONE1:	ILDB	A,X
	JUMPE	A,IIONE2
	CAIN	A,APOS
	SKIPA	A,["'"]
	ADDI	A,"A"-1
	PUSHJ	P,DISDEP
	JRST	IIONE1

IIONE2:	MOVE	X,[POINT 7,[ASCIZ/"
/]]
	PUSHJ	P,COPX
	PUSH	Z,C
	PUSH	Z,[0]
	HLRE	A,Z
	ADDI	A,DPYLEN
	MOVEM	A,DPYSIZ
	UPGIOT	1,DPYHDR

	PUSHJ	P,DPYSTT	;SETUP TO CLEAR DISPLAY
	CW(1,46,2,0,4,17)	;USUAL FCN, NULL SELECT, LINE =360
	CW(3,2,3,2,5,00)	;LINE=360, COLUMN=2, LOW LINE MUST BE LAST!!
	PUSH	Z,DDERS		;ERASE LINE
	PUSH	Z,[0]
	HLRE	A,Z
	ADDI	A,DPYLEN
	MOVEM	A,DPYSIZ	;ALL SET TO CLEAR THIS ON EXIT

	OUTSTR	[ASCIZ/*/]
	INCHWL	A
	MOVEI	B,1		;INDEX FOR TRII.7
	CAIE	A,"C"
	CAIN	A,"c"
	JRST	TRII.7
	UPGIOT	1,DPYHDR	;DISPLAY AGAIN TO ERASE SCREEN
	JRST	TRYFBX		;RETURN TO PROCESS COMMAND AS IF NORMAL.

DIGMES:	ASCIZ/Select a displayed word by number
/

>;IFN STANSW
	SUBTTL	THE HELP MESSAGE
	PAGE

;HELP MESSAGE FOR DPYS AND TTYS
;DO NOT CHANGE THE LENGTH OR NUMBER OF LINES BECAUSE YOU'LL SCREW UP MY DISPLAY
HELMSG:
	ASCIZ/A Accept word.
I Accept word and insert it
  in the dictionary.
R Replace this word. User will
  be able to type replacement word.
X accept this word, then finish
  recopying without any checking.
W Save the incremental insertions,
  then ask again about this word.
L Load an auxiliary dictionary,
  then reconsider this word.
/
HELMG1:	ASCIZ/D Display the current line again.
/
HELMGS:	ASCIZ/S Select from list of guesses.
/
HELMGC:	ASCIZ/C Correct this word with SPELL's guess.
/

HELMSZ:						;HERE TO DISPLAY HELP MESSAGE
IFN STANSW,<	TLNE	FL,IIISW!DDDSW
		JRST	DOIIIN			;DO III INITIALIZATION MSG >

	OUTSTR	[ASCIZ/
You have the following options:
/]
	SKIPN	A,CANDID		;PUT OUT "S" OR "C" LINE ONLY IF
	JRST	HLPOUT			; APPROPRIATE
	CAIN	A,1
	 JRST	[OUTSTR	HELMGC
		JRST HLPOUT]
	OUTSTR	HELMGS
HLPOUT:	OUTSTR	HELMSG
	OUTSTR	HELMG1
	POPJ	P,

	SUBTTL	REPCHK, SETNUM
	PAGE
REPCK:	MOVE	X,CANDID	;CHECK FOR REPEATS OF THE SAME WORD.
	CAIG	X,1		;ICK! THIS IS N-SQUARED IN CANDID.
	POPJ	P,
	MOVEI	X,1
REPK1:	MOVEI	Y,1(X)
REPK2:	MOVE	Z,CANDBF-1(X)
	CAMN	Z,CANDBF-1(Y)
	JRST	[PUSH	P,Z
		SOS	Z,CANDID
		MOVE	Z,CANDBF(Z)
		MOVEM	Z,CANDBF-1(Y)
		POP	P,Z
		JRST	REPCK]
	CAMGE	Y,CANDID
	AOJA	Y,REPK2
	ADDI	X,1
	CAMGE	X,CANDID
	JRST	REPK1
	POPJ	P,

;GET DICTIONARY NUMBER FROM TTY, THEN FLUSH REST OF LINE.
SETNM0:	SKIPA	B,[0]		;DEFAULT NUMBER IS #0
SETNM1:	MOVEI	B,1		;DEFAULT NUMBER IS #1
	MOVEM	B,IDNUM
	JRST	SETNUM

SETNM3:	OUTSTR	[ASCIZ/Dictionary number too large. Maximum is 31. 
Dictionary number:  /]
SETNUM:	PUSHJ	P,INDEC		;ENTER HERE TO READ DICTIONARY NUMBER
	PUSHJ	P,FLUTTY
	CAILE	B,37		;DICT NUMBER IN BOUNDS?
	JRST	SETNM3		;NO. TRY AGAIN
	SKIPE	B
	MOVEM	B,IDNUM
	POPJ	P,
	SUBTTL	X1SRCH	TRY TO CORRECT ONE MISSPELLED LETTER
	PAGE

X1SRCH:	PUSHJ	P,HASHCP
	JUMPL	Z,CPOPJ			;QUICK FAILURE
	ICOUNT
	PUSHJ	P,SR1WL			;SPECIAL SEARCH
	PUSHJ	P,SAVWD			;SAVE THE LOSING WORD
	MOVEI	A,APOS			;TRY ALL SECOND LETTERS (INCLUDING APOS)
	MOVEM	A,TLET.1
X1SRC2:	DPB	A,[POINT 5,WORDIN,9]	;TWEAKING THE SECOND LETTER
	PUSHJ	P,MATCH
	JFCL
	JRST	X1SRC3			;FAILURE
	AOS	A,CANDID
	CAILE	A,CNBFSZ-1
	MOVEI	A,CNBFSZ-1
	MOVEM	A,CANDID
	MOVEM	X,CANDBF-1(A)
	ICOUNT
X1SRC3:	SOSLE	A,TLET.1
	JRST	X1SRC2
	PUSHJ	P,UNSVWD		;RESTORE ORIGINAL WORD
	MOVEI	A,Z5			;TRY ALL FIRST LETTERS (NOT INCL. APOS)
	MOVEM	A,TLET.1
X1SRC4:	DPB	A,[POINT 5,WORDIN,4]	;TWEAKING THE FIRST LETTER
	PUSHJ	P,MATCH
	JFCL
	JRST	X1SRC5			;FAILURE
	AOS	A,CANDID
	CAILE	A,CNBFSZ-1
	MOVEI	A,CNBFSZ-1
	MOVEM	A,CANDID
	MOVEM	X,CANDBF-1(A)
	ICOUNT
X1SRC5:	SOSLE	A,TLET.1
	JRST	X1SRC4
	JRST	UNSVWD		;REPAIR WORD AND RETURN


;	SPECIAL SEARCH FOR ONE LETTER MISPELLINGS

SR1WL:	ICOUNT
	JUMPLE	Z,CPOPJ		;GIVE UP
	CAIGE	W,3
	POPJ	P,
	PUSH	P,W
	IDIVI	W,7
	JUMPE	X,.+2
	ADDI	W,1
	MOVEM	W,WWLEN		;# WORDS OF 5BIT
	POP	P,W
	TRNE	FL,LEFT
	HLRZ	X,HASHTB(Z)
	TRNN	FL,LEFT
	HRRZ	X,HASHTB(Z)
	JUMPE	X,CPOPJ		;TIME TO QUIT
SR1WL1:	ICOUNT
	HRRZ	N,(X)		;NEXT IN THE CHAIN
	MOVE	Y,(X)		;PICK UP FLAGS WORD
	ADDI	X,1
	MOVEI	K,-1(X)		;BASE ADDRESS OF WORD,-1
	TLNE	Y,MISSPL	;SKIP IF NO MISSPL BIT
	HRRZ	K,-2(X)		;THIS IS A MISSPELLING. CORRECTION-1
	ADDI	K,1
	MOVE	Y,CANDID
	MOVEM	K,CANDBF(Y)	;STUFF ADDRESS IN CASE OF SUCCESS
	SETZB	A,Y		;Y INDEX TO WORDIN, A COUNTS WRONG LETTERS
SRWL1A:	ICOUNT
	MOVE	K,(X)
	XOR	K,WORDIN(Y)
SR1WL3:	JFFO	K,SRWL2A	;LOCATE FIRST ERROR BYTE
	ADDI	Y,1
	CAMGE	Y,WWLEN
	AOJA	X,SRWL1A
	AOS	X,CANDID
	CAILE	X,CNBFSZ-1
	MOVEI	X,CNBFSZ-1
	MOVEM	X,CANDID
SR1WL4:	ICOUNT
	MOVEI	X,(N)		;LINK ON TO NEXT WORD
	JUMPN	X,SR1WL1
	POPJ	P,

SRWL2A:	JUMPG	A,SR1WL4	;TOO MANY ERRORS ALREADY
	IDIVI	L,5		;HERE ON ERROR BYTE.  GET BYTE FROM THE TABLE
	DPB	A,SR1WLT(L)	;ZERO ERROR BYTE
	AOJA	A,SR1WL3	;COUNT ERROR. TEST REMAINDER OF MACHIN WORD.

SR1WLT:	POINT 5,K,4
	POINT 5,K,9
	POINT 5,K,14
	POINT 5,K,19
	POINT 5,K,24
	POINT 5,K,29
	POINT 5,K,34
	SUBTTL	X1EXL	MAYBE HE TYPED ONE EXTRA LETTER
	PAGE
COMMENT/
FOR W TIMES, COPY W-1 LETTERS FROM WDSVWX TO WORDIN
ON THE I'TH COPY, SKIP LETTER NUMBER W-I+1
/

X1EXL:	ICOUNT
	CAIGE	W,3
	POPJ	P,		;CAN'T CORRECT A SHORT WORD
	PUSHJ	P,SAVWD
	MOVEM	W,TLET.1	;TLET.1 WILL SELECT THE LETTER TO
				;SKIP
X1EXL1:	ICOUNT
	SETZM	WORDIN		;READY FOR BLT
	MOVE	A,[XWD WORDIN,WORDIN+1]
	BLT	A,WORDIN+5
	MOVE	B,[POINT 5,WORDIN]
	MOVE	C,[POINT 5,SVWDWX]
	SETZ	D,		;COUNT THE CHARACTERS MOVED
X1EXL2:	ICOUNT
	ILDB	A,C
	ADDI	D,1
	CAME	D,TLET.1
	IDPB	A,B
	BCHECK(B,WORDIN+10)
	CAMGE	D,W
	JRST	X1EXL2
	SUBI	W,1
	PUSHJ	P,MATCH
	JFCL
	JRST	X1EXL3
	AOS	A,CANDID
	CAILE	A,CNBFSZ-1
	MOVEI	A,CNBFSZ-1
	MOVEM	A,CANDID
	MOVEM	X,CANDBF-1(A)
X1EXL3:	ICOUNT
	ADDI	W,1
	SOSLE	TLET.1
	JRST	X1EXL1
	PUSHJ	P,UNSVWD
	POPJ	P,
	SUBTTL	XTRNP	ONE PAIR TRANSPOSITION
	PAGE

XTRNP:	ICOUNT
	PUSHJ	P,SAVWD
	MOVEM	W,TLET.1
	SOS	TLET.1
XTRNP1:	ICOUNT
	SETZM	WORDIN
	MOVE	A,[XWD WORDIN,WORDIN+1]
	BLT	A,WORDIN+5
	MOVE	B,[POINT 5,WORDIN]
	MOVE	C,[POINT 5,SVWDWX]
	SETZ	D,
XTRNP2:	ICOUNT
	ILDB	A,C
	ADDI	D,1
	CAMN	D,TLET.1
	JRST	[PUSH	P,A
		ILDB	A,C
		ADDI	D,1
		IDPB	A,B
		POP	P,A
		JRST  .+1]
	IDPB	A,B
	BCHECK(B,WORDIN+10)
	CAMGE	D,W
	JRST	XTRNP2
	PUSHJ	P,MATCH
	JFCL
	JRST	XTRNP3
	AOS	A,CANDID
	CAILE	A,CNBFSZ-1
	MOVEI	A,CNBFSZ-1
	MOVEM	A,CANDID
	MOVEM	X,CANDBF-1(A)
XTRNP3:	ICOUNT
	SOSLE	TLET.1
	JRST	XTRNP1
	PUSHJ	P,UNSVWD
	POPJ	P,
	SUBTTL	X1LMS   ONE LETTER MISSING
	PAGE

;THE IDEA HERE IS THAT WE MAKE A NULL CHARACTER AND SLIDE IT THRU THE
;WORD, AND AT EACH POSITION WE TRY THE ONE LETTER WRONG MATCH.
;INSTEAD OF PUTTING THE NULL IN THE FIRST OR SECOND CHARACTER, WE TRY
;ALL THE POSSIBLE VALUES OF FIRST AND SECOND.

X1LMS:	ICOUNT
	PUSHJ	P,SAVWD
	MOVEM	W,TLET.2
	AOS	TLET.2
X1LMS1:	ICOUNT
	SETZM	WORDIN
	MOVE	A,[XWD WORDIN,WORDIN+1]
	BLT	A,WORDIN+5
	MOVE	B,[POINT 5,WORDIN]
	MOVE	C,[POINT 5,SVWDWX]
	SETZ	D,
X1LMS2:	ICOUNT
	ILDB	A,C
	ADDI	D,1
	CAMN	D,TLET.2
	IBP	B		;SLIDE PAST THIS BYTE
	IDPB	A,B
	BCHECK(B,WORDIN+10)
	CAMGE	D,W
	JRST	X1LMS2
	ADDI	W,1
	PUSHJ	P,HASHCP
	PUSHJ	P,SR1WL
	SUBI	W,1
	SOS	A,TLET.2
	CAILE	A,2
	JRST	X1LMS1

;NOW TRY ALL VALUES FOR THE SECOND CHARACTER

	SETZM	WORDIN
	MOVE	A,[XWD WORDIN,WORDIN+1]
	BLT	A,WORDIN+5
	MOVE	B,[POINT 5,WORDIN]
	MOVE	C,[POINT 5,SVWDWX]
	ILDB	A,C
	IDPB	A,B
	IBP	B	;SKIP SECOND CHARACTER
	MOVEI	D,2	;START D ONE TOO BIG
X1LMS3:	ILDB	A,C
	IDPB	A,B
	BCHECK(B,WORDIN+10)
	CAIGE	D,(W)
	AOJA	D,X1LMS3

	ADDI	W,1			;SET NEW, LONGER LENGTH.
	ICOUNT
	MOVEI	A,APOS			;ALL POSSIBLE SECOND LETTERS (INC. APOS)
	MOVEM	A,TLET.2
X1LMS4:	DPB	A,[POINT 5,WORDIN,9]
	PUSHJ	P,MATCH
	JFCL
	JRST	X1LMS5
	AOS	A,CANDID
	CAILE	A,CNBFSZ-1
	MOVEI	A,CNBFSZ-1
	MOVEM	A,CANDID
	MOVEM	X,CANDBF-1(A)
	ICOUNT
X1LMS5:	SOSLE	A,TLET.2
	JRST	X1LMS4

;NOW TRY ALL VALUES FOR FIRST CHARACTER.

	LDB	A,[POINT 5,WORDIN,4]	;GET FIRST LETTER
	DPB	A,[POINT 5,WORDIN,9]	;COPY FIRST LETTER TO SECOND
	MOVEI	A,Z5			;ALL POSSIBLE FIRST LETTERS (NOT INC. APOS)
	MOVEM	A,TLET.2
X1LMS6:	DPB	A,[POINT 5,WORDIN,4]
	PUSHJ	P,MATCH
	JFCL
	JRST	X1LMS7
	AOS	A,CANDID
	CAILE	A,CNBFSZ-1
	MOVEI	A,CNBFSZ-1
	MOVEM	A,CANDID
	MOVEM	X,CANDBF-1(A)
	ICOUNT
X1LMS7:	SOSLE	A,TLET.2
	JRST	X1LMS6
	JRST	UNSVWD			;RESTORE ORIGINAL WORD
	SUBTTL	SAVEME  WRITE OUT CORE IMAGE USING SWAP UUO.
	PAGE

; OTHER SYSTEMS WILL HAVE TO TRY DUMP  MODE I-O

SAVEME:	SKIPG	NMIS
	JRST	SAVEM0
	OUTSTR	[ASCIZ/Type Y to flush the misspellings: /]
	INCHWL	A
	PUSHJ	P,FLUTTY
	CAIE	A,"Y"
	CAIN	A,"Y"+40
	PUSHJ	P,MISFLU
SAVEM0:


IFN STANSW,<	OUTSTR	[ASCIZ/By what name shall I save thENDC]
		PUSHJ	P,GETFIL
		JRST	[OUTSTR	[ASCIZ/Default name is SPELL.DMP
/]
			MOVE	K,[SIXBIT/SPELL/]
			MOVEI	M,0
			SETZB	L,N
			JRST	.+1]
		SKIPN	K-1,M		;GET DEVICE NAME, IF ANY
		MOVSI	K-1,'DSK'	;USE DSK IF NO NAME GIVEN
		JUMPN	L,.+2
		MOVSI	L,'DMP'		;DEFAULT EXTENSION
		SETZ	M,		;USE EXISTING SIZE AND START ADDRESS
		MOVSI	0,K-1		;ADDRESS OF SWAP BLOCK INTO LEFT SIDE OF 0
		SWAP	0,
		POPJ	P,		>;IFN STANSW

IFN TENEX,<
SAVEM1:		OUTSTR	[ASCIZ /By what name shall I save this? /]
		HRROI	L,[ASCIZ /SPELL/]
		SKIPGE	TNXEOL		;[Tops20] RUNNING ON TENEX?
		SKIPA	M,[-1,,[ASCIZ /EXE/]]	;[Tops20] NO, USE TOPS20 STD.
		HRROI	M,[ASCIZ /SAV/]	;[Tops20] YES, USE TENEX STD.
		MOVEM	L,DEFALT+4
		MOVEM	M,DEFALT+5
		MOVSI	A,460003
		MOVEM	A,DEFALT+0
		MOVEI	1,DEFALT
		MOVE	2,[100,,101]
		GTJFN
		 JRST	[HRROI	1,[ASCIZ /  ?  /]
			PSOUT
			JRST	SAVEM1]
		HRLI	1,400000		;FORK,,JFN
		MOVE	2,[-700B17+520B26+000B35]
		SETZ	3,
		SSAVE
		TLZ	1,-1
		CLOSF
		 JFCL
		POPJ	P,		>;END IFN TENEX

IFE STANSW!TENEX,<
		OUTSTR	[ASCIZ/SSAVE this core image, then restart the program.
/]
SAVE1A:		EXIT	1,
		POPJ	P,		;IF HE CAN CONTINUE. 
>;;;[decus] end IFE STANSW!TENEX

	SUBTTL	TENEX UUO HANDLER
	PAGE
IFN TENEX,<

UUOH:	PUSH	P,A
	PUSH	P,B		;SAVE 2 AC'S
	HRRZ	B,40
	CAIN	B,1		;CHANGE LOWCOR ADDRESSES TO POINT AT STACK
	MOVEI	B,-1(P)
	CAIN	B,2
	MOVEI	B,0(P)
	LDB	A,[POINT 9,40,8]	;GET OPCODE PART
	CAIL	A,UUOTLN		;IN BOUNDS?
	MOVEI	A,0
	XCT	CUUOT(A)		;YES. B HAS EFFECTIVE ADDR.
	JRST	.+2			;DIRECT RETURN
UUOSKR:	AOS	UUOHX			;SKIP RETURN
UUORET:	POP	P,B
	POP	P,A
	JRSTF	@UUOHX

UUOUND:	HRROI	1,[ASCIZ /
UNDEFINED UUO AT LOC /]
	PSOUT
	PUSH	P,C
	MOVEI	1,101
	HRRZ	2,UUOHX
	MOVEI	3,10
	NOUT
	 JFCL
	HRROI	1,CRLF		;[Tops20]
	PSOUT			;[Tops20]
	POP	P,C
	POP	P,B
	POP	P,A
	HALTF
	JRST	@UUOHX			;IN CASE HE CONTINUES

CUUOT:	JRST	UUOUND		;0
	PUSHJ	P,OPNFIL	;1 ENTER
	PUSHJ	P,OPNFIL	;2 LOOKUP
	PUSHJ	P,UCLS		;3 CLOSE (NEED TO SET UP K)
	JFCL			;4 RELEAS
	JRST	UTTCA0		;5 INCHRW
	JRST	UTTCA1		;6 OUTCHR
	JRST	UTTCA2		;7 INCHRS
	JRST	UTTCA3		;10  OUTSTR
	JRST	UTTCA4		;11  INCHWL
	JRST	UUOUND		;12  GETLCH - ILLEGAL
	JRST	UTTC11		;13  CLRBFI
UUOTLN==.-CUUOT


UCLS:	PUSH	P,K			;SAVE K.
	MOVSI	K,-UCLTLN
	LDB	A,[POINT 4,40,12]	;GET THE AC FIELD OF UUO
	HRRZ	B,UCLTAB(K)		;GET A CHANNEL NUMBER
	CAIE	A,(B)
	AOBJN	K,.-2			;SEARCH
	JUMPGE	K,UCLS1
	HLRZ	K,UCLTAB(K)
	PUSHJ	P,FILCLS
UCLS1:	POP	P,K
	POPJ	P,

UCLTAB:	DICTBF,,DICT
	CORRBF,,CORR
	EXCPBF,,EXCP
	DATABF,,DATA
UCLTLN==.-UCLTAB


;TTY UUOS
UTTCA1:	HRRZ	1,0(2)
	PBOUT
	JRST	UUORET

UTTCA3:	HRROI	1,0(B)
	PSOUT
	JRST	UUORET

UTTC11:	MOVEI	1,100
	CFIBF
	SETZM	NTTYCH		;KILL TTY-IN LINE TOO
	JRST	UUORET

UTTCA4:
UTTCA0:	PUSH	P,N
	SKIPGE	N,NTTYCH	;ARE THERE CHRS ALREADY?
	JRST	GETCH4		;YES
	SETZB	N,NTTYCH	;NO: SUCK 'EM IN TIL END OF LINE
LOOP4:	PBIN
	CAIE	1,"M"&37	; {[Tops20] CR?
	 JRST	LOOP4A		; NO
	MOVEI	1,100		; YES, SEE IF LF FOLLOWS
	PUSH	P,2		; AVOID AC2 CLOBBER
	SIBE
	 CAIA			; NORMAL CASE (THERE SHOULD BE A LF)
	 JRST	LOOP4B		; STRANGE CASE (A TOPS20 FAILURE?)
	PBIN
	CAIN	1,LF		; A LF?
	 JRST	LOOP4B		; YES, PROCEED
	MOVEI	1,100		; NO, BACKUP (ANOTHER TOPS20 FAILURE?)
	BKJFN
	 JFCL
LOOP4B:	MOVEI	1,"M"&37	; CR (WHAT WE GOT TYPED...)
	POP	P,2
LOOP4A:	CAIN	1,37		; A BBN EOL?
	 MOVEI	1,CR		; YES, FORCE A CR
	CAIN	1,"V"&37	; ^V (QUOTING CHAR)
	 JRST	CTRLV
	CAIN	1,"W"&37	; ^W (DELETE WORD)
	 JRST	CTRLW
	CAIN	1,177		; DEL (USED BY TOPS20, WHY NOT ALSO US?)
	 JRST	CTRLA
	CAIE	1,"H"&37	; ANSI/ASCII STANDARD BACKSPACE
	CAIN 1,"A"&37
	 JRST CTRLA
	CAIN	1,"U"&37	; ^U (TOPS20 STANDARD...)
	 JRST	CTRLQ
	CAIE	1,"X"&37	; ANSI/ASCII STANDARD CANCEL LINE
	CAIN 1,"Q"&37
	 JRST CTRLQ
	CAIN 1,"R"&37
	 JRST CTRLR
	MOVEM	1,TTYLIN(N)	;STASH THE CHR
	AOJ	N,		;AND COUNT IT
;;;	CAIE	1,EOL
	CAIE	1,CR		; }[Tops20]
	CAIN	1,LF
	 JRST	ENDLIN
	CAIE	1,ESC
	JRST	LOOP4
ENDLIN:	JUMPE	N,LOOP4		;IF LINE EMPTY
	MOVN	N,N
	HRLZ	N,N
	HRRI	N,TTYLIN	;N= -NCHRS,,TTYLIN
	JRST	GETCH4

CTRLA:	JUMPE	N,[MOVEI 1,7	;CTRL-A: ERASE LAST CHR
		PBOUT
		JRST LOOP4]
	MOVEI	1,"\"
	PBOUT
	MOVE	1,TTYLIN-1(N)
	PBOUT
	SOJA	N,LOOP4

CTRLQ:	HRROI	1,[ASCIZ /_
/]
	PSOUT
	SETZ	N,		;CTRL-Q: ZAP THE LINE SO FAR
	JRST	LOOP4

CTRLR:	PUSH	P,C		;CTRL-R: RETYPE LINE SO FAR
	PUSH	P,D
	HRROI	1,CRLF		;[Tops20]
	PSOUT			;[Tops20]
	MOVE	C,N
	MOVEI	D,TTYLIN
CTRLR1:	SOJL	C,CTRLR2
	MOVE	1,(D)
	PBOUT
	AOJA	D,CTRLR1

CTRLR2:	POP	P,D
	POP	P,C
	JRST	LOOP4

CTRLV:	PUSH	P,2		; ACCEPT AN ARB CHAR
	PUSH	P,3
	MOVEI	1,100
	RFCOC
	PUSH	P,2
	PUSH	P,3
	MOVE	2,[252525,,252525]	; INDICATE ALL CONTROLS
	MOVE	3,2
	SFCOC
	RFMOD
	PUSH	P,2
	IORI	2,17B23		; BE SURE TO WAKE UP
	SFMOD
	BIN			; GET THE CHAR
	MOVEM	2,TTYLIN(N)	; STUFF IT IN PLACE
	POP	P,2
	SFMOD
	POP	P,3
	POP	P,2
	SFCOC
	POP	P,3
	POP	P,2
	AOJA	N,LOOP4		; DONE !!!

CTRLW:				; ^W: ERASE LAST "WORD"
	JUMPE	N,[MOVEI 1,7
		   PBOUT	; NOTHING TO ERASE
		   JRST LOOP4]
	MOVEI	1,"\"
	PBOUT
	MOVE	1,TTYLIN-1(N)
	PBOUT
	SOJE	N,CTRLW2
	CAILE	1," "		; A "SEPARATOR"?
	 JRST	CTRLW1		; NO, GO DELETE UNTIL WE GET ONE
CTRLW0:
	MOVE	1,TTYLIN-1(N)	; SEPARATOR, GO LOOK FOR A NON-SEP
	PBOUT
	SOJE	N,CTRLW2
	CAIG	1," "		; SEPARATOR?
	 JRST	CTRLW0		; YES, KEEP LOOKING
CTRLW1:
	MOVE	1,TTYLIN-1(N)
	CAIG	1," "		; SEPARATOR?
	 JRST	CTRLW2		; YES, DON'T DELETE IT, WE'RE DONE
	PBOUT			; NO, DELETE IT
	SOJE	N,CTRLW2
	 JRST	CTRLW1		; KEEP LOOKING FOR A SEP
CTRLW2:
	MOVEI	1,"\"		; DONE
	PBOUT
	 JRST	LOOP4

UTTCA2:	PUSH	P,N
	SKIPN	N,NTTYCH	;IS THERE A CHR?
	JRST	CA2EX		;NO
	AOS	UUOHX		;YES - SET SKIP RETURN AND GRAB IT
GETCH4:	MOVE	1,(N)
	MOVEM	1,0(2)
	AOBJN	N,.+1		;COUNT THE CHR, BUMP THE ADDRESS
	MOVEM	N,NTTYCH
CA2EX:	POP	P,N
	JRST	UUORET

FLUTTY:	SETZM	NTTYCH		;FLUSH REST OF CHRS IN LINE
	POPJ	P,

;ADDITIONAL INITIALIZATION FOR TENEX
INITX:	MOVEI	1,100		;SET WAKEUP SET SO REG'S WAIT FOR LINE,
	RFMOD			;PICK AT CHRS, FLUSH REST OF LINE
	ANDCMI	2,17B23		;STUFF WORKS RIGHT
	IORI	2,14B23		;FORMATTING AND NON-FORMATTING CONTROLS
	SFMOD
	RFCOC			;NO ECHO FOR ^A, ^H, ^Q, ^R, ^V, ^W, ^X
	ANDCM	2,[3B3+3B17+3B35]
	ANDCM	3,[3B1+3B9+3B11+3B13]
	SFCOC
	SETZM	NTTYCH
	MOVE	1,[JSYS [UUOHX,,UUOH]]
	MOVEM	1,41		;SET UUO HANDLER INSTR.
	SETZM	DICTBF+7	;SET TO NO IO ACTIVE
	SETZM	DATABF+7	
	SETZM	EXCPBF+7
	SETZM	CORRBF+7
	POPJ	P,

>;END IFN TENEX


	SUBTTL	LENGTH	COUNT THE LENGTH OF THE HASH CHAINS.
	PAGE

;INTENDED FOR WIZARDS ONLY - CALL FROM DDT VIA PUSHJ P,
IFN XCNT,<
ERLENG:	OUTSTR	[ASCIZ/SPELL.DAT ENTER FAILED./]
	HALT	.+1
LENGTH:	MOVEI	M,0		;USE DSK: FOR DEVICE (NON-TENEX ONLY)
	PUSHJ	P,INDCTO	;INIT DICTIONARY CHANNEL IN OUTPUT MODE

IFE TENEX,<	MOVE	K,['SPELL ']
		MOVSI	L,'DAT'
		SETZB	M,N	>;IFE TENEX

IFN TENEX,<	OUTSTR	[ASCIZ/LENGTH FILE: /]
		MOVEI	K,DICTBF
		HRROI	L,[ASCIZ/SPELL/]
		HRROI	M,[ASCIZ/DAT/]
		PUSHJ	P,GETFIL
		JRST	.-1	>;IFN TENEX

	ENTER	DICT,K
	JRST	ERLENG
	MOVEI	Y,62
	MOVSI	Z,-HASHTL	;THE MAIN INDEX - AOBJN
LEN.0:	CAIGE	Y,62		;TIME FOR FRESH PAGE?
	JRST	LEN.1		;NO
	MOVEI	Y,0
	MOVEI	B,[ASCIZ/     2     3     4     5     6     7     8/]
	PUSHJ	P,WRSDCT
	MOVEI	B,[ASCIZ/     9    10    11+

/]
	PUSHJ	P,WRSDCT
LEN.1:	MOVEI	C,0			;NUMBER OF COLUMNS
	HLRZ	X,HASHTB(Z)
	PUSHJ	P,LCNT		;DO LEFT SIDE
	HRRZ	X,HASHTB(Z)
	PUSHJ	P,LCNT		;DO RIGHT SIDE
	HLRZ	X,HASHTB+1(Z)
	PUSHJ	P,LCNT		;DO LEFT SIDE
	HRRZ	X,HASHTB+1(Z)
	PUSHJ	P,LCNT		;DO RIGHT SIDE
	HLRZ	X,HASHTB+2(Z)
	PUSHJ	P,LCNT		;DO LEFT SIDE
	HRRZ	X,HASHTB+2(Z)
	PUSHJ	P,LCNT		;DO RIGHT SIDE
	HLRZ	X,HASHTB+3(Z)
	PUSHJ	P,LCNT		;DO LEFT SIDE
	HRRZ	X,HASHTB+3(Z)
	PUSHJ	P,LCNT		;DO RIGHT SIDE
	HLRZ	X,HASHTB+4(Z)
	PUSHJ	P,LCNT		;DO LEFT SIDE
	HRRZ	X,HASHTB+4(Z)
	PUSHJ	P,LCNT		;DO RIGHT SIDE
	CAIL	C,12*6		;WAS ANYTHING ON THIS LINE?
	JRST	LEN.2		;NO
	ADDI	C,2
	MOVEI	A," "
	PUSHJ	P,WDICT		;OUTPUT SPACES
	SOJG	C,.-1
	MOVEI	A,(Z)
	IDIVI	A,5			;DIVIDE 0 TO 675
	IDIVI	A,32			;FIRST LETTER IN A, SECOND IN B
	ADDI	A,"A"
	PUSHJ	P,WDICT			;WRITE ONE CHARACTER
	MOVEI	A,"A"(B)
	PUSHJ	P,WDICT			;WRITE ANOTHER
	MOVEI	B,CRLF
	PUSHJ	P,WRSDCT
	AOS	Y			;COUNT LINE WRITTEN
LEN.2:	ADD	Z,[5,,5]
	JUMPL	Z,LEN.0			;LOOP
	CLOSE	DICT,0
IFE TENEX,<	STATZ	DICT,740000
		JRST	DDE	>
	POPJ	P,

LCNT:	MOVEI	A,0			;COUNT THE NUMBER OF WORDS
LCNT.1:	JUMPE	X,LCNT.2		;JUMP IF DONE
	HRRZ	X,0(X)			;LINK ON.
	AOJA	A,LCNT.1		;COUNT 1 AND LOOP

LCNT.2:	ADDI	C,6			;NUMBER OF COLUMNS SO FAR
	JUMPE	A,CPOPJ			;NOTHING IN THIS LIST
	PUSHJ	P,LCNTD
	SETZ	C,
	POPJ	P,

>
	SUBTTL	THE DEBUG QUEUE
	PAGE
COMMENT  $
IF "COUNTS" IS NON ZERO THEN A QUEUE OF THE
LAST 100 LABELS PASSED WILL BE KEPT.

This code is absolutely NOT recommended for use anywhere at all!

$

IFN COUNTS,<

DEBQUE:	TRNE	FL,NOTRAC		;HERE WITH DEBA SETUP TO STORE A QUEUE ENTRY
	POPJ	P,
	ADD	DEBX,[XWD 1,1]
	MOVEM	DEBA,(DEBX)
	JUMPL	DEBX,DEBQU1
	MOVE	DEBX,[XWD %DBT+%DTL,%DBT]
	BLT	DEBX,%DBT+%DTL-1
	MOVE	DEBX,[IOWD %DTL,%DBT+%DTL]
DEBQU1:	POPJ	P,


;HERE TO WRITE THE QUEUE TO A FILE.

QDUMP:	MOVEI	B,[ASCIZ/
DUMP OF THE QUEUE OF STATEMENTS EXECUTED.
/]
	PUSHJ	P,WRSDCT
	HRRZ	C,DEBX		;LAST ADDRESS STORED IN
	MOVEI	D,%DBT
QDUMP1:	MOVE	A,(D)
	PUSHJ	P,OCTPEX
	MOVEI	B,CRLF
	PUSHJ	P,WRSDCT
	CAMGE	D,C
	AOJA	D,QDUMP1
	POPJ	P,

;HERE FROM INTCFN TO WRITE A CRASH FILE

CRASH:	TRO	FL,NOTRAC
	PUSHJ	P,INDCTO

IFE TENEX,<	MOVE	K,[SIXBIT/CRASH0/]
	CRASH0:	MOVSI	L,'TRC'
		SETZ	M,
		MOVE	N,XPPN
		LOOKUP	DICT,K
		JRST	.+2
		AOJA	K,CRASH0
		MOVSI	L,'TRC'
		SETZ	M,
		MOVE	N,XPPN	>	;IFE TENEX

IFN TENEX,<	MOVSI	A,(1B0!1B16!1B17)
		MOVE	B,[100,,101]
		GTJFN
		 0
		MOVEM	A,3(K)		;K SETUP BY INDCTO >;IFN TENEX


	ENTER	DICT,K
	POPJ	P,
	JRST	DTRACX

IFN STANSW,<XPPN:	SIXBIT	/  SREG/>
IFE STANSW,<XPPN:	SIXBIT	/DMPREG/>
>
	SUBTTL	DTRACE,DTRACY  TRACE DUMP ROUTINE
	PAGE

IFN COUNTS,<

DTRACE:	PUSH	P,[ENDIT]		;
DTRACY:	OUTSTR	[ASCIZ/File name for the trace counts:  /]
	TRO	FL,NOTRAC

IFE TENEX,< 	PUSHJ	P,GETFIL
		JRST	[OUTSTR	[ASCIZ/default name is TRACE.DAT
/]
			MOVE	K,[SIXBIT/TRACE/]
			MOVSI	L,'DAT'
			SETZB	M,N
			JRST	.+1]
		PUSHJ	P,INDCTO
		JRST	DTRACY	>;IFE TENEX


IFN TENEX,<	PUSHJ	P,INDCTO
		MOVEI	K,DICTBF
		HRROI	L,[ASCIZ/TRACE/]
		HRROI	M,[ASCIZ/DAT/]
		PUSHJ	P,GETFIL
		JRST	.-1			>;IFN TENEX

	ENTER	DICT,K
	JRST	[PUSHJ	P,ENTFAI
		JRST	DTRACY]

DTRACX:	PUSHJ	P,QDUMP
	MOVEI	B,[ASCIZ/	Statement execution counts

/]
	PUSHJ	P,WRSDCT
	SETZ	Y,
DTRA.1:	CAIL	Y,ICTABX-ICTAB
	JRST	DTRA.2
	MOVE	A,Y
	PUSHJ	P,OCTPEX
	MOVEI	A,11
	PUSHJ	P,WDICT
	MOVE	A,ICTAB(Y)
	MOVEI	C,0
	PUSHJ	P,DECPTY
	MOVEI	B,CRLF
	PUSHJ	P,WRSDCT
	AOJA	Y,DTRA.1

DTRA.2:	CLOSE	DICT,
	RELEAS	DICT,
	POPJ	P,

OCTPEX:	IDIVI	A,10
	HRLM	B,(P)
	JUMPE	A,.+2
	PUSHJ	P,OCTPEX
	HLRZ	A,(P)
	ADDI	A,"0"
	JRST	WDICT

>;IFN COUNTS

IFN COUNTS!XCNT<

WRSDCT:	HRLI	B,(<POINT 7,0>)
WRSDC1:	ILDB	A,B
	JUMPE	A,CPOPJ
	PUSHJ	P,WDICT
	JRST	WRSDC1

;IF C GT 0, IT TELLS NUMBER OF COLUMNS WITHIN WHICH TO RIGHT JUSTIFY.
LCNTD:					;ENTRY NAME FOR XCNT
DECPTY:	IDIVI	A,12
	HRLM	B,(P)
	SOS	C
	JUMPE	A,.+2
	PUSHJ	P,DECPTY
LCNTD1:	SOSL	C
	JRST	[MOVEI	A," "
		PUSHJ	P,WDICT
		JRST	LCNTD1]
	HLRZ	A,(P)
	ADDI	A,"0"
	JRST	WDICT

>
	SUBTTL	STATS   STATISTICS TYPEOUT
	PAGE

;THIS RATHER PEDESTRIAN HUNK OF STRAIGHT-LINE CODE TYPES OUT THE
;STATISTICS OF WORDS PROCESSED, CONTENTS OF DICTIONARIES,
;AND (IF TENEX, BECAUSE I DON'T KNOW THE CALLS IN TEN50)
;TIME USAGE.
STATS:	MOVE	A,NWA
	JUMPE	A,STAT1
	OUTSTR	[ASCIZ/
Accepted  (A)/]
	MOVEI	C,14
	PUSHJ	P,DECPTX
STAT1:	MOVE	A,NWR
	JUMPE	A,STAT1A
	OUTSTR	[ASCIZ/
Replaced  (R)/]
	MOVEI	C,14
	PUSHJ	P,DECPTX
STAT1A:	MOVE	A,NWC
	JUMPE	A,STAT2
	OUTSTR	[ASCIZ/
Corrected (C,==>)/]
	MOVEI	C,10
	PUSHJ	P,DECPTX
STAT2:	MOVE	A,NWI
	ADD	A,NWRI
	JUMPE	A,STAT3
	OUTSTR	[ASCIZ/
Inserted  (I)/]
	MOVEI	C,14
	PUSHJ	P,DECPTX
STAT3:	MOVE	A,NWA
	ADD	A,NWR
	ADD	A,NWC
	ADD	A,NWI
	JUMPE	A,STAT4
	MOVEM	A,NWNR
	OUTSTR	[ASCIZ/
Total not recognized/]
	MOVEI	C,5
	PUSHJ	P,DECPTX
	MOVE	A,NWNR
	MOVEI	C,7
	PUSHJ	P,DECPTX
STAT4:	MOVE	A,NWAF
	JUMPE	A,STAT5
	OUTSTR	[ASCIZ/
Matched by affix-stripping/]
	MOVEI	C,6
	PUSHJ	P,DECPTX
STAT5:	MOVE	A,NWEX
	JUMPE	A,STAT6
	OUTSTR	[ASCIZ/
Matched exactly/]
	MOVEI	C,21
	PUSHJ	P,DECPTX
STAT6:	MOVE	A,NWNR
	ADD	A,NWAF
	ADD	A,NWEX
	JUMPE	A,STAT7
	OUTSTR	[ASCIZ/
Total words processed/]
	MOVEI	C,13
	PUSHJ	P,DECPTX
STAT7:	OUTSTR	[ASCIZ/

Dict  Words Misspl
/]
	MOVNI	D,40
STAT7A:	MOVE	A,NDICTI+40(D)
	ADD	A,NMISI+40(D)
	JUMPE	A,STAT8
	MOVEI	A,40(D)
	MOVEI	C,4
	PUSHJ	P,DECPTX
	MOVE	A,NDICTI+40(D)
	MOVEI	C,7
	PUSHJ	P,DECPTX
	MOVE	A,NMISI+40(D)
	MOVEI	C,7
	PUSHJ	P,DECPTX
	OUTSTR	CRLF
STAT8:	AOJL	D,STAT7A
	OUTSTR	[ASCIZ/Total/]
	MOVE	A,NDICT
	MOVEI	C,6
	PUSHJ	P,DECPTX
	MOVE	A,NMIS
	MOVEI	C,7
	PUSHJ	P,DECPTX
	OUTSTR	CRLF
IFN TENEX,<			;TYPE "USED MM:SS IN MM:SS"
	HRROI	1,[ASCIZ/
Used /]
	PSOUT
	MOVEI	1,400000
	RUNTM
	IDIV	3,2
	PUSH	P,3
	IDIV	1,2
	SUB	1,CPUTIM
	MOVE	4,1
	MOVEI	1,101
	SETZB	2,3
	MOVSI	5,(1B0+1B17)
	ODTNC
	HRROI	1,[ASCIZ/ in /]
	PSOUT
	POP	P,4
	SUB	4,REALTM
	MOVEI	1,101
	ODTNC
	HRROI	1,CRLF		;[Tops20]
	PSOUT			;[Tops20]
	PSOUT	> 		;[Tops20] END IFN TENEX
	POPJ	P,

	LIT
	SUBTTL	SOME OF THE STORAGE STUFF
	PAGE
IFE TENEX,<	RELOC 0>		;LOW SEGMENT. MDA 790112
PDLEN==40		;LENGTH OF PDL
LINSIZ==200		;LENGTH OF LINE BUFFER
CNBFSZ==50		;LENGTH OF CANDBF
PRELEN==5		;LENGTH OF PREFIX STACK
SUFLEN==20		;LENGTH OF SUFFIX STACK

PDLIST:	BLOCK	PDLEN	;PUSH DOWN LIST STORAGE
PATCH1:	BLOCK	10
PATCH2:	BLOCK	10
PATCH3:	BLOCK	10	;"PATCHES, I'LL ALWAYS BE TRUE..."

IFE TENEX,<			;DEC AND STANFORD BUFFERS ARE PLACED HERE.
QMODE:	BLOCK	1		;FILE SCANNER FLAG
DICTFF:	BLOCK	DBFSIZ*BUFFNO
DATAFF:	BLOCK	DBFSIZ*BUFFNO
EXCPFF:	BLOCK	DBFSIZ*BUFFNO
CORRFF:	BLOCK	DBFSIZ*BUFFNO
BAKFLG:	BLOCK	1		;FLAG FOR CREATION OF .BAK OF INPUT
CORBLK:	BLOCK	4		;LOOKUP BLOCK FROM OUTPUT FILE
INBLK:	BLOCK	4		;LOOKUP BLOCK FROM INPUT FILE
DUMBLK:	14			;OPEN BLOCK
	SIXBIT/DSK/		;TO DELETE BAK FILE
	0
DEVBLK:	BLOCK 4			;BLOCK FOR OBTAINING DEVICE OF INPUT FILE
			>;IFE TENEX

DICTBF:	BLOCK	HDRSIZ
DATABF:	BLOCK	HDRSIZ
EXCPBF:	BLOCK	HDRSIZ
CORRBF:	BLOCK	HDRSIZ

UCASE:	BLOCK	1	;DICTIONARY NUMBER TO ADD UPPERCASE INTO.

HASHTL==32*32*5		;26*26*10/2
HASHTB:	BLOCK	HASHTL	;"Ugh!"

BTABLE:	BLOCK	12	;10. CHAINS PER LETTER PAIR 
HEAPSZ:	BLOCK	1	;TEMP CELL FOR DICTIONARY MERGE
LISTFF:	BLOCK	1	;FIRST FF FOR LIST STRUCTURES.
NDICT:	0		;TOTAL #WDS IN DICT, 0 AT LOAD TIME
NDICT1:	0		;# WORDS IN DICT 1 AT START
NDICTI:	BLOCK 40	;# WORDS IN INDIVIDUAL DICTS
NMISI:	BLOCK 40	;# MISSPELLINGS IN INDIVIDUAL DICTS
NMIS:	0		;TOTAL # OF MISSPELLINGS
NWA:	0		;#WDS ACCEPTED
NWR:	0		;#WDS REPLACED
NWRI:	0		;#WDS INSERTED AFTER REPLACED
NWC:	0		;#WDS CORRECTED
NWI:	0		;#WDS INSERTED
NWNR:	0		;#WDS NOT RECOGNIZED
NWAF:	0		;#WDS MATCHED VIA AFFIX-STRIPPING
NWEX:	0		;#WDS MATCHED EXACTLY
REALTM:	0		;CLOCK TIME AT START OF SESSION
CPUTIM:	0		;CPU TIME AT START OF SESSION
TRDNUM:	0		;DICT# FOR TRAINING SET
NTRDCT:	0		;#WDS IN TRAINING DICT AT START
NQTRN:	0		;NUMBER OF Q-TRAINING WORDS WRITTEN OUT

WORDIN:	BLOCK	6	;5BIT
WORDIX:	BLOCK	13	;7BIT (MUST FOLLOW WORDIN)
LETCNT:	BLOCK	1	;COUNT OF LETTERS (OMITTING APOS) SEEN IN LDWORD

REPLIN:	BLOCK	21	;SAVE WORDIN+WORDIX DURING REPLACE
REPLW:	BLOCK	1	;SAVE W DURING REPLACEMENT
RPLXCT:	BLOCK	1	;INSTR TO XCT DURING REPLACE COMMAND
RPLXC1:	BLOCK	1	;INSTR TO XCT DURING REPLACE COMMAND

PREWD:	BLOCK	6	;STORAGE FOR PREFIX REMOVAL
PREW:	BLOCK	1
PREPTR:	BLOCK	1

SVWDWX:	BLOCK	6	;STORAGE FOR SUFFIX REMOVAL AND CORRECTION HEURISTICS
SVWDLN:	BLOCK	1
STEM:	BLOCK	1		;POINTS TO WORD (STEM) FOUND IN DICTIONARY
PRESTK:	BLOCK	PRELEN		;HOLDS STRIPPED PREFIXES
SUFSTK:	BLOCK	SUFLEN		;HOLDS STRIPPED SUFFIX LETTERS
RECON:	BLOCK	6		;STORAGE FOR RECONS

WWLEN:	BLOCK	1
TVE:	BLOCK	1
LIBUF:	BLOCK	LINSIZ
LOBUF:	BLOCK	LINSIZ
INPTR:	BLOCK	1
OUTPTR:	BLOCK	1
INPTR1:	BLOCK	1
LSTBPY:	BLOCK	1
INITMP:	BLOCK	1

CANDID:	BLOCK	1
CANDBF:	BLOCK	CNBFSZ	;HOLDS ADDRESS OF CORRECTED WORD. POINTS TO TEXT!

IFN STANSW,<
SAVEFL:	0
CPXCHR:	0
DDDCOL:	0
DPYHDR:	200000,,DPYBUF	;POINTER TO DISPLAY BUFFER.  FOR DD, DOUBLE FIELD MODE.
DPYSIZ:	0		;LENGTH OF DISPLAY BUFFER IS STORED HERE
DDDONE:	0		;FOR DD, TELLS WHEN TRANSFER IS DONE (IF OVERLAPPED)
DDPNTR:	DPYBUF+1	;POINTER TO COMMAND WORD CONTAINING LOW ORDER LINE SEL.
DPYLEN==1000		;MAXIMUM LENGTH OF DISPLAY BUFFER
DPYBUF:	BLOCK	DPYLEN	;BUFFER FOR DISPLAY PROGRAM
>

TLET.1:	BLOCK	1
TLET.2:	BLOCK	1
X1BYPT:	BLOCK	1
SAVEXS:	BLOCK	1
CANDBX:	BLOCK	1
PAGENO:	BLOCK	1	;PAGE NUMBER IN INPUT FILE
LINENO:	BLOCK	1	;LINE NUMBER IN INPUT FILE
IDNUM:	BLOCK	1	;NUMBER OF DICTIONARY TO SAVE IN
PICKPG:	BLOCK	1	;PAGE ON WHICH TO TERMINATE PICKUP MODE
PICKLN:	BLOCK	1	;LINE ON WHICH TO TERMINATE PICKUP MODE
CASEBT:	BLOCK	2
CASEPT:	BLOCK	1


IFG COUNTS,<	ICTAB:	BLOCK	%QXX+1
		ICTABX:	BLOCK	1
		%DTL==62
		%DBT:	BLOCK	2*%DTL		;QUEUE FOR TRACE OF EXECUTION>

IFN TENEX,<
TNXEOL:	BLOCK	1		;[Tops20] SET TO -1 IF RUNNING ON TOPS20, ELSE 37
UUOHX:	BLOCK	1		;JSYS WILL STORE PC HERE, JUMP TO UUOH
NTTYCH:	BLOCK	1
TTYLIN:	BLOCK	30		;HOLDS TTY INPUT LINE.
DEFALT:	.-.,,0			;FLAGS,,DEFAULT VERSION FOR GETJFN
	100,,101		;PRIMARY IO
	0			;USE SYSTEM DEFAULT DEVICE DSK:
	0			;USE SYSTEM DEFAULT DIRECTORY (CONNECTED ONE)
	.-.			;DEFAULT FILE NAME
	.-.			;DEFAULT FILE EXTENSION
	0			;USE SYSTEM DEFAULT ACCOUNT
	0			;USE SYSTEM DEFAULT PROTECTION
	0			;NO SPECIAL JFN NUMBER.	>

	END	START