C BIGTAPE.FTN
C TAPE POSITION CONTROL TASK AND TAPE-DISK UTILITY FOR
C FIXED RECORD LENGTH RECORDS IN ASCII/EBCDIC.
C  THIS PROGRAM HAS MANY OPTIONS (TYPE 'HELP' TO LIST)
C AND ALLOWS MANUAL CONTROL OF TAPE MOTION AND READ/WRITE
C ACCESS TO FILES ON TAPE. BEST AT CARD IMAGE FILES BLOCKED
C UP TO 100. TAPE MAY BE IN ASCII OR EBCDIC AND CAN BE READ
C OR WRITTEN IN EITHER. ALSO CAN READ RECORD LENGTHS OTHER
C THAN 80 USING THE "B UNIT,BLKSIZE" COMMAND.
C
C THIS VERSION ALLOWS THE CREATION OF FILES FROM A UNIX (V6) TAR
C TAPE (3/1/82) CRUDELY. 2 OUTPUT FILES WILL BE CREATED; THE
C FIRST WILL BE CALLED "TARDIR.DIR" AND WILL CONTAIN JUST THE
C FULL UNIX PATHNAME ON THE TAPE IN THE ORDER THE PATHS ARE
C ENCOUNTERED. THE SECOND NAMES WILL BE THE LAST (NAME) PART
C OF THE PATHNAME AND THESE WILL BE ENTERED INTO THE CURRENT
C DIRECTORY AS FOUND. IT IS EXPECTED THAT THE TARDIR.DIR
C MAY BE EDITED TO COPY FILES FROM THE CURRENT ACCOUNT
C (POSSIBLY USING A PIP /BR DIRECTORY TO GET VERSION NUMBERS
C IN THE SAME ORDER) INTO ACCOUNTS WANTED. THIS IS A VERY VERY
C CRUDE METHOD BUT ALLOWS ONE TO CAPTURE FILES AS ONE
C DESIRES.
C  NOTE THAT THE DIMENSION OF LLN IS NOW 11000 BYTES TO
C ALLOW DEFAULT UNIX STYLE BLOCKS TO FIT.
C   ===> SINCE 1ST DATA BYTE IS 407,410,411 FOR MOST UNIX BINARY
C FILES, TRY AND KEEP TRACK OF THIS AND FILL IN AN * INTO TARDIR.DIR
C ENTRY FOR SUCH CASES. THIS SHOULD FACILITATE LISTING ONLY SOURCE
C FILES (UNIX DOES A POOR JOB KEEPING THESE IDENTIFIABLE OTHERWISE)
C AND WILL RESULT IN NOT TREATING LF AS A SEPARATOR FOR BINARY DATA
C ALSO.
C
C ROOT FOR TPP TASK
C	TAPE POSITION CONTROLLER AND 80-BYTE/RECORD DATA COPIER
	INTEGER*2 IPTRS
	DIMENSION IPTRS(4),IDESC(7)
	DIMENSION LINE(132,100),LLN(13200)
	BYTE LINE,LLN,LLINE(8000)
	EQUIVALENCE(LLN(1),LINE(1,1))
	EQUIVALENCE(LLN(1),LLINE(1))
	DIMENSION IBF(4200)
	INTEGER *2 IBF
C	NOTE LINE AND IBF ARE THE SAME AREA AND THEIR DIMENSIONS
C	MUST BE COMPATIBLE!
	BYTE OLINE
	DIMENSION OLINE(514)
	DIMENSION RBF(110)
	REAL * 4 RBF
	EQUIVALENCE(RBF(1),IBF(1))
	EQUIVALENCE(IBF(1),LINE(1))
	BYTE AA,BB
	BYTE CCC
	DIMENSION CCC(2)
	EQUIVALENCE (AA,CCC(1)),(BB,CCC(2))
	EQUIVALENCE (JJJ,CCC(1))
	INTEGER*4 IGRN,NFILKK
	INTEGER * 4 IRECCT
	INTEGER*4 NFILBY,NFILB2,BPBK
	BYTE LFNM(100),UFNM(100)
	BYTE DFNM(50)
	INTEGER*4 IVAL
	EXTERNAL IVAL
	DATA BPBK/512/
C	DO TAPE OPERATIONS
C SET FLAG THAT UNIX BINARY FLAG NOT SEEN (FOR T MODE)
	IUXBN=0
	KSZ=80
C MVBIT <> 0 MEANS REVERSE 4 BIT GROUPS OFF TAPE.
C ACTUALLY GETS NEXT INT., READS IN THAT.
	MVBIT=0
	MULTRC=1
20	CONTINUE
	IBCDFG=0
	DO 22 I4300=1,5000
22	IBF(I4300)=0
	CALL GETCML(LINE,3HTPP,MCRSZ,72)
	IRECCT=0
	CALL FFINIT(IPTRS,LINE,MCRSZ,IERR)
	CALL FFSTR(IPTRS,JJJ,2)
D	JJJJ=JJJ
	BB=32
	ICMD=JJJ
	CALL FFINTG(IPTRS,IUNIT)
