From:	CSBVAX::CSBVAX::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 11-DEC-1988 19:03
To:	MRGATE::"ARISIA::EVERHART"
Subj:	Re: Re: TAB substitution


Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Tue, 29 NOV 88 10:39:31 PDT
Received: from CUNYVM.CUNY.EDU by KL.SRI.COM with TCP; Tue, 29 Nov 88 10:11:03 PST
Received: from ISUMVS.BITNET by CUNYVM.CUNY.EDU (IBM VM SMTP R1.1) with BSMTP id 2050; Tue, 29 Nov 88 13:00:43 EDT
Date:      Tue, 29 Nov 88 11:56:35 CST
To:        <INFO-VAX@KL.SRI.COM>
From:      "John Hascall" <GG.SPY%ISUMVS.BITNET@CUNYVM.CUNY.EDU>
Subject:   Re: Re: TAB substitution

> Date:         Wed, 23 Nov 88 09:58:59 GMT
> From:         "Eoin C. Bairead" <EBAIREAD%IRLEARN.BITNET@CUNYVM.CUNY.EDU>
> Subject:      Re: TAB substitution
> Comments: To: INFO-VAX@KL.SRI.COM
> To:           John Hascall <GA.JPH@ISUMVS>
>
>
> -------------------------------------------------------------------------
> Eoin C. Bairead               Heanet:      EOIN@ccvax.ucd.ie
> Systems Analyst               EARN/Bitnet: EBAIREAD@irlearn.bitnet
> Computer Center               PSI:         PSI%+27243154000712::EOIN
> University College Belfield   Uucp:        EOIN%ccvax.ucd.ie
> Dublin 4.                     Ean:         EOIN@ccvax.ucd.irl
> Ireland                       Telex:       (0500) 91196 UCD EI to BAIREAD
>                               Voice:       +353-1-693244 Ext 2463
> FAX: +353-1-694409            ICBMnet:     53 18 20 N; 06 13 38 W; 25m
> -------------------------------------------------------------------------
>
>
> ----------------------------Original message----------------------------
>     > Is there an easy way to substitute all the TABs in a file with to
>     > correct number of blanks? Can I change the TAB key definition in EDT
>     > to do so? ( Assuming tab stops every 8 characters )
>
>     There is a "cheating" way of doing this. However, the trick only works
>     for VMS sites (8-) running JNET interface to Bitnet. You simply send
>     the file to yourself using the $SEND/FILE command but using the
>     /FORTRAN qualifer as well. This will get JNET to expand TABS to
>     spaces.  However, I am not sure how many spaces off the top of my
>     head.
> ------------------------------------------------------------------------------
-
>     Such sites can also PRINT files with control characters/non-printable
>     characters/any sort of garbage:-
>
>     $SEND/FILE/PRINT filename PRINTER@your node
>

   Here is a macro program which replaces tabs, we used to do this with a
FORTRAN program (why would anyone write a character-string oriented program
in FORTRAN???), but I got tired of its slowness.  I realize the following
is not a great example of structured coding, but it gets the job done here.

   As always, use it at your own risk.

p.s. It does use the "LOCC" instruction (to find the tabs), which is
     emulated in software on some of the newer VAXen, I am not sure
     what effect this will have on its speed on those machines.

------- cut here -----
        .title  DELTABS Replace Tabs with Spaces
        .sbttl  Definitions
;
        $LIBDEF
        $RMSDEF
        $FABDEF
        $RABDEF
        $XABDEF
        $XABFHCDEF
;
;       Define Record Management Services (RMS) Parameters
;
IO_MBC          ==      8               ; RMS I/O buffer size (blocks)
IO_MBF          ==      4               ; # of RMS I/O buffers
;
;
        .macro  $dinit  base,start=0
base'$NXT$      =       start
        .endm
        .macro  $def    base,symbol,size=4
base'symbol     =       base'$NXT$
base'$NXT$      =       base'$NXT$ + size
        .endm
