Google
 

Trailing-Edge - PDP-10 Archives - custsupcuspmar86_bb-x130b-sb - soscmd.mac
There are 3 other files named soscmd.mac in the archive. Click here to see a list.
	TITLE	SOSCMD - Command Decoder and Dispatcher
;		--------------------------------------
; 
;  This file contains three modules:
;	1. The Command Decoder and Dispatcher
;	2. Range specifier routines
;	3. Line number search
;	4. The indirect command (@).
; 
 
	SEARCH	SOSTCS
	$INIT
 
	SUBTTL	Command Decoder and Dispatcher
 
; Here is the command decoder and dispatcher

; Note that errors during COPY and TRANSFER commands still come back
; to here and are recovered from by checking the ISCOP flag and
; branching to the COPY/TRANSFER error recovery routine.
;
; Also note that any errors that occur while the user tries to get
; another filename cause a transfer back to SOSEND.

COMND::	SKIPE	INTFLG##	;WHAT TO READ XSOS.INI
	 PUSHJ	P,DOINI		;YES--DO IT NOW
	SETZM	FRCPAG		; Clear assumed page word
	TRZ	FL,CNTF		; This may still be set
IFN CKPSW,<
	PUSHJ	P,WRTBLK##	; Write checkpoint file now
>
	SETZM	ACCUM		; Make sure this is clear also
	SETZM	DELCNT
	TLO	FL2,BELLF	; Allow bells
	SKIPE	SVCRLF		; Did this get left setup?  Error or ^C
	PUSHJ	P,RSCRLF##	; Yes, go restore it now
	MOVE	T1,TABINI	; Get initial tab setting
	PUSHJ	P,SETTAB##	; Fix up TAB setting if needed
	ONECHO			; Make sure this is on
	SETZM	STOPGF
	CLEARM	<LOLN,HILN>
	SETZM	SAVCHR		; Scan should get reset at this point
	MOVE	T1,LNZERO##
	SKIPN	CLN		; Is current line zero?
	MOVEM	T1,CLN		; Make it a real zero then
	TRZ	FL2,ALLPDF	; Clear process dependent flags
IFN	%UAHPQ,<
	PUSHJ	P,HPQOFF##	;[UA WRS] Give the scheduler a break
>
	SKIPN	T1,TEMINC	; Temp incr?
	MOVE	T1,INCR 	; No: use current one
	MOVEM	T1,INCR 	; Yes: restore old one
	SETZM	TEMINC		; Clear temp
	TLNE	FL,SRCOP	; Doing a copy-search
	JRST	INCOPY		; Yes
	SKIPE	ISCOP
	JRST	COPDON##	; Yes, do special clear out
	SKIPA	P,[IOWD PDLSIZ,PDL]; Reset PDL (In case of errors)
INCOPY: MOVE	P,COPDL 	; Pick up special search PDL pointer
	PUSHJ	P,CHKCCI##	; Check for ^C^C
	SKIPE	ENDFLG		; If trying to get another file
	JRST	OFIU1##		; Go back and try again
	SETZM	ERSW		; In case just starting an ER
	MOVE	T1,SVJFF2	; Nominal .JBFF at command start
	MOVEM	T1,.JBFF##	; Restore for all to see
	TDO	T1,CAUNIT	; To next page boundary
	CAME	T1,.JBREL##	; Growing?
	CORE	T1,		; Yes, give it back now
	  JFCL
	TLZE	FL2,DOENDF	; Need end command?
	JRST	CMDEND		; Yes: go do it
; 
	TLZ	FL2,NORENT!RENTF!L2.NAB	; Clear reenter flags
	TRNN	FL,READOF	; Avoid auto-save if read-only or...
	SKIPN	SSAVEN		; Not activated...
	JRST	CMDA
	SKIPG	SAVEN		; Ready for auto-save??
	JRST	CMDSAV		; Yes, go do it
CMDA:	TRNN	FL2,SUPN	; Suppress * after pretty print
	SKIPE	COMFLF		; or if in command file
	CAIA
	PUSHJ	P,CPRMPT	; Go prompt the user
	TRZ	FL2,SUPN	; Turn off some bits
	PUSHJ	P,ENBINT##	; Make sure enabled correctly
IFN	EXTEND,<
	MOVEI	T1,LSNUM	; Reset line search strings
	MOVEM	T1,LSBUFN
>
	SKIPN	COMFLF		; In a command file?
	JRST	CMND1		; No
	MOVE	T2,LN1##	; Increment command count
	MOVE	T1,COMCNT
	PUSHJ	P,ASCIAD##	; Ascii adder
	MOVEM	T1,COMCNT	; Store
CMND1:	PUSHJ	P,GNCH##	; Read a character
	CAIE	C,15
	JUMPE	CS,CMND1	; Ignore spaces etc
	TLNE	CS,LETF_16	; Check to see if letter
	TRZ	C,40		; And convert to upper case
CMND2:	MOVSI	T1,-CMDLG	; Get length of command table
; 
CMND2A: HRRZ	T2,CMD1(T1)	; Get the command letter
	TRZ	T2,XMODF	; Clear any flags before compare
	CAIE	C,(T2)		; Compare
	AOBJN	T1,CMND2A	; Look again if no match
	JUMPG	T1,CMND3	; If not command, try line number
	MOVS	T2,CMD1(T1)	; Fetch entry again and swap
	TLNN	T2,XMODF	; Skip if command modifies file
	JRST	(T2)		; No, dispatch to command
	TRNE	FL,READOF	; Yes, are we in read-only mode?
	NERROR	IRO		; Yep, then this command is an error
	SOS	SAVEN		; Decrement save count and
	JRST	(T2)		; Then go do command
 
CMDSL:	PUSHJ	P,GNCH		; Get next character
	MOVE	CS,CTBL(C)	;  and bits
	MOVEM	C,SAVC		; Save character for rescan
	TLNE	CS,LETF_16	; Is it a letter
	PJRST	SET##		; Yes, treat as set command
	SETZM	HILN		; Force top of page (line 00000)
	TRZ	FL2,STARF	; Clear this, since may still be set
	PUSHJ	P,GETPG		; Get a page number
	JRST	CMND3A		; Finish unnamed command

; Try to get just a line number
 
CMND3:	MOVEM	C,SAVC		; Back up one character
	PUSHJ	P,GET1S 	; Get a single line number
CMND3A:	PUSHJ	P,CKTRMF	; Make sure command is complete
	DMOVE	T1,HILN		; Line number/Page number parsed
	DMOVEM	T1,CLN		; Store as new logical position
	JRST	COMND		; Go back for more


; Come here to do auto save
 
CMDSAV:	PUSHJ	P,ASVCOD##	; Do the save
	JRST	COMND		; Then next command
 
; Here for the null command
 
NULCMD: PUSHJ	P,GNCH		; Grntee LF after CR command
	CAIE	C,12		; Is it?
	NERROR	ILC		; No: lose
	JRST	COMND		; Yes: win
 