C  FREE FORMAT COMMANDS:
C	LETTER,NUMBER[,NUMBER]
C	WHERE
C	LETTER=R,REWIND UNIT (0 OR 1)
C	      =E, WRITE ENDFILE ON UNIT 0 OR 1
C	      =S, SKIP +- N RECORDS ON UNIT 0 OR 1
C	      =F, SKIP +- N FILES ON UNIT 0 OR 1
C	      =C, COPY PDP11 FILE TO TAPE
C	      =W, WRITE TAPE FILE TO DISK.
C	      =P, COPY PDP11 FIILE TO TAPE IN EBCDIC FOR PUNCH
C	      =I, COPY TAPE FILE TO PDP11, TAPE IN EBCDIC
C	      =G, GET DG FORMAT TAPE FILE, DUMP TO PDP11
C			(200 BIT CLEARED ON INPUT IN ALL BYTES)
C	      =O, OUTPUT TAPE WITH RECORDS TERMINATED BY C.R.
C			O UNIT,BLKFACTOR,FLAG  (FLAG=1 MEANS SET 200
C				BIT IN ALL OUTPUT CHARS, =ANYTHING ELSE
C				MEANS LEAVE 200 BIT OFF ALWAYS.
C	      =A,CHARAC  ALTER TAPE CHARAC TO VALUE CHARAC
C (FOR OTHERS SEE "HELP" PRINTOUT)
	IEBFLG=0
C	IF EBCDIC, SET IEBFLG NONZERO.
	CALL ALUN(IUNIT)
C	ASSIGN 'MAGLUN' (GLOBAL) TO MT0: OR MT1:
	IF (ICMD.EQ.'X') CALL EXIT
	IF (ICMD.NE.'H') GO TO 28
C	WRITE HELP MESSAGE
	WRITE (6,24)
24	FORMAT(' CMD UNIT COUNT,EXTRA INFO ',/,
     1 ' CMD=R  REWIND UNIT',/,
     2 '    =E  WRITE EOF ON UNIT',/,
     3 '    =S  SKIP COUNT RECORDS (+ OR -)',/,
     4 '    =F  SKIP COUNT FILES (+ OR -)',/,
     5 '    =C  COPY PDP11 FILE TO TAPE IN ASCII, BLK FACTOR=COUNT',/,
     6 '    =W  WRITE TAPE FILE TO DISK IN ASCII,BLK FACTOR=COUNT',/,
     7 '    =P  WRITE PDP11 FILE TO TAPE IN EBCDIC, BLK FAC=COUNT',/,
     8 '    =I  INPUT EBCDIC FILE TAPE TO PDP11, BLK FAC. = COUNT',/,
     9 '    =A  ALTER TAPE CHARAC. TO COUNT',/,
     A '    =B  SET RECORD SIZE TO COUNT')
	WRITE(6,26)
26	FORMAT('    =Z  ENTER UNIT RECORD MODE',/,
     1 '    =G  GET DG FORMAT TAPE FILE, DUMP TO PDP11',/,
     1 '    =J  GET DG FORMAT TAPE AND READ IN AS 7TRK',/,
     2 '    =O  WRITE TAPE, RCRDS TERM BY CR;FLAG=1==>SET 200 BIT',/,
     3 '    =U  READ IN AS G OPTION BUT BIG RECORDS ALLOWED',/,
     A '    =V  SET BIT REVERSE FLAG TO COUNT. 0=NONE, 1=SWAP 4BITS',/,
     C '    =M  SET MULTIPLE RECORD MODE(DEFAULT)',/,
     D '    =D  ENTER TAPE DUMP MODE (ASKS MORE QUESTIONS)',/,
     E '    =X  EXIT',/,
     F '    =H  PRINT THIS MESSAGE',/,
     G '    =Y  READ BCD TAPE INTO PDP11 FILE, BLK FACTOR=COUNT',/,
     H '    =T  READ U.V6 TAR TAPES TO PDP & CREATE TARDIR.DIR',/,
     I ' UNIT = 0 OR 1 FOR MT0: OR MT1:',/,
     J ' COUNT, EXTRA=EXTRA NUMERIC INFORMATION AS REQUIRED')
28	CONTINUE
	IF (ICMD.NE.'Z') GO TO 30
	MULTRC=0
30	CONTINUE
	IF (ICMD.NE.'M') GO TO 32
	MULTRC=1
32	CONTINUE
	IF (ICMD.NE.'A') GO TO 34
C	ALTER CHARACTERISTICS OF TAPE
	CALL FFINTG(IPTRS,ICHARA)
	CALL MSETCH(ICHARA)
34	CONTINUE
	IF (ICMD.NE.'B') GOTO 36
	CALL FFINTG(IPTRS,KSZ)
	IF(KSZ.LT.1.OR.KSZ.GT.160)KSZ=80
36	CONTINUE
	IF (ICMD.NE.'V') GOTO 38
	CALL FFINTG(IPTRS,MVBIT)
38	CONTINUE
	IF (ICMD.NE.'I') GO TO 40
	IRECCT=0
	IEBFLG=1
	GO TO 132
40	CONTINUE
	IF (ICMD.NE.'Y') GO TO 42
	IRECCT=0
	IBCDFG=1
	GO TO 132
42	CONTINUE
	IF (ICMD.NE.'P') GO TO 44
	IRECCT=0
	IEBFLG=1
	GO TO 152
44	CONTINUE
	IF (ICMD.NE.'D') GO TO 84
C	DUMP TAPE
C	MUST FIND OUT HOW TO DO IT. ASK FOLLOWING OPTIONS:
C	1. SWAP BYTES?
C	2. SWAP WORDS?
C	3. DUMP OCTAL 16/OCTAL 32/DECIMAL 32/FLOATING PDP11/FLOATING IBM
C	ASSUME OCTAL DUMP AT FIRST
CCCCCC
	WRITE(6,46)
46	FORMAT(' TO SWAP BYTES ENTER 1, ELSE 0')
	READ (5,48)ISWPF
48	FORMAT(I1)
	WRITE(6,50)
50	FORMAT(' TO SWAP WORDS ENTER 1, ELSE 0')
	READ(5,48)IWDSF
	WRITE(6,52)
52	FORMAT(' ENTER 0 FOR OCTAL, 1 FOR DECIMAL 16,2=DEC 32,3=IBM FP')
	READ(5,48)IDSPF
54	CONTINUE
	CALL BCLR(IBF,5000)
	CALL MREAD(IBF,10400,JRECCT,JFLG)
	CALL ERFLG(JFLG,JFLG)
	IF (JFLG.EQ.1.OR.JFLG.EQ.2.OR.JFLG.EQ.3.OR.JFLG.EQ.6)GOTO 82
	IF (ISWPF.NE.0)CALL SWPBYT(IBF,JRECCT)
	IF (IWDSF.NE.0)CALL WRDSWP(IBF,JRECCT)
	NWD2=JRECCT/4
C	NWD2 IS NO. 32 BIT WORDS
	IF (NWD2.LT.1) GO TO 82
	IF (IDSPF.NE.3) GO TO 58
	DO 56 III=1,NWD2
	RBF(III)=FLTIBM(RBF(III))
56	CONTINUE
58	CONTINUE
C	NOW HAVE DATA IN FROM RECORD
C	NOW DISPLAY DATA (MAKE IT OK FOR A TERMINAL)
	N2DO=JRECCT/2
	IF (IDSPF.EQ.3)N2DO=JRECCT/4
C	IF DISPLAY TTPE=4, DUMP ASCII
	IF (IDSPF.EQ.4)NN2D=JRECCT/80
	IF (IDSPF.NE.4)NN2D=N2DO/8
	IDSPF1=IDSPF+1
	MMM0=1
	DO 80 III=1,NN2D
	GO TO (60,64,68,72,76),IDSPF1
60	CONTINUE
C	16 BIT OCTAL
	MMMM=MMM0+7
	WRITE(6,62)MMM0,(IBF(IV),IV=MMM0,MMMM)
	MMM0=MMM0+8
62	FORMAT(1X,I4,8O7)
	GO TO 80
64	CONTINUE
C	16 BIT DECIMAL
	MMMM=MMM0+7
	WRITE(6,66)MMM0,(IBF(IV),IV=MMM0,MMMM)
	MMM0=MMM0+8
66	FORMAT(1X,I4,8I7)
	GO TO 80
68	CONTINUE
C	32 BIT DECIMAL
	MMMM=MMM0+7
	WRITE(6,70)MMM0,(IBF(IV),IV=MMM0,MMMM)
	MMM0=MMM0+8
70	FORMAT(1X,I4,8I9)
	GO TO 80
72	CONTINUE
C	IBM F.P.
	MMMM=MMM0+8
	WRITE(6,74)MMM0,(RBF(IV),IV=MMM0,MMMM)
	MMMM=MMMM+8
74	FORMAT(1X,8F10.4)
	GO TO 80
76	CONTINUE
C	ASCII
	MMMM=MMM0+40
	WRITE(6,78)(IBF(IV),IV=MMM0,MMMM)
	MMM0=MMM0+40
78	FORMAT(1X,40A2)
	GO TO 80
80	CONTINUE
	IF (MULTRC.NE.0)GO TO 54
82	CONTINUE
	GO TO 188
84	CONTINUE
	IF (ICMD.NE.'O') GO TO 92
C	OUTPUT DATA TERMINATED BY C.R. ONLY
	CALL FFINTG(IPTRS,IBLKF)
	IF (IBLKF.LE.0)IBLKF=1
	IF (IBLKF.GT.100)IBLKF=100
C	OUTPUT 0,1 FOR 1 72 CHAR RECORD. A 3RD PARAMETER WILL SEE IF
C	WE NEED TO SET 200 BIT IN WHOLE RECORD
	IBITST=0
	CALL FFINTG(IPTRS,IBITST)
C	IF WE SEE OUTPUT 0,1,1 THEN SET BIT. OTHER VALUES LEAVE IT OFF.
	CALL GETCML(LINE,3HDGO,MCRSZ,72)
	CALL ASSIGN(3,LINE,MCRSZ)
	ITXTI=1
86	CONTINUE
	ITXTI=1
	ITXTI2=ITXTI+68
	DO 88 IREC=1,IBLKF
	READ(3,156,END=90,ERR=90)(LLINE(IIII),IIII=ITXTI,ITXTI2)
	LLINE(ITXTI2+1)=13
	ITXTI=ITXTI+70
	ITXTI2=ITXTI2+70
88	CONTINUE
	NWRTB=72*IBLKF
	LLINE(NWRTB+1)=0
C	NO. BYTES IN 3 RECORDS (INCLUDING 3 C.R. CHARACTERS), +1 TO MAKE EVEN
	IF (IBITST.EQ.1)CALL SET8(LINE,NWRTB)
	CALL MWRITE(LINE,NWRTB,NFLAG)
	CALL ERFLG(NFLAG,NFLAG)
	IF (NFLAG.EQ.6.OR.NFLAG.EQ.1.OR.NFLAG.EQ.3
     1  .OR.NFLAG.EQ.2)GOTO 188
	GO TO 86
90	CONTINUE
C	ENDFILE SEEN...CLOSE AND GO AWAY
	CALL CLOSE(3)
	GO TO 188
92	CONTINUE
	IF (ICMD.EQ. 'U') GOTO 94
	IF ((ICMD.NE.'J').AND.(ICMD.NE.'G')) GO TO 112
C	GET DG TAPE DATA (RECORDS TERMINATED BY C.R.)
C
C	NOTE: FORMAT OF DATA GENERAL (RDOS) TAPES IS
C	255 WORDS DATA CHARACTERS
C	1 WORD FILE NUMBER (0-99=LEGAL RANGE)
C	1 WORD FILE NUMBER (0-99=LEGAL RANGE)
C		TOTAL 257 WORDS
	IUUUU=0
	GO TO 96
94	CONTINUE
	IUUUU=1
96	CONTINUE
C
	CALL GETCML(LINE,3HDGI,MCRSZ,72)
C	CALL ASSIGN(3,LINE,MCRSZ)
	LINE(MCRSZ+1,1)=0
	OPEN (UNIT=3,TYPE='NEW',CARRIAGECONTROL='LIST',DISPOSE='SAVE',
     1  RECORDSIZE=180,
     2  NAME=LINE,INITIALSIZE=10,EXTENDSIZE=12)
	ITXTO=1
98	CONTINUE
C	READ TAPE, THEN OUTPUT TO PDP11 WITH RECORD BOUNDARIES AT C.R.
	ITXTI=1
	CALL BCLR(LINE,5100)
	CALL MREAD(LINE,10200,NREAD,MFLAG)
	CALL ERFLG(MFLAG,MFLAG)
	IF (MFLAG.EQ.6.OR.MFLAG.EQ.1.OR.MFLAG.EQ.3.OR.MFLAG.EQ.2)GOTO 110
C SWAP NIBBLES IF 7TRK INPUT USED (DUMP MODE OF COURSE.)
	IF (ICMD.EQ.'J')CALL BITSWP(LINE,NREAD)
C	REMOVE H.O. BIT FROM ALL TEXT BYTES...
	CALL OFF8(LINE,NREAD)
C	NREAD=NUMBER BYTES FOUND IN BUFFER
C	COPY DATA TO OLINE UNTIL:
C	1. A C.R. CHAR IS ENCOUNTERED IN OUTPUT, OR
C	2. TAPE DATA IS EXHAUSTED
C	THROW OUT CONTROL CHARACTERS (ZERO FILL)
C
C	THE FOLLOWING WILL ENSURE ONLY 255 WORDS (510 BYTES) ARE USED AS TEXT
	IF (IUUUU.NE.1)NREAD=510
C
100	CONTINUE
	ISAVE=LLINE(ITXTI)
	ITXTI=ITXTI+1
	IF (ISAVE.EQ.13) GO TO 102
C CHECK PRINTABLE CHARACTERS AND FILTER OUT EVERYTHING ELSE.
	IF (((ISAVE.NE.9).AND.(ISAVE.NE.12)).AND.
     1  ((ISAVE.LT.32).OR.(ISAVE.GT.127))) ISAVE=0
	OLINE(ITXTO)=ISAVE
	IF (ITXTO.LT.130)ITXTO=ITXTO+1
	IF (ITXTI.LT.NREAD) GO TO 100
C	READ MORE TAPE IF WE MUST, TO GET NEXT PART OF LINE
	GO TO 98
102	CONTINUE
C	HERE EMIT OUTPUT LINE AND CLEAR ITXTO POINTER
	WRITE (3,104)(OLINE(I95),I95=1,ITXTO)
104	FORMAT(131A1)
	ITXTO=1
106	DO 108 I95=1,132
	OLINE(I95)=0
108	CONTINUE
C	WHEN DONE WRITING THIS RECORD, GO TRY FOR MORE.
	GO TO 100
110	CALL CLOSE(3)
	GO TO 188
112	CONTINUE

	IF (ICMD.NE.'T') GO TO 130
C HANDLE UNIX TAR INPUT TAPES
C NOTE: FORMAT IS EMPIRICALLY DERIVED FROM DUMP OF UNIX V6 TAR TAPE
	IFRST=0
	IUXBN=0
	IUUUU=1
	IGRN=512
	IHDRSZ=512
	WRITE(6,9159)
9159	FORMAT(' ENTER C=COPY+DIR,D=DIR,Q=QUERY COPY:')
	READ(5,9158)DFNM
	IKP=0
	IF(DFNM(1).EQ.'D')IKP=1
	IF(DFNM(1).EQ.'Q')IKP=2
C READ REPLIES ON LUN 2 FILE FOR SELECTED COPY IN...
	IF(IKP.EQ.2)CALL ASSIGN(2,'SY:TARFIL.LST')
9167	WRITE(6,9157)
9157	FORMAT(' ENTER DEV:UIC>')
	READ(5,9158)DFNM
9158	FORMAT(80A1)
	IF(IKP.NE.1)GOTO 9160
C IF ONLY DIRECTORY WANTED, SHOVE TO NL:
	DFNM(1)='N'
	DFNM(2)='L'
	DFNM(3)=':'
	DO 9161 NV=4,50
9161	DFNM(NV)=0
9160	CONTINUE
	DO 9162 NV=1,50
	NN=51-NV
	IF(DFNM(NN).GT.32)GOTO 9163
	DFNM(NN)=0
9162	CONTINUE
9163	CONTINUE
C NN HAS NAME LENGTH.
	NDFNM=NN+1
C IGRN=GRANULARITY OF DATA. ASSUME IT'S RECORDED IN 512 BYTE BLKS
C ON TAPE SO A NEW FILE WILL BEGIN ATTHE NEXT 'IGRN' BYTE
C BOUNDARY.
	CALL ASSIGN(4,'SY:TARDIR.LIS')
C ENTRY POINT EITHER INITIALLY OR WHERE WE SAW EOF AND EXHAUSTED TAPE
C RECORD. NOTE WE ASSUME 512 BYTE MULTIPLES...
114	CONTINUE
C
	CALL BCLR(LINE,5480)
C TAR FORMAT BLOCKS 10240 BYTES, SO WE ALLOW A LITTLE EXTRA JUST FOR LAUGHS
	CALL MREAD(LINE,10900,NREAD,MFLAG)
	CALL ERFLG(MFLAG,MFLAG)
C CHECK FOR EOF,EOT, ETC.
C NOTE WE PROCESS TO 1ST EOF ALWAYS
	IF (MFLAG.EQ.6.OR.MFLAG.EQ.1.OR.MFLAG.EQ.3.OR.MFLAG.EQ.2)GOTO5020
	NFILB2=NREAD
C ENTRY POINT WHERE WE GOT TO ENDFILE BUT DIDN'T EXHAUST TAPE RECORD
C RECORD HAS BEEN MOVED UP (TO NEXT 'IGRN' BDY) AND NREAD IS SET UP
C AS THE AMOUNT LEFT IN THE BUFFER AFTER EXHAUSTING THE LAST FILE
C (WHOSE SIZE IS ROUNDED UP TO THE NEXT 'IGRN' BYTES FROM TAPE).
6567	CONTINUE
	KFRST=1
C WRITE OUT UNIX PATHNAME
	DO 6570 IV=1,100
6570	UFNM(IV)=LLINE(IV)
C	WRITE(4,5000)(LLINE(III),III=1,64)
5000	FORMAT(1X,32A1,40A1)
	CALL OFF8(LINE,NREAD)
C MASSAGE THE FILE NAME TO GET THE LAST PART
	LSLSH=0
	LSTN=1
	KPER=0
C FIND FILENAME FROM PATH NAME
C THIS ACCOUNTS FOR THE FILENAME SYNTAX DIFFERENCE BETWEEN THE SYSTEMS.
C  BASICALLY IT USES THE LAST PART OF THE PATHNAME AS THE FILENAME,
C  WITH SPECIAL TREATMENT FOR EXTRA EMBEDDED PERIODS, DOLLAR SIGNS,
C  AND UNDERSCORES. UNIX ALLOWS ALL KINDS OF WEIRD CHARACTER FILENAMES
C  WHICH WE DON'T WANT TO LET RSX TRY TO HANDLE.
C
C FOR VMS, PERMIT FILE 3 TO BE WRITTEN WHICH HAS DERIVED NAMES IN ORDER
C SO THEY MAY BE ASSOICATED WITH TARDIR
C
	IF(LLINE(1).EQ.'.')LLINE(1)=32
	DO 5001 N5001=1,99
	IF(LLINE(N5001).EQ.'/')LSLSH=N5001
C END SCAN ON ANY CONTROL CHARACTERS
	IF(LLINE(N5001).LE.31)GO TO 5002
C FOLD FUNNY CHARACTERS INTO VALID RSX ONES FOR FILESPECS
	IF(LLINE(N5001).EQ.'_')LLINE(N5001)='0'
	IF(LLINE(N5001).EQ.'$')LLINE(N5001)='1'
C ELIMINATE ALL BUT LAST PERIOD OF FILENAME
	IF(LLINE(N5001).EQ.'.'.AND.KPER.NE.0)LLINE(KPER)='2'
	IF(LLINE(N5001).EQ.'.')KPER=N5001
C MAKE FILENAMES UPPER CASE
	IF(LLINE(N5001).GT.96)LLINE(N5001)=LLINE(N5001)-32
C MUNGE ALL OTHER INVALID CHARACTERS INTO 3'S
	IF(.NOT.((LLINE(N5001).GE.'0'.AND.LLINE(N5001).LE.'9')
     1  .OR.(LLINE(N5001).EQ.'.')
     2  .OR.(LLINE(N5001).GE.'A'.AND.LLINE(N5001).LE.'Z')))
     3  LLINE(N5001)='3'
5001	CONTINUE
5002	LSTN=N5001
	IF(LSLSH+1.NE.LSTN)GOTO 6741
C FIXUP CASES OF TOTALLY NULL NAMES...USE RSX NULL NAMES.
	LLINE(LSTN)='.'
	LSTN=LSTN+1
6741	CONTINUE
	LLINE(LSTN)=0
C FORCE LEGAL LENGTH FILE NAME BY ZEROING BYTE AFTER TOO MANY CHARS
	IF(KPER.GT.LSLSH)GOTO 6500
C HERE THERE IS NO PERIOD AFTER THE LAST SLASH... ZERO THE 9TH CHAR
C AFTER THE BUFFER
C THUS LLINE(LSLSH+1) THRU LLINE(LSLSH+9) ARE FILE NAME
C THIS INCLUDES THE CASE KPER=LSLSH=0.
	LLINE(LSLSH+10)=0
	GOTO 6502
6500	CONTINUE
C HERE THERE IS A PERIOD IN THE FILENAME. CLR THE 3RD CHAR AFTER IT
C SO ALL'S WELL...
	IF(KPER.GT.0)LLINE(KPER+4)=0
C SINCE FILE NAME MIGHT STILL BE TOO LONG, CHECK THAT (KPER-LSLSH_
C DOES NOT EXCEED MAX RSX LIMIT OF 10 AND ZERO FILENAME IF IT DOES
C AFTER 9 CHARS
	IF((KPER-LSLSH).GT.10)LLINE(LSLSH+10)=0
6502	CONTINUE
C LINE(125) ON IS LENGTH OF FILE IN BYTES (IN OCTAL)
C FIND END OF FILENAME
	KDTT=LSLSH
6561	IF(LLINE(KDTT+1).LE.0)GOTO 6562
	KDTT=KDTT+1
	GOTO 6561
6562	CONTINUE
	DO 6564 IV=1,20
6564	LFNM(IV)=32
	IVV=0
	IVVVV=LSLSH+1
	DO 6563 IV=IVVVV,KDTT
	IVV=IVV+1
	LFNM(IVV)=LLINE(IV)
6563	CONTINUE
6560	FORMAT(20A1)
C LENGTH IS 12 BYTE DECIMAL. ZERO AT END AS FLAG.
C	LLINE(137)=0
	NFILBY=IVAL(LLINE(125))
	IVVVV=NDFNM-1
	DO 9168 NV=1,20
	DFNM(IVVVV+NV)=LLINE(LSLSH+NV)
9168	CONTINUE
	NOPNF=1
C FIND OUT IF WE WANT TO REALLY WANT TO OPEN FILE
	IF(IKP.EQ.0)GOTO 9169
	IF(IKP.EQ.1)GOTO 9171
C IKP=2 IS QUERY MODE. ONLY ACCEPT FILES WITH COL 1 HAVING Y
C IN IT ON READIN...
C OLINE IS FREE AT THIS POINT SO USE IT FOR SCRATCH...
	READ(2,9158,END=9171,ERR=9171)(OLINE(IVVVV),IVVVV=1,80)
	IF(OLINE(1).EQ.'Y')GOTO 9169
9171	CONTINUE
C HERE FOR DIRECTORY OR IF QUERY FILE IS SHORTER THAN TAPE...
	OPEN(UNIT=3,RECORDSIZE=512,NAME='NL:',TYPE='NEW')
	GOTO 9170
9169	CONTINUE
	OPEN (UNIT=3,TYPE='NEW',CARRIAGECONTROL='LIST',DISPOSE='SAVE',
     1  RECORDSIZE=512,
     2  NAME=DFNM)
9170	CONTINUE
C FLAG FIRST RECORD SITUATION AND NONBINARY FOR STARTERS.
	IFRST=0
	IUXBN=0
	ITXTO=1
116	CONTINUE
C	READ TAPE, THEN OUTPUT TO PDP11 WITH RECORD BOUNDARIES AT C.R.
	ITXTI=1
C ACCOUNT FOR HEADER'S IHDRSZ BYTES IN FILE...
	NREAD=NFILB2-IHDRSZ
	IF(KFRST.EQ.0.OR.NREAD.LE.0)GOTO 9315
C MOVE BUFFER UP BY IHDRSZ AND GO ON
	KFF=IHDRSZ
	DO 9317 IVV=1,NREAD
	KFF=KFF+1
9317	LLINE(IVV)=LLINE(KFF)
	GOTO 9316
9315	CONTINUE
C NEED TO READ ANOTHER TAPE RECORD SINCE HEADER WAS IN END OF LAST ONE
C BCLR WILL ZERO BUFFER PRIOR TO REFILL.
	CALL BCLR(LINE,5490)
	CALL MREAD(LINE,10900,NREAD,MFLAG)
C KFRST FLAG SET ONLY WHEN WE READ A HDR (OR GET A HDR)
9316	KFRST=0
	NFILB2=NREAD
C CHECK FOR BINARY FILE.
	IF (IFRST.NE.0) GOTO 6430
	IFRST=1
C LOOK FOR MAGIC NUMBERS THAT TELL US FILE IS BINARY...
	IF (IBF(1).LT."407.OR.IBF(1).GT."411) GOTO 6465
C FLAG THIS A BINARY FILE
	NFILKK=NFILBY+IGRN-1
	NFILKK=NFILKK/IGRN
	WRITE(4,5008)(UFNM(IV),IV=1,64),
     1   (LFNM(IV),IV=1,20),IBF(1),NFILKK
5008	FORMAT(1X,14A1,50A1,' -> ',20A1,' BIN, FLG=',O6,' ',I7)
	IUXBN=1
	GOTO 6430
6465	CONTINUE
	NFILKK=NFILBY+IGRN-1
	NFILKK=NFILKK/IGRN
	WRITE(4,6466)(UFNM(IV),IV=1,64),
     1   (LFNM(IV),IV=1,20),NFILKK
6466	FORMAT(1X,14A1,50A1,' -> ',20A1,' ASCII ',I7)
6430	CONTINUE
C COMPUTE BYTES LEFT THIS FILE
	IF(NFILB2.GT.NFILBY)GOTO 6001
C NFILB2 = ACTUAL NUMBER BYTES READ OFF TAPE.
	NFILBY=NFILBY-NFILB2
	ILSTBK=0
	GOTO 6002
6001	CONTINUE
	NREAD=NFILBY
C FLAG LAST BLOCK OF FILE FOR READING NEW TAPE RECORD
C ILSTBK = LENGTH LEFT IN BUFFER
	ILSTBK=NFILB2-NFILBY
	NFILBY=0
	IF(ILSTBK.LT.IGRN)ILSTBK=0
6002	CONTINUE
	CALL ERFLG(MFLAG,MFLAG)
	IF (MFLAG.EQ.6.OR.MFLAG.EQ.1.OR.MFLAG.EQ.3.OR.MFLAG.EQ.2)GOTO5020
C	REMOVE H.O. BIT FROM ALL TEXT BYTES...
C	CALL OFF8(LINE,NREAD)
C	NREAD=NUMBER BYTES FOUND IN BUFFER
C	COPY DATA TO OLINE UNTIL:
C	1. A C.R. CHAR IS ENCOUNTERED IN OUTPUT, OR
C	2. TAPE DATA IS EXHAUSTED
C	THROW OUT CONTROL CHARACTERS (ZERO FILL)
C
118	CONTINUE
	ISAVE=LLINE(ITXTI)
	ITXTI=ITXTI+1
C ALLOW END OF RECORD IF EITHER C.R. OR L.F. SEEN
C UNIX USES LF AS END OF RECORD BUT ALLOW EITHER.
C NOTE IF FILE WAS BINARY, JUST TREAT AS 512 BYTE IMAGES.
	IF (IUXBN.NE.0) GOTO 6347
	IF (ISAVE.EQ.10) GO TO 120
	IF (ISAVE.EQ.13) GO TO 120
6347	CONTINUE
	OLINE(ITXTO)=ISAVE
C WRITE OUTPUT AFTER 512 BYTES EVEN IF NO LF SEEN YET.
	IF (ITXTO.GE.512) GOTO 120
	ITXTO=ITXTO+1
C	READ MORE TAPE IF WE MUST, TO GET NEXT PART OF LINE
	IF (ITXTI.LE.NREAD)GO TO 118
	IF(NFILBY.LE.0) GOTO 120
C THE ABOVE CLOSES THE FILE IF WE GOT TO END OF THE INPUT FILE ON THE TAR
	GO TO 116
120	CONTINUE
C	HERE EMIT OUTPUT LINE AND CLEAR ITXTO POINTER
	WRITE (3,122)(OLINE(I95),I95=1,ITXTO)
122	FORMAT(132A1,132A1,132A1,120A1)
	ITXTO=1
C ZERO OUTPUT RECORD AGAIN.
124	DO 126 I95=1,512
	OLINE(I95)=0
126	CONTINUE
C	WHEN DONE WRITING THIS RECORD, GO TRY FOR MORE.
C CONTINUE TO USE BUFFER UNLESS WE REACHED END FILE ON LAST WRITE
	IF (ITXTI.GT.NREAD.AND.NFILBY.LE.0)GOTO 128
	GO TO 118
128	CALL CLOSE(3)
C GO TRY ANOTHER FILE TILL EOF
C FIRST BE SURE WE DON'T HAVE DATA LEFT IN THIS RECORD.	
	IF(ILSTBK.EQ.0)GOTO 114
C MOVE DATA UP BY (ILSTBK/IGRN) * IGRN BYTES
C AND ADJUST NREAD TO WHAT WAS LEFT.
	NREAD=IGRN*(ILSTBK/IGRN)
	KBFCT=NFILB2/IGRN
	LSTART=IGRN*KBFCT-NREAD
C LSTART,NREAD ARE START, SIZE OF AREA TO MOVE
	L00=LSTART
	DO 6569 IV=1,NREAD
	L00=L00+1
	LLINE(IV)=LLINE(L00)
6569	CONTINUE
C NOW WHOLE AREA IS MOVED UP SO THAT WE APPEAR TO HAVE READ IN A
C "SHORT" TAPE RECORD AND HAVE UPDATED NREAD TO THE RECORD.
C  TO FIX UP FOR OTHER BLOCK SIZES WE NEED ONLY UPDATE
C  IGRN, WHICH MUST BE 1 AT LEAST. HOWEVER, ONE EXPECTS
C  THAT IT WILL BE 512. OR MAYBE 1024. OR 2048. FOR OTHER FLAVORS
C  OF UNIX. (PROBABLY CORRESPONDS TO DISK BLOCK SIZE).
C ALSO FIX UP NFILB2 TO NEW LENGTH AND SET NREAD UP ALSO AS AMOUNT
C LEFT IN BUFFER.
	NFILB2=NREAD
	GO TO 6567
5020	CALL CLOSE(4)
	CALL CLOSE(3)
	CALL CLOSE(2)
	GO TO 188
130	CONTINUE

	IF (ICMD.NE.'W') GO TO 150
C	WRITE PDP11 FILE FROM TAPE FILE. USER GIVES NAME.
	IRECCT=0
132	CALL FFINTG(IPTRS,IBKFAC)
	IF (IBKFAC.LT.1)IBKFAC=1
	IF (IBKFAC.GT.120)IBKFAC=120
C ALLOW FOR CASE OF LONG RECORDS BY HAND HERE. CRUDE SOLUTION ONLY!
	IF ((IBKFAC*KSZ).GT.10400)WRITE(6,134)KSZ
134	FORMAT(' ** BLOCK FACTOR TOO LONG FOR RECORD SIZE ',I4)
	IF ((IBKFAC*KSZ).GT.10400)IBKFAC=10400/KSZ
	CALL GETCML(LINE,3HINP,MCRSZ,72)
	LINE(MCRSZ+1,1)=0
C	CALL ASSIGN(3,LINE,MCRSZ)
	OPEN (UNIT=3,TYPE='NEW',CARRIAGECONTROL='LIST',DISPOSE='SAVE',
     1  RECORDSIZE=180,
     2  NAME=LINE,INITIALSIZE=10,EXTENDSIZE=12)
136	CONTINUE
	CALL BCLR(LINE,5200)
	CALL MREAD(LINE,10500,NREAD,MFLAG)
	IF (MVBIT.NE.0)CALL BITSWP(LINE,NREAD)
	CALL ERFLG(MFLAG,MFLAG)
	IF (MFLAG.EQ.6.OR.MFLAG.EQ.1.OR.MFLAG.EQ.3.OR.MFLAG.EQ.2)GOTO 146
C	TRANSLATE EBCDIC TO ASCII
	IRECCT=IRECCT+1
	KTMP=IBKFAC*KSZ
	IF (IEBFLG.NE.0)CALL EA(LINE(1,1),LINE(1,1),KTMP)
	IF (IBCDFG.NE.0)CALL BCDASC(LINE(1,1),KTMP)
	DO 144 ICNT=1,IBKFAC
C FIND END OF RECORD AND CHOP OFF TRAILING SPACES.
C CHOP OFF TRAILING WHITESPACE REGARDLESS...
	IWW=KSZ
CD	IF(KSZ.NE.80)GOTO 140
	KQ1=KSZ-2
	KQ2=KSZ+1
	DO 138 IW=1,KQ1
	IWW=KQ2-IW
	IF (LINE(IWW,ICNT).NE.32) GOTO 140
138	CONTINUE
140	CONTINUE
	KTMP=KSZ*(ICNT-1)+1
	KTMP2=KTMP+KSZ-1
CD	IF(KSZ.EQ.80)KTMP2=KTMP+IWW-1
	KTMP2=KTMP+IWW-1
	WRITE(3,142)(LLN(III),III=KTMP,KTMP2)
142	FORMAT(180A1)
144	CONTINUE
	IF (MULTRC.EQ.0) GO TO 146
C	SINGLE INPUT IF UNIT MODE SELECTED.
	GO TO 136
146	CONTINUE
	WRITE(6,148)IRECCT
148	FORMAT(' TPP-- ',I10,' RECORDS PROCESSED')
	CLOSE(UNIT=3)
C	CALL CLOSE(3)
	GO TO 188
150	CONTINUE
	IF (ICMD.NE.'C') GO TO 170
C	COPY FILE. GET PDP11 FILE SPECS FIRST.
	IRECCT=0
152	CONTINUE
	CALL FFINTG(IPTRS,IBKFAC)
	IF (IBKFAC.LT.1)IBKFAC=1
	IF (IBKFAC.GT.120)IBKFAC=120
	CALL GETCML(LINE,3HWRT,MCRSZ,72)
C	READ IN FILE SPECS.
	CALL ASSIGN(3,LINE,MCRSZ)
	CALL FDBSET(3,'READONLY','SHARE')
C	SET UP ONLY READ ACCESS NEEDED FOR FILE.
C	WRITE 1ST RECORD=FILE NAME SPECS
C	*********
C	GO TO 110
154	CONTINUE
	isb=1
	DO 160 ICNT=1,IBKFAC
	lsb=isb+ksz-1
	READ(3,156,END=162,ERR=166)(lln(kkkk),kkkk=isb,lsb)
156	FORMAT(2(132a1:))
158	CONTINUE
C	TRANSLATE ASCII TO EBCDIC
	IF (IEBFLG.NE.0)CALL AE(LINE(1,ICNT),lln(isb),ksz)
	isb=isb+ksz
160	CONTINUE
	IRECCT=IRECCT+1
	CALL MWRITE(LINE,ksz*IBKFAC,NFLAG)
	CALL ERFLG(NFLAG,NFLAG)
	IF (NFLAG.EQ.3.OR.NFLAG.EQ.6) GO TO 166
	GO TO 154
162	CONTINUE
	WRITE(6,148)IRECCT
	IF (IBKFAC.EQ.1) GO TO 164
	CALL MWRITE(LINE,80*IBKFAC,NFLAG)
	CALL ERFLG(NFLAG,NFLAG)
164	CONTINUE
C	READ TO END-OF-FILE
C	WRITE 2 EOF ON TAPE AND BACKSPACE OVER ONE OF THEM.
	CALL MEOF(2)
	CALL MSKIPR(-1)
C	THAT DOES IT.
	CALL CLOSE(3)
	GO TO 188
166	CONTINUE
	WRITE (6,168)
168	FORMAT(' TPP--WRITE ERROR FOR SOME REASON--OPERATION ABORTED.')
	CALL CLOSE(3)
	GO TO 188
170	CONTINUE
	IF (ICMD.NE.'R') GO TO 172
C	REWIND TAPE
	CALL MREWIN
	GO TO 178
172	CONTINUE
	IF (ICMD.NE.'E') GO TO 174
C	WRITE AN EOF ON TAPE
	CALL MEOF(1)
	GO TO 178
174	CONTINUE
	IF (ICMD.NE.'S') GO TO 176
C	SKIP RECORDS. GET RECORD COUNT FROM STRING
	CALL FFINTG(IPTRS,NRECS)
	CALL MSKIPR(NRECS)
	GO TO 178
176	IF (ICMD.NE.'F') GO TO 184
C	SKIP FILES. GET FILE COUNT FROM STRING.
	CALL FFINTG(IPTRS,NRECS)
	CALL MSKIPF(NRECS)
178	CONTINUE
C	HERE HAVE DONE A TAPE I/O OP. TEST STATUS.
	CALL MSTAT(JERR)
C	DECODE ERRORS
	CALL ERFLG(JERR,JERR)
	IF (JERR.LE.0) GO TO 184
	IF (JERR.EQ.6) WRITE (6,182)IUNIT
	IF (JERR.NE.6) WRITE (6,180)IUNIT
180	FORMAT(' TPP -- I/O ERROR ON UNIT MT',I1,': -OPERATION ABORTED')
182	FORMAT(' TPP -- TAPE UNIT MT',I1,': UNMOUNTED')
184	CONTINUE
CD	WRITE (6,186)JJJJ,IUNIT,NRECS
CD186	FORMAT(' ICMD=',A2,' IUNIT= ',I4,'NRECS= ',I4 )
188	GO TO 20
	END
	INTEGER*4 FUNCTION IVAL(LIADDR)
	INTEGER*4 IACC,IWRK,I10
	BYTE LIADDR(12)
C I10 IS RADIX.
	DATA I10/8/
C COMPUTE A NUMBER IN OCTAL
	IACC=0
	KSW=0
	DO 1000 N1000=1,12
	II=0
C MASK TO 7 BIT ASCII
	II=LIADDR(N1000).AND.127
C CHECK LEGAL NUMERIC RANGE CHARS
	IF(II.GE.48.AND.II.LT.58)GOTO 1001
C IGNORE LEADING NON NUMERICS BUT END ON TRAILING ONES
	IF(KSW.NE.0)GOTO 1002
	IWRK=0
	GOTO 1000
1001	IWRK=II-48
	IACC=IACC*I10+IWRK
	KSW=1
1000	CONTINUE
1002	IVAL=IACC
	RETURN
	END
	INTEGER*4 FUNCTION IVAL(LIADDR)
	INTEGER*4 IACC,IWRK,I10
	BYTE LIADDR(12)
C I10 IS RADIX.
	DATA I10/8/
C COMPUTE A NUMBER IN OCTAL
	IACC=0
	KSW=0
	DO 1000 N1000=1,12
	II=0
C MASK TO 7 BIT ASCII
	II=LIADDR(N1000).AND.127
C CHECK LEGAL NUMERIC RANGE CHARS
	IF(II.GE.48.AND.II.LT.58)GOTO 1001
C IGNORE LEADING NON NUMERICS BUT END ON TRAILING ONES
	I
