.TITLE $ENTAB .IDENT /V1.01/ ;+ ; Compress an ASCII record by changing multiple spaces to (8-space) tabs ; and trimming off trailing spaces. The following control characters are ; also handled specially: ; ; Null & delete characters are removed completely, ; CR resets to LH column, but allows overprint, ; BS backspaces 1 column, cancelling previous space (if any), ; HT advances to next tab stop, as expected, ; others copied to output, but assumed not to advance column pointer. ; ; It would be nice to be able to handle escape sequences, and stop them ; affecting the current position, but unfortunately, they're terminal ; dependent. ; ; Author: C J Doran, Sira Ltd., South Hill, Chislehurst, Kent, BR7 5EH, England ; Tel: +44 1 467 2636, Telex: 896649, Fax: +44 1 467 6515 ; ; Enter with: ; ; R0 containing the address of the text string to be converted. ; R1 containing the address of the output area for the converted string, ; which can be the same as the input string, in which case R1=R0. ; R2 the number of bytes in the string to be converted. ; ; On exit: ; R0 points just past the end of the input area ; R1 points just past the end of the output area ; R2 is the length of the output area ;- BS=10 CR=15 SPACE=40 DEL=177 COLNOW=R3 ; R3 contains current actual column COLNXT=R4 ; R4 contains column for next printing character ; Advance to next tab stop .MACRO NEXTAB COL ADD #8.,COL BIC #7,COL .ENDM NEXTAB .PSECT PUR$I,I,RO $ENTAB::MOV R3,-(SP) ; Save registers MOV R4,-(SP) MOV R1,-(SP) ; Save start of destination CLR COLNOW ; Clear current column CLR COLNXT ; Clear next column TESTCH: TST R2 ; Any (more) text? BEQ EXIT ; Done if not TSTB (R0) ; Null? BEQ NEXTCH ; Yes, ignore it CMPB (R0),#DEL ; Delete? BEQ NEXTCH ; Ditto CMPB (R0),#SPACE ; Space? BHI PRINT ; ASCII codes > space are all printing BNE CONTRL ; Not space itself, do controls ADVCOL: INC COLNXT ; Space just increments next reqd column NEXTCH: INC R0 ; Advance character pointer DEC R2 ; Decrement counter BR TESTCH ; Repeat while more to do ; Deal with control chars CONTRL: CMPB (R0),#HT ; Tab? BNE 20$ ; No, branch NEXTAB COLNXT ; Set to position of next tab stop BR NEXTCH ; Get another character 20$: CMPB (R0),#CR ; Return to left margin? BNE 30$ ; No, branch MOVB (R0),(R1)+ ; Yes, output CR CLR COLNOW ; Yes, clear both counters BR 40$ ; (COLNXT done at 40$) 30$: CMPB (R0),#BS ; Backspace? BNE PRINT ; No, store any other control DEC COLNXT ; Yes, step back 1 char BPL NEXTCH ; OK if result >=0 40$: CLR COLNXT ; But don't step back past LH margin BR NEXTCH ; Have a non-whitespace character. Flush any intervening spaces before ; storing it. PRINT: CMP COLNOW,COLNXT ; Are we at the right place already? BEQ 140$ ; Yes, no spacing required BGT 135$ ; Backspace if COLNOW>COLNXT ; Output a tab if there is a tab stop between COLNOW and COLNXT. If not, ; just print any odd spaces. MOV COLNXT,-(SP) ; See if only 1 space is required SUB COLNOW,(SP) DEC (SP)+ BLE 120$ ; If so, as space is as good as a tab 110$: MOV COLNXT,-(SP) ; Copy required position BIC #7,(SP) ; Find previous tab stop CMP COLNOW,(SP)+ ; Passed this tab stop already? BGE 120$ ; Yes, can;t use any more tabs MOVB #HT,(R1)+ ; No, put in a tab NEXTAB COLNOW ; Set to next tab stop BR 110$ ; Repeat while more to do ; Output any odd spaces as fillers 120$: CMP COLNOW,COLNXT ; Reached required position? BHIS 140$ ; Yes, done MOVB #SPACE,(R1)+ ; No, put in space INC COLNOW ; Note we have BR 120$ ; And repeat ; Backspace(s) required 135$: MOVB #BS,(R1)+ ; Store backspace DEC COLNOW ; Point back one character BR PRINT ; Go see if done ; All spaces written. Print the given character. 140$: MOVB (R0),(R1)+ ; Store it CMPB (R0),#SPACE ; Was it a printing char? BLOS NEXTCH ; Do, don't count position INC COLNOW ; Yes, note carriage moved BR ADVCOL ; Go get next char EXIT: MOV R1,R2 ; Copy end pointer SUB (SP)+,R2 ; To return length of new buffer MOV (SP)+,R4 ; Restore registers MOV (SP)+,R3 RTS PC ; Return .END