CMTCMD:	PUSHJ	P,GNCH		; Get next
	CAIE	C,12		; Look for terminator
	JRST	CMTCMD		; Until found
	JRST	COMND		; Then return

; Here for the form feed command
FFCMD:	PUSHJ	P,DOFF		;PROCESS <FF>
	JRST	COMND		;THEN RETURN

DOFF::	SKIPE	COMFLF		;SEE IF IN COMMAND FILE?
	 POPJ	P,		;YES--IGNORE
	SKIPE	TMFCLR		;CAN WE CLEAR SCREEN?
	 XCT	TMFCLR		;YES--CLEAR SCREEN
	OUTCHR	[15]		;GIVE FREE <CR>
	POPJ	P,		;AND RETURN

; Here if we need an "E" command
 
CMDEND: MOVEI	C,"E"		; Dummy cmd
	TLZ	FL2,RENTF	; Clr flag
	MOVEI	T1,12
	TLNN	FL,SRCOP	; Need dummy LF if not copy
	MOVEM	T1,LIMBO
	JRST	CMND2		; Process
 

; Here to tell users that the old quit command is gone

OQUIT:	PUSHJ	P,SCAN##
	TRNE	FL,TERMF	; Incorrectly terminated?
	SKIPE	EXPFLG		; Or expert
	NERROR  ILC		; Yes, say illegal command
	OUTSTR	[ASCIZ/%Type EQ to quit, W to save the world/]
	JRST	CRLFCM##

; Routine to prompt the user
 
CPRMPT::MOVE	T1,CMDPMT	; Get command prompt
PROMPT::MOVEM	T1,PMTSTR	; Save prompt string
RPRMPT::HRRZ	T1,PMTSTR	; Get string address
	SKIPE	MACLVL##	;SEE IF IN A MACRO
	 POPJ	P,		;YES--NEVER PROMPT
	JUMPE	T1,CPOPJ	; If length is zero
	SKPINC			;Clear ^O
	 JFCL			;..
	OUTSTR	(T1)		; Type it
	POPJ	P,		; And return
	SUBTTL	Table of Commands
 
; Flags (in LH of dispatch word)
 
XMODF== 400000			; Command modifies the file
 
	DEFINE	CMNDS,<
	X	"A",  ALTER,      ;; Alter mode
	X	"B", BEGINN,	;; Go to beginning
	X	"C",   COPY,      ;; Copy a range
	X	"D",  DELET, XMODF;; Delete a range
	X	"E",  ENDIT,	;; End the edit
	X	"F", SEARCH,	;; Find a string
	X	"G",   GEND,	;; Exit and go
	X	"H",   HELP,	;; Type help message
	X	"I", INSERT, XMODF;; Insert some lines
	X	"J",   JUST, XMODF;; Join and justify
	X	"K",   KILL, XMODF;; Kill a page mark
	X	"L",   LIST,	;; List a range
	X	"M",   MARK, XMODF;; Mark a page
	X	"N", NUMBER, XMODF;; Resequence
	X	"O", OCMD,	;; Output
	X	"P",  PRINT,	;; Print
	X	"Q", OQUIT,	;; Old quit
	X	"R", REPLAC, XMODF;; Delete and insert
	X	"S",  SUBST, XMODF;; Substitute
	X	"T",  TRANS, XMODF;; Transfer a range
	X	"V",  VCMD,  XMODF;; Convert case over a range
	X	"W",  SVCOD, 	  ;; Save the world
	X	"X",  XPAND, XMODF;; Expand a line
	X	"@", COMFIL,	;; Do a command file
	X	".", MOVE,	;; Go to a line
	X	"_",	SET,	;; Set a parameter
	X	"/",	CMDSL,	;; Set a parameter or a page
	X	"=",   GIVE,	;; Print a parameter
	X	12, NXTLIN,	;; Print next line (LF)
	X	200, BAKLIN,	;; Print previous line ($)
	X	15, NULCMD,	;; Null command (CR)
	X	14, FFCMD	;; FORM FEED COMMAND
	X	";", CMTCMD,	;; Comment line
	X	"!", MACCMD##,	;; EVALUATE MACRO STRING
>
 
; Command table
 
	DEFINE	X(A,B,C),<
	IF2,<IFNDEF B,<EXTERN B>>
	XWD	B,A!C
>
 
CMD1:	CMNDS
CMDLG==.-CMD1
 
	SUBTTL	Range Specifier Routines
 
; Routine to get one line number from input stream. handles + and -

GETL:	TRZ	FL,LINSN!ADDL!SUBL
	TRZ	FL2,STARF
	TLZ	FL2,UARWF
	CAIN	C,"^"
	JRST	DOFST
	CAIN	C,"*"
	JRST	DOLST
	CAIE	C,"+"		; Check for implicit '.'
	CAIN	C,"-"
	PUSHJ	P,IMPDOT	; Go handle it
IFN	EXTEND,<
	CAIN	C,200		; Do we have to search for it
	PUSHJ	P,LSRCH 	; Ok then here we go
>
	TRZN	FL,NUMF
	POPJ	P,		; Scan did not see a number return
				; (caller can giver err)
	MOVEM	T1,HILN 	; Save the number here
GETL1:	TRO	FL,LINSN	; Set a flag to say we saw the line
	PUSHJ	P,SCAN		; Scan for + or -
	CAIN	C,"+"
	JRST	ADDNUM
	CAIE	C,"-"
	POPJ	P,		; Neither
	TROA	FL,SUBL 	; Set subtract flag
ADDNUM: TRO	FL,ADDL 	; Set add flag
	PUSHJ	P,SCAN		; Scan another
	TRZN	FL,NUMF 	; Was it a number
	NERROR	ILC		; Anything else is illegal
	MOVEM	T2,SVINC	; Save it
	JRST	SCAN		; Return after scanning one more
 
; Here for the '*' meaning last line on page
 
DOLST:	TRO	FL2,STARF
	JRST	GETL1
 
; Here for the '^' meaning first line on page
 
DOFST:	TLO	FL2,UARWF
	JRST	GETL1

 
; Routine to resolve the + and - in the line number. we must wait
; Until the page has been defined before doing this

ADDSUB: MOVE	SINDEX,HILN	; Get the number
	MOVE	T1,HIPG 	; Get the required page
	MOVEM	T1,DPG		; And set it as the desired one
	TLNE	FL2,UARWF
	JRST   [MOVE SINDEX,LNZERO##
		PUSHJ P,FIND##
		SKIPE T1	; Find any
		CAMN T1,PGMK
		 SKIPA T1,INCR	;ASSUMED START
		MOVEM T1,HILN	 ;Setup HILN correctly for now
		MOVE SINDEX,T1
		JRST DOAS]
	TRNN	FL2,STARF
	JRST	DOAS
	MOVE	SINDEX,[<ASCII /99999/>!1]; Find a big line
	PUSHJ	P,FIND
	CAME	T1,[<ASCII /99999/>!1]; If its there its last
	PUSHJ	P,FINDB##	; Else back up
	SKIPE	T1		; Check to see if empty page
	CAMN	T1,PGMK
	SKIPA
	MOVE	SINDEX,T1	; Ok, use one found, else leave big
	MOVEM	SINDEX,HILN	; Save for +, - line numbers
