; PRSVAL - PARSE A VALUE FROM THE VAL INPUT STREAM ; LAST EDIT: 15-OCT-81 ; .NLIST .NLIST BEX .LIST TTM .TITLE PRSVAL .LIST ; ; ;+ ; THIS ROUTINE PARSES STRING ITEMS FROM THE CURRENT VAL BUFFER AND REQUESTS ; INPUT IF THE BUFFER IS EMPTY. IT IS INTENDED FOR INPUTTING FILE NAMES ; AND SIMILAR ITEMS WHICH MAY CONTAIN VAL SEPERATORS. ; ; CALL PRSVAL(NAME,PROMPT,BUF,LEN[,L,SEPSTR,ITERM]) ; ; WHERE: NAME AND PROMPT HAVE THEIR USUAL VAL INTERPRETATIONS ; BUF IS A BUFFER OF LENGTH LEN TO RECEIVE THE STRING READ ; LEN IS THE LENGTH OF BUF ; THE REMAINING PARAMETERS ARE OPTIONAL ; L RECEIVES THE NUMBER OF CHARACTERS RETURNED ; SEPSTR SEPERATOR LIST AS DESCRIBED BELOW ; THIS SHOULD BE A ZERO TERMINATED STRING. ; ITERM INTEGER LOCATION RECEIVES THE ASCII CODE OF THE ; TERMINATING CHARACTER. ; ; THE STRING PARSED IS PLACED IN BUF AND ZERO TERMINATED, IF L IS SPECIFIED ; IT RECEIVES THE NUMBER OF CHARACTERS PLACED IN BUF EXCLUDING THE ZERO BYTE. ; AS A ZERO BYTE IS ALWAYS RETURNED THE BUFFER SHOULD BE ONE BYTE LONGER ; THAT THE LONGEST STRING EVER TO BE READ. ; IF LEN CHARACTERS ARE FOUND BEFORE A TERMINATOR IS REACHED THE REMAINDER ; OF THE STRING IS DISGARDED. ; ; PARSING RULES: ; 1) LEADING BLANKS AND TABS ARE ALWAYS DISGARDED. ; 2) THE FIRST NON-BLANK CHARACTER AND SUBSEQUENT CHARACTERS ARE COPIED TO ; BUF UNTIL A SEPERATOR IS ENCOUNTERED. ; 3) DEFAULT SEPERATORS ARE SPACE, COMMA AND END-OF-LINE. AN ALTERNATIVE ; SEPERATOR LIST MAY BE SPECIFIED AS THE ARGUMENT 'SEPSTR'. HOWEVER ; END-OF-LINE ALWAYS TERMINATES THE STRING. ; 4) IF THE FIRST NON-BLANK CHARACTER OF A STRING IS ' OR " THE STRING ; IS COPIED UP TO A MATCHING QUOTE OR END-OF-LINE WHICHEVER IS ; ENCOUNTERED FIRST. THE ENCLOSING QUOTE(S) ARE DISGARDED. ; 5) WITHIN A STRING, TEXT ENCLOSED IN PARENTHESES () [] {} OR QUOTES '' "" ; IS NOT SCANNED FOR TERMINATORS. ; ; ;- ; .PSECT VALIO ; ; DEFINE FORTRAN PARAMETER BLOCK OFFSETS P1=2 P2=4 P3=6 P4=10 P5=12 P6=14 P7=16 ; ; DEFINE CHARACTER CONSTANTS SPACE=40 TAB=11 COMMA=54 SQUOTE=47 DQUOTE=42 CTRLZ=32 CTRLA=1 ; RDOFF$ ;DEFINE READIT BLOCK OFFSETS E..ABT=VI.SAV+2 ;OFFSET TO ABORT PROCESSOR ROUTINE ; ; PRSVAL::MOV R5,-(SP) CALL VPRMPT CALL VMAP MOV RD.KP(R0),R2 ;GET CHARACTER POINTER TSTB (R2) BNE 2$ MOV #NULL,R5 CALL VINPUT ;GET A NEW LINE CALL VMAP MOV RD.KP(R0),R2 ;GET BACK POINTER ; 2$: MOV (SP),R5 ;RESTORE ARGUMENT LIST 3$: CMPB (R2),#SPACE ;SKIP SPACES AND TABS BEQ 4$ CMPB (R2),#TAB BNE 10$ ;NOT BLANK OR ABORT 4$: INC R2 BR 3$ ;KEEP SKIPPING ; 10$: MOV R2,-(SP) ;SAVE START OF THE STRING CMPB (R2),#SQUOTE ;CHECK FOR QUOTES BEQ 11$ CMPB (R2),#DQUOTE BNE 20$ 11$: MOVB (R2)+,R4 ;GET TERMINATING CHAR. INC (SP) ;AND BUMP THE STRING POINTER MOV R4,-(SP) ;FORM A SEPERATOR LIST MOV SP,R3 ;SET A POINTER TO IT CALL PARSE ;PARSE PARSE TO SEPERATOR TST (SP)+ ;POP TERMINATOR BR 25$ ;GO RETURN STRING ; 20$: MOV #DTERM,R3 ;GET THE DEFAULT TERMINATOR LIST CMPB (R5),#6 ;IS THERE A USER SUPPLIED ONE BLT 21$ CMP P6(R5),#-1 ;IS IT NULL BEQ 21$ MOV P6(R5),R3 ;GET USER TERMINATOR LIST 21$: CALL PARSE ; ; 25$: CMPB (R2),#CTRLZ BEQ 40$ CMPB (R2),#CTRLA BEQ 40$ ; ; HERE WE HAVE THE START OF THE STRING ON TOP OF THE STACK ; AND THE STRING TERMINATOR POINTER IN R2 ; 30$: MOV (SP)+,R0 ;POP START OF STRING MOV (SP)+,R5 ;RESTORE THE ARGUMENT LIST MOV P3(R5),R1 ;GET USER BUFFER MOV @P4(R5),R4 ;GET USER BUFFER LENGTH DEC R4 ;ALLOW FOR ZERO BYTE BLE 32$ ;JUST IN CASE 31$: CMP R0,R2 ;END OF STRING ? BEQ 32$ ;BREAK IF SO MOVB (R0)+,(R1)+ ;COPY CHAR SOB R4,31$ ; 32$: CLRB (R1) ;ADD THE ZERO BYTE CMPB (R5),#5 ;IS # OF CHARS NEEDED ? BLT 33$ CMP P5(R5),#-1 ;IS ARGUMENT NULL BEQ 33$ SUB P3(R5),R1 ;GET NUMBER OF CHARACTERS MOV R1,@P5(R5) 33$: CMPB (R5),#7 ;TERMINATING CHARACTER REQUIRED ? BLT 34$ CMP P7(R5),#-1 ;IS ARGUMENT NULL BEQ 34$ MOVB (R2),R4 ;GET TERMINATING CHAR MOV R4,@P7(R5) ;AND RETURN IT ; 34$: CALL VMAP ;RESTORE R0,R1 ; ; SKIP THE TERMINATING CHARACTER. ; IF THE TERMINATOR WAS SPACE THEN SKIP TRAILING SPACES. TSTB (R2) ;ARE WE AT END OF STRING ? BEQ 36$ ;IF SO SKIP CMPB (R2)+,#SPACE ;SKIP CHAR. AND WAS IT SPACE ? BNE 36$ 35$: CMPB (R2)+,#SPACE ;EAT UP SPACES BEQ 35$ DEC R2 ;LEAVE THE NON-BLANK CHAR. 36$: MOV R2,RD.KP(R0) ;UPDATE CHARACTER POINTER CALL VRSCTX ;BACK TO USER MAPPING RETURN ; ; PROCESS AN CTRL-Z OR CTRL-A ABORT 40$: CLRB @(SP) ;TERMINATE THE BUFFER CALL VRSCTX ;RESTORE USER CONTEXT CALL @E..ABT(R0) ;CALL THE ABORT PROCESSOR CALL VMAP ;FROM WHICH WE MAY RETURN MOV (SP),R2 ;END OF STRING POINTER (NULL) BR 30$ ; ; DTERM: .BYTE SPACE,COMMA,TAB,0 NULL: .WORD 0 ; ; ; ; ; PARSE - PARSE A STRING UP TO A TERMINATOR ; ; INPUT: R2 STRING ADDRESS ; R3 POINTER TO TERMINATOR LIST ; ; OUTPUT: R2 POINTER TO TERMINATING CHAR. ; ; PARENTHESIZED OR QUOTED TEXT WITHIN A STRING IS NOT SCANNED FOR ; TERMINATORS. ; ; CTRL-Z OR CTRL-A ALWAYS TERMINATES A STRING ; ; PARSE: CMPB (R2),#CTRLZ BEQ 20$ CMPB (R2),#CTRLA BEQ 20$ MOV R3,R4 ;COPY TERMINATOR LIST 1$: CMPB (R2),(R4) ;TERMINATOR ? BEQ 20$ ;SKIP IF SO TSTB (R4)+ ;NEXT IN TERM. LIST BNE 1$ ;AND TRY AGAIN IF NOT FOUND ; ; CHECK FOR QUOTES AND PARENTHESES MOV #QTAB,R4 ;POINT TO QUOTE LIST 2$: CMPB (R2),(R4) ;COMPARE WITH CHAR IN LIST. BEQ 3$ ;SKIP IF WE MATCH ADD #2,R4 ;ELSE ON TO NEXT OPEN QUOTE TST (R4) ;CHECK FOR END OF QUOTE LIST BEQ 10$ ;SKIP IF NOTHING MATCHES BR 2$ ;ELSE KEEP LOOPING ; IF WE FIND AN OPEN QUOTE OR PARENTHESIS, CALL PARSE TO MATCH IT. 3$: INC R2 ;SKIP THE OPEN 'QUOTE' MOV R3,-(SP) ;SAVE OUR CURRENT TERMINATOR MOVB 1(R4),R4 ;GET THE CLOSE 'QUOTE' CHAR. MOV R4,-(SP) ;SAVE IT MOV SP,R3 ;SET THE LIST POINTER CALL PARSE ;GO (COME?) MATCH IT TST (SP)+ ;POP TERMINATOR WORD MOV (SP)+,R3 ;RESTORE PREVIOUS TERMINATOR LIST INC R2 ;SKIP CLOSE 'QUOTE' BR PARSE ;AND KEEP PARSING. ; ; ; ; HERE THE CHAR. WE ARE LOOKING AT IS NEITHER A TERMINATOR OR A QUOTE. 10$: INC R2 ;ON TO NEXT CHARACTER BR PARSE ;AND BACK TO THE TOP. ; 20$: RETURN ; ; ; THIS TABLE DETERMINES THOSE CHARACTER PAIRS WHICH MAY 'QUOTE' TEXT. ; QTAB: .ASCII /()[]{}''""/ .WORD 0 ; ; LINK THE DEFAULT CTRL-Z PROCESSOR ; .PSECT VALIMP OVR,D,GBL ; VALIMP: .=VALIMP+E..ABT .WORD ABORT ;CTRL-Z PROCESSOR ROUTINE ; ; .END