;
;       Define Local Variables
;
        $dinit  base=L$_
        $def    L$_,IFAB,FAB$C_BLN
        $def    L$_,OFAB,FAB$C_BLN
        $def    L$_,IRAB,RAB$C_BLN
        $def    L$_,ORAB,RAB$C_BLN
        $def    L$_,IXAB,XAB$C_FHCLEN
        $def    L$_,GET_ARG,8
        $def    L$_,PUT_ARG,8
        $def    L$_,IO_PAGES,4
        $def    L$_,IO_BUFFER,4
        $def    L$_,IDESCR,8
        $def    L$_,ODESCR,8
        $def    L$_,IFILE,256
        $def    L$_,OFILE,256
        $def    L$_,SIZE,0
        .page
        .sbttl  Readonly
        .psect  READONLY,RD,NOWRT,NOEXE
;
;       Define message strings
;
BLANK::
        .ascid  \  \
EXPLAIN1::
        .ascid  \DELTABS reads an input file and writes an output file in which
EXPLAIN2::
        .ascid  \are replaced with spaces.  Tab positions are assumed to be 9, 1

IPROMPT::
        .ascid  \     Enter input filespec: \
OPROMPT::
        .ascid  \     Enter output filespec: \
        .page
        .sbttl  CODE
        .psect  CODE,EXE,RD,NOWRT
;
;       Do the Work
;
        .entry  DELTABS,M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
        SUBL2   #L$_SIZE,SP             ; room for local variables
        BICL2   #7,SP                   ; quadword align stack
        MOVL    SP,R11                  ; R11 -> locals
        MOVC5   #0,#0,#0,-              ; zero fill
                #L$_SIZE,-              ; local variables
                (R11)
        PUSHAQ  BLANK                   ; give explanation
        CALLS   #1,gLIB$PUT_OUTPUT
        PUSHAQ  EXPLAIN1
        CALLS   #1,gLIB$PUT_OUTPUT
        PUSHAQ  EXPLAIN2
        CALLS   #1,gLIB$PUT_OUTPUT
        PUSHAQ  BLANK
        CALLS   #1,gLIB$PUT_OUTPUT
        MOVZBL  #255,L$_IDESCR(R11)     ; set up descr for Input
        MOVAB   L$_IFILE(R11),L$_IDESCR+4(R11)  ; file name
        PUSHAW  L$_IDESCR(R11)
        PUSHAQ  IPROMPT
        PUSHAQ  L$_IDESCR(R11)
        CALLS   #3,gLIB$GET_INPUT      ; get input file name
        BLBS    R0,1$
        BRW     99$                     ; exit on error
1$:     MOVZBL  #255,L$_ODESCR(R11)     ; set up descr for Output
        MOVAB   L$_OFILE(R11),L$_ODESCR+4(R11)  ; file name
        PUSHAW  L$_ODESCR(R11)
        PUSHAQ  OPROMPT
        PUSHAQ  L$_ODESCR(R11)
        CALLS   #3,gLIB$GET_INPUT      ; get output file name
        BLBS    R0,2$
        BRW     99$                     ; exit on error
2$:     MOVB    #FAB$C_BID,-            ; set up File Access Block (FAB)
                L$_IFAB+FAB$B_BID(R11)  ; for Input file
        MOVB    #FAB$C_BLN,-
                L$_IFAB+FAB$B_BLN(R11)
        $FAB_STORE-
                FAB=L$_IFAB(R11),-
                FAC=<GET>,-             ; File ACcess=GET (read)
                FNA=L$_IFILE(R11),-     ; File Name Address
                FNS=L$_IDESCR(R11),-    ; File Name Size
                FOP=<SQO>,-             ; File OPtions=SeQuential Only
                RTV=#255,-              ; ReTrieVal window size=MAX
                SHR=GET,-               ; SHaring=other READERs
                XAB=L$_IXAB(R11)        ; eXtend Attribute Block
        MOVB    #XAB$C_FHCLEN,-         ; set up XAB for
                L$_IXAB+XAB$B_BLN(R11)  ; File Header Characteristics
        MOVB    #XAB$C_FHC,-
                L$_IXAB+XAB$B_COD(R11)
        $XABFHC_STORE,-
                XAB=L$_IXAB(R11)
        PUSHAL  L$_IFAB(R11)
        CALLS   #1,gSYS$OPEN           ; open Input File
        BLBS    R0,3$
        BRW     99$                     ; exit on error