DOAS:	TRZE	FL,ADDL 	; Did we want to add?
	JRST	ADLIN		; Yes, go add
	TRZN	FL,SUBL 	; Or subtract?
CPOPJ:: POPJ	P,		; No, return
	PUSHJ	P,FIND##	; Get the desired line
SUBL1:	SOSGE	SVINC		; Do we want to go back still farther
	POPJ	P,		; No, all done
	PUSHJ	P,FINDB 	; Get the previous line
	MOVE	SINDEX,LNZERO##	; Assume zero
	SKIPE	T1
	CAMN	T1,PGMK 	; Was it a page mark?
	NERROR	NLN		;NO SUCH LINES GONE TOO FAR
	MOVE	SINDEX,T1	; Set up SINDEX
	JRST	SUBL1		; Go try for more
	MOVE	SINDEX,LNZERO##
	POPJ	P,

ADLIN:	PUSHJ	P,FIND##	; Get desired line
	CAME	T1,PGMK 	; Was it a page mark?
	JUMPN	T1,ADLIN1	; Or 0 (i.e. end of file)
	JRST	ADDTOP		; IF OFF THE PAGE
ADLIN1: CAME	T1,HILN 	; See if an exact match
	SOS	SVINC		; If no, already are +1
	MOVE	SINDEX,T1	; Get the word we have found
ADLIN2: SOSGE	SVINC		; Need to go further
	POPJ	P,		; No, return results
	PUSHJ	P,FINDN##	; Get the next line in sequence
	CAME	T1,PGMK 	; Page mark?
	SKIPN	T1		; Or EOF
	JRST	ADDTOP		; If off the page
	MOVE	SINDEX,T1	; Accept new number
	JRST	ADLIN2		; And look for more
 
ADDTOP:	TLZN	FL,L1.MCM	;SEE IF IN MARK COMMAND AND FLAG
	 NERROR	NLN		;NO--NO SUCH LINES GONE TOO FAR
	POPJ	P,		; and exit
; Routine to handle implicit dot, i.e. +nn and -nn are treated
; As if .+nn or .-nn had been typed.
 
IMPDOT::MOVEM	C,SAVC		; Save current character for scan
	MOVEI	C,"."		; Lets get a dot...
	MOVEM	C,SAVCHR	; And fake out scan with it
	PJRST	SCAN		; Call scan and return
 
; Subroutine to verify that a command has been correctly terminated
; Call with
;	PUSHJ	P,CKTRMF
;	<return here if okay>
; Does not return if error but gives ILC error to user
 
CKTRMF::TRNN	FL,TERMF
	NERROR	ILC
	POPJ	P,

; Subroutine to check for command that are illegal in
; BASIC mode.

NOTBSC::SKIPN	BASICF		; Check flag
	POPJ	P,		; If all is well
	NERROR	IBM		; If basic mode
 
; Routine gets a full seq number of form A/B

GETLAS: PUSHJ	P,SCAN
GETLA:	TRZ	FL,PGSN 	; No page seen yet
	PUSHJ	P,GETL		; Get the line number part
	SKIPE	T2,FRCPAG	; Did we get a forced page? %,. or #
	MOVEM	T2,HIPG		; Yes, set it
	MOVE	T2,CPGL 	; Assume LSRCH set the page
	TRNE	FL,PGSN 	; Did LSRCH get page?
	MOVEM	T2,HIPG 	; Yes, set it
	SETZM	FRCPAG		; It's been used.  Clear it now.
	CAIE	C,"/"		; Is this a page comming?
	JRST	NOPG		; No, a line number at most
GETPG:	PUSHJ	P,SCAN		; Yes, get the page number
	CAIE	C,"+"		; Check for implicit '.'
	CAIN	C,"-"
	PUSHJ	P,IMPDOT	; Go handle implicit dot
	CAIN	C,"*"
	JRST	LASTPG		; Get last page #
	CAIE	C,"^"		; Uparrow means
	JRST	GETLPG		; Get page 1
	MOVEI	T2,1
	TRO	FL,NUMF 	; Make like number
GETLPG: SKIPLE	T2		; Numbers .le. 0 lose
	TRZN	FL,NUMF 	; Was it a number
	NERROR	ILC		; Lose lose
	TRO	FL,PGSN 	; Yep, we saw it
	MOVEM	T2,HIPG 	; Save that number
	PUSHJ	P,SCAN		; Check for + or -
	CAIN	C,"+"
	JRST	PGPLS
	CAIE	C,"-"
	JRST	NOPG		; No, go do adsub on line number
 
; Here for -
 
	PUSHJ	P,SCAN		; Get the number
	TRZN	FL,NUMF 	; Must be a number
	NERROR	ILC
	MOVE	T1,HIPG
	SUB	T1,T2
	MOVEM	T1,HIPG 	; Fill in number
NOPGA:	PUSHJ	P,SCAN		; Scan past number
NOPG:	TRNN	FL,LINSN!PGSN	; Did we see a line or a page?
	NERROR	ILC		; No, something is wrong
	PUSH	P,T1		; Save (have already scanned)
	PUSH	P,T2
	PUSHJ	P,ADDSUB	; Take care of + and - for line
	POP	P,T2
	POP	P,T1
	MOVEM	SINDEX,HILN	; Save result
	POPJ	P,		; And return

; Here for +
 
PGPLS:	PUSHJ	P,SCAN		; Get number to add
	TRZN	FL,NUMF 	; A number?
	NERROR	ILC		; No, nerror
	ADDM	T2,HIPG 	; Add it in
	JRST	NOPGA		; And clean up
 
; Here for * as the page number
 
LASTPG: TRNE	FL,BGSN 	; Seen last
	JRST	LSTPG1		; Yes: skip code
	MOVSI	T1,1
	MOVEM	T1,DPG		; Try for large
	MOVEI	SINDEX,0
	PUSHJ	P,FIND
	TRNN	FL,BGSN 	; Should see it now
	ERROR	ICN
LSTPG1: MOVE	T2,BGPG
	TRO	FL,NUMF 	; Number seen
	JRST	GETLPG
 

 
; Routine sets HIPG in case none seen by GETLA, then calls GETLA

GET1S:: PUSHJ	P,SCAN
GET1::	MOVE	T3,CPGL
	MOVEM	T3,HIPG
	JRST	GETLA
 

 
; Get a pair of form A/B:C/D, LOLN is set by caller before call

GET2SD::PUSHJ	P,SCAN##	; Scan
GET2D::	MOVEI	T4,GET2		; Set non-null
	JRST	GET2D1		; Join processing

