.TITLE EDI04 .psect EDI04 .IDENT /X01/ .NLIST BEX ; ; EDITOR (TEMP FILE VERSION) ; ; VERSION X01 ; ; DAVID G. CONROY 10-APR-78 ; ; ; as modified by Eric Levy ; fix pattern match bug, checking prev pattern used r1 instead of r2 ; .if df mutask .macro pure .psect pur,ro .endm .macro impure .psect ipur,rw .endm .iff .macro pure .endm .macro impure .endm .endc .GLOBL COMPIL .GLOBL REKILL .GLOBL AMATCH .GLOBL MATCH .GLOBL PBUF .GLOBL ORG .MCALL CALL .MCALL CALLR .MCALL RETURN ; ; GLOBAL EQUIVALENCES ; PBS == 128. ;SIZE OF PATTERN BUFFER ; ; LOCAL EQUIVALENCES ; PATTERN MATCH OPCODES ; END = 0 ;END OF PATTERN CHAR = 2 ;CHARACTER BOL = 4 ;BEGINNING OF LINE EOL = 6 ;END OF LINE ANY = 10 ;ANY CHARACTER CCL = 12 ;CHARACTER CLASS NCCL = 14 ;NEGATED CHARACTER CLASS CLO = 16 ;CLOSURE BLANK = 40 ;ASCII BLANK ; ; LOCAL DATA ; ORG: .BLKW 1 ;PTR TO LINE ORIGIN (FOR '^') PBUF: .BYTE END ;PATTERN BUFFER .BLKB PBS-1 ; pure ;+ ; ** COMPIL -- COMPILE A TEXT PATTERN ; ; COMPILE THE FOLLOWING TEXT PATTERN INTO INTERNAL FORM, AS NEEDED ; BY MATCH. ; JUMP DIRECTLY TO ?3 OR ?0 ON ERRORS, AFTER FIRST KILLING THE NEW ; (BAD) EXPRESSION. ; ONLY CERTAIN CHARACTERS MAY BE USED AS TEXT DELIMITERS. BAD ONES ; DRAW A ?9. THIS STOPS THE EDITOR FROM DOING EVIL THINGS IF A BAD ; LINE BEGINNING WITH 'S', 'V' OR 'G' IS ENTERED. ; ; INPUTS: ; R0=DELIMITER ; ; OUTPUTS: ; PBUF=COMPILED PATTERN ;- COMPIL: MOV R0,-(SP) ;SAVE REGISTERS MOV R1,-(SP) ; MOV R2,-(SP) ; MOV R3,-(SP) ; CMP R0,#1 ;IS IT A CONTROL A (OK IF IT IS) ;JUL09EL BEQ 5$ ;JUL09EL CMP R0,#'! ;DELIMITER A CONTROL CHARACTER ;; BLO ERR9 ;YES, ERROR BLO jerr9 ;YES, ERROR need branch aid here CMP R0,#'0 ;LEGAL UP TO '0' BLO 5$ ; CMP R0,#': ;DIGITS ILLEGAL BLO ERR9 ; CMP R0,#'A ;LETTERS AND SOME HIGH GRAPHICS BHIS ERR9 ;ILLEGAL 5$: MOV R0,R3 ;SAVE DELIMITER MOV #PBUF,R1 ;GET POINTER TO PATTERN BUFFER CALL GETC ;PICK UP FIRST CHARACTER CMP R0,R3 ;NULL EXPRESSION BNE 11$ ;NO CMPB (R1),#END ;YES, IS THERE AN EXPRESSION BEQ ERR3 ;NO BR 120$ ;YES 10$: CALL GETC ;GET PATTERN CHARACTER 11$: CMP R0,#NL ;ERROR ON NEWLINE bne 15$ ; cmp r3,#1 ;special check for control-a as delim beq 110$ ;if ^a is delim, then nl is valid end br err3 ;delim. else nl is error here. 15$: CMP R0,#EOF ;OR GLOBAL EOF BEQ ERR3 ; CMP R0,R3 ;DELIMITER BEQ 110$ ;YES, GO WRAP UP CMPB R0,#'* ;CLOSURE BNE 40$ ;BR IF NOT CMP R1,#PBUF ;IF NOTHING TO CLOSE THEN BEQ ERR3 ;ERROR CMPB (R2),#BOL ;^* IS ILLEGAL ;;change r1 to r2, fix pattern bug BEQ ERR3 CMPB (R2),#EOL ;$* IS ILLEGAL BEQ ERR3 CMPB (R2),#CLO ;** IS ILLEGAL BEQ ERR3 call getc ;1 last check for safety cmpb r0,#'* ; ** is illegal beq err3 ; mov r0,peek ;its ok, back it goes mov #'*,r0 ;restore it MOV #END,R0 ;PUT END ON THE CLOSED PATTERN CALL PUTPAT CALL PUTPAT ;ALLOW ROOM FOR THE CLO MOV R1,-(SP) ;SAVE POINTER TO PATTERN END 20$: DEC R1 ;SLIDE THE CLOSED CMP R1,R2 ;PATTERN BLOS 30$ ;ALONG MOVB -1(R1),(R1) ;AS THE CLO OPCODE BR 20$ ;GOES FIRST 30$: MOVB #CLO,(R1) ;INSERT CLOSURE OPCODE MOV (SP)+,R1 ;RESTORE OUTPUT POINTER BR 10$ ;NEXT jerr9=. jmp err9 ;branch aid 40$: MOV R1,R2 ;SET POINTER TO LAST PATTERN CMPB R0,#'. ;ANY BNE 50$ ;NO MOV #ANY,R0 ;YES, GET OPCODE BR 100$ ;STORE 50$: CMPB R0,#'^ ;BEGINNING OF LINE BNE 60$ ;NO MOV #BOL,R0 ;YES, GET OPCODE BR 100$ ;STORE 60$: CMPB R0,#'$ ;END OF LINE BNE 70$ ;NO MOV #EOL,R0 ;YES, GET OPCODE BR 100$ ;STORE 70$: CMPB R0,#'[ ;CHARACTER CLASS BNE 80$ ;NO CALL GETCC ;YES, GET CHARACTER CLASS BR 10$ ;GO FOR MORE 80$: CMPB R0,#'\ ;ESCAPE BNE 90$ ;NO CALL GETC ;GET ACTUAL CHARACTER CMP R0,#EOF ;ERROR IF EOF BEQ ERR3 ; 90$: MOV R0,-(SP) ;SAVE CHARACTER MOV #CHAR,R0 ;PUT OUT OPCODE CALL PUTPAT ;FOR CHARACTER MOV (SP)+,R0 ;GET CHARACTER BACK TST OS ;IS THE MATCH CASELESS BNE 100$ ;YES CALL MAPLOW ;MAKE UNIFORM CASE (CASELESS MATCH) 100$: CALL PUTPAT ;SAVE IN PATTERN AND BR 10$ ;GO FOR MORE 110$: MOV #END,R0 ;FINISH OFF PATTERN CALL PUTPAT 120$: MOV (SP)+,R3 ;RESTORE REGISTERS MOV (SP)+,R2 ; MOV (SP)+,R1 ; MOV (SP)+,R0 ; RETURN ;RETURN TO CALLER ERR9: MOV #9.,R1 ;FUNNY R.E. DELIMITER JMP ERROR ; ERR3: MOVB #END,PBUF ;BAD R.E. MOV #3,R1 ; JMP ERROR ; ;+ ; ** GETCC -- COMPILE A CHARACTER CLASS SPECIFIER. ; ; INPUTS: ; R1=POINTER INTO OUTPUT BUFFER FOR PATTERN ; ; OUTPUTS: ; R1=ADVANCED ; ; USES: ; R0 ;- GETCC: MOV R2,-(SP) ;SAVE REGISTERS CALL GETC ;GET CHARACTER FROM PATTERN CMP R0,#'^ ;NEGATED CLASS BEQ 10$ ;YES MOV R0,PEEK ;PUT THE CHARACTER BACK MOV #CCL,R0 ;OPCODE BR 15$ ; 10$: MOV #NCCL,R0 ;OPCODE 15$: CALL PUTPAT ;SAVE IN THE PATTERN MOV R1,R2 ;ADDRESS OF COUNT CLR R0 ;PUT OUT BYTE COUNT CALL PUTPAT ;INITIALLY AS ZERO 20$: CALL GETC ;GET CHARACTER FROM PATTERN CMP R0,#NL ;ERROR ON NEWLINE BEQ ERR3 ; CMP R0,#EOF ;AND EOF BEQ ERR3 ; CMPB R0,#'] ;END OF PATTERN? BEQ 40$ ;YES CMPB R0,#'\ ;ESCAPE BNE 30$ ;NO CALL GETC ;GET ACTUAL CHARACTER CMP R0,#EOF ;ERROR IF EOF BEQ ERR3 ; 30$: call ranges ;check for a-z, control-a etc. TST OS ;IS THE MATCH CASELESS BNE 32$ ;NO CALL MAPLOW ;FORCE UNIFORM CASE 32$: CALL PUTPAT ;PUT IN PATTERN INCB (R2) ;FIXUP CHARACTER COUNT BEQ ERR3 ;>255 CHARACTERS BR 20$ ;GO FOR MORE 40$: MOV (SP)+,R2 ;RETURN RETURN ; ;+ ; ** REKILL -- KILL OFF SAVED R.E. ; ; USES: ; NONE ;- REKILL: MOVB #END,PBUF ;THATS ALL THERE IS TO IT RETURN ; ;+ ; ** PUTPAT -- STORE A BYTE INTO THE PATTERN (IF IT FITS) ; ; INPUTS: ; R0=PATTERN BYTE ; R1=POINTER INTO PBUF ; ; OUTPUTS: ; R1=UPDATED ;- PUTPAT: CMP R1,#PBUF+PBS ;DOES IT FIT BHIS 10$ ;NO MOVB R0,(R1)+ ;YES, STORE IT RETURN ;DONE 10$: MOVB #END,PBUF ;KILL OFF THE R.E. CLR R1 ;?0 JMP ERROR ; ;+ ; ** MAPLOW -- MAP TO LOWER CASE ; ; INPUTS: ; R0=CHARACTER ; ; OUTPUTS: ; R0=CHARACTER ;- MAPLOW: CMPB R0,#'A ;RANGE CHECK BLO 10$ ;TOO LOW CMPB R0,#'Z BHI 10$ ;TOO HIGH ADD #BLANK,R0 ;MAKE LOWER CASE 10$: RETURN ;DONE ;+ ; ** AMATCH -- LOOK FOR A MATCH ANYWHERE IN THE LINE ; ; INPUTS: ; PBUF=PATTERN ; R0=POINTER TO ASCIZ LINE ; ; OUTPUTS: ; C BIT CLEAR IF MATCH ;- AMATCH: MOV R0,-(SP) ;SAVE STUFF MOV R1,-(SP) ; MOV R2,-(SP) ; MOV R0,ORG ;SET LINE ORIGIN MOV R0,R2 ;WORKING POINTER MOV #PBUF,R1 ;PATTERN 10$: TSTB (R2) ;MORE TO DO BEQ 20$ ;NO MOV R2,R0 ;YES, TRY FOR A MATCH CALL MATCH ; BCC 30$ ;YES, GOT ONE INC R2 ;MOVE ALONG 1 CHARACTER AND BR 10$ ;TRY AGAIN 20$: SEC ;NO MATCH 30$: MOV (SP)+,R2 ;RETURN MOV (SP)+,R1 ; MOV (SP)+,R0 ; RETURN ; ;+ ; ** MATCH -- PATTERN MATCHER ; ; INPUTS: ; R0=POINTER TO ASCIZ TEXT STRING ; R1=POINTER TO PATTERN ; ; OUTPUTS: ; R0=POINTER PAST THE MATCHED TEXT (SUCCESS ONLY) ; C BIT CLEAR IF MATCH; SET OTHERWISE ;- MATCH: MOV R1,-(SP) ;SAVE REGISTERS MOV R2,-(SP) MOV R3,-(SP) 10$: MOVB (R1)+,R2 ;PATTERN OPCODE JMP @20$(R2) ;GO TO EXECUTOR 20$: .WORD 150$ ;END .WORD 30$ ;CHAR .WORD 40$ ;BOL .WORD 50$ ;EOL .WORD 60$ ;ANY .WORD 70$ ;CCL .WORD 80$ ;NCCL .WORD 90$ ;CLO 30$: MOVB (R0)+,R2 ;CHAR FROM THE TEXT TST OS ;IS THE MATCH CASE SENSITIVE BNE 35$ ;YES CMP R2,#'A ;MAP R2 TO LOWER CASE BLO 35$ ; CMP R2,#'Z ; BHI 35$ ; ADD #BLANK,R2 ; 35$: CMPB R2,(R1)+ ;CHECK FOR MATCH BEQ 10$ ;YES BR 160$ ;NO 40$: CMP R0,ORG ;AT BOL BEQ 10$ ;BR IF YES BR 160$ ;NO 50$: CMPB (R0),#NL ;AT EOL BEQ 10$ ;YES BR 160$ ;NO 60$: CMPB (R0)+,#NL ;TRYING TO MATCH EOL BNE 10$ ;NO, OK BR 160$ ;EOL FAILS 70$: CALL CMATCH ;MATCH CHARACTER CLASS BCC 10$ ;IF MATCH, OK BR 160$ ;OTHERWISE FAIL 80$: CALL CMATCH ;MATCH CHARACTER CLASS BCS 10$ ;IF NO MATCH, OK BR 160$ ;OTHERWISE, FAIL 90$: MOV R0,-(SP) ;SAVE WHERE WE ARE MOV R0,-(SP) ;AND HOW FAR I GOT 100$: CALL MATCH ;MATCH AS MANY TIMES AS YOU CAN BCS 110$ MOV R0,(SP) ;REMEMBERING HOW FAR YOU GOT BR 100$ 110$: MOV (SP)+,R0 ;GET POINTER TO CHARACTER THAT FAILED 120$: CMPB (R1)+,#END ;NO NESTED CLOSURES WILL WORK BNE 120$ 130$: MOV R0,-(SP) ;SAVE POINTER CALL MATCH ;TRY TO MATCH THE REST BCC 140$ ;YES, ENTIRE PATTERN MATCHES MOV (SP)+,R0 ;BACKUP 1 BYTE DEC R0 CMP R0,(SP) ;UNTIL NULL MATCH BHIS 130$ TST (SP)+ ;CLEANUP BR 160$ ;REPORT FAILURE 140$: CMP (SP)+,(SP)+ ;CLEANUP 150$: CLC ;SUCCESS BR 170$ 160$: SEC ;FAILURE 170$: MOV (SP)+,R3 ;RESTORE REGISTERS MOV (SP)+,R2 MOV (SP)+,R1 RETURN ;TO CALLER ;+ ; ** CMATCH -- MATCH A CHARACTER CLASS ; ; INPUTS: ; R0=POINTER TO TEXT ; R1=POINTER TO COUNT OF CLASS ; ; OUTPUTS: ; R0=POINTER TO NEXT CHARACTER ; R1=POINTER PAST THE PATTERN ; C BIT SET IF NO MATCH; CLEAR IF OK MATCH ;- CMATCH: MOVB (R0)+,R2 ;GET TEXT BYTE TST OS ;IS THE MATCH CASE SENSITIVE BNE 10$ ;YES CMP R2,#'A ;MAP TO LOWER CASE BLO 10$ ; CMP R2,#'Z ; BHI 10$ ; ADD #BLANK,R2 ; 10$: CLR R3 ;GET NUMBER OF CHARACTERS IN CLASS BISB (R1)+,R3 BEQ 40$ ;NULL, SUCCESS 20$: CMPB R2,(R1)+ ;MATCH CLASS CHARACTER BEQ 30$ ;YES DEC R3 ;TRY THEM BNE 20$ ;ALL SEC ;FAILURE BR 50$ 30$: ADD R3,R1 ;FIXUP R1 DEC R1 40$: CLC ;SUCCESS 50$: RETURN ;TO CALLER .END