3$:     MOVB    #RAB$C_BID,-            ; set up Record Access Block
                L$_IRAB+RAB$B_BID(R11)
        MOVB    #RAB$C_BLN,-
                L$_IRAB+RAB$B_BLN(R11)
        $RAB_STORE,-
                RAB=L$_IRAB(R11),-
                FAB=L$_IFAB(R11),-
                MBC=#IO_MBC,-           ; Multi-Block Count
                MBF=#IO_MBF,-           ; Multi-BuFfer count
                ROP=<RAH>,-             ; Record OPtions=Read AHead
                RAC=SEQ                 ; Record ACcess=SEQuential
        PUSHAL  L$_IRAB(R11)
        CALLS   #1,gSYS$CONNECT        ; prepare for record access
        BLBS    R0,4$
        BRW     99$                     ; exit on error
4$:     MOVB    #FAB$C_BID,-            ; set-up Output FAB
                L$_OFAB+FAB$B_BID(R11)
        MOVB    #FAB$C_BLN,-
                L$_OFAB+FAB$B_BLN(R11)
        $FAB_STORE-
                FAB=L$_OFAB(R11),-
                FAC=<PUT,TRN>,-         ; File ACcess=PUT & TRUNCATE
                FNA=L$_OFILE(R11),-     ; File Name Address
                FNS=L$_ODESCR(R11),-    ; File Name Size
                FOP=<SQO,MXV,TEF>,-     ; File Options=SeQuential Only,
                -                       ; MaXimize Version number,
                -                       ; Truncate at End of File
                ORG=SEQ,-               ; ORGanization=SEQuential
                RAT=L$_IFAB+FAB$B_RAT(R11),-    ; Record ATtributes
                -                       ; copied from Input File
                RFM=VAR,-               ; Record ForMat=VARiable
                MRS=#0,-                ; Maximum Record Size=Unlimited
                RTV=#255,-              ; ReTrieVal Windows=MAX
                SHR=NIL                 ; SHaRing=NONE
        PUSHAL  L$_OFAB(R11)
        CALLS   #1,gSYS$CREATE         ; Create/Open Output File
        BLBS    R0,5$
        BRW     99$                     ; exit on error
5$:     MOVB    #RAB$C_BID,-            ; set-up Output RAB
                L$_ORAB+RAB$B_BID(R11)
        MOVB    #RAB$C_BLN,-
                L$_ORAB+RAB$B_BLN(R11)
        $RAB_STORE,-
                RAB=L$_ORAB(R11),-
                FAB=L$_OFAB(R11),-
                MBC=#IO_MBC,-           ; Multi-Block Count
                MBF=#IO_MBF,-           ; Multi-BuFfer count
                ROP=<WBH>,-             ; Record Options=Write BeHind
                RAC=SEQ                 ; Record ACcess=SEQuential
        PUSHAL  L$_ORAB(R11)
        CALLS   #1,gSYS$CONNECT        ; prepare for record access
        BLBS    R0,6$
        BRW     99$                     ; exit on error
6$:     MOVZWL  L$_IXAB+XAB$W_LRL(R11),R2       ; R2 = Max Inp Rec Len
        ASHL    #-6,R2,R2               ; * 8 char/tab / 512 byte/block
        INCL    R2                      ; round up
        MOVL    R2,L$_IO_PAGES(R11)     ; R2 = Max Out Rec Len (blocks)
        PUSHAL  L$_IO_BUFFER(R11)       ; addr to rec'v addr of IO buf
        PUSHAL  L$_IO_PAGES(R11)        ; # pages (blocks) in IO buffer
        CALLS   #2,gLIB$GET_VM_PAGE    ; Get Virtual Memory Pages
        BLBS    R0,7$
        BRW     99$                     ; exit on error
