C      VTAPEIN - READ LABELED TAPES WITH VERIABLE RECORD LENGTHS
C
C      R. COUCH PRIME MARKETING SUPPORT N.Y.C.   03/28/85
C
C  *** Reads tapes created by:
C  ***    VAX with Unix using ANSITAR utility
C  ***    VAX with VMS  using the COPY utility
C  ***    DECSYSTEM-20 using the WRITEL program
C
C  *** These will come from VAX/VMSM, RSX-11 or RSTS/E sites
C
C  *** This routine is written to read tapes written as follows:
C
C  *** 9 Track, 1600 BPI
C
C  *** ANSI labels (each label is an 80-byte ASCII record)
C  *** Each label begins with a 4-char identifier, like VOL1,HDR1,EOF.,EOV1
C  *** Volume name is in columns 5-10 (Vol labels only at beginning of tape)
C  *** HDR1 - file name is in columns 5-21
C  *** HDR2 - column 5 is record format (F, D, or S) (I only work with D)
C  ***               6-10 block length (I use what they tell me from keyboard)
C  ***               1-15 record length (this program defaults to 300
C  ***                                   it doesn't matter anyway because
C  ***                                   this is a max record size)
C  *** There may be an EOF1 and EOF2 they are skipped
C  *** At the end of the tape there is supposed to be an EOV1 and EOV2
C  *** followed by a double tape mark.
C
C  *** Record Format "D":
C  *** Variable length records with a 4-digit ASCII length field at
C  *** the beginning of each record (the length includes the length field)
C  *** Line terminators are stripped, and there is no record crossing
C  *** a block boundry . The record may be padded at the end with 1, 2,
C  *** or 3 circumflex characters, which are not included in the field
C  *** length. (this programer did not know what the heck a circumflex
C  *** character was and did not take them into account. This routine
C  *** did however, work on the tape I had to test with.)
C  *** My spec called for block sizes of 2048, 4096, and 8192 characters
C  *** only, so this program only allows that selection. If there were
C  *** other block sizes to wory about simply allow that size to be entered.
C
C
         LOGICAL
     * OPEN$A,YSNO$A,CSTR$A,LSTR$A
C
C
         INTEGER
     * IUNIT,HRSIZE,READRC,STATUS(6),CODE,HAT,PUNIT,GCHR$A,
     * ZERO,GSTAT,TSTAT(6),TCODE,IBUF(4200),TCHAR,RLEN,MAXCHR,
     * I,J,K,L,OCTAL,TEXT,LSIZ(2),LBUF(150),EARY(152),FIXODD,
     * ESIZ,BUFPNT,RSIZ, DATASZ,FSTCHR,LSTCHR,FNAM(8),EOF,
     * NUNAM(9),NLEN,NLEN$A,RWIND,XCODE,GTPMRK,WDATSZ,JOBNO,
     * TSTNAM(8),TSTLEN,CKLEN,SKPREC
C
C
         INTEGER*4
     * BIGZRO
C
C
       EQUIVALENCE
     * (EARY(1),LSIZ(1)),
     * (EARY(3),LBUF(1)),
     * (IBUF(2),NUNAM(1)),
     * (IBUF(3),FNAM(1))
