.Title AlvCMD Command Processing Routines .Psect Alvin,GBL,CON .Ident /LVL51 / .MCALL $ALVIN,$Span .Globl Span,PutByte,GetByte $Alvin $Span ;;********************************************************************** ;; Removed from ALVSB 10-Jul-84 DVJensen - CmdMatch, CmdCopy, Press. ;+ ;;********************************************************************** ;; SUBROUTINE TO MATCH AN INPUT COMMAND IN A COMMAND STRING TO ;; AN ENTRY IN A COMMAND TABLE, WHERE THE COMMAND TABLE IS OF ;; THE FORM: ;; COMMAND_TABLE: .WORD (ADDRESS OF START OF COMMAND ENTRIES) ;; .WORD (LAST ADDRESS OF COMMAND ENTRIES) ;; .WORD (SIZE IN EVEN BYTES OF AN ENTRY, >=8.) ;; ;; COMMAND_ENTRIES: .WORD (REQUIRED # OF CHARS TO MATCH THIS ENTRY) ;; .WORD (ADDRESS OF 1ST CHAR OF THIS ENTRY) ;; .WORD (ADDRESS OF LAST CHAR OF THIS ENTRY) ;; .WORD (VALUE RETURNED WHEN THIS ENTRY MATCHES) ;; . ;; . ;; . ;; END_OF_TABLE: .WORD (LAST WORD OF THE LAST ENTRY IN THE TABLE) ;; EACH COMMAND ENTRY IN THE TABLE IS A MINIMUM OF 4 WORDS LONG. ;; THERE IS NO SET LIMIT ON HOW MANY ENTRIES THERE MAY BE. ;; IT IS ASSUMED THAT COMMAND STRINGS HAVE BEEN PRE-PROCESSED ;; AS DEFINED BY THE CMDCOPY SUBROUTINE. ;; WHEN A MATCH IS FOUND THE COMMAND STRING IS UPDATED TO POINT ;; TO THE NEXT FIELD IN THE COMMAND ASSUMING A SINGLE BLANK ;; SEPARATOR; IF THE COMMAND STRING IS EXHAUSTED, THE BEGIN ;; POINTER WILL BE HIGHER THAN THE COMMAND END POINTER. ALSO, ;; THE VALUE SPECIFIED IN THE TABLE WILL BE RETURNED IN REG 0. ;; IF THERE IS NO MATCH, REGISTER 0 WILL BE RESTORED AND THE ;; COMMAND STRING DESCRIPTOR WILL NOT BE MODIFIED. ;; EXPECTS CALLS OF THE FORM: ;; JSR R5,CMDMATCH ;(CAN BE SHORTENED TO CMDMAT) ;; .WORD (ADDRESS OF THE COMMAND TABLE DESCRIPTOR) ;; .WORD (ADDRESS OF THE COMMAND STRING DESCRIPTOR) ;; BR NO_MATCH ;; NOTE: IF THE COMMAND STRING DESCRIPTOR ADDRESS IS ZERO, THEN ;; THIS ADDRESS IS ASSUMED TO BE IN REGISTER 3. ;; ;RETURN WITH SUCCESS VALUE IN REGISTER 0. ;- CMDMATCH:: MOV R4,-(SP) ;SAVE REGISTERS USED MOV R3,-(SP) MOV R2,-(SP) MOV R1,-(SP) MOV R0,-(SP) ;REG 0 IS RESTORED IF THERE IS NO MATCH MOV (R5)+,R2 ;GET TABLE DESCRIPTOR ADDRESS MOV (R5)+,R4 ;GET INPUT COMMAND STRING DESCRIPTOR ADR BEQ CMDM05 ;IF ZERO THEN ALREADY IN REG 3 MOV R4,R3 ;ELSE PUT IT IN REG 3 CMDM05: MOV (R2)+,R4 ;GET STARTING ADR OF COMMAND TABLE ENTRIES MOV R2,-(SP) ;SAVE PTR TO END ADR OF TABLE ON THE STACK CMP (R2),R4 ;IS THIS A VALID COMMAND TABLE? BLOS CMDMX ;NO, BRANCH TO FAIL EXIT CMP (R3),2(R3) ;ARE THERE ANY CHARS IN THE COMMAND STRING? BHI CMDMX ;NO, BRANCH TO FAIL EXIT CMDM10: MOV (R4),R1 ;GET CHAR MATCH COUNT FOR ENTRY MOV 2(R4),R2 ;GET STARTING ADDRESS OF ENTRY STRING MOV (R3),R0 ;GET STARTING ADDRESS OF INPUT COMMAND STR CMDM20: CMPB (R0)+,(R2)+ ;DO CHARS IN STRINGS MATCH? BNE CMDM50 ;NO, BRANCH DEC R1 ;DECREMENT MATCH COUNTER CMP R2,4(R4) ;IS THE ENTRY STRING EXHAUSTED? BHI CMDM40 ;YES, BRANCH CMP R0,2(R3) ;IS THE COMMAND STRING EXHAUSTED? BLOS CMDM20 ;NO, LOOP FOR NEXT CHAR TST R1 ;YES, DID REQUIRED # CHARS MATCH? BGT CMDM60 ;NO, TRY NEXT ENTRY CMDM30: INC R0 ;SUCCESS - INCR CMD BEGIN POINTER MOV R0,(R3) ;UPDATE COMMAND STRING DESCRIPTOR MOV 6(R4),R0 ;LOAD THE RETURN VALUE FOR THIS ENTRY TST (R5)+ ;INCR RETURN ADR FOR SUCCESS CMP (SP)+,(SP)+ ;POP TABLE END PTR AND REG 0 BR CMDMXS ;EXIT VIA SUCCESS RETURN ;; CMDM40: CMP R0,2(R3) ;ENTRY MATCH - COMMAND EXHAUSTED? BHI CMDM30 ;YES, SUCCESS CMPB #BLANK,(R0) ;NO, BUT IS NEXT COMMAND CHAR A BLANK? BEQ CMDM30 ;YES, SUCCESS BR CMDM60 ;NO, TRY NEXT ENTRY ;; CMDM50: TST R1 ;CHAR MATCH FAIL - SATISFIED MINIMUM COUNT? BGT CMDM60 ;NO, TRY NEXT ENTRY CMPB #BLANK,-(R0) ;YES, BUT WAS BLANK LAST COMMAND CHAR? BEQ CMDM30 ;YES, THEN THIS IS A MATCH CMPB #BLANK,-(R0) ;WAS BLANK LAST MATCHED CHAR IN STRING? BEQ CMDM30 ;YES, THEN THIS IS A MATCH CMDM60: MOV (SP),R2 ;GET TABLE DESC END POINTER ADD 2(R2),R4 ;INCREMENT TO NEXT ENTRY IN TABLE CMP R4,(R2) ;IS THE TABLE EXHAUSTED? BLO CMDM10 ;NO, TRY MATCH ON NEXT ENTRY CMDMX: TST (SP)+ ;POP TABLE END ADR FROM STACK MOV (SP)+,R0 ;RESTORE REG 0 FOR FAIL EXIT CMDMXS: MOV (SP)+,R1 ;RESTORE REGISTERS USED MOV (SP)+,R2 MOV (SP)+,R3 MOV (SP)+,R4 RTS R5 ;RETURN ;+ ;;********************************************************************** ;; SUBROUTINE TO COPY CHARS FROM AN ALVIN BUFFER TO A COMMAND ;; STRING AND PREPROCESS AS A COMMAND STRING. ;; REMOVES ALL CONTROL CHARS AFTER TAB AND BACKSPACE PROCESSING. ;; REMOVES ALL PREFIX & MULTIPLE OCCURANCES OF BLANKS. ;; FORCES ALL LOWER CASE CHARACTERS TO UPPER CASE. ;; COPIES TO A BUFFER DESCRIBED BY A COMMAND STRING DESCRIPTOR: ;; COMMAND_STRING_DESC: .WORD (ADDRESS OF START OF STRING - DYNAMIC) ;; .WORD (ADDRESS OF END OF STRING - DYNAMIC) ;; .WORD (ADDRESS OF END OF STRING - STATIC) ;; .WORD (ADDRESS OF START OF STRING - STATIC) ;; THE 2 DYNAMIC POINTERS WILL BE SET BY "CMDCOPY". ;; THE STRING WILL BE TRUNCATED ON THE RIGHT IF THERE IS ;; INSUFFICIENT ROOM TO STORE THE ENTIRE COMMAND. ;; THE COUNT OF CHARS IN THE STRING WILL BE RETURNED IN REG 0. ;; EXPECTS CALLS OF THE FORM: ;; JSR R5,CMDCOPY ;CAN BE SHORTENED TO CMDCOP ;; .WORD (ADDRESS OF ALVIN BUFFER DESCRIPTOR) ;; .WORD (ADDRESS OF COMMAND STRING DESCRIPTOR) ;; NOTE-1: IF THE ALVIN BUFFER DESCRIPTOR ADDRESS IS ZERO, THEN ;; THIS ADDRESS IS ASSUMED TO BE IN REGISTER 4. ;; NOTE-2: IF THE COMMAND STRING DESCRIPTOR ADDRESS IS ZERO, THEN ;; THIS ADDRESS IS ASSUMED TO BE IN REGISTER 3. ;- CMDCOPY:: MOV R4,-(SP) ;STACK REGISTERS USED MOV R3,-(SP) MOV R2,-(SP) MOV R1,-(SP) MOV (R5)+,R2 ;GET BUFFER DESC ADR PARM BEQ CMDC10 ;IF ZERO, THEN IT IS ALREADY IN REG 4 MOV R2,R4 ;ELSE PUT IT IN REG 4 CMDC10: MOV (R5)+,R2 ;GET COMMAND STRING DESC ADR PARM BEQ CMDC20 ;IF ZERO, THEN IT IS ALREADY IN REG 3 MOV R2,R3 ;ELSE PUT IT IN REG 3 CMDC20: MOV 6(R3),R2 ;GET ABSOLUTE START OF STRING ADR MOV R2,(R3) ;RESET COMMAND STRING DYNAMIC STARTING ADR CLR R1 ;ZERO THE CHAR COUNTER CMDC30: JSR R5,SPAN ;LOOK FOR TABS IN THE ALVIN BUFFER .WORD 0 .WORD RETURN+NOUPDATE+UNTIL!HT ;SPAN UNTIL A TAB BR CMDC40 ;WHEN NO TABS FOUND, EXIT TAB LOOP MOVB #BLANK!200,(R0) ;OVERRIDE A TAB TO A BLANK W/PARITY BR CMDC30 ;LOOP UNTIL ALL TABS FOUND ;; CMDC40: JSR R5,PRESS ;PROCESS BACKSPACES .WORD 0 ;BUF DESC ADR IS IN REG 4 ;; CMDC50: JSR R5,SPAN ;REMOVE ALL MULTIPLE BLANKS & CONTROL CHARS .WORD 0 .WORD BLANK BR CMDC70 ;WHEN BUFFER IS EMPTY, THEN DONE CMDC60: JSR R5,GETBYTE ;GET NEXT BYTE FROM THE BUFFER .WORD 0 BR CMDC70 ;WHEN BUFFER IS EMPTY, THEN DONE BIC #177600,R0 ;CLEAR PARITY AND ALL HIGHER ORDER BITS CMP #BLANK,R0 ;IS THIS A CONTROL CHAR? BHI CMDC60 ;YES, IGNORE IT CMP #141,R0 ;IS THIS A LOWER CASE "A"? BHI CMDC65 ;NO, NOT LOWER CASE AT ALL CMP #172,R0 ;IS THIS A LOWER CASE "Z"? BLO CMDC65 ;NO, IT IS ABOVE SUB #40,R0 ;YES, CONVERT LOWER CASE TO UPPER CASE CMDC65: MOVB R0,(R2)+ ;MOVE THE CHAR TO THE STRING INC R1 ;COUNT CHARS IN STRING CMP R2,4(R3) ;IS THE STRING FULL? BHI CMDC70 ;YES, THEN DONE CMP #BLANK,R0 ;WAS THE CHAR JUST STORED A BLANK? BEQ CMDC50 ;YES, THEN SPAN MULTIPLE BLANKS BR CMDC60 ;ELSE PROCEED WITH NEXT CHAR ;; CMDC70: MOV R1,R0 ;MOVE CHAR COUNT TO RETURN REGISTER BNE CMDC80 ;IF NOT ZERO, THEN BRANCH CLRB (R2)+ ;ELSE SET 1ST CHAR TO NULL (NULL STRING) CMDC80: DEC R2 ;BACK UP END-OF-STR ADR TO ACTUAL LAST CHAR MOV R2,2(R3) ;UPDATE DYNAMIC END-OF-STRING ADR IN DESC MOV (SP)+,R1 ;RESTORE REGISTERS USED MOV (SP)+,R2 MOV (SP)+,R3 MOV (SP)+,R4 RTS R5 ;RETURN WITH CHARACTER COUNT IN REGISTER 0 ;+ ;;********************************************************************** ;; SUBROUTINE TO PROCESS BACKSPACES OUT OF AN ALVIN BUFFER. ;; SPANS TO FIND THE FIRST TAB CHARACTER OR END OF BUFFER. ;; THEN PROCESSES BACKWARDS FROM THIS POINT TO THE OUTPUT PTR, ;; REMOVING ALL BACKSPACES AND CHARS WHICH WERE BACKED OVER. ;; AND RETAINING ALL PREFIX BACKSPACES. ;; THE OUTPUT POINTER IS UPDATED WHEN DONE. ;; EXPECTS CALLS OF THE FORM: ;; JSR R5,PRESS ;; .WORD (BUFFER DESCRIPTOR ABSOLUTE ADDRESS) ;; NOTE: IF THE BUFFER DESCRIPTOR ABSOLUTE ADDRESS IS ZERO, THEN ;; THIS ADDRESS IS ASSUMED TO BE IN REGISTER 4. ;- DEL=177 ;RUBOUT/DELETE CHARACTER (ALTERNATE BACK SPACE) ;; PRESS:: MOV R4,-(SP) ;SAVE REGISTERS USED MOV R3,-(SP) MOV R2,-(SP) MOV R1,-(SP) MOV R0,-(SP) MOV (R5)+,R3 ;GET BUF DESC ABS ADR BEQ PRESGO ;IF ZERO, THEN IS ALREADY IN REG 4 MOV R3,R4 ;PUT IT IN REG 4 PRESGO: JSR R5,SPAN ;FIND CURRENT END OF BUFFER .WORD 0 ;(BUF DESC IS IN REG 4) .WORD NOUPDATE+RETURN+UNTIL!HT ;CANNOT BACK OVER A TAB NOP ;END-OF-SPAN ADDRESS IN REG 0 (1ST TAB OR END-OF-BUF) MOV R0,R1 ;PUT BUF END ADR IN REG 1 CLR R3 ;CLEAR BACKSPACE COUNTER PRESLP: CMP R0,2(R4) ;PROCESSED TO OUTPUT POINTER? BEQ PRESDONE ;YES, DONE DEC R0 ;BACKUP ONE CMP R0,4(R4) ;IS PROCESS PTR=BUF START? BHIS PRES05 ;NO, CAN PROCEED MOV 6(R4),R0 ;YES, MUST WRAP-AROUND TO END OF BUF PRES05: MOVB (R0),R2 ;GET NEXT CHAR IN BUF BIC #177600,R2 ;CLEAR HIGH-ORDER AND PARITY BITS CMP #BS,R2 ;IS THIS A BACKSPACE? BEQ PRES07 ;YES CMP #DEL,R2 ;IS THIS A DELETE OR RUBOUT CHAR? BNE PRES10 ;NO, NOT A BACKSPACE PRES07: INC R3 ;INCR BACKSPACE COUNTER BR PRESLP ;LOOP ;; PRES10: TST R3 ;HAVE A CHAR, SHOULD BACK OVER IT? BEQ PRES20 ;NO, BRANCH DEC R3 ;YES, BACK UP BACKSPACE COUNTER BR PRESLP ;LOOP - IGNORE CHAR ;; PRES20: DEC R1 ;BACKUP MOVE-IN POINTER CMP R1,4(R4) ;IS IT AT THE BEGINNING OF THE BUFFER? BHIS PRES25 ;NO, BRANCH MOV 6(R4),R1 ;YES, WRAP-AROUND TO END OF BUFFER. PRES25: MOVB (R0),(R1) ;SAVE THIS CHAR - RETAIN ORIGINAL PARITY BR PRESLP ;LOOP ;; PRESDONE: DEC R3 ;ARE THERE STILL BACKSPACES? BMI PRESUP ;NO, QUIT DEC R1 ;YES, MUST MOVE IN THE PREFIX BACKSPACES CMP R1,4(R4) ;UPDATE MOVE-IN POINTER BHIS PRES30 MOV 6(R4),R1 ;WRAP-AROUND TO END OF BUFFER PRES30: MOVB #BS!200,(R1) ;MOVE IN A BACKSPACE (FORCED&EVEN PARITY) BR PRESDONE ;LOOP FOR ALL REMAINING BACKSPACES ;; PRESUP: MOV R1,2(R4) ;UPDATE BUF DESC OUTPUT POINTER MOV (SP)+,R0 ;RESTORE REGISTERS MOV (SP)+,R1 MOV (SP)+,R2 MOV (SP)+,R3 MOV (SP)+,R4 RTS R5 ;RETURN ;;**************************** .End