GET1SD::MOVEI	T4,GET1 	; Where to go if not null param
	PUSHJ	P,SCAN##	; Here if null line nr. defaults to .
GET2D1:	TRNE	FL,TERMF	; Was a terminator seen?
	JRST	GETSD1		; Go fake a dot
	CAIE	C,","		; Comma => null line number
	CAIN	C,";"		; So does ;
	JRST	GETSD1		; Fake a dot
	CAIE	C,"_"		; Underscore => null line number
	CAIN	C,"="		; So does =
	JRST	GETSD1		; Fake a dot
; 
	CAIN	T4,GET2 	; Looking for 2 numbers
	CAIE	C,":"		; Yes, do we have a colon?
	JRST	(T4)		; Go do real scan
 
GETSD1: MOVEM	C,SAVC		; Save scanned character
; 
	MOVEI	C,"."		; Fetch up a dot
	MOVEM	C,SAVCHR	; Save character for scan
; 
	JRST	-1(T4)		; And finish scan
 
GET2S:: PUSHJ	P,SCAN
GET2::	TRZ	FL,CNTF 	; Not a ! command
	CAIE	C,"+"		; Check for implicit dot
	CAIN	C,"-"
	PUSHJ	P,IMPDOT	; Go handle implicit dot
	CAIN	C,"!"		; Also check for implicit dot here
	PUSHJ	P,IMPDOT	; Do it
;CODE FOR EF AND BF STOLEN FROM VERSION 23(220)
	TRNE	FL,IDF		;TEST FOR AN IDENTIFIER
	 JRST	GET2SY		;YES, POSSIBLE SYMBOLIC RANGE
	PUSHJ	P,GET1		; Get a line and page number pair
	MOVE	T3,HIPG 	; Now set lower page to the one seen
	MOVEM	T3,LOPG
	MOVE	T3,HILN 	; Reset low line is a number seen
	TRNE	FL,LINSN
	MOVEM	T3,LOLN
GET2HF::MOVE	T3,[<ASCII /99999/>!1]; Set up a large number
	TRNN	FL,LINSN	; If no line number seen
	MOVEM	T3,HILN
	TRZ	FL,PGSN 	; So delete can detect a second page spec
	CAIN	C,"!"		; Is it a ! command?
	JRST	GET2CT		; Go take care of it
	CAIE	C,":"		; Check for second set
	POPJ	P,		; Nope, return
	SETZM	FRCPAG		; Clear this from first scan
	MOVEM	T3,HILN 	; Set HILN anyway
	PUSHJ	P,SCAN		; Scan next
	TRNE	FL,IDF		;CHECK FOR IDENTIFIER
	 JRST	GETEFC		;YES--CHECK FOR BF/EF
	CAIE	C,","		; Switch delimiter?
	TRNE	FL,TERMF	; Or command end?
	PUSHJ	P,IMPDOT	; Fake a dot
	CAIN	C,";"		; Semicolon (for R command)
	PUSHJ	P,IMPDOT	; Yes, setup implied dot
	JRST	GETLA		; Go get the rest

GET2CT: TRO	FL,CNTF 	; Set the appropriate flag
	PUSHJ	P,SCAN		; There should be a number here
	TRNN	FL,NUMF
	NERROR	ILC		; Lose
	MOVEM	T2,SVCNT	; Hang on to it
	JRST	SCAN		; Scan next and return

;CODE FOR EF AND BF STOLEN FROM VERSION 23(220)

GETEFC:	MOVS	T1,ACCUM	;GET THE IDENTIFIER, SWAPPED
	CAIE	T1,'EF '	;TEST FOR "...:EF" RANGE
	NERROR	ILC		;  NO, ERROR
GET2AL:	MOVE	T3,[<ASCII /99999/>!1] ;GET LARGEST POSSIBLE LINE #
	MOVEM	T3,HILN		; & STORE
	MOVSI	T3,1		;GET EXTREMELY LARGE PAGE #
	MOVEM	T3,HIPG		; & STORE
	TRZ	FL,LINSN!ADDL!SUBL ;CLEAR LINE-TYPE FLAGS
	TRO	FL,PGSN		;SHOW PAGE # SEEN
	JRST	SCAN		;GO SCAN NEXT & RETURN

GET2SY:	MOVS	T1,ACCUM	;GET THE IDENTIFIER, SWAPPED
	CAIE	T1,'BF '	;TEST FOR "BF..." FORMAT
	CAIN	T1,'EF '	;TEST FOR "EF" FORMAT
	TDZA	T3,T3		;EITHER, GET 0 STARTING LINE
	NERROR	ILC		; NEITHER, ERROR
	MOVEM	T3,HILN		;SET AS ENDING LINE #
	MOVEM	T3,LOLN		;SET AS STARTING LINE #
	MOVEI	T3,1		;GET PAGE # 1
	MOVEM	T3,HIPG		;SET AS ENDING PAGE #
	MOVEM	T3,LOPG		;SET AS STARTING PAGE #
	TRZ	FL,PGSN!ADDL!SUBL ;CLEAR FLAGS
	TRO	FL,LINSN	;SHOW LINE # SEEN
	CAIN	T1,'EF '	;TEST FOR "EF" RANGE
	JRST	GET2AL		;  YES, JUMP
	PUSHJ	P,SCAN		;GET NEXT ATOM IF "BF..."
	CAIE	C,"!"		;TEST FOR RANGE SPECIFIER
	CAIN	C,":"		;TEST FOR RANGE SPECIFIER
	JRST	GET2HF		;  YES, GO READ THE RANGE
	NERROR	ILC		;  NO, "BF" IS ILLEGAL
	SUBTTL	Line Number Search
 
IFN	EXTEND,<
; Search for a line and use its number instead of .
; Mostly plagiarized from search

LSRCH:: PUSH	P,SVINC 	; Save previously gathered line numbers
	PUSH	P,SVCNT
	PUSH	P,HIPG
	PUSH	P,LOLN
	PUSH	P,LOPG
	PUSH	P,FL		; Save flags in case called by search
	PUSH	P,FL2
	PUSH	P,FNDPMT	; Save prompt string
	TLZ	FL,ASSMF	; Clear all flags
	SETZM	LOLN		; Just like everyone else has to
	SETZM	LSCNT		; Start with zero
	MOVE	T1,[2,,[ASCIZ/L*/]]
	MOVEM	T1,FNDPMT	; Save for next string prompt
	TLO	FL2,L2.NAB
	SOSGE	LSBUFN		; Get string buffer number
	NERROR	TMS		; Nesting too deep
	MOVE	T2,LSBUFN	; Index in string buffer tables
	MOVE	T1,LSPTR(T2)	; Set up byte pointer
	MOVE	T3,LSPTT(T2)	; And pointer to byte pointer table
	PUSHJ	P,SSTRNG##	; Get a search string
	  JRST [MOVE T2,LSBUFN ; Index to pointers
		SKIPN @LSPTT(T2)	; Was string set?
		NERROR NSG	; No, tell him
		CAIN C,12
		JRST ASLMD1	; Special continue mode
		JRST .+1]	; Yes, use old one
	TLZ	FL,NUMSRF!DECID!EXCTSR; Clear flags
	SKIPE	EXACTF		; All searches to be exact?
	TLO	FL,EXCTSR	; Yes, set the exact bit
	PUSHJ	P,SCAN		; Check for what comes after
	TRNN	FL,TERMF	; If terminator
	CAIN	C,","		; Or ,
	JRST	ASLMDT		; Set up limits specially
	CAIE	C,"!"
	CAIN	C,":"
	JRST	ASLMDT		; Let him specify 2nd half of range
	PUSHJ	P,GET2		; Else call usual limit routine