7$:     ASHL    #9,R2,L$_IRAB+RAB$W_USZ(R11)    ; Max Inp Rec Len (char)
        MOVL    L$_IO_BUFFER(R11),-     ; move addr of IO buffer
                L$_IRAB+RAB$L_UBF(R11)  ;  to Input FAB
        MOVL    L$_IO_BUFFER(R11),-     ;  and
                L$_ORAB+RAB$L_RBF(R11)  ;  to Output FAB
        MOVL    #1,L$_GET_ARG(R11)      ; 1 argument to SYS$GET
        MOVL    #1,L$_PUT_ARG(R11)      ; 1 argument to SYS$PUT
        MOVAB   L$_IRAB(R11),L$_GET_ARG+4(R11)  ; argument for SYS$GET
        MOVAB   L$_ORAB(R11),L$_PUT_ARG+4(R11)  ; argument for SYS$PUT
        MOVAB   L$_GET_ARG(R11),R8      ; R8 -> SYS$GET arguments
        MOVAB   L$_PUT_ARG(R11),R12     ; R12 -> SYS$PUT arguments
8$:     CALLG   (R8),gSYS$GET          ; GET next record
        CMPL    R0,#RMS$_EOF            ; End of File?
        BEQL    100$                    ;  Yes, were all done
        BLBC    R0,99$                  ; Error?
        MOVL    L$_IRAB+RAB$L_UBF(R11),-        ; R6 -> line read
                R6
        MOVW    L$_IRAB+RAB$W_RSZ(R11),R10      ; R10 = line length
        MOVW    R10,L$_ORAB+RAB$W_RSZ(R11)      ; copy to Output RAB
9$:     LOCC    #09,R10,(R6)            ; Locate a TAB?
        BNEQ    10$                     ;  Yes, replace it w/space(s)
        CALLG   (R12),gSYS$PUT         ;  No, PUT in Outfile
        BLBS    R0,8$                   ;  Again if no errors
99$:    RET                             ; QUIT on ERROR
100$:   MOVL    #1,R0                   ; EXIT on COMPLETION
        RET
;
10$:    ADDL3   #1,R0,R10               ; R10 = # chars after TAB
        ASHL    #-3,R1,R6               ; R6 = position of TAB / 8
        INCL    R6                      ; Increment to next TAB stop
        ASHL    #3,R6,R6                ; TAB stop * 8 = char offset
        MOVB    #32,(R1)+               ; replace TAB with a space
        SUBL3   R1,R6,R7                ; # extra spaces to TAB stop
        BEQL    9$                      ; Done with this TAB if zero
        MOVL    R1,R9                   ; R9 -> 1st char after TAB
        MOVC3   R0,(R9),(R6)            ; Shift rest of line right
        MOVC5   #0,#0,#32,R7,(R9)       ; Fill gap with spaces
        ADDW2   R7,L$_ORAB+RAB$W_RSZ(R11)       ; increase line length
        BRB     9$                      ; look for more TABS
        .end    DELTABS
------ cut here -----


{ John Hascall             GGUUU@ISUMVS.BITNET                 (daily)
{ VAX/NAS Systems Groups   GVJPH@ISUVAX.BITNET                 (daily)
{ ISU Computation Center   GVJPH@CCVAX.IaState.EDU             (daily)
{ 104 Atanasoff Hall       hascall@atanasoff.cs.IaState.EDU    (weekly)
{ Ames, Iowa  50011        john@iris.ecil.IaState.EDU          (on occasion)
{ (515) 294-0005           john@callisto.ecil.IaState.EDU      (1/blue moon)


