.TITLE EDI02 .PSECT EDI02 .IDENT /X01/ mutask=1 .ENABL LC .ENABL ama ; ; EDITOR (TEMP FILE VERSION) ; ; VERSION X01 ; ; DAVID G. CONROY 05-JAN-78 ; ; ; as modified by Eric Levy ; .if df mutask .macro pure .psect pur,ro .endm .macro impure .psect ipur,rw .endm .iff .macro pure .endm .macro impure .endm .endc .GLOBL ACOM .GLOBL CCOM .GLOBL DCOM .GLOBL ECOM .GLOBL FCOM .GLOBL GCOM .GLOBL ICOM .GLOBL JCOM .GLOBL KCOM .GLOBL MCOM .GLOBL OCOM .GLOBL PCOM .GLOBL PCOM1 .GLOBL QCOM .GLOBL RCOM .GLOBL SCOM .GLOBL UCOM .GLOBL VCOM .GLOBL WCOM .GLOBL XCOM .GLOBL ZCOM .GLOBL DEFDOT .GLOBL DEFall .GLOBL NONZER .GLOBL NOADDR .globl sstore .MCALL CALL .MCALL CALLR .MCALL RETURN .MCALL FDAT$R .MCALL OPEN$ .MCALL OPEN$W .MCALL PUT$S .MCALL EXIT$S .mcall dir$,qiow$ .MACRO POP A MOV (SP)+,A .ENDM .MACRO PUSH A MOV A,-(SP) .ENDM ; ; LOCAL DATA ; impure wattr: qiow$ io.wat,2,7,,pios,,<0,alist> ;write attributes alist: .byte 2,2 ;write protection of output file .word protec ;and get it from here pios:: .word 0,0 ;write attr status last.s: .word -1 ;last sub's address (seek) last.d: .word -1 ;and the dot value at the time ABUFR: .BLKB 100. ;TEMP FOR APPEND CMD ABUFRE: .BLKB 2 ;END OF BUF AND SPARE FOR SAFETY. mes1: .asciz / <- temp f.err-> / NOTRAIL: .ASCII /P/<12> ;P AND NEWLINE APLINE: .ASCII <1>/$/<1> ;CONTROL A AS A DELIMETER INLINE: .ASCII <1>/^/<1> ;LIKEWISE .EVEN FUDGE: .BLKW 1 ;DELTA ADDRESS FOR K VFLAG: .BLKW 1 ;GLOBAL/EXCLUDE FLAG SANY: .BLKW 1 ;ANYTHING AT ALL FOR SUBSTITUTE FP: .BLKW 1 ;FILE I/O POINTER SFLAG: .BLKW 1 ;ONCE FLAG FOR SUBSTITUTE FC: .BLKW 1 ;RECORD COUNT SNUM: .BLKW 1 ;NUMBER IN S# SWNUM: .BLKW 1 ;PER LINE COPY OF SNUM P1FLAG: .WORD 0 ;MARK ON LINE PRINT pure ;+ ; ** COMMAND PROCESSORS ; ; THESE ROUTINES ARE CALLED BY THE COMMAND DISPATCHER TO EXECUTE THE ; USER'S COMMANDS. THEY EITHER RETURN TO THE DISPATCHER SUCCESSFULLY ; OR JUMP DIRECTLY TO ERROR. ;- ; ; APPEND ; ACOM: CALL DEFDOT ;DEFAULTS CALL GETC ;ANY THING ON THE LINE CMP R0,#NL ;NOT IF NL BEQ 10$ ;SO CONTINUE AS USUAL MOV R0,PEEK ;PUT IT BACK FOR LATER MOV #APLINE,R0 ;ELSE CONSTRUCT A SUB CMD CALLR ONLINE ;AND GO DO IT. 10$: CLR OLDCMD ;CLEAR COMMAND ON LINE FLAG MOV #GETTY,R4 ;ROUTINE MOV ADR2,R5 ;WHERE TO APPEND CALLR APPEND ;GO APPEND ; ; ONLINE -- ON LINE APPEND OR INSERT, CONSTRUCT THE SUB COMMAND. ; R0=ADDR OF STRING TO PUT BACK ; THE LENGTH IS 3. USED ONLY BY INSERT AND APPEND ; ONLINE: MOV #ABUFR,R1 ;ADDR OF TEMP BUFFER MOVB (R0)+,(R1)+ ;MOVE A CHAR MOVB (R0)+,(R1)+ ;MOVE A CHAR MOVB (R0)+,(R1)+ ;MOVE A CHAR 15$: PUSH R1 CALL GETC POP R1 MOVB R0,(R1)+ ;MOVE USER STRING TO TEMP BUFFER TOO. CMP R0,#EOF ;TEST FOR GLOBAL EOF BNE 16$ ;SKIP IF NOT MOV #NL,R0 ;ELSE USE NL 16$: CMP R0,#NL ;LAST CHAR TO MOVE? BEQ 17$ ;YEP IF EQ CMP R1,#ABUFRE ;TOO LONG A STRING TO FIT IN TEMP BUFF? BHI 20$ ;YES IF HI BR 15$ ;ELSE BACK FOR MORE 17$: SUB #ABUFR,R1 ;COMPUTE LENGTH OF LINE MOV #ABUFR,R0 ;SET UP PUTBACK PARMS CALL PUTBAK CALLR SCOM ;NOW GO DO THE SUB CMD 20$: CLR R1 ;ERROR 0 JMP ERROR ; ; PUTR0 -- PUTBACK R0 ; PUTR0: PUSH R1 PUSH R0 MOV SP,R0 ;ADDRESS OF THE CHAR MOV #1,R1 ;LENGTH CALL PUTBAK ;GO DO IT POP R0 POP R1 RETURN ; ; CHANGE ; CCOM: CALL NONZER ;DEFAULTS CALL TDELIM ; CLR OLDCMD ;CLEAR COMMAND ON LINE FLAG CALL DELETE ;MAKE TEXT GO AWAY MOV #GETTY,R4 ;ROUTINE MOV ADR1,R5 ;APPEND PLACE TST -(R5) ; CALLR APPEND ; ; ; DELETE ; DCOM: CALL NONZER ;DEFAULTS tst guptr ;in global (0=no) bne 5$ ;yes, skip bounce check push r0 call getc ;safe guard against bounce problems cmp r0,#'p beq 3$ cmp r0,#'P beq 3$ cmp r0,#nl bne 10$ ;only 1 d command on a line (unless global) 3$: mov r0,peek ;put it back pop r0 5$: CALLR DELETE ; 10$: mov #2,r1 jmp error ; ; EDIT ; ECOM: CALL NOADDR ;NO ADDRESS IS LEGAL CALL FILE MOV ZERO,DOL ;CLEAR TEXT MOV ZERO,DOT ; CLR TPTR ;START AT TEMPFILE BLOCK 0 MOV ZERO,R5 ;READ IN STUFF FROM FILE CALL SAVEFN ;SAVE THE NAME IF SYNTAX OK CALL READN2 ;GO DO THE INPUT NOW MOV ZERO,DOT ;GO TO LINE 1 ADD #2,DOT CMP DOT,DOL ;MAKE SURE NOT ZERO FILE BLOS 10$ MOV DOL,DOT ;IF SO, SET DOL TO DOT 10$: call autostart ;execute line 1 if its auto execute RETURN ; ; FACTS ; FCOM: ;now - ADDRESS IS ALLOWED 10$: CALL GETC ;SKIP OVER BLANKS CMP R0,#' ; BEQ 10$ ; CMP R0,#NL ;BR IF NO FILENAME BEQ 50$ ; CMP R0,#EOF ; BEQ 50$ ; MOV #SFN,R1 ;GET POINTER TO SAVE FILE BUFFER 20$: CMP R1,#SFN+FNS-1 ;DOES IT FIT BHIS 30$ ;NO, IGNORE MOVB R0,(R1)+ ;SAVE THE CHARACTER 30$: CALL GETC ;CONTINUE TILL NEWLINE CMP R0,#NL ; BEQ 40$ ; CMP R0,#EOF ; BNE 20$ ; 40$: CLRB (R1) ;THEN APPEND A NULL 50$: TSTB SFN ;IS THERE A FILE NAME BEQ 80$ ;NO MOV #SFN,R1 ;YES, POINT AT IT 60$: MOVB (R1)+,R0 ;PRINT TILL THE NULL BEQ 70$ ; CALL TTYC ; BR 60$ ; 70$: CALL TTYNL ;APPEND A NEWLINE, AND 80$: RETURN ;DONE ; ; GLOBAL ; EXCLUDE ; GCOM: CLR VFLAG ;GLOBAL BR GV ; VCOM: MOV #1,VFLAG ;EXCLUDE GV: CALL DEFALL ;DEFAULT TO 1,$ TST GUPTR ;IN A GLOBAL BEQ 20$ ;NO MOV #9.,R1 ;CANNOT NEST GLOBALS JMP ERROR ; 20$: CALL GETC ;GET PATTERN CALL COMPIL ; ; ; MARK ALL LINES FOR WHICH THE COMMAND LINE ; WILL BE EXECUTED. ; MOV ZERO,R1 ;MARK THE LINES 30$: TST (R1)+ ; CMP R1,DOL ;SEE IF DONE BHI 60$ ;YES BIC #1,(R1) ;REMOVE OLD MARK CMP R1,ADR1 ;DUCK OUT IF NOT IN RANGE BLO 30$ ; CMP R1,ADR2 ; BHI 30$ ; MOV (R1),R0 ;MATCH HERE CALL GETLIN ; MOV #LBUF1,R0 ; CALL AMATCH ; BCS 40$ ;BR IF NOT TST VFLAG ;MARK LINE IF GLOBAL BNE 30$ ; INC (R1) ; BR 30$ ; 40$: TST VFLAG ;NO MATCH, MARK IF EXCLUDE BEQ 30$ ; INC (R1) ; BR 30$ ; ; ; COLLECT UP COMMAND LINE ; 60$: MOV #GUBUF,R1 ;COLLECT UP THE LINE 70$: CALL GETC ;UNTIL NEWLINE CMP R0,#'\ ;ESCAPE BNE 72$ ;NO CALL GETC ;GET ACTUAL CHARACTER cmp r0,#nl ;fix \\ in beq 74$ ;pass nl's only (else \ is literal) mov r0,peek ;put back next char mov #'\,r0 ;restore the \ and copy it BR 74$ ; 72$: CMP R0,#NL ; BEQ 80$ ; 74$: CMP R1,#GUBUF+GUBS-1;GIVE ?0 IF THE LINE IS TOO LONG BHIS 90$ ; MOVB R0,(R1)+ ; BR 70$ ; ; ; SET GLOBAL I/O ; RETURN TO COMMAND SCANNER ; 80$: CLRB (R1) ;MARK END MOV R1,GUPTR ;WILL GET EOF IMMEDIATELY RETURN ; 90$: CLR R1 ;?0 JMP ERROR ; ; ; INSERT ; ICOM: CALL GETC ;SEE IF ANYTHING ON LINE CMP R0,#NL ;IS IT A NEW LINE BEQ 5$ ;IF IT IS, CONTINUE AS USUAL MOV R0,PEEK ;PUT IT BACK FOR LATER MOV #INLINE,R0 ;ELSE MAKE UP A SUB CMD CALLR ONLINE ;GO DO IT 5$: MOV R0,PEEK ;PUT BACK THE TERMINATOR CMP ZERO,DOL ;EMPTY BUFFER BNE 10$ ;NO MOV ZERO,ADR2 ;ITS JUST A 0A BR 20$ ; 10$: CALL NONZER ;DEFAULTS SUB #2,ADR2 ; 20$: CALL TDELIM ; CLR OLDCMD ;CLEAR OLD COMMAND FLAG MOV #GETTY,R4 ;ROUTINE MOV ADR2,R5 ;INSERT TEXT CALLR APPEND ; ; ; COPY (KOPY) ; KCOM: CALL NONZER ;DEFAULTS CALL ADDRES ;GET THE COPY DESTINATION MOV R0,PEEK ;PUT THE DELIMITER BACK call defd.t ;accept a default of dot here TST R2 ;MUST GET AN ADDRESS (unless nl delimeter) BEQ 20$ ;OR ?9 CLR FUDGE ;ADDRESS ADJUSTMENT FUDGE CMP R2,ADR2 ;EASY BHIS 10$ ;YES CMP R2,ADR1 ;IMBEDDED BHIS 20$ ;YES, ?9 MOV #2,FUDGE ;MUST FUDGE ADDRESSES 10$: MOV #30$,R4 ;GET ROUTINE MOV R2,R5 ;APPEND PLACE CALLR APPEND ;APPEND TEXT AND RETURN 20$: MOV #9.,R1 ;?9 JMP ERROR ; 30$: CMP ADR1,ADR2 ;ANY MORE BHI 40$ ;NO MOV ADR1,R1 ;GET SOURCE ADD #2,ADR1 ;FIX ADD FUDGE,ADR1 ;THE ADD FUDGE,ADR2 ;ADDRESSES MOV (R1),R0 ;PICK UP SEEK ADDRESS CALL GETLIN ;PULL LINE CLC ;GOT ONE RETURN ; 40$: SEC ;NO MORE LINES RETURN ; ; ; MOVE ; MCOM: CALL NONZER ;CHECK OUT ADDRESES CALL ADDRES ;GET WHERE TO MOVE TO MOV R0,PEEK ; call defd.t ;accept a default of dot here TST R2 ;MUST GET ONE (unless nl delimeter) BEQ 50$ ; CMP R2,ADR2 ;MOVING UP BHI 10$ ;BR IF YES CMP R2,ADR1 ;MOVING INTO THE MIDDLE BHIS 50$ ;NOT LEGAL MOV R2,R1 ;SET UP FOR THE MOVE TST (R1)+ ; MOV ADR2,R2 ; MOV ADR1,R5 ; MOV ADR2,DOT ;RESET CURRENT LINE SUB R5,DOT ; ADD R1,DOT ; CMP R5,R1 ;QUICK CHECK FOR NO WORK BEQ 40$ ;EXIT TST -(R5) ; BR 20$ ;GO DO THE MOVE 10$: MOV ADR1,R1 ;UPWARDS MOVE MOV ADR2,R5 ; MOV R2,DOT ;RESET CURRENT LINE 20$: call marktg 25$: MOV R5,R3 ;DO THE MOVE TST (R3)+ ; MOV R3,R4 ; TST (R4)+ ; MOV (R3),R0 ;SAVE BOUNDRY 30$: MOV -(R3),-(R4) ;MOVE CMP R3,R1 ; BHI 30$ ; MOV R0,(R3) ;PUT DOWN THE BOUNDRY LINE TST (R1)+ ;MOVE FORWARD TST (R5)+ ; CMP R5,R2 ;DONE BLO 25$ ;NO 40$: call retag RETURN ;DONE 50$: MOV #9.,R1 ;?9 FOR FUNNY STUFF JMP ERROR ; ; ; OPTIONS ; OCOM: CALL NOADDR ;NO ADDRESS FOR OPTIONS COMMAND 10$: CALL GETC ;GET OPTION CHARACTER CMP R0,#NL ;NEWLINE BEQ 60$ ;YES, DONE CMP R0,#'? ;PRINT TEMP FILE POINTER VALUE BNE 140$ ;NOPE MOV $TPTR,R1 ;GET IT CALL TTYNUM ;PRINT IT ;; CALL TTYNL ;AND A NEWLINE mov #mes1,r0 call ttystr movb f.err+fdb,r1 ;get last error code call ttynum call ttynl BR 10$ ;THATS ALL 140$: CMP R0,#'* ;reset all toggles o* BNE 15$ clr oa ;clear toggles mov #-1,ol clr ob mov #177770,tabmsk BR 10$ 15$: BIC #' ,R0 ;FORCE UPPER CASE CMP R0,#'T ;OT BNE 16$ ;NO CLR OV ;CLEAR OPTIONS VERBOSE BR 10$ ; 16$: CMP R0,#'H ;OH half tab oh BNE 17$ ;NO cmp tabmsk,#177770 ;was it full bne oc1 ;ne so make it full mov #177774,tabmsk ;yes, so make it half tab br oc4 oc1=. mov #177770,tabmsk oc4=. BR 10$ ; 17$: CMP R0,#'L ;OL ol BNE 18$ ;NO com ol ;automatic clear of centerline going into lmode BR 10$ ; 18$: CMP R0,#'B ;ob ob BNE 20$ ;NO com ob ;don't replace blanks with tabs BR 10$ ; 20$: CMP R0,#'V ;OV ov BNE 30$ ;NO INC OV ;SET OPTIONS VERBOSE BR 10$ ; 30$: CMP R0,#'S ;OS os BNE 40$ ;NO INC OS ;SET OPTIONS SENSITIVE CALL REKILL ;KILL OFF SAVED R.E. BR 10$ ; 40$: CMP R0,#'I ;OI oi BNE 45$ ;NO CLR OS ;SET OPTIONS INSENSITIVE BR 10$ ;NEXT OPTION 45$: CMP R0,#'E ;oe OPTION oe BNE 48$ TST OE ;ALLREADY DID IT? BLT 47$ ;YES IF LT, SO NO NEED TO DO AGAIN DEC OE ;ELSE SET FLAG MOV S100,-(SP) MOV C100,S100 ;SWAP C AND S COMMANDS MOV (SP)+,C100 47$: BR 10$ ; 48$: CMP R0,#'F ;OFF LINE NUM OPTION of BNE 49$ CLR ONUM ;ELSE TURN OFF OPTION BR 10$ 49$: CMP R0,#'N ;ON LINE NUM OPT on BNE 490$ MOV #-1,ONUM ;TURN ON OPTION BR 10$ 490$: CMP R0,#'A ;ON automatic indenting oa BNE 50$ com oa ;toggle OPTION BR 10$ 50$: MOV #9.,R1 ;?9 IF BAD OPTION JMP ERROR ; 60$: MOV #NL,PEEK ;DONE RETURN ; ; PRINT ; PCOM: CALL NONZER ;DEFAULTS PCOM1: MOV ADR1,R1 ;GET POINTER TO MOV (R1),R0 ;TEXT CALL GETLIN ; TST ONUM ;LINE NUM OPTION? BEQ 10$ ;NOT IF ZERO PUSH R0 ;PLAY IT SAFE PUSH R1 MOV ADR1,R1 ;GET THIS LINE # SUB ZERO,R1 ;COMPUTE ACTUAL LINE # ASR R1 CALL TTYNUM ;OUTPUT LINE # MOV #'),R0 ;MAKE LISTING NICE CALL TTYC ;OUTPUT ) AND TAB CMP ADR1,DOT BNE 5$ ;SEE IF WE CAN MARK LINE 'DOT' TST P1FLAG ;BUT ONLY IF FROM THE Z COMMAND BEQ 5$ MOV #'-,R0 ; CALL TTYC MOV #'-,R0 ;MARK WITH -- CALL TTYC 5$: MOV #11,R0 ; A TAB CALL TTYC ;TYPE IT OUT POP R1 POP R0 10$: MOV #LBUF1,R0 ;PUT OUT TO THE TTY CALL TTYSTR ; ADD #2,ADR1 ;GET NEXT LINE CMP ADR1,ADR2 ; BLOS PCOM1 ;STILL MORE TO DO MOV ADR2,DOT ;RESET CURRENT LINE RETURN ; ; ; QUIT ; QCOM: TST WDONE ;DID HE W YET (someday this should be smarter) BEQ NOTYET qcom1: CALL NOADDR ;NO ADDRESS ALLOWED EXIT$S ; NOTYET: INC WDONE ;IF HE WANTS, HE MAY RE-ISSUE Q. call getc cmp r0,#'q beq qcom1 ;let a qq do a direct exit cmp r0,#'Q ;check both cases beq qcom1 ;let a qq do a direct exit mov r0,peek ;put back the char MOV #13.,R1 ;DID NOT WRITE YET ERROR. JMP ERROR ; ; READ ; RCOM: CALL DEFDOT ;DEFAULTS MOV ADR2,R5 ;READ STUFF FROM FILE CALL READIN ; TSTB SFN ;IF NO SAVED NAME BNE 10$ ;THEN CALL SAVEFN ;SAVE THE NAME 10$: RETURN ; ; ; SUBSTITUTE ; SCOM: CALL NONZER ;DEFAULTS ; CLR SNUM ;SET WHICH ONE TO DO MOV #1,SNUM ;USE DEFAULT OF 1 CALL GETC ;ZERO MEANS ALL CMP R0,#'0 ; BLO 10$ ; CMP R0,#'9 ; BHI 10$ ; CALL GETNUM ; MOV R1,SNUM ; CALL GETC ; 10$: MOV R0,R2 ;SAVE R.E. DELIMITER CALL COMPIL ;THE PATTERN ; ; COPY RHS TO BUFFER 2. ; MOV #LBUF2,R1 ;COPY OVER R.H.S. 20$: CALL GETC ;GET CHARACTER CMP R0,#NL ;ERROR FOR NEWLINE BEQ 37$ ; CMP R0,#EOF ;OR GLOBAL EOF BEQ 37$ ; CMP R0,#'\ ;ESCAPE BNE 30$ ;NO CALL RSTORE ;SAVE THE ESCAPE CALL GETC ;GET THE ACTUAL CHARACTER CMP R0,#EOF ;CANNOT BE GLOBAL EOF BEQ 35$ ; CALL RSTORE ; BR 20$ ; 30$: CMP R0,R2 ;END OF R.H.S. BEQ 40$ ;YES CALL RSTORE ;SAVE THE CHARACTER BR 20$ ; 35$: MOV #9.,R1 ;?9 IS HERE SO IT REACHES JMP ERROR ; 37$: PUSH R0 ;PUT BACK THE P AND PUSH R1 MOV #NOTRAIL,R0 ;ADDR OF PUTBACK STRING MOV #2,R1 ;LEN OF PUTBACK STRING CALL PUTBAK POP R1 POP R0 ; BR 40$ ;CONTINUE 40$: push r0 call getc ;SEE IF NEXt char is a g mov r0,peek ;put back if its not bic #40,r0 ;map to upper cmp r0,#'G ;is it a global substitute the old way bne 44$ ;not if ne clr snum ;else make it global mov #-1,peek ;and kill the putback 44$: pop r0 CLRB (R1) ;PUT NULL ON R.H.S. END CLR SANY ;SET NO MATCHES AT ALL ; ; TOP OF THE ONCE PER LINE LOOP. ; 50$: MOV SNUM,SWNUM ;RESET SOME VARIABLES CLR SFLAG ; MOV @ADR1,R0 ;GET SOURCE LINE CALL GETLIN ; MOV #LBUF1,R2 ;POINT AT ORIGINAL TEXT MOV R2,ORG ;FOR MATCH MOV #PBUF,R1 ;FOR MATCH MOV #LBUF3,R3 ;DESTINATION POINTER ; ; TOP OF THE NEXT MATCH LOOP. ; 60$: TSTB (R2) ;ANY MORE BEQ 160$ ;NO MOV R2,R0 ;TRY FOR A MATCH CALL MATCH ; BCS 85$ ;NO TST SNUM ;DO THEM ALL BEQ 80$ ;YES DEC SWNUM ;NO, DO THIS ONE BNE 85$ ;BR IF NO 80$: CMP R0,R2 ;IS THIS A ZERO LENGTH MATCH BNE 90$ ;NO TST SFLAG ;DO IT BEQ 90$ ;BR IF YES 85$: MOVB (R2)+,R5 ;JUST MOVE ALONG CALL SSTORE ; BR 60$ ; 90$: MOV #LBUF2,R4 ;GET POINTER TO R.H.S. 100$: MOVB (R4)+,R5 ;PICK UP CHARACTER BEQ 150$ ;DONE CMP R5,#'\ ;ESCAPE BNE 110$ ;NO MOVB (R4)+,R5 ;MOVE NEXT CHARACTER BR 140$ ; 110$: CMP R5,#'& ;REPLACE TEXT BNE 140$ ;NO call caseck ;check for & options such as case bcs 100$ ;cs means its been done for us by caseck. MOV R4,-(SP) ;SAVE R.H.S. POINTER MOV R2,R4 ;GET POINTER TO WHAT GOT MATCHES 120$: CMP R4,R0 ;COPY OVER BHIS 130$ ; MOVB (R4)+,R5 ; CALL SSTORE ; BR 120$ ; 130$: MOV (SP)+,R4 ;RESTORE R.H.S. BR 100$ ; 140$: CALL SSTORE ;STORE DOWN THE CHARACTER BR 100$ ; 150$: INC SFLAG ;SET WE DID ONE INC SANY ;SET WE DID ONE AT ALL MOV R0,R2 ;MOVE ALONG BR 60$ ; ; ; END OF LINE. ; 160$: TST SFLAG ;ANY CHANGES ON THIS LINE BEQ 165$ ;NO, GO ON CLR R5 ;APPEND A NULL CALL SSTORE ; MOV #LBUF1,R0 ;COPY BUF3 TO BUF1 MOV #LBUF3,R1 ; 162$: MOVB (R1)+,(R0)+ ; BNE 162$ ; CALL PUTLIN ;WRITE NEW LINE TO TEMPFILE mov @adr1,last.s ;save for the undo command MOV R0,@ADR1 ;AND UPDATE THE POINTER TO IT MOV ADR1,DOT ;MOVE DOT TO LAST LINE CHANGED mov dot,last.d ;save dot too ; ; ADVANCE TO NEXT LINE. ; 165$: ADD #2,ADR1 ;ANY MORE CMP ADR1,ADR2 ; BHI 170$ ;NO JMP 50$ ;GO DO ANOTHER LINE 170$: TST GUPTR ;IN A GLOBAL BNE 180$ ;YES tst macflg ;in a macro BNE 180$ ;YES TST SANY ;NO, DID ANYTHING CHANGE BNE 180$ ;YES, OK MOV #1,R1 ;?1 JMP ERROR ; 180$: RETURN ;DONE ; ; undo ; ucom: call noaddr ;no addresses cmp last.s,#-1 ;is it setup yet beq 10$ ;skip if not cmp dot,last.d ;compare dot's bne 10$ mov last.s,@dot ;restore it return 10$: mov #4.,r1 jmp error ;bad address error is good enuf ; ; WRITE ; JOIN ; NEW VERSION (X COMMAND) ; .ENABL LSB XCOM: INC WDONE ;INDICATE DONE MOV #FO.WRT,R5 ;FOR WRITE NEW FILE CALL DEFALL ;DEF TO ENT FILE NAME CALL FILE ;GET NAME OPEN$ #FDB,R5 ;OPEN WITH NEW VERSION BCC W5$ ;IF NO ERROR FINISH UP IN "W" CODE JMP OPERR ;Cannot open error with code WCOM: MOV #FO.UPD,R5 ;WRITE, FIRST TEST IS UPDATE INC WDONE ;INDICATE A WRITE HAS BEEN DONE BR WJ ; JCOM: MOV #FO.APD,R5 ;JOIN, FIRST TEST IS APPEND WJ: CALL DEFALL ;DEFAULT TO ENTIRE FILE CALL FILE ;GET THE FILE NAME OPEN$ #FDB,R5 ;TRY TO OPEN THE FILE BCC 10$ ;OK CMPB F.ERR(R0),#IE.NSF ;IS THE ERROR NO FILE BNE 60$ ;NO, HARD ERROR OPEN$W ;OPEN FOR PLAIN WRITING BCS 60$ ;ERROR W5$: ;ENTRY FOR X COMMAND tst pflg ;do we write protection attributes beq 10$ ;only write protection on control-z dir$ #wattr 10$: FDAT$R ,#R.VAR,#FD.CR ;MAKE SURE ATTRIBUTES ARE OK CLR FC ;RECORD COUNT MOV #LBUF2,FP ;WORK POINTER 20$: MOV @ADR1,R0 ;GET ADDRESS OF LINE CALL GETLIN ;GET TEXT MOV #LBUF1,R2 ; 30$: MOVB (R2)+,R0 ;PUT OUT ALL THE CHARACTERS BEQ 40$ ; CALL 70$ ; BR 30$ ; 40$: ADD #2,ADR1 ;BUMP TO NEXT LINE CMP ADR1,ADR2 ;DONE BLOS 20$ ;BR IF NOT MOV #FDB,R0 ;CLOSE FILE WITH TRUNCATION CALL .TRNCL ; TST GUPTR ;IN GLOBAL BNE 50$ ;YES MOV FC,R1 ;PUT OUT THE COUNT CALL TTYNUM ; CALL TTYNL ; 50$: TSTB SFN ;IS THERE A SAVED NAME BNE 55$ ;YES CALL SAVEFN ;NO, SAVE THE NAME 55$: RETURN ; 60$: ;OPEN FILE ERROR OPERR=. MOVB F.ERR(R0),R1 ;OUTPUT THE ERROR CODE BIS #177400,R1 CALL TTYNUM MOV #40,R0 CALL TTYC ;AND A SPACER, THEN MOV #8.,R1 ;FILE OPEN ERROR JMP ERROR ; 70$: CMP R0,#NL ;NEWLINE BEQ 80$ ;YES CMP FP,#LBUF2+LBS ;NO, DOES IT FIT BHIS 100$ ;NO ?10 MOVB R0,@FP ;PUT IN THE BUFFER INC FP ; BR 90$ ; 80$: MOV FP,R1 ;COMPUTE RECORD SIZE SUB #LBUF2,R1 ; PUT$S #FDB,#LBUF2,R1 ;PUT OUT THE RECORD BCS 100$ ;ERROR INC FC ;COUNT UP 1 RECORD MOV #LBUF2,FP ;BACK UP POINTER 90$: RETURN ;DONE 100$: CALL .TRNCL ;ERROR, CLOSE THE FILE MOVB F.ERR(R0),R1 ;OUTPUT THE ERROR CODE BIS #177400,R1 CALL TTYNUM MOV #40,R0 CALL TTYC ;AND A SPACER, THEN MOV #10.,R1 ;?10 JMP ERROR ; .DSABL LSB ;+ ; ; ** ZCOM Z COMMAND ; ;- ZCOM: CALL DEFDOT ;DEFAULT TO DOT MOV ADR2,ADR1 ;USE ONLY ONE ADDRESS CALL GETC ;NEXT CHAR->R1 CMP #'+,R0 ;Z+N? BNE 20$ CALL NCHK ;R1 = NUMBER OR 20 (DEF) ADD R1,ADR2 ;LIST DOWN PART BR 50$ 20$: CMP #'-,R0 ;Z-N BNE 30$ CALL NCHK SUB R1,ADR1 ;BACKWARD LIST BR 50$ 30$: CMP #'Z,R0 BEQ 32$ CMP #'z,R0 BEQ 32$ BR 33$ 32$: MOV #4000.,R1 BR 40$ 33$: CALL NCHK1 ;DON'T GET CHAR, ALLREADY HAVE IT ASR R1 BIC #1,R1 ;MUST BE EVEN 40$: ADD R1,ADR2 SUB R1,ADR1 50$: CMP ADR2,DOL ;CHECK ADR1,2 RANGE BLOS 55$ MOV DOL,ADR2 ;DON'T GO PAST END 55$: CMP ADR1,ZERO BHI 60$ MOV ZERO,ADR1 ADD #2,ADR1 60$: PUSH DOT MOV #-1,P1FLAG ;LET IT MARK WHERE WE ARE CMP ADR1,ADR2 ;CHECK FOR NULL BUFFER BHI 65$ ;THIS FIXES THE ZZ + Z HANG PROBLEM CALL PCOM1 ;LIST IT 65$: CLR P1FLAG ;BUT NO MORE POP DOT RETURN NCHK: CALL GETC ;GET CHAR NCHK1: CMP R0,#NL ;END OF LINE BNE 10$ MOV #40.,R1 ;USE DEFAULT MOV R0,PEEK ;PUT BACK TERMINATOR RETURN 10$: CMP R0,#'0 ;MAKE SURE ITS A NUMBER BLO 20$ CMP R0,#'9 BHI 20$ CALL GETNUM ASL R1 ;TIMES 2 RETURN 20$: MOV #14.,R1 ;BAD NUM ERROR JMP ERROR ;+ ; ** DEFDOT - DEFAULT TO .,. ; ** DEFALL - DEFAULT TO 1,$ ; ** TDELIM - CHECK FOR LEGAL TEXT DELIMITER ; ** NONZER - DISALLOW LINE ZERO ; ** NOADDR - DISALLOW ANY ADDRESS ; ; THESE ROUTINES ARE USED TO VALIDATE THE ADDRESSES OF COMMANDS. ALL ; JUMP DIRECTLY TO ERROR ROUTINES IF THEY MUST. ;- DEFDOT: TST ADR2 ;IS THERE AN ADDRESS BNE 10$ ;YES MOV DOT,ADR1 ;SET BOTH TO DOT MOV DOT,ADR2 ; 10$: RETURN ; TDELIM: CALL GETC ;GET CHARACTER CMP R0,#NL ;IS IT A NEWLINE BEQ 10$ ;YES, OK CMP R0,#' ;IS IT A BLANK BNE ERR9 ;NO, ERROR 10$: RETURN ; NOADDR: TST ADR2 ;ANY ADDRESS BNE ERR9 ;YES, ERROR RETURN ; .ENABL LSB DEFALL: TST ADR2 ;IS THERE AN ADDRESS BNE 10$ ;YES MOV ZERO,ADR1 ;SET 1 ADD #2,ADR1 ; MOV DOL,ADR2 ;SET $ BR 10$ ; NONZER: CALL DEFDOT ;DEFAULT ADDRESS 10$: CMP ADR1,ADR2 ;CHECK FOR WRAPAROUND BLOS 20$ ; MOV #5,R1 ;?5 JMP ERROR ; 20$: CMP ADR1,ZERO ;LINE ZERO BEQ ERR9 ;YES, ERROR RETURN ; .DSABL LSB ERR9: MOV #9.,R1 ;?9 JMP ERROR ; ;+ ; ** RSTORE - STORE R.H.S. CHARACTER ; ** SSTORE - STORE RESULT CHARACTER ; ; THESE TWO SMALL ROUTINES ARE USED BY THE SUBSTITUTE COMMAND. THEY ; PROBABLY SHOULD HAVE BEEN PUT UP WITH IT. ;- RSTORE: CMP R1,#LBUF2+LBS-1 ;WILL IT FIT BHIS ERR0 ;NO MOVB R0,(R1)+ ;YES RETURN ; SSTORE: CMP R3,#LBUF3+LBS-1 ;WILL IT FIT BHIS ERR0 ;NO MOVB R5,(R3)+ ;YES RETURN ; ERR0: CLR R1 ;?0 IF OVERFLOW JMP ERROR ; ;+ ; ** SAVEFN - SAVE THE FILE NAME ; ; THIS LITTLE ROUTINE IS CALLED FROM THE R, E AND W COMMANDS TO SAVE ; THE FILE NAME (IN FN) IN THE SAVED NAME (SFN). ; ; USES: ; R0, R1 ;- SAVEFN: MOV #FN,R0 ;NAME MOV #SFN,R1 ;SAVED NAME 10$: MOVB (R0)+,(R1)+ ;COPY BNE 10$ ; RETURN ; defd.t: ;input =r2 output r2=dot or unchanged registers tst r2 ;skip if address already in r2 bne 5$ cmp r0,#nl ;must be only thing on line bne 5$ mov dot,r2 ;passed all tests, its a copy or move to dot 5$: return .END