.TITLE INDPRM ; ; PROCESS INDIRECT COMMAND ; ; USE TPARS TO PARSE THE COMMAND NAME AND PARAMETERS ; ACTION ROUTINES PUSH THE PRESENT COMMAND FILE CLOSED ; AND OPEN A NEW FILE THAT HAS THE NAME OF THE COMMAND. ; THEY ALSO EXTRACT BOTH POSITIONAL AND KEYWORD PARAMETERS ; FROM THE COMMAND LINE. KEYWORD PARAMETERS ARE ENTERED ; INTO THE SYMBOL TABLE WITH THE FIRST SIX CHARACTERS OF ; THE KEYWORD AS THE SYMBOL NAME AND THE VALUE OF THE ; KEYWORD AND THE SYMBOL VALUE(STRING). POSITIONAL PARAMETERS ; ARE ENTERED WITH A SYMBOL NAME OF $NN WHERE NN IS 0 FOR THE ; COMMAND, 1 FOR THE FIRST PARAMETER, 2 FOR THE SECOND AND SO ON. ; THE COMMAND PARAMTERS MAY THEN BE REFERENCED AS ANY OTHER STRING ; VARIABLE. ; .MCALL ISTAT$,STATE$,TRAN$ .GLOBL COMND,SUBPRM ; ; STATE TABLES USED TO PARSE A COMMAND LINE ; ISTAT$ STATES,KEYTAB ; ; STATE TABLE TO EXTRACT COMMAND NAME ; STATE$ COMND TRAN$ !CMND,,PUTCMD ; ; ONE OR MORE BLANKS SEPERATE COMMAND FROM PARMATERS ; STATE$ TRAN$ $EOS,$EXIT TRAN$ $BLANK ; ; STATE TO LOOK FOR THE NEXT PARAMETER ; STATE$ NXTPAR TRAN$ !KEYWRD,KEYVAL,PUTKEY TRAN$ !VALUE,ANYMOR,PUTPV TRAN$ $EOS,$EXIT ; ; STATE TO GET A KEYWORD VALUE ; STATE$ KEYVAL TRAN$ !DELIM,NXTPAR ; MAY BE NULL VALUE TRAN$ !VALUE,ANYMOR,PUTKV ; OR SAME SYNTAX AS POSITIONAL VALUE TRAN$ $LAMDA ; DROP THRU TO ANYMOR FOR TERMINATOR ; ; STATES TO CHECK PARAMETER TERMINATOR TO SEE IF ANY MORE TO DO ; STATE$ ANYMOR TRAN$ $EOS,$EXIT ; EXIT IF END OF LINE TRAN$ !DELIM,NXTPAR ; ELSE MUST BE VALID DELIMITER ; ; SUBSTATE TO PARSE DELEMITERS BETWEEN PARAMETERS ; DELEMITERS ARE OF THE FORM [ ][,][ ] ; STATE$ DELIM TRAN$ $BLANK,DELIM1 ; LEADING BLANKS TRAN$ <',>,DELIM2 ; OR COMMA WITH NO LEADING BLANKS STATE$ DELIM1 TRAN$ <',>,DELIM2 ; COMMA AFTER LEADING BLANKS TRAN$ $LAMDA,$EXIT ; OR ONLY BLANKS STATE$ DELIM2 TRAN$ $BLANK,$EXIT ; BLANKS AFTER COMMA TRAN$ $LAMDA,$EXIT ; BUT NOT REQUIRED ; ; SUBSTATE TO PARSE A KEYWORD ; KEYWORDS ARE OF THE FORM [A-Z OR $][ALPHAMERIC][=] ; STATE$ KEYWRD TRAN$ '$,KEYW2 ; START WITH DOLLAR DIGN TRAN$ $ALPHA ; OR ALPHA CHAR STATE$ KEYW2 TRAN$ $STRNG,KEYW3 ; THEN ANY ALPHAMERIC STRING TRAN$ $LAMDA ; BUT ONLY ON CHAR REQUIRED STATE$ KEYW3 TRAN$ !EQUALS,$EXIT ; THEN AN EQUAL SIGN ; ; SUBSTATE TO PARSE AN EQUAL SIGN WITH OPTIONAL BLANKS ; STATE$ EQUALS TRAN$ $BLANK,EQU2 ; LEADING BLANKS? TRAN$ $LAMDA ; NOT REQUIRED STATE$ EQU2 TRAN$ '= ; MUST GET EQUAL SIGN STATE$ TRAN$ $BLANK,$EXIT ; OPTIONAL TRAILING BLANKS TRAN$ $LAMDA,$EXIT ; NOT REQUIRED ; ; SUBSTATE TO PARSE A VALUE OPTIONALLY QUOTED ; STATE$ VALUE TRAN$ $LAMDA,,IVALUE ; NULL TRANSITION TO INIT VARIABLES ; STATE$ TRAN$ '",QVAL ; OPENING QUOTE TRAN$ '(,SVAL,OPNPRN ; OR SUBPARAMTER TRAN$ $LAMDA ; OTHERWISE DROP THRU TO NORMAL ; STATE$ VALUE2 TRAN$ $ANY,VALUE2,NDELIM ; COLLECT CHARACTERS UNTIL THE ACTION ; ROUTINE FINDS A DELIMITER AND CAUSED ; THE TRANSITION TO FAIL TRAN$ $EOS,$EXIT ; DONE IF END OF INPUT LINE TRAN$ $LAMDA,$EXIT ; THEN RETURN WITH WHATEVER WE COLECTED ; ; STATE TO COLLECT A QUOTED STRING ; STATE$ QVAL TRAN$ '",DBLQ ; POSSIBLE IMBEDDED QUOTE TRAN$ $ANY,QVAL,STOCHR ; COLLECT ALL OTHER CHARACTERS ; STATE$ DBLQ TRAN$ '",QVAL,STOCHR ; COLLECT A QUOTE IF TWO IN A ROW TRAN$ $LAMDA,$EXIT ; OTHERWISE TERMINATE DUE TO 1ST ONE ; ; STATE TO COLLECT SUBPARAMTERS ; STATE$ SVAL TRAN$ '(,SVAL,INCPRN ; COUNT NESTING DEPTH TRAN$ '),$EXIT,DECPRN ; DONE IF ACTION ROUTINE DETECTS ; BALANCED PARENS TRAN$ $ANY,SVAL,STOCHR ; COLLECT ANYTHING ELSE ; ; SUBSTATE TO EXTRACT THE COMMAND(FILE) NAME ; STATE$ CMND TRAN$ $LAMDA,,IVALUE ; DUMMY TRANSITION TO INIT POINTERS STATE$ CMND2 TRAN$ $ALPHA,CMND2,STOCHR ; COLLECT ANY ALPHA CHARS TRAN$ $DIGIT,CMND2,STOCHR ; OR DIGIT TRAN$ <'.>,CMND2,STOCHR TRAN$ <':>,CMND2,STOCHR TRAN$ <'[>,CMND2,STOCHR TRAN$ <']>,CMND2,STOCHR TRAN$ <',>,CMND2,STOCHR TRAN$ <'/>,CMND2,STOCHR TRAN$ <'->,CMND2,STOCHR TRAN$ $LAMDA,$EXIT ; ; STATE TO SCAN FOR A GIVEN SUBPARAMETER OF A STRING ; STATE$ SUBPRM TRAN$ $LAMDA,,ISUBPR ; DUMMY TRANSITION TO INIT VARIABLES ; STATE$ SUBP2 TRAN$ !VALUE,$EXIT,SPACT ; IS THIS A VALID VALUE? TRAN$ !VALUE,SPMORE ; SKIP THE UNWANTED VALUE TRAN$ $EOS,$EXIT ; EXIT IF END OF STRING ; STATE$ SPMORE TRAN$ !DELIM,SUBP2 ; IF DELIMITER, GO LOOK FOR MORE TRAN$ $LAMDA,SUBP2 ; LET SUBP2 FIND END OF STRING ; STATE$ .PAGE ; ; ACTION ROUTINES FOR TRANSITIONS DETECTED BY TPARS ; ; ; SAVE ADDRESS AND LENGTH OF A KEYWORD ; PUTKEY:; MOV .PSTCN,KWSCN ; SAVE LENGTH MOV .PSTPT,KWSPT ; AND ADDRESS RETURN ; RETURN ; ; PUT A KEYWORD AND ITS VALUE IN THE SYMBOL TABLE ; PUTKV:; MOV R3,-(SP) ; SAVE R3 MOV R4,-(SP) ; AND R4 MOV R5,-(SP) ; AND R5 MOVB #STR,SYMTP ; SET TYPE TO STRING MOV KWSPT,R0 ; GET ADDRESS OF SYMBOL CALL PRSYM1 ; PUT IT IN SYMBOL TABLE BR PUTVAL ; PUT THE VALUE IN SYMBOL TABLE ; ; PUT A POSITIONAL PARAMETER VALUE IN SYMBOL TABLE ; PUTPV: MOV R3,-(SP) ; SAVE R3 MOV R4,-(SP) ; AND R4 MOV R5,-(SP) ; AND R5 MOVB #'$,SCR ; PUT DOLLAR SIGN IN SCRATCH BUFFER MOV #SCR+1,R0 ; SET UP BUFFER ADDRESS MOV ARGNO,R1 ; GET POSITON NUMBER CLR R2 ; SUPPRESS LEADING ZEROS CALL $CBDMG ; CONVERT TO DECIMAL CHAR STRING MOV #SCR,R0 ; GET ADDRESS OF SYMBOL MOV .LIFLG,-(SP) ; PUSH FLAGS ON STACK BIC #DEFGLS,.LIFLG ; TEMPORARILY SUPPRESS GLOBALS MOVB #STR,SYMTP ; SET TYPE TO STRING CALL PRSYM1 ; PUT SYMBOL IN TABLE MOV (SP)+,.LIFLG ; RESTORE FLAGS INC ARGNO ; INCREMENT ARGUMENT NUMBER ; ; PUT SYMBOL VALUE IN SYMBOL TABLE ; PUTVAL: MOV #PRMSCR,R0 ; GET START OF VALUE STRING MOV PRMT5,R1 ; GET NEXT AVAIL BYTE SUB R0,R1 ; CALC LENGTH CALL ASVALS ; PUT STRING IN TABLE MOV (SP)+,R5 ; RESTORE R5 MOV (SP)+,R4 ; AND R4 MOV (SP)+,R3 ; AND R3 BCS 100$ ; BR IF SYMBOL TABLE OVERFLOW 20$: RETURN ; RETURN OF OK 100$: TRAP ERSOV ; REPORT THE ERROR ; ; NESTED INDIRECT COMMAND, OPEN NEW FILE, FIX UP SYMBOL ; TABLE POINTERS AND SAVE COMMAND NAME AS POSITIONAL ; PARAMTER 0. ; PUTCMD:; MOV R3,-(SP) ; SAVE R3 MOV R4,-(SP) ; SAVE R4 MOV R5,-(SP) ; AND R5 ; MOV .PSTPT,R1 ; GET COMMAND STRING ADDRESS MOV .PSTCN,R2 ; AND LENGTH MOV #GCML,R5 ; POINT TO GCML CONTROL BLOCK CALL $MGCL4 ; OPEN NEW FILE ; 10$: MOV R5,R0 ; COPY FILE FDB ADDRESS CALL PSHSYM ; FIX UP SYMBOL TABLE POINTERS ; CALL PUTPV ; SAVE COMMAND NAME AS POSITIONAL ; ; PARAMETER $0 MOV (SP)+,R5 ; RESTORE R5 MOV (SP)+,R4 ; AND R4 MOV (SP)+,R3 ; AND R3 RETURN .PAGE ; ACTION OUTINES TO COLLECT CHARACTERS OF A PARAMETER VALUE AND ; TO DO SOME OF THE SYNTAX CHECKING NOT EASILY DONE BY THE ; AVAILABLE TRANSITION TYPES. ; ; ; INIT POINTER TO SCRATCH BUFFER ; ; A SCRATCH BUFFER IS USED BECAUSE THE VALUE COLLECTED MAY HAVE ; CHARACTERS REMOVED, QUOTES, PREVENTING USING A SUBSTRING OF THE ; ORIGINAL COMMAND. ; IVALUE: MOV #PRMSCR,PRMT5 ; SET POINTER TO START OF BUFFER RTS PC ; RETURN ; ; INIT OPEN PAREN COUNT. PAREN COUNT KEEPS TRACK OF NESTED ; SUBPARAMETER LEVEL. WHEN IT IS BACK TO ZERO WE ARE COMPLETELY ; UNNESTED. ; OPNPRN: CLR PRMPRN ; INIT COUNTER RTS PC ; RETURN ; ; CHECK TO SEE IF CHARACTER JUST PARSED IS A DELIMITER AND ; REJECT THE TRANSITION IF IT IS. ELSE COLLECT THE CHARACTER. ; THIS IS A SIMPLER WAY TO COLLECT ANY CHARACTER EXCEPT A COMMA ; OR A BLANK THAN CODING TRANSITIONS FOR ALL POSSIBLE SPECIAL ; CHARACTERS. ; NDELIM:; MOVB .PCHAR,R0 ; GET THE CHARACTER JUST PARSED BY $ANY CMPB R0,#', ; IS IT A COMMA? BEQ 20$ ; BR IF SO CMPB R0,#' ; IS IT A BLANK? BEQ 20$ ; BR IF SO CMPB R0,#' ; IS IT A TAB? BNE STOCHR ; GO STORE THE CHARACTER ; 20$: ADD #2,(SP) ; BUMP RETURN ADDRESS TO REJECT TRANSITION RTS PC ; RETURN ; ; STORE A CHARACTER JUST PARSED IN OUTPUT BUFFER ; STOCHR: MOVB .PCHAR,@PRMT5 ; PUT IT IN BUFFER INC PRMT5 ; BUMP POINTER RTS PC ; RETURN ; ; ACTION ROUTINES TO HANDLE PARENS. EACH OPEN PAREN BUMPS THE ; PAREN COUNTER AND IS COLLECTED. EACH CLOSE PAREN DECREMENTS THE ; PAREN COUNTER. IF THE PAREN COUNTER GOES NEGATIVE INDICATING ; ALL NESTING IS UNNESTED, THE TRANSITION IS ALLOWED TERMINATING ; THE VALUE COLLECTION. IF WE ARE STILL NESTED THE TRANSITION ; IS REJECTED AND THE PAREN IS COLLECTED BY THE $ANY TRANSITION. ; INCPRN: INC PRMPRN ; COUNT OPEN PAREN BR STOCHR ; COLLECT IT ; DECPRN: DEC PRMPRN ; DEC PEREN COUNT BMI 10$ ; BR IF UNNESTED ADD #2,(SP) ; REJECT TRANS CAUSING PAREN TO BE COLLECTED ; BY THE $ANY TRANSITION 10$: RTS PC ; RETURN ; ; ROUTINE TO INIT SUBPARAMETER INDEX ; ISUBPR:; CLR PRMT4 ; SET TO ZERO RTS PC ; RETURN ; ; ACTION ROUTINE FOR COUNTING SUBPARAMETERS ; ; EACH TIME A VALID VALUE IS FOUND BY THE SUBPARAMETER STATE ; TABLES, THIS ROUTINE COUNTS THE SUBPARAMTER AND IF IT IS THE ; ON REQUESTED BY THE USER COMMAND LINE ITS LOCATION AND LENGTH ; ARE SAVED FOR THE STRING SUBSTITUTION ROUTINE. ; SPACT: INC PRMT4 ; INCREMENT SUBPARAMETER NUMBER CMP PRMT4,PRMT3 ; IS IT THE ONE WE WANT? BEQ 20$ ; TAKE NORMAL EXIT IF SO ADD #2,(SP) ; REJECT TRANSITION IF NOT MOV #PRMSCR,PRMT5 ; FORCE NULL OUTPUT STRING 20$: RTS PC ; RETURN ; ; ; ; LOCAL VARIABLES ; ARGNO:: .WORD 0 ; NUMBER OF POSITIONAL ARGUMENT KWSCN: .WORD 0 ; LENGTH OF KEYWORD KWSPT: .WORD 0 ; ADDRESS OF KEYWORD ; PRMT3:: .WORD 0 ; REQUESTED SUBPARAMETER NUMBER PRMT4:: .WORD 0 ; CURRENT SUBPARAMETER BEING PARSED PRMT5:: .WORD 0 ; POINTER TO TEMP BUFFER PRMPRN: .WORD 0 ; PAREN NESTING LEVEL ; PRMSCR:: .BLKB 80. ; BUFFER TO HOLD VALUE BEING COLLECTED .END