;<PUP>PFUCMD.MAC;3 2-SEP-79 15:57:17 EDIT BY TAFT
;<PUP>PFUCMD.MAC;2 2-JUN-77 21:34:33 EDIT BY TAFT
; Make control-F not echo
;<PUP>PFUCMD.MAC;1 10-MAR-77 14:04:33 EDIT BY TAFT
; Split out from PUPFTP.MAC
; Copyright 1979 by Xerox Corporation
TITLE PFUCMD -- PUP FTP USER COMMAND INTERPRETER ROUTINES
SUBTTL E. A. Taft / March 1977
SEARCH PUPDEF,PFUDEF,STENEX
USEVAR FTPVAR,FTPPVR
; Input keyword from terminal
; A/ -length ,, address of keyword table
; Returns +1: Not found, no word input, or line delete typed
; +2: Found, A/ address of matching keyword table entry
; In either case, the word that was input is described by
; WRDLEN and WRDBYT. Recognition is performed if the keyword
; is terminated by Escape, and the tail is appended to CMDBUF.
; On either return, D contains the attributes of the terminating
; character.
; Clobbers A-D
INKEY:: PUSHJ P,SAVE1## ; Get another ac
MOVE P1,A ; Use it to hold cmd tbl ptr
INKEY1: MOVEI A,KEYHLP ; Routine to call on "?"
MOVSI B,(C.ALPH+C.NUM) ; Only alphanumerics allowed
TRO F,RAISEF ; Raise lower case letters
PUSHJ P,INWORD ; Input a word
JRST INKEY9 ; Line delete typed, return +1
JUMPE C,INKEY9 ; Give error return on empty word
HRROI A,TEMP## ; Copy the word here
PUSHJ P,CPYWRD
MOVE A,P1 ; Set command table ptr
HRROI B,TEMP## ; Get byte ptr to start of word
PUSHJ P,NAMSRC## ; Search for name in table
JRST INKEY2 ; Not found
JRST INKEY6 ; Found, give success return
; If exact match not found, check for unique initial substring.
; A/ AOBJN ptr to smallest entry > key
INKEY2: JUMPGE A,INKEY8 ; Fail if off end of table
AOBJP A,INKEY3 ; Advance to next, jump if none
PUSHJ P,NAMCMP## ; Compare strings
JUMPN D,[TRNN F,ESCAPF ; Ambiguous, terminated by Escape?
JRST INKEY8 ; No, fail as if not found
ERROR <> ; Yes, ring bell to say ambiguous
JRST APWORD] ; Resume INWORD for more input
JRST INKEY3 ; Did not match, continue
PUSHJ P,SCREWUP## ; Wasn't supposed to match!
INKEY3: SUB A,[1,,1] ; Now back to current entry
PUSHJ P,NAMCMP## ; Compare strings
JUMPN D,INKEY4 ; Jump if initial substring
JRST INKEY8 ; No match, fail
PUSHJ P,SCREWUP##
; Got unique initial substring
; Print and append tail if input terminated by Escape
; D/ String pointer to tail
INKEY4: TRNN F,ESCAPF ; Input terminated by Escape?
JRST INKEY6 ; No, just give success return
PUSH P,A ; Yes, save ptr to matching entry
TYPE <%4S> ; Print tail
PUSHJ P,BAKBYT ; Back up to overwrite terminator
INKEY5: ILDB A,D ; Get char of tail
JUMPN A,[IDPB A,CMDBYT ; If non-null, append to command
AOS WRDLEN ; Account in word length
JRST INKEY5] ; Repeat
MOVEI A,33 ; Put Escape on end
IDPB A,CMDBYT
POP P,A ; Restore ptr to matching entry
; Here to take success return
INKEY6: PUSHJ P,ESPACE ; Print space if Escape typed
AOS 0(P) ; Preset +2 return
; Here to take fail return
INKEY8: LDB B,CMDBYT ; Recover terminator
MOVE D,CHRTAB(B) ; Return attributes for terminator
INKEY9: TRZ F,RAISEF ; Stop raising lower-case letters
POPJ P,
; Help routine called from within INWORD if "?" typed
; P1/ Keyword table pointer (as passed to INKEY)
; Returns +1
; Clobbers A, B
KEYHLP: TYPE < One of the following:%/>
SKIPA D,P1 ; Copy keyword table pointer
KEYHL1: PRINT "," ; Comma
MOVEI A,101 ; Get width of page
RFMOD
LDB C,[POINT 7,B,17]
RFPOS ; Get current position on page
CAIGE C,↑D15(B) ; Room for another keyword?
PRINT EOL ; No, go to new line
HLRO B,0(D) ; Get key name string ptr
TYPE < %2S> ; Print it
AOBJN D,KEYHL1 ; Repeat for all
POPJ P,
; Copy last word input (not including terminator) to another place.
; Characters are quoted as appropriate for inclusion in property
; lists.
; A/ Destination string ptr
; Returns +1
; Updates A, clobbers B, C, appends null to destination string
CPYWRD::TLC A,-1 ; Turn -1 lh into byte ptr
TLCN A,-1
HRLI A,(POINT 7)
MOVE B,WRDBYT ; Get ptr to start of last word
CPYWR1: ILDB C,B ; Get a byte
CAMN B,CMDBYT ; Was that the terminator?
JRST [ MOVE B,A ; Yes, append null
SETZ C,
IDPB C,B
POPJ P,] ; Done
CAIE C,"(" ; Character need quoting?
CAIN C,")"
JRST .+3 ; Yes
CAIE C,PQUOTE
JRST CPYWR2 ; No
MOVEI C,PQUOTE ; Yes, insert quote
IDPB C,A
LDB C,B ; Recover the character
CPYWR2: IDPB C,A ; Store it
JRST CPYWR1 ; Repeat
; Confirm typed-in command by awaiting carriage return
; Returns +1: Aborted
; +2: Confirmed
; Clobbers A-D
CONFRM::LDB A,CMDBYT ; Get existing terminator
MOVE D,CHRTAB(A) ; Get attributes for character
MOVEI A,100 ; Set to wakeup on all characters
MOVEI B,77B23+2B25+1B29
SFMOD
CONFR1: TLNE D,(C.CEOL) ; End-of-line character?
JRST SKPRET## ; Yes, return +2
TLNE D,(C.SPAC) ; Space?
JRST .+3 ; Yes, just ignore
ERROR < ? > ; No, complain
PUSHJ P,BAKBYT ; Remove byte from buffer
HRROI A,[ASCIZ /Confirm with carriage return/]
SETZ B, ; No legal word constituents
PUSHJ P,INWORD ; Input a character
POPJ P, ; Line delete, abort command
JRST CONFR1 ; Got char, check it
; Input and edit word up to a terminator
; A/ String pointer to text to print if "?" input
; or 0,,address of routine to call
; B/ Attribute bits denoting legal constituent characters
; Returns +1: Line delete encountered
; +2: Normal, A/ Terminating character
; B/ Byte pointer to start of word (also in WRDBYT)
; C/ Character count (also in WRDLEN)
; D/ Attribute bits for terminating character
; Leading spaces and tabs are ignored if space is not a legal
; constituent character (but are still stored in the buffer).
; Terminating character stored in buffer but not included in count.
; If the terminator is Escape, the ESCAPF flag is set.
INWORD::MOVEM A,HLPDAT ; Store help data
MOVEM B,WRDATR ; Store character attributes
SETZM WRDLEN ; Init # characters in current word
MOVE A,CMDBYT ; Preserve pointer to start
MOVEM A,WRDBYT
POP P,WRDXIT ; Save return in case APWORD called
MOVEM P,WRDPDP ; Save stack pointer too
JRST INWOR0 ; Enter edit loop
; Enter here to append to an existing word
; Overwrites existing terminator (assumed to be Escape)
; Returns to where INWORD was last called from!
APWORD::MOVE P,WRDPDP ; Get stack ptr from INWORD call
PUSHJ P,BAKBYT ; Back up byte pointer
INWOR0: PUSH P,WRDXIT ; Put exit point back on stack
; Loop here for each character input
INWOR1: TRNE F,NEOLEF ; Want EOL echoing off?
JRST [ MOVEI A,100 ; Yes, get current control bits
RFCOC
PUSH P,B ; Save current settings
PUSH P,C
TRZ B,3B21+3B27 ; Turn off cr, lf, eol
TRZ C,3B27
SFCOC ; Issue revised settings
BIN ; Input the char
EXCH B,-1(P) ; Save char, restore old settings
POP P,C
SFCOC
POP P,A ; Restore char
JRST .+2]
PBIN ; Input character from terminal
TRZ F,ESCAPF ; Assume it is not Escape
INWOR2: MOVE D,CHRTAB(A) ; Get attributes and dispatch adr
TRNE D,-1 ; Is there a special dispatch?
JRST 0(D) ; Yes, take it
INWOR3: IDPB A,CMDBYT ; No, append char to string
HRRZ B,CMDBYT ; Make sure not overflowing buffer
CAIL B,CMDBUF+CMDLEN-1
JRST [ MOVSI D,(C.CDEL) ; Treat as command delete
ERROR(<%/Command too long>,1)]
TDNN D,WRDATR ; Is this a terminating character?
JRST INWOR4 ; Yes
AOS WRDLEN ; No, count characters in word
JRST INWOR1 ; Back for more
INWOR4: PUSHJ P,APPNUL ; Append null to command
LDB A,CMDBYT ; Recover terminating char
MOVE B,WRDBYT ; Get starting byte pointer
MOVE C,WRDLEN ; Get character count
JRST SKPRET## ; Return +2
; Special characters handled by INWORD
; Lower case letters
LOWERC: TRNE F,RAISEF ; Want to raise lower case letters?
SUBI A,40 ; Yes, do so
JRST INWOR3
; Control-V
CTRLV: PBIN ; Input next character literally
MOVSI D,(C.ALPH) ; Treat as alphabetic
JRST INWOR3
; Control-A
CTRLA: SKIPG WRDLEN ; Any characters to delete?
JRST [ ERROR <> ; No, ring bell
JRST INWOR1] ; Ignore
PRINT "\" ; Yes, print backslash
LDB A,CMDBYT ; Get last character typed in
TRNN F,NECHOF ; Unless echoing off
PRINT (A) ; Print it
PUSHJ P,BAKBYT ; Back up byte pointer
SOS WRDLEN ; Decrement count
JRST INWOR1 ; On to next character
; Control-W
CTRLW: SKIPG WRDLEN ; Any characters to delete?
JRST [ ERROR <> ; No, ring bell
JRST INWOR1] ; Ignore
PRINT "←" ; Yes, note word delete
SETZM WRDLEN ; Zero character count
MOVE A,WRDBYT ; Reset byte pointer
MOVEM A,CMDBYT
JRST INWOR1 ; On to next character
; "?"
INQUES: SKIPE WRDLEN ; First character of word?
JRST INWOR3 ; No, treat normally
MOVE A,HLPDAT ; Yes, get help data word
TLNE A,-1 ; String pointer?
TYPE < %1S> ; Yes, type string
TLNN A,-1
PUSHJ P,0(A) ; No, use as address of routine
JRST CTRLR1 ; Retype command line
; Control-R
CTRLR: TRNE F,NECHOF ; Echoing off?
JRST [ ERROR <> ; Yes, refuse to retype (since
JRST INWOR1] ; we might type a password)
CTRLR1: PRINT EOL ; Print crlf
PUSHJ P,APPNUL ; Append null to command string
HRROI A,CMDBUF ; Print contents of command string
PSOUT
JRST INWOR1 ; On to next char
; More INWORD special characters
; Space or tab
INSPAC: TDNN D,WRDATR ; Is space a terminator?
SKIPE WRDLEN ; Yes, is this a leading space?
JRST INWOR3 ; No, handle normally
IBP WRDBYT ; Yes, advance start of word
IDPB A,CMDBYT ; Store the character
TRNE F,NECHOF ; Echoing off?
PRINT 0(A) ; Yes, do the echo ourselves
JRST INWOR1 ; On to next char
; Carriage return
INCR: PBIN ; Flush following line feed
JRST INEOL1 ; Substitute EOL
; Line feed
INLF: PRINT 15 ; Print carriage return
INEOL1: MOVEI A,37 ; Substitute EOL
JRST INWOR2 ; Treat as if EOL was input
; Escape
INESC: TDNE D,WRDATR ; Is Escape a terminator?
JRST [ ERROR <> ; No, don't allow
JRST INWOR1]
TRO F,ESCAPF ; Yes, note Escape hit (for NOISE)
JRST INWOR3
; Control-Q, control-X
CTRLQ: TYPE <←←←%/>
JRST INDEL1
; Delete
INDEL: TYPE <XXX%/>
INDEL1: POPJ P, ; Take +1 return
; Initialize editor at beginning of command
; Returns +1
; Clobbers A-C
INIEDT::MOVE A,[POINT 7,CMDBUF] ; Initialize byte pointer
MOVEM A,CMDBYT
PUSHJ P,OKECHO ; Normalize terminal parameters
MOVE B,[BYTE(2) 0,0,1,1,1,1,0,2,0,2,2,1,1,2,1,1,1,0]
MOVE C,[BYTE(2) 0,1,1,1,0,0,0,1,1,0,1,1,1,3]
SFCOC ; Set desired control echoing
POPJ P,
; Back up CMDBYT byte pointer
; Returns +1
; Clobbers A
BAKBYT::MOVE A,CMDBYT ; Get byte pointer
BKJFN ; Let Tenex back it up
PUSHJ P,SCREWUP
MOVEM A,CMDBYT ; Store it back
POPJ P,
; Append null to command string without affecting pointer
; Returns +1
; Clobbers A, B
APPNUL::MOVE A,CMDBYT ; Get byte pointer
SETZ B, ; Append null
IDPB B,A
POPJ P,
; Turn echoing off and on
; Returns +1
; Clobbers A, B
NOECHO::TROA F,NECHOF ; Echoing off
OKECHO:: TRZ F,NECHOF ; Echoing on
MOVEI B,16B23+1B29 ; Wakeup on punct & control, Ascii
TRNN F,NECHOF ; Want echoing?
IORI B,2B25 ; Yes
MOVEI A,100 ; Set new terminal bits
SFMOD
POPJ P,
; Type crlf if not already at left margin
; Returns +1
; Clobbers A, B
CRIF:: MOVEI A,101 ; Get current position
RFPOS
TRNE B,-1 ; At left margin already?
PRINT EOL ; No, go there
POPJ P,
; If last char was Escape, substitute and print a space
; Returns +1
; Clobbers nothing
ESPACE::PUSH P,A
LDB A,CMDBYT ; Get last char input
CAIE A,33 ; Escape?
JRST ESPAC1 ; No
MOVEI A," " ; Yes, substitute space
DPB A,CMDBYT
PBOUT ; Print space also
ESPAC1: POP P,A
POPJ P,
; Handlers for command-related UUOs
; NOISE <string>
; Type noise word iff last input was terminated by Escape
%UNOIS::TRNN F,ESCAPF ; Last terminator Escape?
POPJ P, ; No
PUSHJ P,ESPACE ; Yes, ensure turned into space
; Rest same as PROMPT
; PROMPT <string>
; Type the given string and also append to command buffer (for ↑R)
%UPROM::PUSHJ P,FORMAT## ; Call formatter
MOVE A,CMDBYT ; Setup string ptr to cmd buffer
PUSHJ P,%UPRO2 ; Completion -- fix ptr, type text
POPJ P,
%UPRO2: MOVE B,A ; Copy string ptr
SETZ C, ; Append null
IDPB C,B
EXCH A,CMDBYT ; Store end pointer, recover start
PSOUT ; Type the text
POPJ P,
; Character attribute and dispatch table
; Attributes from list in PFUDEF.MAC
DEFINE X(CHAR,ATTR) <IRP CHAR<
RELOC CHRTAB+CHAR
ATTR
>>
DEFINE XRNG(CHAR1,CHAR2,ATTR) <
RELOC CHRTAB+CHAR1
REPEAT CHAR2-CHAR1+1,<ATTR>
>
CHRTAB::
; Editing characters
X <"A"-100,"H"-100>,CTRLA
X <"R"-100>,CTRLR
X <"V"-100>,CTRLV
X <"W"-100>,CTRLW
X <"?">,C.PUNC+INQUES
; Non-editing controls
X <0>,INWOR1 ; Flush nulls
XRNG "B"-100,"G"-100,C.CTRL
X <"K"-100>,C.CTRL
XRNG "N"-100,"P"-100,C.CTRL
XRNG "S"-100,"U"-100,C.CTRL
XRNG "Y"-100,"Z"-100,C.CTRL
XRNG 34,36,C.CTRL
; End-of-line characters
X <12,14>,C.CEOL+INLF
X <15>,C.CEOL+INCR
X <33>,C.ESC+INESC
X <37>,C.CEOL
; Line delete characters
X <"Q"-100,"X"-100>,C.CDEL+CTRLQ
X <177>,C.CDEL+INDEL
; Punctuation characters
X <"I"-100," ">,C.SPAC+INSPAC
X <"+","#">,C.PUNC+C.HSTP
X <"-","/">,C.PUNC+C.HSTC
X <"!",42,"$","%","&","'","(",")","*">,C.PUNC
X <54,".",":",";",74,"=",76,"@">,C.PUNC
XRNG 133,140,C.PUNC
XRNG 173,176,C.PUNC
; Alphanumeric characters
XRNG "A","Z",C.ALPH
XRNG "a","z",C.ALPH+LOWERC
XRNG "0","9",C.NUM
RELOC CHRTAB+200
; Storage for command processor
LS CMDBUF,CMDLEN ; Command string buffer
LS CMDBYT ; Byte ptr to tail of command string
LS WRDBYT ; Byte ptr to start of current word
LS WRDLEN ; Length of current word
LS WRDATR ; Attributes of legal word constituents
LS HLPDAT ; Data for help message ("?")
LS WRDXIT ; Return pc for last call of INWORD
LS WRDPDP ; Stack level of last call of INWORD
END