;<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