.TITLE EDI04 .IDENT /X01/ .NLIST BEX ; ; EDITOR (TEMP FILE VERSION) ; ; VERSION X01 ; ; DAVID G. CONROY 10-APR-78 ; .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 ; ;+ ; ** 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,#'! ;DELIMITER A CONTROL CHARACTER BLO ERR9 ;YES, ERROR 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 BEQ ERR3 ; 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 (R1),#BOL ;^* IS ILLEGAL BEQ ERR3 CMPB (R1),#EOL ;$* IS ILLEGAL BEQ ERR3 CMPB (R1),#CLO ;** IS ILLEGAL BEQ ERR3 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 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$: 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