;======================================================================== ;= = ;= Programmer: Hunter Goatley = ;= Program: DETAB.MAR = ;= Language: VAX-11 MACRO32 = ;= Purpose: Replace ASCII TABs with blanks = ;= System: VAX 11/785 VAX/VMS v4.2 = ;= Shop: WKU/ACRS = ;= Date: May 18, 1986 = ;= = ;======================================================================== ;= = ;= DETAB replaces ASCII TABs in a file with the proper number of = ;= ASCII blanks to space to the next tab stop. = ;= = ;= DETAB will work only on sequential files; the record format = ;= and attributes are not changed. = ;= = ;= The tab stops are fixed at every 8 positions. = ;= = ;= DETAB must be defined as a foreign command -- the input file = ;= should be specified on the command line. = ;= = ;======================================================================== ; .PSECT DATA,NOEXE,LONG .SUBTITLE Macro definitions CR=13 LF=10 TAB=9 TABCOL = 8 ; $RMSDEF ; RMS symbols $FABDEF ; FAB symbols $RABDEF ; RAB symbols ; ;======================================================================== ;= = ;= D E S C M A C R O -> Macro to create a string descriptor = ;= = ;======================================================================== ; .MACRO DESC LEN,ADDR .WORD LEN ; The length of the string .BYTE DSC$K_DTYPE_T ; The type (character) .BYTE DSC$K_CLASS_S ; The class (string) .ADDRESS ADDR ; The address of the string .ENDM ; .MACRO ON_ERR WHERE,?LABEL BLBS R0,LABEL BRW WHERE LABEL: .ENDM ON_ERR ; .SUBTITLE FABs and RABs .ALIGN LONG ; ;*** File Access Block for input ; INFAB: $FAB FAC=GET, - ; File Access (GET only) SHR= ; Sharing => allow others to read also ; ;*** Record Access Block for input ; INRAB: $RAB FAB=INFAB, - ; The File Access Block RAC=SEQ, - ; Record Access is sequential UBF=INREC, - ; Input buffer address USZ=512 ; The max size of an input record ; ; ;*** File Access Block for output ; OUTFAB: $FAB FAC=PUT, - ; File Access (GET only) FOP=MXV, - ; Maximize Version number RFM=VAR, - ; VARiable length records MRS=512, - ; Maximum record size RAT=CR, - ; Carriage Return format ORG=SEQ ; SEQuential organization ; ;*** Record Access Block for output ; OUTRAB: $RAB FAB=OUTFAB, - ; The File Access Block RAC=SEQ, - ; Record Access is sequential RBF=OUTREC ; The record buffer address ; .ALIGN LONG INREC: .=.+512 ; Input buffer OUTREC: .=.+512 ; Output buffer FOR_DESC: ; Descriptor for command line buffer DESC 80,FOR_BUFF FOR_BUFF: ; Command line buffer .BLKB 80 FOR_LEN: .BLKW 1 ; Length of FOREIGN string returned ; FOR_PROMPT: ; Prompt used if file is not specified .ASCID /_File: / ; ;=============================================================================== ; .SUBTITLE Main routine .PSECT DETAB,EXE,NOWRT ; .ENTRY DETAB,^M<> PUSHAW FOR_LEN ; Set up call to retrieve command line PUSHAQ FOR_PROMPT ; Prompt if file is not specified PUSHAQ FOR_DESC ; ... CALLS #3,G^LIB$GET_FOREIGN ; ... MOVZWL FOR_LEN,R0 ; Move the length to register 0 BNEQU 5$ ; Was a filename specified? BRW BYE ; No -- die 5$: MOVAB INFAB,R2 ; Move addr to register for efficiency MOVAB OUTFAB,R3 ; ... MOVAB INRAB,R4 ; ... MOVAB OUTRAB,R5 ; ... $FAB_STORE - ; Store the filename in the FAB FAB=(R2), - FNA=FOR_BUFF, - FNS=R0 $FAB_STORE - ; Store the filename in the FAB FAB=(R3), - FNA=FOR_BUFF, - FNS=R0 ; $OPEN FAB=(R2) ; Open the input file for reading ON_ERR ERR_BYE ; .... Error? Go report it CMPB #FAB$C_SEQ,FAB$B_ORG(R2) ; Is it a sequential file? BEQLU 7$ ; Yes -- continue MOVL #RMS$_IOP,R0 ; No -- move error code to R0 BRW ERR_BYE ; ... and EXIT 7$: $CONNECT RAB=(R4) ; Connect ON_ERR ERR_BYE ; .... Error? Go report it ; MOVB FAB$B_RAT(R2),FAB$B_RAT(R3) ; Make the Record Attributes the same MOVB FAB$B_RFM(R2),FAB$B_RFM(R3) ; Make the Record Formats the same $CREATE FAB=(R3) ; Open the same file for output ON_ERR ERR_BYE ; .... Error? Go report it $CONNECT RAB=(R5) ; Connect ON_ERR ERR_BYE ; .... Error? Go report it ; ;===== Initialize registers and read in a record ; 10$: CLRL R7 ; Clear the end address MOVAB INREC,R6 ; Move the address to reg for efficiency MOVAB OUTREC,R8 ; Move addr to reg ; $GET RAB=(R4) ; Read a record from ACTDAT CMPL R0,#RMS$_EOF ; End of file? BEQL FIN ; Yes --- go back ON_ERR ERR_BYE ; Error? Report and die ADDW3 RAB$W_RSZ(R4),R6,R7 ; Get the addr of end of record read ; ;===== Trim any blanks and tabs off the end of the record ; 12$: CMPB #^A/ /,-1(R7) ; Is the last character a blank? BLSSU 15$ ; No -- greater than blank -- skip rest BNEQU 13$ ; No -- less than a blank -- check TAB DECL R7 ; Decrement the pointer into the buffer BRB 12$ ; Go check the next character 13$: CMPB #TAB,-1(R7) ; Is the character a TAB? BNEQU 15$ ; No -- go process the record DECL R7 ; Decrement the pointer into the buffer BRB 13$ ; Go check next character ; ;===== Begin looking for a TAB (tab fields are 8 characters wide) ; 15$: MOVZBL #TABCOL,R9 ; Move the TAB boundary to R9 (counter) ; 20$: CMPL R6,R7 ; Reached the end of the record? BNEQU 25$ ; No -- keep processing ; SUBL2 #OUTREC,R8 ; Yes -- get the length to write MOVW R8,RAB$W_RSZ(R5) ; Move it to the OUTRAB $PUT RAB=(R5) ; Write the modified record out BRB 10$ ; Go get next record and process it ; 25$: CMPB #TAB,(R6) ; Is the character a TAB? BEQLU 30$ ; Yes -- go substitute blanks for it MOVB (R6)+,(R8)+ ; No -- move the char to the output buff DECL R9 ; Decrement TAB field length BNEQ 20$ ; At the end of the TAB field? No - 20$ BRB 15$ ; Yes -- process next field ; ;===== Here when a TAB was found -- replace it with the proper number of blanks ; 30$: INCL R6 ; Bump up inrec pointer over TAB 35$: MOVB #^A/ /,(R8)+ ; Move a blank to output buffer DECL R9 ; Decrement TAB field length BNEQ 35$ ; If not end of field, move another / / BRB 15$ ; If so, go process next field ; FIN: $CLOSE FAB=(R2) ; Close input file $CLOSE FAB=(R3) ; Close output file BYE: $EXIT_S ERR_BYE: $EXIT_S CODE=R0 .END DETAB