LSC4:	MOVE	T1,HILN 	; Save end of range
	MOVEM	T1,LSHILN
	MOVE	T1,HIPG
	MOVEM	T1,LSHIPG
	CAIE	C,","		; Any more arguments?
	JRST	LSC1		; No, check terminator and proceed
	PUSHJ	P,SCAN		; Yes, see what it is
	TRNN	FL,IDF		; Should be ident or number
	JRST	LSC2		; Not ident, check for number of searches
	MOVS	T1,ACCUM	; Get the ident
	CAIN	T1,(<SIXBIT /N  />); And find out what it is
	TLO	FL,NUMSRF!DECID
	CAIN	T1,(<SIXBIT /D  />)
	TLO	FL,DECID	; Wants to decide on line
	TLNN	FL,NUMSRF!DECID ; Was it either?
	JRST	LSC3		; No, check e
	PUSHJ	P,SCAN		; Continue looking
	CAIE	C,","
	JRST	LSC1		; No more arguments
	PUSHJ	P,SCAN		; Well what kind is this one?
	TRNN	FL,IDF		; More idents?
	JRST	LSC2		; No, must be number of searches
	MOVS	T1,ACCUM
LSC3:	CAIE	T1,(<SIXBIT /E  />)
	NERROR	ILC		; No, he must have made a mistake
	TLO	FL,EXCTSR	; Yes, remember it
	PUSHJ	P,SCAN		; And check for more
	CAIE	C,","
	JRST	LSC1		; No more
	PUSHJ	P,SCAN		; Only one thing it can be now
LSC2:	TRNN	FL,NUMF
	NERROR	ILC		; Nope, lose
	MOVEM	T2,LSCNT	; Save as count of lines to find
	PUSHJ	P,SCAN		; Get terminator (we hope)
LSC1:	PUSHJ	P,CKTRMF	; Check that command is complete
LSCH1A: MOVE	T1,LSBUFN
	MOVE	T1,LSPTT(T1)	; Get pointer to strings
	PUSHJ	P,CODSR##	; And generate code
	MOVE	T1,LOPG 	; Get set to hunt it
	MOVEM	T1,DPG
	MOVEM	T1,LSPG 	; Flag to say if we should print page
	MOVE	SINDEX,LOLN
	PUSHJ	P,FIND
	TRZ	FL,LINSN	; No lines yet
ONLSC:	PUSHJ	P,ONMOV##	; Check range
	  JRST	ENDLSC		; Done
	TLZE	FL,ASSMF	; First time and want .+1?
	JRST   [CAME T1,LOLN	; Is there exact match?
		JRST .+1	; No, this is .+1
		AOS SVCNT	; Pretend we didnt see it
		JRST LSNXT]	; And take next
	CAMN	T1,PGMK 	; Pages are special
	JRST	LSNXT		; So take good care of them
	MOVE	T2,LSBUFN
	MOVE	T2,LSPTT(T2)	; Pointer to strings
	PUSHJ	P,COMSRC##	; Go search this line
	JRST	LSNXT		; Loser
	MOVE	T2,CPG		; Get current page
	CAME	T2,LSPG 	; And see if we should print it
	PUSHJ	P,PGPRN##	; Yes
	MOVE	T2,CPG		; Now set it as current
	MOVEM	T2,CPGL
	MOVEM	T2,LSPG 	; Also reset flag
	MOVE	T2,(PNTR)	; Also set line
	MOVEM	T2,CLN
	TRO	FL,LINSN	; We saw one
	TLNN	FL,DECID	; Does he want option?
	JRST	LSNXTC		; No, go get next one or stop
	TLNE	FL,NUMSRF	; Do we want only line numbers?
	JRST	LSCNUM		; Yes
	MOVE	T1,PNTR 	; Go print line
	PUSHJ	P,OUTLIN##
 
LSNXT1: PUSHJ	P,GETONE##
	CAIN	T1,177		; Did he say rubout(do not use)?
	JRST	REJECT		; Yes, go find another
	CAIN	T1,15		; Did he say <CR>?
	PUSHJ	P,GETONE##
	CAIE	T1,12
	CAIN	T1," "		; Space means use it
	JRST	ACCEPT
	ANDI	T1,137		; Force upper case
	OCRLF			; Spit out a CR-LF here
	CAIE	T1,"Q"
	CAIN	T1,"E"		; Does he want out
	JRST	COMND		; Yes: quit
	OUTSTR	[BYTE (7) "?"," ",7,0,0]
	CLRBFI			; Clear him out
	JRST	LSNXT1		; Try again
 
ACCEPT: 
IFN XSARSW,<
	SKIPN	EXPFLG		; Print correct accept message