C
C
$INSERT SYSCOM>A$KEYS
$INSERT SYSCOM>ERRD.INS.FTN
C
C
       HRSIZE = 40   /* HEADER RECORD SIZE
       READRC = :042600   /* READ A RECORD (BLOCK)
       RWIND  = :000040   /* REWIND TAPE
       GSTAT  = :100000   /* GET TAPE STATUS (CAUSES A WAIT ON SEMIPHORE)
       GTPMRK = :022200   /* GET TAPE MARK
       SKPREC = :062200
       ZERO = 0
       BIGZRO = 0
       OCTAL = 7777
       TEXT = 0000
       HAT = '^ '
       EOF = 0
C
5      CONTINUE
       CALL TONL
       CALL TNOUA ('ENTER TAPE DRIVE #: ',20)
       READ (1,10,ERR=5) IUNIT
10     FORMAT (I2)
15     CONTINUE
       CALL TNOUA ('BLOCK SIZE (2048,4096 OR 8192 ONLY): ',37)
       READ (1,20,ERR=15) DATASZ
20     FORMAT (I4)
       WDATSZ = DATASZ / 2
       IF (DATASZ.NE.2048 .AND.
     *     DATASZ.NE.4096 .AND.
     *     DATASZ.NE.8192) GOTO 15
C
C  ***  REWIND TO BEGINNING OF TAPE
C  ***  READ THE VOLUME LABEL
C
       CALL T$MT (IUNIT,BIGZRO,ZERO,RWIND,TSTAT,TCODE)
C
C  *** DURING REWIND LET'S SEE WHAT HE WANT'S TO DO
C
70     CONTINUE
       JOBNO = 0  /* READ ALL FILES
       IF (YSNO$A('READ FULL TAPE ',15,A$NDEF)) GO TO 90
       JOBNO = 1  /* READ A SINGLE FILE
       IF (YSNO$A('READ A SINGLE FILE ',19,A$NDEF)) GOTO 80
       JOBNO = 2  /* READ ALL FILES CONTAINING STRING
       IF (YSNO$A('READ ALL FILES CONTAINING STRING ',33,A$NDEF))
     * GOTO 80
       GOTO 70
80     CONTINUE
       CALL TNOUA ('ENTER FULL NAME OR STRING (16 CHAR MAX): ',41)
       READ (1,85) TSTNAM
85     FORMAT (8A2)
       TSTLEN = NLEN$A (TSTNAM,16)
       IF (TSTLEN.EQ.0) GOTO 80
90     CONTINUE
       CALL T$MT (IUNIT,BIGZRO,ZERO,GSTAT,TSTAT,XCODE)
       IF (TCODE.NE.0) GOTO 9020
       CALL T$MT (IUNIT,LOC(IBUF),HRSIZE,READRC,STATUS,CODE) /* VOLUME HEADER
       CALL T$MT (IUNIT,BIGZRO,ZERO,GSTAT,TSTAT,TCODE)
C
C  *** READ THE HDR1 RECORD , TURN ON THE :200 BIT IN EACH CHARACTER
C  *** GET THE FILE NAME OUT OF COLUMNS 5-21, AND OPEN A SAM FILE OF
C  *** THAT NAME FOR WRITTING. (ON THE TAPE THAT I HAD SOME OF THE FILE
C  *** NAMES BEGAN WITH DIGITS, SO I INSERTED 'V.' IN FRONT OF THE NAME)
C
100    CONTINUE
       CALL T$MT (IUNIT,LOC(IBUF),HRSIZE,READRC,STATUS,CODE) /* HEADER
       CALL T$MT (IUNIT,BIGZRO,ZERO,GSTAT,TSTAT,TCODE)
       IF (AND(STATUS(2),:400).NE.0) GOTO 9500   /* MUST BE END OF VOLUME
       DO 1055 I = 1,50
       IBUF(I) = OR(IBUF(I),:100200)
1055    CONTINUE
       NUNAM(1) = 'V.'
       NLEN = NLEN$A(NUNAM,18)
       CKLEN = NLEN - 2
       CALL TNOU (FNAM,CKLEN)
       IF (JOBNO.EQ.0) GOTO 104  /* READ ALL FILES
       IF (JOBNO.NE.1) GOTO 103
       IF (CSTR$A(TSTNAM,TSTLEN,FNAM,CKLEN)) GOTO 104
       GOTO 375
103    CONTINUE
       IF (LSTR$A(TSTNAM,TSTLEN,FNAM,CKLEN,FSTCHR,LSTCHR))
     * GOTO 104
       GO TO 375
104    CONTINUE
       CALL TNOUA ('OPENING ',8)
       CALL TNOU (NUNAM,NLEN)
       IF (OPEN$A(A$WRIT+A$SAMF+A$GETU,NUNAM,NLEN,PUNIT)) GOTO 105
       CALL TNOUA ('CAN''T OPEN ',11)
       GOTO 9000
105    CONTINUE
C
C  *** DON'T CARE ABOUT BALANCE OF HEADER STUFF, SO SKIP TO NEXT TAPE
C  *** THIS IS THE ACTUAL DATA STUFF
C
110    CONTINUE
       CALL T$MT (IUNIT,BIGZRO,ZERO,GTPMRK,TSTAT,XCODE)
C
C  *** READ A BLOCK OF THE ACTUAL TAPE DATA, TURN ON THE :200 BIT
C  *** IN EACH CHARACTER
C
200    CONTINUE
       CALL T$MT (IUNIT,LOC(IBUF),WDATSZ,READRC,STATUS,CODE)
       CALL T$MT (IUNIT,BIGZRO,ZERO,GSTAT,TSTAT,TCODE)
       IF (STATUS(3).EQ.0) GOTO 300
       MAXCHR = STATUS(3) * 2 - 1
       DO 205 I = 1,WDATSZ
       IBUF(I) = OR(IBUF(I),:100200)
205    CONTINUE
       BUFPNT = 0
       FSTCHR = 1
       LSTCHR = 4
C
C  *** FIRST 4 CHAR OF EACH DATA RECORD AR THE RECORD LENGTH
C  *** IN CHARACTERS (THIS INCLUDES THE 4 CHAR).
C  *** MOVE THE RECORD OUT OF THE TAPE BUFFER INTO A LINE BUFFER
C  *** STUFF A SPACE AT THE END TO TAKE CARE OF ODD CHAR LENGTH RECORDS
C  *** WRITE IT TO THE DISK FILE, BUMP THE TAPE BUFFER POINTERS
C  *** IF LAST CHARA POINTER IS POINTING BEYOND NUMBER OF WORDS
C  *** READ IN THIS BLOCK WE ARE READY TO GET THE NEXT BLOCK
C
210    CONTINUE
       CALL MSUB$A (IBUF,DATASZ,FSTCHR,LSTCHR,LSIZ,4,1,4)
       DECODE (4,225,LSIZ,ERR=400) ESIZ
225    FORMAT (I4)
       IF (ESIZ.GT.304) GOTO 5000  /* LINE IS OUT OF RANGE
       LSTCHR = FSTCHR + ESIZ - 1
       CALL MSUB$A (IBUF,DATASZ,FSTCHR,LSTCHR,EARY,304,1,ESIZ)
       RSIZ = ESIZ - 4
       RLEN = (RSIZ + 1) / 2
       FIXODD = RSIZ + 1
       CALL MCHR$A (LBUF,FIXODD,' ',1)
       CALL WTLIN$ (PUNIT,LBUF,RLEN,CODE)
       IF (CODE.NE.0) GOTO 9010
       FSTCHR = FSTCHR + ESIZ
       LSTCHR = FSTCHR + 3
       IF (LSTCHR.GE.MAXCHR) GOTO 300
       GOTO 210
C  *** THE TAPE BUFFER IS NOW EMPTY, IF WE HAVEN'T READ A TAPE MARK
C  *** GO GET THE NEXT DATA BLOCK.
C  *** IF WE HAVE READ A TAPE MARK IT'S END OF FILE, SKIP THE END
C  *** FILE LABEL AND GO GET THE NEXT FILE
C
300    CONTINUE
       IF (AND(STATUS(2),:400).EQ.0) GOTO 200
325    CONTINUE
       CALL CLOS$A (PUNIT)
       IF (JOBNO.EQ.1) GOTO 9510
C
C  *** WE GO FORWARD ONE TAPE MARK HERE.
C  *** FRANKLY, I DON'T KNOW IF I'M SKIPPING THE TAPE MARK I READ
C  *** WHEN I TRIED TO GET THE NEXT DATA BLOCK OR IF I'M SKIPPING THE
C  *** THE 'EOF' RECORD, BUT IT SEEMS TO WORK.
C
350    CONTINUE    /* COME DIRECTLY HERE TO SKIP AN EOF RECORD
       CALL T$MT (IUNIT,BIGZRO,ZERO,GTPMRK,STATUS,CODE)
       CALL T$MT (IUNIT,BIGZRO,ZERO,GSTAT,TSTAT,XCODE)
       GOTO 100
375    CONTINUE    /* COME DIRECTLY HERE TO SKIP A FILE
C  *** SKIP HEADER TAPE MARK
       CALL T$MT (IUNIT,BIGZRO,ZERO,GTPMRK,STATUS,CODE) /* HEADER
       CALL T$MT (IUNIT,BIGZRO,ZERO,GSTAT,TSTAT,XCODE)
       CALL T$MT (IUNIT,BIGZRO,ZERO,GTPMRK,STATUS,CODE) /* DATA FILE
       CALL T$MT (IUNIT,BIGZRO,ZERO,GSTAT,TSTAT,XCODE)
       GOTO 350  /* GO SKIP THE TRAILER LABEL
C
400    CONTINUE
       WRITE (1,405) FSTCHR,MAXCHR
405    FORMAT ('POINTING AT CHAR#',I5,' READ',I5,' CHARS',/,
     *         'IF TAPE MARK GET NEXT FILE ELSE NEXT BLOCK')
       IF (AND(STATUS(2),:400).NE.0) GOTO 325
       GOTO 200
C
C
5000   CONTINUE
       WRITE (1,5005) ESIZ
5005   FORMAT ('THAT''S STUPID   RECORD SIZE CAN''T BE ',I5)
       STOP 200
C
C
9000   CONTINUE
       CALL EXIT
C
9010   CONTINUE
       WRITE (1,9015) CODE
9015   FORMAT ('ERROR',I6,' WRITTING DATA FILE')
       GOTO 9000
9020   CONTINUE
       IF (TCODE.NE.E$NASS) GOTO 9030
       CALL TNOU ('** TAPE NOT ASSIGNED **',23)
       CALL EXIT
9030   CONTINUE
       IF (TCODE.NE.E$BNWD) GOTO 9040
       CALL TNOU ('** BAD BLOCK SIZE **',20)
       CALL EXIT
9040   CONTINUE
       WRITE (1,9045) TCODE
9045   FORMAT ('TAPE ERROR -',I5)
       CALL EXIT
9500   CONTINUE
       CALL CLOS$A (PUNIT)
       CALL TONL
       CALL TNOU ('      *** END OF TAPE ***',25)
       CALL EXIT
9510   CONTINUE
       CALL TNOU ('FILE COMPLETE',13)
       CALL EXIT
       END