>
	OUTSTR	[ASCIZ '[Accepted]
']
	JRST	LSOUT
 
REJECT: 
IFN XSARSW,<
	SKIPN	EXPFLG		; Print correct reject message
>
	OUTSTR	[ASCIZ '[Rejected]
']
	TRZ	FL,LINSN	; Didn't count since he rejected it
	JRST	LSNXT

 
LSNXTC: SOSG	LSCNT		; Have we found enough
	JRST	LSOUT		; Yes, give up 
LSNXT:	PUSHJ	P,FINDN 	; Get next line to look a
	JRST	ONLSC
 
LSCNUM: MOVE	T1,(PNTR)	; Print sequence number
	MOVEM	T1,PRNTO1
	OUTSTR	PRNTO1
	JRST	LSNXT1		; And decide
 
ENDLSC: TRZN	FL,LINSN	; Did we see one?
	NERROR	NLN		; Null range
	JRST	LSOUT
 
LSOUT:	POP	P,FNDPMT
	POP	P,FL2		; Restore the flags we used
	POP	P,T1
	AND	T1,[XWD ASSMF!NUMSRF!EXCTSR!DECID,ADDL!SUBL!CNTF]
	ANDCM	FL,[XWD ASSMF!NUMSRF!EXCTSR!DECID,ADDL!SUBL!CNTF]
	IOR	FL,T1
	POP	P,LOPG		; Restore previous line numbers
	POP	P,LOLN
	POP	P,HIPG
	POP	P,SVCNT
	POP	P,SVINC
	DMOVE	T1,CLN		; Load current line/page which we found
	TRO	FL,NUMF!PGSN	; And make like scan saw a number
	AOS	LSBUFN		; Go back to previous level if any
	POPJ	P,		; And exit victorious
ASLMD1: TROA	FL,CNTF 	; Mark as keep end of range
ASLMDT: TRZ	FL,CNTF 	; Just in case
	TLO	FL,ASSMF	; We assume .+1
	MOVE	T1,CLN		; Set things up for . to infinity
	MOVEM	T1,LOLN
	MOVEM	T1,HILN 	; As good as anything with the page we will
	MOVE	T1,CPGL 	; Use
	MOVEM	T1,LOPG
	TRZE	FL,CNTF 	; Keep end?
	JRST	LNOSPC		; Yes
	CAIE	C,":"		; If a : or !
	CAIN	C,"!"
	JRST	HALFLS		; Get the second half (.+1 to given)
	MOVSI	T1,377777	; Get a large page
	MOVEM	T1,HIPG
	JRST	LSC4		; Back into things

HALFLS: MOVEM	T1,HIPG 	; Set top as /.
	PUSHJ	P,GET2HF	; Get the second half
	JRST	LSC4		; And go

LNOSPC: MOVE	T1,LSHIPG
	MOVEM	T1,HIPG 	; Put back end
	MOVE	T1,LSHILN
	MOVEM	T1,HILN
	JRST	LSCH1A
>
SVLOLN::DMOVE	T1,LOLN		; Fetch low
	JRST	SVLOL2		; Store and return

SVHILN::DMOVE	T1,HILN		; Fetch from HILN
SVLOL2::SKIPN	T1		; If zero line number
	MOVE	T1,LNZERO##	; Convert to ASCID
	DMOVEM	T1,LSLOLN	; Save value
	POPJ	P,		; and return
	SUBTTL	HELP  Type help text

SEGMRK=="^"-100			; Use ^^ for segment mark
HLPEOF==PDFL1			; EOF flag
HLPSWT==PDFL2			; User typed H/switchname

HELP:	PUSHJ	P,SCAN##	; Scan for argument
	SETZ	T4,		; Anticipate no argument
	TRNE	FL,TERMF	; Terminated?
	JRST	HELP0		; Yes, just first part of text
	CAIN	C,"/"		; Did we get H/...
	JRST	[TRO	FL2,HLPSWT
		 PUSHJ	P,SCAN##  ; Get name
		 TRNN	FL,IDF	  ; Must be an ident
		 NERROR ILC
		 PUSHJ  P,XCODE## ; 
		 SKIPE	ACCUM	; Find something
		 JRST	HELP1
		 JRST	XERR##]
	CAIE	C,","		; Did we get a comma?
	NERROR	ILC		; Nope, he typed it wrong
	PUSHJ	P,SCAN##	; Get command name
	TRNE	FL,TERMF	; Must be an argument
	NERROR	ILC		; is an error
	TRNN	FL,IDF		; Find an indentifier
	SKIPA	T4,C		; No, save character
HELP1:	MOVE	T4,ACCUM	; Yes, save identifier
	PUSHJ	P,SCAN##	; Then scan the end
	PUSHJ	P,CKTRMF	; and make sure that we terminated
HELP0:	MOVSI	T1,'DOC'
	JSP	T5,OPNHLP
	MOVSI	T1,'HLP'
	JSP	T5,OPNHLP
	NERROR	FNF

DOHLP:	TLO	FL2,NORENT	; Protect against wild reentering
	PUSH	P,CHIN		; Save character input routine
	JUMPE	T4,HTYPLP	; Go type first segment
	MOVEI	T1,GHLPC	; So scan looks at help file
	MOVEM	T1,CHIN		; Stash it
DOHLP1:	PUSHJ	P,GHLPC		; Get a character
	TRNE	FL2,HLPEOF	; End of file?
	JRST	NOHELP		; Yes, text not found
	CAIE	C,SEGMRK	; End of segment?
	JRST	DOHLP1		; No, get next
	TRNN	FL2,HLPSWT	; Looking for a switch?
	JRST	DOHLP2		; No, skip check for /
	PUSHJ	P,GHLPC		; Check next character
	CAIE	C,"/"		; Must be a /
	JRST	DOHLP1		; No, check next record
DOHLP2:	SETZM	SAVCHR		; Clear scanner
	PUSHJ	P,SCAN##	; Look for an ident or something
	TRNN	FL,IDF		; Ident?
	SKIPA	T1,C		; No, fetch special character
	MOVE	T1,ACCUM	; Yes, get the identifier
	CAME	T1,T4		; Is it the one we are looking for?
	JRST	DOHLP1		; No, on to the next record
	PUSHJ	P,SCAN##	;GET NEXT ATOM
	CAIE	C,"/"		;SWITCH COMING?
	 JRST	HTYLOP		;NO--MATCHES
	PUSHJ	P,SCAN##	;YES--GET IT
	TRNN	FL,IDF		;IDENT?
	 JRST	HTYLOP		;NO--BAD FORMAT
	MOVSI	T1,-SSTLEN	;GET SPECIAL SWITCH TABLE
	MOVE	T2,ACCUM	;GET SWITCH WE SCANNED
	CAME	T2,SSTTAB(T1)	;MATCH?
	 AOBJN	T1,.-1		;NO--LOOP FOR ALL
	JUMPGE	T1,HTYLOP	;TYPE IF NO MATCH
	XCT	SSTXCT(T1)	;SEE IF ENABLED FOR THIS SWITCH
	 JRST	DOHLP1		;NO--SKIP ON
				;YES--TYPE IT
HTYLOP:	PUSHJ	P,ICUR##	;FANCY CURSOR OUTPUT IF WE CAN
HTYPLP:	PUSHJ	P,GHLPC		; Get a character
	TRNE	FL2,HLPEOF	; End of file yet?
	JRST	HLPDON
	CAIN	C,"L"-100	; Page mark
	MOVEI	C,12		; Make into line feed
	CAIN	C,SEGMRK	; or segment mark
	JRST	HLPDON
	PUSHJ	P,OCHR##	; Type it
	JRST	HTYPLP		; Loop over whole record

GHLPC:	CHKREN	HLPABT
	SOSGE	HLPBUF+.BFCTR	; Check buffer
	JRST	GHLPCG		; Get more data
	ILDB	C,HLPBUF+.BFPTR	; Get a character
	MOVEI	T1,1		; Sequence bit
	TDNN	T1,@HLPBUF+.BFPTR ; Is it on?
	POPJ	P,		; Return the character
	MOVNI	T1,5		; Skip next five
	ADDM	T1,HLPBUF+.BFCTR; By incrementing count by 5
	AOS	HLPBUF+.BFPTR	; And pointer by one whole word
	JRST	GHLPC		; Go get something else

GHLPCG:	INUUO	LPT,		; Read another buffer full
	JRST	GHLPC		; And try again
	TRO	FL2,HLPEOF	; Flag end of file
	MOVEI	C,12		; Return something to avoid loops
	POPJ	P,		; Non-skip return

OPNHLP:	MOVEM	T1,LPDEVI+.OPDEV; Setup the device
OPNHP0:	MOVEI	T1,4		; Length of block
	MOVEM	T1,LSTBLK
	HRROI	T1,.GTPRG	; Program name
	GETTAB	T1,		; Read it
	  MOVSI	T1,'SOS'	; No table, assume its called SOS.HLP
	MOVSI	T2,'MAN'	;of the help file
	DMOVEM	T1,LSTBLK+.RBNAM; into the lookup block
	SETZM	LSTBLK+.RBPPN	; Clear the PPN
	OPNDSK	LPT,LPDEVI	; Look for the file
	  JRST	OPNHP1		; Try physical
	XLOOKP	LPT,LSTBLK	; Look for the help file
	  JRST	OPNHP1		; Try physical
	  JRST	OPNHP1		; Try physical
	HRRZS	LPDEVI+.OPMOD	; Clear physical only if set
	JRST	DOHLP

OPNHP1:	MOVE	T1,LPDEVI+.OPMOD
	TLCE	T1,(UU.PHS)	; Physical only?
	JRST	(T5)		; Yes, already tried that trick
	MOVEM	T1,LPDEVI+.OPMOD
	JRST	OPNHP0

HLPABT:	ADJSP	P,-1		; Delete call to GHLPC
	PUSHJ	P,CTTBFO##	; Clear TTY output buffer
	JRST	HLPXIT		; Release LPT and return

NOHELP:	POP	P,CHIN		; Restore input routine
	OUTSTR	[ASCIZ/%No help for "/]
	TRNE	FL2,HLPSWT	; Switch name?
	OUTCHR	["/"]		; Yes, add /
	TLNN	T4,770000
	JRST	NOHLP1		; If not SIXBIT
	MOVE	T1,T4		; Character
	MOVEI	T3,FOCHR##	; Output character routine
	PUSHJ	P,PRTSX##	; Yes, type it
	JRST	NOHLP2

NOHLP1:	MOVE	C,T4		; Get the character
	PUSHJ	P,FOCHR##	; Print it
NOHLP2:	OUTSTR	[ASCIZ/"
/]
	JRST	HLPXI1

HLPDON:	PUSHJ	P,FORCE##
	PUSHJ	P,FCUR##	;DONE WITH CURSOR PRINT
HLPXIT:	POP	P,CHIN		; Restore input routine
	SETZM	SAVCHR		; Clear scanner
HLPXI1:	RELEAS	LPT,
	JRST	COMND		; And fetch the next command

DEFINE	SST,<
	X	NEWCOMMAND,<SKIPN NEWCMD##>
	X	OLDCOMMAND,<SKIPE NEWCMD##>
	X	NEWALTER  ,<SKIPN NEWALT##>
	X	OLDALTER  ,<SKIPE NEWALT##>
>

DEFINE X(SWT,TST),<EXP SIXBIT /SWT/>

SSTTAB:	SST
SSTLEN==.-SSTTAB

DEFINE X(SWT,TST),<TST>

SSTXCT:	SST
	SUBTTL	The Indirect (@) Command
 
; Input routine for command file
 
RDCHAR::SOSG	INDBUF+2	; Check empty buffer
	JRST	DOINP		; Read from file
RDCHR1: ILDB	C,INDBUF+1	; Get a char
	JUMPE	C,RDCHAR	; Skip nulls
	MOVE	CS,@INDBUF+1	; Fetch word
	TRNN	CS,1		; Seq bit
	POPJ	P,		; No - return
	MOVNI	C,5		; Skip 5 more chars (tab included)
	ADDM	C,INDBUF+2
	AOS	INDBUF+1	; Adjust byte pointer
	JRST	RDCHAR		; Get the next character

DOINP:	SKIPGE	CMFFLG		;READING FROM INTERNAL BUFFER?
	  JRST	DOINP1		;YES--SPECIAL
	INUUO	IND,0
	JRST	RDCHR1		; Aok
	GETSTS	IND,C
	RELEAS	IND,		; Get status and close chl
	TRNN	C,740000
	  JRST	DOINP1		;JUST EOF
	MOVE	T1,SVCCIN	; Retstore input routine
	MOVEM	T1,CHIN
	SETZM	COMFLF		; Error - clear command file flag
	NERROR CMERR		; Lose 
DOINP1:	SOSG	COMFRP		;MORE REPEATS TO GO?
	  JRST	DOINP3		;EOF
	SETOM	CMFFLG		;FLAG FILE READ
	MOVEI	C,200*5		;RESET CHAR COUNT
	MOVEM	C,INDBUF+2	;..
	MOVE	C,[POINT 7,COMBUF+3];POINT TO BUFFER
	MOVEM	C,INDBUF+1	;..
	MOVE	C,LN1##		;RESET LINE COUNTER
	MOVEM	C,COMCNT	;..
	JRST	RDCHR1		;NOW, THATS BETTER THEN READING THE FILE

DOINP3:	MOVE	T1,SVCCIN	;Retstore input routine
	MOVEM	T1,CHIN
	SETZM	COMFLF		;Error - clear command file flag
	NERROR CMEND		;Lose 
; Handle @ command - read commands from file.  we may link command
; Files but not nest them.
 
COMFIL: SETZM	COMFRP		;CLEAR REPEAT COUNT
	MOVEI	T1,5		;Length of files spec
	MOVEM	T1,INDFIL+.RBCNT; Set it up
	MOVEI	T1,.IOASL	; ASCII line mode
	MOVEM	T1,INDDVI+.OPMOD; Set up
	MOVEI	T1,INDBUF	; Buffer header
	MOVEM	T1,INDDVI+.OPBUF; Set it up too
	PUSHJ	P,SCAN		; Read file name
	MOVEI	T1,CMPATH	; Place to store the path
	MOVEM	T1,INDFIL+.RBPPN; Set up the pointer
	MOVEI	T3,INDFIL	; Place to put file name
	PUSHJ	P,SETNM1##	; Fetch file spec
	  CAIA			; MAY LOOK BAD--CHECK FOR REPEAT COUNT
	JRST	CMF1		;ALL SET
	CAIE	C,","		;NUMBER COMING?
	  NERROR ILC		;NO--ERROR
	PUSHJ	P,SCAN		;YES--READ IT
	CAIN	C,"*"		;INFINATE?
	  JRST	[HRLOI T2,377777;YES
		 JRST  CMF2]	;AND STORE
	TRNN	FL,NUMF		;NUMBER?
	  NERROR ILC		;NO--ERROR
CMF2:	MOVEM	T2,COMFRP	;STORE REPEAT COUNT
	PUSHJ	P,SCAN		;FIND END
	PUSHJ	P,CKTRMF	;CHECK TERMINATOR
CMF1:				;
	SKIPN	T1,TMPDEV	; Check for device
	SKIPA	T4,[POINT 18,[SIXBIT/DSKTEDSYS   /]]
	MOVE	T4,[POINT 36,GIFDEV]
	MOVSM	T1,GIFDEV	; Given device
	HLLZ	T1,INDFIL+.RBEXT
	HLLOM	T1,GIFEXT	; Save extension in case typed
	SKIPN	DFXSW##		; Default to be used?
	SKIPA	T5,[POINT 18,GIFEXT]	; No, use the real one
	MOVE	T5,[POINT 18,[SIXBIT/CCLCMD   ___/]]
CMF3:	MOVE	T3,T5		; Reset extension list
	ILDB	T1,T4		; Get a device
	JUMPE	T1,[NERROR FNF]	; End of list
	MOVSM	T1,INDDVI+.OPDEV
	OPEN	IND,INDDVI	; Open file etc..
	  JRST	CMF3		; Try another device
CMF4:	ILDB	T1,T3		; Get an extension
	CAIN	T1,'___'	; Check for end marker
	JRST	CMF3		; Do next device
	HRLZM	T1,INDFIL+.RBEXT
	XLOOKP	IND,INDFIL
	  JRST	COMND		; Serious error--message already typed
	  JRST	CMF4		; Not this time, try another extension
	MOVE	T1,INDFIL+.RBSIZ;GET SIZE
	CAILE	T1,200		;UNDER 1 BLOCK?
	 SKIPG	COMFRP		;AND NOT REPEAT COMMAND MODE?
	  CAIA			;YES
	NERROR	CFB		;NO--TOO BIG
SETFIL:				;
	MOVEI	T1,COMBUF	; Setup buffer
	MOVEM	T1,.JBFF##	; Point to buffer (.JBFF will be reset
				; by command dispatcher)
	INBUF	IND,1		; ***
	MOVE	T1,LNZERO##	; Set up cmd count
	MOVEM	T1,COMCNT
	SKIPE	COMFLF		; Are we already in a command file?
	JRST	COMND		; Yes, do not nest
	SETOM	COMFLF		; We are now reading from a command file
	MOVEI	T1,RDCHAR	; Set up input routine
	EXCH	T1,CHIN 	; And save current
	MOVEM	T1,SVCCIN
	SETZM	CMFFLG		;FLAG FILE NOT READ YET
	JRST	COMND
	SUBTTL	DOINI -- HANDLE XSOS.INI

DOINI::	SETZM	COMFRP		;CLEAR REPEAT COUNT
	SETZM	INTFLG##	;CLEAR INIT FLAG
	OPEN	IND,INIDVI##	;OPEN DEVICE
	 NERROR	FNF		;ERROR
	SETZM	INIFIL+.RBPPN	;CLEAR PPN
	LOOKUP	IND,INIFIL##	;READ FILE
	 NERROR	FNF		;ERROR
	PJRST	SETFIL		;AND SETUP FOR READER
	SUBTTL	Move Command (.)

MOVE::	PUSHJ	P,GET1SD	; Get a position, allow naked dot
	PUSHJ	P,CKTRMF	; Verify correct termination
	PUSHJ	P,FINDHI##	; Get HILN/HIPG
	MOVE	T2,CPG		; Page we found
	CAME	T2,HIPG		; Is it the one we wanted?
	NERROR	NSP		; No, gronk user
	MOVE	T1,HILN		; Get desired line
	DMOVEM	T1,CLN		; Setup new current line/page
	JRST	COMND		; Next command, please
	SUBTTL	The B and BP commands.  Go to beginning of file or page

BEGINN::PUSHJ	P,SCAN##	; Scan next character
	MOVS	T1,ACCUM	; Get token
	CAIN	T1,'F  '	;SEE IF 'F'
	 JRST	[SETZM	ACCUM	;YES--SCAN ONE MORE CHASR
		 PUSHJ	P,SCAN	;..
		 JRST	BEGIN1]	;AND TREAT LIKE B
	CAIE	T1,'P  '	; A 'P'?
	JRST	BEGIN1		; No, assume B command
	SETZM	ACCUM
	PUSHJ	P,SCAN
	SKIPA	T1,CPGL		; Fetch current logical page number
BEGIN1:	MOVEI	T1,1		; Use page 1
	PUSHJ	P,CKTRMF	; Was command terminated?
	MOVEM	T1,CPGL		; Store logical page
	MOVE	SINDEX,LNZERO##	; [ASCIZ/00000/!1]
	MOVEM	T1,DPG
	MOVEM	SINDEX,CLN
	JRST	COMND
	SUBTTL	 The V command -- change case of a range of line

IFE VCMDSW,<VCMD:NERROR	ILC>

IFN VCMDSW,<

VCMD:	PUSHJ	P,GNCH##	; Get switch
	MOVEI	T1,40		; Case bit
	TRZ	C,40		; Convert switch to upper case
	CAIN	C,"V"		; Complement?
	TLO	T1,(TRC	C,)	; Setup complement instruction
	CAIN	C,"L"		; Force to lower case?
	TLO	T1,(TRO	C,)	; Set the case bit instruction
	CAIN	C,"U"		; Force to upper case?
	TLO	T1,(TRZ	C,)	; Clear the case bit instruction
	TLNN	T1,-1		; Find a valid switch?
	NERROR	ILC		; No, abort now
	MOVEM	T1,INOCHR##	; As good a place as any
	PUSHJ	P,GET2SD	; Full range, allow default dot
	PUSHJ	P,CKTRMF	; Make sure no junk at end of line
	PUSHJ	P,FINDLO##	; Find LOLN/LOPG
				;REMOVE CALL TO SVLOLN (FINDLO DID IT)
	TRZ	FL,LINSN	; None seen yet
VCRNGE:	PUSHJ	P,ONMOV##	; In range
	  JRST	VCDONE		; No, done
	TRO	FL,LINSN	; We saw a line
	PUSHJ	P,GETLTH##	; Length of the line
	IMULI	T1,5		;  in characters
	SUBI	T1,6		; Subtract out the sequence number size
	MOVEI	T2,1(PNTR)	; First data word in line
	HRLI	T2,(POINT 7,0,6) ; Point to the first data character
VCLOOP:	ILDB	C,T2		; A character
	MOVE	CS,CTBL(C)	; Get the character bits
	TLNE	CS,LETF_16	; Is this a letter?
	XCT	INOCHR		; Yes, fix it
	DPB	C,T2		; Restore the converted character
	SOJG	T1,VCLOOP	; Loop over the whole line
	MOVE	T1,0(PNTR)	; Last line processed
	MOVE	T2,CPG		; And page
	DMOVEM	T1,CLN		; Store logical Line/Page
	PUSHJ	P,FINDN##	; Find the next line
	JRST	VCRNGE		; And over the whole range

VCDONE:	TRNN	FL,LINSN	; Did we do something?
	NERROR	NLN		; No, error
	AOS	CHGCNT##	; Yes, we changed the file
	JRST	COMND		; Get next command

>; End of VCMDSW conditional

	END