1 ! ! M A G I N T 2! Program: MAGINT 3! Version: V02A 4! Edit: 03 7! Edit Date: 13-Aug-80 9! Author: Brant Cheikes 15 EXTEND ! This program operates in BASIC-PLUS EXTEND mode for long ! variable names 20 ! & & & ! M o d i f i c a t i o n H i s t o r y & & & ! Version/Edit Edit Date Reason & 21! V01A-01 07-Mar-80 New release & ! V01A-02 10-Mar-80 Patches to EOF handler & ! V01A-03 15-Mar-80 Squash various bugs that & ! were throughout the program & ! V01B-01 21-Mar-80 Prevent transferral of compiled & ! files; add functionality to & ! recover from flag header mis- & ! interpretations; add thorough & ! documentation & ! V01C-01 04-May-80 Allow variable record lengths & ! V02A-01 19-May-80 Update to RSTS/E V7.0 & ! V02A-02 23-Jun-80 Fix memory usage problems & ! V02A-03 13-Aug-80 Fix overlength line checking & & 50 ! & & & ! P r o g r a m D e s c r i p t i o n & & & 60 ! MAGINT is designed to exchange files between magtape and disk & ! in both directions. It handles all required and optional code & ! conversions as specified by the operator in the user dialogue & ! section. & ! & ! This program is designed for use by privileged users though it & ! can also be used by non-privileged users (with a little less & ! functionality). & 500 ! & & & ! V a r i a b l e D e s c r i p t i o n & & & ! Variable Usage & ! -------- ----- & 510 ! ASCII.TO.EBCDIC$ XLATE table string for ASCII to EBCDIC & ! code conversion & ! & ! ASCII.TO.EBCDIC% ASCII to EBCDIC code conversion flag & ! & ! ASCII.TO.EBCDIC%(256%) Code conversion data matrix & ! & ! ASSIGN.TAPE$ Dummy variable for ASSIGN dev: SYS call & ! & ! B% Temporary blocking factor & ! & ! BEEP$ Holds 3 beeps for prompting & ! & ! BLOCKING% Blocking factor for tape (1-20) & ! & ! BUF.SIZ% Holds size of magtape buffer; always & ! 80% * BLOCKING% & ! & ! BUFFER$ Magtape buffer variable & ! 520 ! CNT% Wildcard PPN lookup SYS call index & ! & ! COUNTER% Counter of files transferred & ! & ! COUNTR% Counter of wildcard lookup matches & ! & ! CTRL.C.TRAP$ Ctrl/C enable SYS call string & ! & ! D% Holds internal density value & ! & ! DEFAULT$ Default answers to FNYES.OR.NO% & ! & ! DENSITY% Density value input by user & ! & ! DIR% Do tape directory flag & ! & ! DIR.LU$ CHANGE statement return string & ! & ! DIR.LU%(30%) Directory lookup data matrix & ! & ! DISK.TO.TAPE% Disk to tape processing flag & ! & ! DO.DIR% Flags that a tape directory was & ! requested & ! & ! DUMMY$ Dummy string variable & ! & ! DUMMY% Dummy integer variable & ! 530 ! E% 1600 BPI phase encoded mode value for & ! MAGTAPE system call & ! & ! E1% Holds ERL & ! & ! EBCDIC.TO.ASCII$ XLATE table string for EBCDIC to ASCII & ! code conversion & ! & ! EBCDIC.TO.ASCII% EBCDIC to ASCII conversion flag & ! & ! EBCDIC.TO.ASCII%(256%) Data table matrix for EBCDIC to ASCII & ! code conversion information & ! & ! EOF% End-of-file flag & ! & ! EXT$ Default file extension & ! & ! F.IN$ Input filespec string & ! & ! FIL$ Holds filenames in directory subroutine & ! and in FNFIP$ & ! & ! FIL.IN$ Another input filename string - user & ! entered & ! & ! FIL.OUT$ Output filename string & ! & ! FILES% Counter of files on tape & ! & ! FIRST.RUN% Signals a first run entry & ! & ! FLAG$ Holds user-specified flag header & ! & ! FLAG% 'Flag' record tape flag & ! & ! FLAG1% First flag word returned by wildcard & ! directory lookup SYS call & ! & ! FLAG2% Second flag word & ! 540 ! I% Integer work variable & ! & ! INDEX% Directory lookup index - gets INDEX%+1% & ! filename that matches wildcard spec & ! & ! INFILES$ String of files to transfer from tape & ! to disk & ! & ! J% Loop work variable & ! 550 ! LOOP% Loop variable & ! & ! LOUPE% Another loop variable & ! & ! LP.ERROR% Line printer error flag & ! & ! LUPE% Yet another loop variable & ! & ! M% Holds output file OPEN mode value & ! & ! MORE$ Holds more input filespecs & ! & ! NEW.FIL$ Holds specification of new filename & ! on tape to disk transfer if desired & ! 560 ! OBEY.PPN% Obey PPN specifications flag & ! & ! OPN% File open flag & ! & ! OVERLENGTH$ Used for storing excess data & ! & ! OVR% Overlength line processing flag & ! & ! P% MAGTAPE parity value & ! & ! P1% Project number & ! & ! P2% Programmer number & ! & ! PARITY$ User-specified parity setting & ! & ! PAUSE% Pause/query between files flag & ! & ! POSITION% Holds position of the print head & ! & ! POSTN% Columnar value of next tab stop & ! & ! PPN.LU$ Variable for CHANGE return to & ! execute PPN lookup SYS call & ! & ! PRINTER$ Dummy string variable for printing & ! of filenames in directory subroutine & ! & ! PROG% Holds a programmer number & ! & ! PROJ% Holds a project number & ! 570 ! QUERY$ Holds answers to YES/NO questions & ! & ! RECS% Counter of number of records in a file & ! & ! REC.LEN% Record length for file & ! & ! RESPONSE$ Holds CVT$$'d answer to Y/N questions & ! & ! RESULT$ Holds result of code conversions & ! & ! S$ SYS call dummy variable & ! & ! S% STAY flag for MAGTAPE call & ! & ! SAVE.NULLS% Preserve null characters flag & ! & ! SECT$ Holds one logical record of tape & ! & ! SELECTIVE% Selective file transferral flag & ! & ! SET.TAPE% Dummy variable for MAGTAPE set tape & ! characteristics call & ! & ! START% Loop start point for buffer storage & ! & ! STATS% Holds MAGTAPE status word & ! & ! SUPERSEDE% Supersede output file flag & ! 580 ! TB.TO.SP% Tab to space conversion flag & ! & ! TB.TO.SP%(17%) Matrix holding tab stop information & ! & ! TEMP$ Holds data temporarily & ! & ! TEMP.FIL$ Temporarily holds a filename string & ! & ! TEXT$ Holds data to output to file & ! & ! TOTL% Holds total number of records on tape & ! 590 ! V$ Holds MAGINT's version/edit level & ! & ! V% Integer work variable & ! & ! WIDTH% Holds terminal width & ! & ! WILD.NAME% Wildcard filename flag & ! & ! WILD.PPN% Wildcard PPN flag & ! & ! X$ Dummy string variable & ! & ! Y% Dummy integer work variable - mount & ! tape flag & 600 ! & & & ! F u n c t i o n D e s c r i p t i o n & & & 610 ! FNCONVERT$(DUMMY$) This function performs all conversions & ! on DUMMY$ as requested in the user & ! dialogue section. Code conversions are & ! done, as well as tab to space conversions. FNCONVERT$ does all & ! the necessary formatting of DUMMY$ for output to either disk & ! or tape. & ! & ! & ! FNFIP$ This function processes the filename string & ! F.IN$. It performs all directory lookups & ! and filename verification, returning one & ! validated filename with each call. It is used during disk & ! to tape processing to process the user's filespec string. & ! FNFIP$ uses the filename string scan and the directory lookup & ! SYS calls. & ! & ! & ! FNP$(X$) This function prints X$ in columns for the & ! tape directory subroutine. & ! & ! & ! FNS$(DUMMY%) This function looks at DUMMY%, and if it is & ! not equal to 1%, FNS$ is returned as an 's', & ! else FNS$ is returned as a null. This is used & ! to add an 's' after sentences where, for example, more than 1 & ! file was transferred. & ! & ! & ! FNYES.OR.NO%(DEFAULT$) This function examines QUERY$, comparing & ! it against YES or NO. It returns a & ! -1% if YES or the default (as specified & ! by DEFAULT$) was used, or 0% if NO was entered. & ! & 700 ! & & & ! V a r i a b l e I n i t i a l i z a t i o n & & & 720 FIRST.RUN% = -1% & ! Set up the first run entry flag & 740 BEEP$ = CHR$(7%)+CHR$(7%)+CHR$(7%) & ! Set up a beep string for prompts & 900 ! & & & ! D i m e n s i o n S t a t e m e n t s & & & 910 DIM ASCII.TO.EBCDIC%(256%),EBCDIC.TO.ASCII%(256%),TB.TO.SP%(17%) & ! Dimension conversion matrices & 920 DIM DIR.LU%(30%) & ! Dimension directory lookup information holding matrix & 1000 ! & & & ! M a i n P r o g r a m C o d i n g & & & 1010 V$ = "V02A-03" & ! Set up version/edit level & 1020 ON ERROR GOTO 30000 & \ PRINT & \ PRINT "MAGINT "+V$+" "+ & CVT$$(RIGHT(SYS(CHR$(6%)+CHR$(9%)),3%),4%) & \ PRINT "Magtape Interchange Program" & \ PRINT & ! Set up standard error trap; output the system header & 1030 OPEN 'KB:MAGINT.CMD' FOR INPUT AS FILE 1% & \ CTRL.C.TRAP$ = SYS(CHR$(6%)+CHR$(-7%)) & ! Open keyboard for dialogue; set CTRL/C trapping & 1040 ASSIGN.TAPE$ = SYS(CHR$(6%)+CHR$(10%)+STRING$(20%,0%)+ & "MM"+CHR$(0%)+CHR$(255%)) & \ GOSUB 31000 & ! Try to assign MM0: to the current job; abort if not possible & ! Go initialize data & 1045 ! & & & ! B e g i n U s e r D i a l o g u e & & & 1050 INPUT "Will this be a disk to tape transfer? ";QUERY$ & \ DISK.TO.TAPE% = FNYES.OR.NO%("YES") & \ GOTO 1050 IF DISK.TO.TAPE% = 2% & ! Get the transfer mode & 1060 GOTO 1070 UNLESS DISK.TO.TAPE% & \ INPUT "ASCII to EBCDIC conversion on transfer? ";QUERY$ & \ ASCII.TO.EBCDIC% = FNYES.OR.NO%("YES") & \ GOTO 1060 IF ASCII.TO.EBCDIC% = 2% & \ GOTO 1080 & ! Determine what character conversion to be done if any & 1070 INPUT "EBCDIC to ASCII conversion on transfer? ";QUERY$ & \ EBCDIC.TO.ASCII% = FNYES.OR.NO%("YES") & \ GOTO 1070 IF EBCDIC.TO.ASCII% = 2% & ! Get conversion to be done & 1080 INPUT "Preserve null characters? ";QUERY$ & \ SAVE.NULLS% = FNYES.OR.NO%("NO") & \ GOTO 1080 IF SAVE.NULLS% = 2% & ! Determine if null (CHR$(0%)) characters are to be preserved & 1085 INPUT "Record length? <80> ";REC.LEN% & \ REC.LEN% = 80% UNLESS REC.LEN% & \ IF REC.LEN% < 14% THEN PRINT & "Record length must be greater than 14 bytes" & \ PRINT & \ GOTO 1085 & ! Get the size of each logical record on tape & 1090 INPUT "Enter blocking factor for tape (1-20) <20> ";BLOCKING% & \ BLOCKING% = INT(BLOCKING%) & \ BLOCKING% = 20% UNLESS BLOCKING% & \ IF BLOCKING% < 1% OR BLOCKING% > 20% THEN PRINT & "Blocking factor must be an integer from 1 to 20" & \ PRINT & \ GOTO 1090 & ! Get the blocking factor & 1093 BUF.SIZ% = REC.LEN% * BLOCKING% & \ GOTO 2000 IF DISK.TO.TAPE% & ! Set up buffer size as a variable; skip next query if & ! MAGINT is outputting to tape rather than disk & 1095 INPUT "Supersede existing output files? ";QUERY$ & \ SUPERSEDE% = FNYES.OR.NO%("NO") & \ GOTO 1095 IF SUPERSEDE% = 2% & \ M% = 2% & \ GOTO 2050 UNLESS SUPERSEDE% & \ M% = 0% & \ GOTO 2050 & ! Ask whether output files that already exist are to be zapped & ! or appended to; M% holds the appropriate MODE value, 0% for & ! zap, or overwrite, and 2% for APPEND mode. Skip ahead to disk & ! to tape dialogue section & 2000 GOTO 2020 IF REC.LEN% > 132% & \ INPUT "Convert tabs to spaces? ";QUERY$ & \ TB.TO.SP% = FNYES.OR.NO%("YES") & \ GOTO 2000 IF TB.TO.SP% = 2% & ! Skip this query if records are longer than maximum line width & ! Check whether to convert tabs to spaces & 2020 INPUT "Write 'flag' records? ";QUERY$ & \ FLAG% = FNYES.OR.NO%("YES") & \ GOTO 2020 IF FLAG% = 2% & \ IF NOT FLAG% THEN 3000 & ! Check if the user would like to write flag records & 2030 IF FLAG% THEN PRINT \ PRINT & "Enter flag record header. Filename will follow the last character" & \ PRINT "The default flag record header is 'MAGINT TRANSFER FILE='" & 2035 INPUT LINE #1% FLAG$ & \ FLAG$ = CVT$$(FLAG$,4%) & \ FLAG$ = "MAGINT TRANSFER FILE=" UNLESS LEN(FLAG$) & \ GOTO 2040 IF LEN(FLAG$) > 60% & \ GOTO 3000 & ! Get the flag record header if necessary; when the record is output, & ! the output file name will follow the last character, i.e. a & ! header of 'FILE=' will be output with FILE= & ! If no header is entered, use the default & 2040 PRINT & \ PRINT "Flag record header is too long - limit is 60 characters" & \ PRINT "Please enter a new header" & \ GOTO 2035 & ! Check length of flag record header & 2050 INPUT "Does the tape have 'flag' records? ";QUERY$ & \ FLAG% = FNYES.OR.NO%("YES") & \ GOTO 2050 IF FLAG% = 2% & \ IF NOT FLAG% THEN 2200 & ! See if the tape has flag records & 2060 PRINT & \ PRINT "Enter the keyword which the filename follows " & \ INPUT #1% FLAG$ & \ FLAG$ = "FILE=" UNLESS LEN(FLAG$) & \ PRINT & ! If the tape has flag records, get the keyword to look for & 2070 INPUT "Obey output file PPN specifications? ";QUERY$ & \ OBEY.PPN% = FNYES.OR.NO%("NO") & \ GOTO 2070 IF OBEY.PPN% = 2% & ! See if output PPN specs are to be obeyed & 2075 INPUT "Pause/query between files? ";QUERY$ & \ PAUSE% = FNYES.OR.NO%("NO") & \ GOTO 2075 IF PAUSE% = 2% & ! See if the user would like to be prompted for a new filename & ! before flag file is opened & 2080 INPUT "Default output extension <.MAG> ";EXT$ & \ EXT$ = ".MAG" UNLESS LEN(EXT$) & \ EXT$ = '.' + EXT$ UNLESS INSTR(1%,EXT$,'.') & \ GOTO 3000 & ! In case a file specification on tape has no extension, use & ! a default specified by the user; MAGINT's default is '.MAG' & 2200 PRINT & \ PRINT "Tape is completely unlabelled" & \ PRINT & \ PRINT "To what file should the data be written"; & \ INPUT LINE FIL.OUT$ & \ FIL.OUT$ = CVT$$(FIL.OUT$,4%) & \ GOTO 2200 UNLESS LEN(FIL.OUT$) & ! Tape has no labels whatsoever, therefore it is a string of data & ! Get the file to dump all that data to. & 3000 ! & & & ! T a p e M o u n t i n g S e c t i o n & & & 3005 PRINT & \ PRINT & \ PRINT "*** Tape Mounting Section ***" & \ PRINT & ! Tell the user what he is about to undergo & 3010 OPEN 'MM0:' AS FILE 2%, RECORDSIZE BUF.SIZ%+32767%+1%,MODE 12% & \ GOSUB 10000 & ! Try to open the tape; if the OPEN succeeds, a tape is mounted & ! Go handle such an occurrence & 3020 GET #2% & \ STATS% = MAGTAPE(7%,0%,2%) & ! Try to get tape characteristics & 3030 GOTO 3150 UNLESS DISK.TO.TAPE% & ! Dispatch to proper routine if we are transferring FROM tape & 3040 PRINT & \ PRINT "Parameter","Present Setting","New Setting?" & \ PRINT & ! Print the tape mounting header & 3050 PRINT "Density", & \ IF (STATS% AND 8%) AND (((STATS% AND 24576%)/8192%)=0%) & THEN E% = 256% & \ D%, P%, S% = 0% & \ PRINT "1600 BPI",, & \ GOTO 3070 & ! Check density statistics; if 1600 BPI, then print it & 3060 D% = 3% & \ E%, P%, S% = 0% & \ PRINT "800 BPI",, & ! Print the correct setting & 3070 INPUT DENSITY% & \ GOTO 3090 IF DENSITY% = 0% & \ IF DENSITY% <> 800% AND DENSITY% <> 1600% THEN PRINT & "Valid densities are either 800 or 1600 - please re-enter" & \ PRINT & \ GOTO 3050 & ! Get the new setting if any & 3080 IF DENSITY% = 800% THEN D% = 3% ELSE E% = 256% & ! Set the density flag & 3090 PRINT "Parity", & \ IF (STATS% AND 2048%) THEN P% = 1% & \ PRINT "Even",, & \ GOTO 3110 & ! Show parity setting if Even & 3100 P% = 0% & \ PRINT "Odd",, & ! Tell user parity is set to ODD & 3110 INPUT PARITY$ & \ PARITY$ = LEFT(PARITY$,1%) & \ GOTO 3130 UNLESS LEN(PARITY$) & \ IF PARITY$ <> "O" AND PARITY$ <> "E" THEN PRINT & "Valid parities are either [O]dd or [E]ven - please re-enter" & \ PRINT & \ GOTO 3090 & ! Get new parity setting & 3120 IF PARITY$ = "O" THEN P% = 0% ELSE P% = 1% & ! Set proper parity flag & 3130 ! & & & ! S e t T a p e C h a r a c t e r i s t i c s & & & 3140 SET.TAPE% = MAGTAPE(6%,E%+(D%*4%)+P%+S%,2%) & \ PRINT & \ PRINT "*** The tape is now mounted and on-line ***" & \ PRINT & \ GOTO 6000 IF DISK.TO.TAPE% & \ GOTO 4000 & ! Set tape characteristics; notify user we are ready to go; go! & 3150 ! & & & ! S e t I n p u t T a p e C h a r a c t e r i s t i c s & & & 3160 PRINT "Tape density is "; & \ IF (STATS% AND 8%) AND (((STATS% AND 24576%)/8192%)=0%) & THEN E% = 256% & \ D%, P%, S% = 0% & \ PRINT "1600 BPI "; & \ GOTO 3180 & ! Print the header and check if the tape is 1600 BPI; say so if it & ! is so. & 3170 PRINT "800 BPI "; & \ D% = 3% & \ E%, P%, S% = 0% & ! It's not 1600 BPI therefore it must be 800; notify and set the & ! variables as such & 3180 PRINT "with "; & \ IF (STATS% AND 2048%) THEN P% = 1% & \ PRINT "EVEN "; & \ GOTO 3200 & ! Print secondary header and say even parity if even & 3190 PRINT "ODD "; & \ P% = 0% & ! It's odd, so say so and set the variable & 3200 PRINT "parity." & \ GOTO 3130 & ! Print the end of the sentence & 4000 ! & & & ! T a p e T o D i s k P r o c e s s i n g & & & 4010 IF FLAG% THEN GOSUB 12000 & ! If we are dealing with a tape that has flag records, go to & ! the tape directory subroutine & 4020 PRINT & \ PRINT "Processing Log",TIME$(0%);DATE$(0%) & \ PRINT & \ I% = MAGTAPE(3%,0%,2%) & \ OPN% = 0% & \ COUNTER% = 0% & \ RECS% = 0% & \ TOTL% = 0% & ! Print the processing header; rewind tape; reset important variables & 4030 FIELD #2%, BUF.SIZ% AS BUFFER$ & ! Field the buffer & 4040 LSET BUFFER$ = STRING$(BUF.SIZ%,0%) & \ GET #2% & \ RECS% = RECS% + 1% & \ EOF% = 0% & ! Null out buffer & ! Get a buffer full of data; increment the record counter; & ! reset the EOF flag to indicate a sucessful read & 4045 FOR LOOP% = 1% TO BLOCKING% & 4050 SECT$ = MID(BUFFER$,((LOOP%-1%)*REC.LEN%)+1%,REC.LEN%) & \ GOTO 4060 & ! Slice out a record from the block and put it in SECT$ & 4055 GOTO 4040 IF NOT EOF% UNLESS LEN(BUFFER$) <> (LOOP% * REC.LEN%) & \ GOTO 14200 IF EOF% UNLESS LEN(BUFFER$) <> (LOOP% * REC.LEN%) & \ NEXT LOOP% & \ GOTO 4040 & ! If we have digested the buffer and no EOF was detected, go get & ! a new bufferful of data; if EOF detected and buffer digested, & ! return to EOF handler routine; if buffer partially digested, & ! try to slice out more data; when loop falls through, go suck & ! in some more data & 4060 TEXT$ = FNCONVERT$(SECT$) & \ GOTO 4090 UNLESS FLAG% & \ I% = INSTR(1%,TEXT$,FLAG$) & \ GOTO 4090 UNLESS I% IF OPN% & \ GOTO 4055 UNLESS I% & \ GOTO 4062 UNLESS OPN% & \ CLOSE #3% & \ OPN% = 0% & \ COUNTER% = COUNTER% + 1% & \ PRINT "File";COUNTER%;"transferred to ";FIL.OUT$;" -";RECS%; & "block";FNS$(RECS%);" long" & \ TOTL% = TOTL% + RECS% & \ RECS% = 0% & \ TEMP.FIL$ = FIL.OUT$ & ! Do conversions and put result into TEXT$; go write data to file & ! unless we are looking for flag records; look within string for & ! a flag record header; if no header and a file is open, go write & ! data to file; if no header and no open output file, continue & ! looking for a flag record header label; if previous tests fail, a & ! file is open and we found a flag record, so close the open file, & ! log the transfer, and do incrementing & ! Store the last opened file in a temporary variable & 4062 FIL.OUT$ = RIGHT(TEXT$,I%+LEN(FLAG$)) & \ FIL.OUT$ = FIL.OUT$ + EXT$ UNLESS INSTR(1%,FIL.OUT$,'.') & ! Set up the new filename; add an extension if none & 4065 GOTO 12140 IF SELECTIVE% & ! Go to the proper routine if we are being selective in our tape & ! to disk transferral by flag record & 4070 GOTO 4080 IF OBEY.PPN% & \ CHANGE SYS(CHR$(6%)+CHR$(-10%)+FIL.OUT$) TO DIR.LU% & \ FIL.OUT$ = RAD$(DIR.LU%(7%)+SWAP%(DIR.LU%(8%)))+ & RAD$(DIR.LU%(9%)+SWAP%(DIR.LU%(10%)))+'.'+ & RAD$(DIR.LU%(11%)+SWAP%(DIR.LU%(12%))) & ! Skip this routine if we are to obey any output PPN specs else & ! re-form the file name using a filename string scan omitting any & ! PPN specification & 4080 GOTO 4085 UNLESS PAUSE% & \ PRINT & \ PRINT BEEP$; & \ PRINT "Output filename is ";FIL.OUT$;". New filename"; & \ INPUT LINE NEW.FIL$ & \ NEW.FIL$ = CVT$$(NEW.FIL$,4%) & \ PRINT & \ FIL.OUT$ = NEW.FIL$ IF LEN(NEW.FIL$) & \ GOTO 4600 IF FIL.OUT$ = "CONTINUE" UNLESS M% & \ IF FIL.OUT$ = "CONTINUE" THEN FIL.OUT$ = TEMP.FIL$ & \ GOTO 4100 & ! If the user wants to be prompted, then prompt with a few & ! dings, print old filename and ask for a new one; a RETURN & ! keeps the present filename; if user types CONTINUE, indicating & ! that a header was misinterpreted, set new filename to last & ! filename and print the misinterpreted flag record to the output & ! file; for this function to work; we must not be superseding & ! existing output files; prevent user from entering 'CONTINUE' if & ! output files are being superseded & 4085 OPEN FIL.OUT$ AS FILE 3%, MODE M% & \ OPN% = -1% & \ GOTO 4055 & ! Open the file; set the file open flag; go get another record & 4090 GOTO 4500 IF OPN% & \ GOTO 4100 IF LEN(FIL.OUT$) & \ PRINT & \ PRINT "To what file should further data be written"; & \ INPUT LINE FIL.OUT$ & \ FIL.OUT$ = CVT$$(FIL.OUT$,4%) & ! Go write text if a file is open; go open file if we have a filename & ! and no file is open; else get a filename & 4100 OPEN FIL.OUT$ AS FILE 3%, MODE M% & \ OPN% = -1% & ! Open the file; set file open flag & 4500 PRINT #3% CHR$(0%); IF LP.ERROR% & \ PRINT "Continuing..." IF LP.ERROR% & \ PRINT IF LP.ERROR% & \ LP.ERROR% = 0% & \ PRINT #3% TEXT$; & \ GOTO 4055 & ! If lineprinter error, print a null to see if printer is ready; & ! print the text; reset error flag & 4600 PRINT "% 'CONTINUE' option unavailable with supersede" & \ GOTO 4080 & ! If output files are being superseded and 'CONTINUE' option was & ! specified, tell user he can't do dat; go reprompt & 6000 ! & & & ! D i s k T o T a p e P r o c e s s i n g & & & 6010 PRINT "Input from: "; & \ INPUT LINE #1% F.IN$ & \ COUNTER% = 0% & \ RECS% = 0% & \ TOTL% = 0% & ! Get the input file(s) & ! Reset our counter of files processed & ! Reset our other counters & 6020 I% = INSTR(1%,F.IN$,"/M") & \ IF I% THEN PRINT "More> "; & \ INPUT LINE #1% MORE$ & \ F.IN$ = LEFT(F.IN$,I%-1%) + ";" + MORE$ & \ GOTO 6020 & ! See if the user has more filespecs to enter (/M switch used); if & ! so, print "More> " bit and get more; see if /M switch used again & 6025 PRINT & \ PRINT & \ PRINT "Processing Log",TIME$(0%);DATE$(0%) & \ PRINT & \ F.IN$ = CVT$$(F.IN$,4%) & \ IF FIRST.RUN% THEN I% = MAGTAPE(3%,0%,2%) & \ FIRST.RUN% = 0% & \ FIELD #2%, BUF.SIZ% AS BUFFER$ & ! Output a header for a log of all MAGINT processing; rewind the & ! tape if this is the first run; field the buffer & 6030 FIL.IN$ = FNFIP$ & \ OPEN FIL.IN$ FOR INPUT AS FILE 3%,MODE 8192% & \ GOTO 6300 IF ASCII(MID(SYS(CHR$(12%)),22%,1%)) AND 64% & \ LSET BUFFER$ = STRING$(BUF.SIZ%,0%) & \ GOSUB 18000 & ! Process the command line; get a file and open it; don't allow & ! processing to continue if the file is compiled (check to see if & ! the 64% bit of the protection code is set); null out buffer & ! and go label the tape if necessary & 6040 FOR LOOP% = START% TO BLOCKING% & ! Start I/O transferral loop & 6050 INPUT LINE #3% TEXT$ UNLESS OVR% & \ LSET BUFFER$ = LEFT(BUFFER$,(LOOP%-1%)*REC.LEN%)+FNCONVERT$(TEXT$) & \ NEXT LOOP% & ! Get a line from the file unless the last line was overlength; & ! pass the line to FNCONVERT for conversion processing; add new & ! converted string to the output buffer; continue loop or fall thru & 6060 PUT #2%, COUNT BUF.SIZ% & \ RECS% = RECS% + 1% & ! Do the full buffer output & 6070 START% = 1% & \ LSET BUFFER$ = STRING$(BUF.SIZ%,0%) & \ GOTO 6040 & ! Start a new loop when the old one falls thru; null out buffer & 6080 PUT #2%,COUNT (REC.LEN% * (LOOP% - 1%)) UNLESS LOOP% = 1% & \ CLOSE #3% & \ RECS% = RECS% + 1% UNLESS LOOP% = 1% & \ COUNTER% = COUNTER% + 1% & \ PRINT FIL.IN$;" transferred to tape -";RECS%;"block";FNS$(RECS%); & " used" & \ TOTL% = TOTL% + RECS% & \ RECS% = 0% & ! Print what's left in the buffer to the tape; close the input file & ! Tell user that the file was transferred & 6200 GOTO 6030 & ! Go get another file to process & 6300 PRINT "? ";FIL.IN$;" is an executable image - unable to transfer"+ & " - ignored" & \ PRINT & \ CLOSE #3% & \ GOTO 6030 & ! Print an error message if file for transfer is a compiled file & 8000 ! & & & ! H a n d l e B a d B l o c k i n g F a c t o r s & & & 8010 PRINT & \ PRINT BEEP$; & \ PRINT "Blocking factor of";BLOCKING%;"is too small" & \ PRINT & ! Tell user the blocking factor he entered is too small, i.e. the & ! block length on the tape is larger than his blocking factor * & ! the record length & 8015 IF ERL = 12030% THEN DO.DIR% = -1% ELSE DO.DIR% = 0% & ! Set flag indicating where processing is to resume & 8020 INPUT "Enter new blocking factor? <20> ";B% & \ B% = 20% UNLESS B% & \ GOTO 8010 IF B% <= BLOCKING% & \ BLOCKING% = B% & \ BUF.SIZ% = REC.LEN% * BLOCKING% & \ Y% = 0% & \ CLOSE #2% & \ GOSUB 10040 & \ SET.TAPE% = MAGTAPE(6%,E%+(D%*4%)+P%+S%,2%) & ! Get new blocking factor; if new one is less than old one, reprint & ! the old message and try again else set up new buffer size; go for & ! an open, set tape characteristics and resume & 8030 PRINT & \ GOTO 12000 IF DO.DIR% & \ GOTO 4030 & ! Dispatch properly & 10000 ! & & & ! S u b r o u t i n e s & & & ! T a p e M o u n t i n g & & 10010 PRINT & 10020 INPUT "Is the tape presently mounted the one you wish to use";QUERY$ & \ Y% = FNYES.OR.NO%("YES") & \ GOTO 10020 IF Y% = 2% & \ PRINT & ! A tape is mounted - see if it's the right one & 10030 IF NOT Y% THEN PRINT & \ PRINT "Please mount the tape with the write enable ring "; & \ PRINT "IN" IF DISK.TO.TAPE% & \ PRINT "OUT" IF NOT DISK.TO.TAPE% & \ PRINT & \ PRINT "Type RETURN to continue" & \ CLOSE #2% & \ GET & ! Tell user to go mount the correct tape & 10035 RESUME 10040 UNLESS Y% & ! Re-enable error trapping if necessary & 10040 IF NOT Y% THEN & OPEN 'MM0:' AS FILE 2%, RECORDSIZE BUF.SIZ%+32767%+1%,MODE 12% & ! Open the magtape & 10050 Y% = 0% & \ STATS% = MAGTAPE(7%,0%,2%) & \ IF (STATS% AND 1024%) <> 0% AND DISK.TO.TAPE% THEN PRINT & \ PRINT "? Write enable ring OUT - please re-mount tape ring IN" & \ PRINT & \ PRINT "Type RETURN to continue" & \ CLOSE #2% & \ GET & \ GOTO 10040 & ! If write locked on tape and we need write access, notify user, & ! have him remount the tape, and wait for a response & 10090 I% = MAGTAPE(3%,0%,2%) & \ RETURN & ! Rewind and return & 12000 ! & & & ! D o T a p e D i r e c t o r y & & & 12010 PRINT "Would you like a directory of the tape? "; & \ INPUT QUERY$ & \ DIR% = FNYES.OR.NO%("NO") & \ GOTO 12010 IF DIR% = 2% & \ GOTO 12120 UNLESS DIR% & ! Ask the user if he would like to know what files are on the & ! tape; this only works if the tape has 'flag' records & 12020 FILES% = 0% & \ RECS% = 0% & \ I% = MAGTAPE(3%,0%,2%) & \ CHANGE SYS(CHR$(6%)+CHR$(16%)+CHR$(0%)+CHR$(255%)) TO DIR.LU% & \ WIDTH% = DIR.LU%(5%)-1% & \ FIELD #2%, BUF.SIZ% AS BUFFER$ & \ LSET BUFFER$ = STRING$(BUF.SIZ%,0%) & \ ON ERROR GOTO 12100 & \ PRINT & ! Reset important counters; rewind the tape; put the terminal width & ! into WIDTH%; field the magtape and set a modular error trap & ! Null out our buffer & 12030 GET #2% & \ EOF% = 0% & \ RECS% = RECS% + 1% & ! Get a block from the tape; reset the EOF flag; increment the & ! record counter & 12040 FOR LOOP% = 1% TO BLOCKING% & ! Start the loop & 12050 SECT$ = MID(BUFFER$,((LOOP%-1%)*REC.LEN%)+1%,REC.LEN%) & \ GOTO 12070 & ! Cut a record out from within the block & 12060 NEXT LOOP% & \ LSET BUFFER$ = STRING$(BUF.SIZ%,0%) & \ GOTO 12030 & ! End loop; restart when loop falls through & 12070 TEXT$ = FNCONVERT$(SECT$) & \ I% = INSTR(1%,TEXT$,FLAG$) & \ GOTO 12060 UNLESS I% & ! Do the necessary conversions on the record; look for the flag & ! keyword; get another record if this record is not a flag record & 12080 FIL$ = RIGHT(TEXT$,I%+LEN(FLAG$)) & \ FIL$ = CVT$$(FIL$,128%) & \ FILES% = FILES% + 1% & \ PRINTER$ = FNP$(FIL$) & \ GOTO 12060 & ! Isolate the filename; increment the file counter; print the name & ! and continue search & 12100 IF ERR <> 11% AND ERR <> 13% THEN ON ERROR GOTO 30000 & \ GOTO 30000 & ! If not EOF error, reset standard error trap and let that routine & ! process this error & 12102 RESUME 12105 & ! Re-enable error trapping & 12105 GOTO 12110 IF EOF% & \ EOF% = -1% & \ GOTO 12030 & ! Dispatch to next line if this is the second EOF detected, an & ! indication of LEOT; set the EOF flag if this is the first time & ! around, and go try to get more data & 12110 PRINT & \ PRINT & \ PRINT "Total of";FILES%;"file";FNS$(FILES%);" on tape" & \ PRINT & \ PRINT "Total of";RECS%;"block";FNS$(RECS%) & \ PRINT & \ ON ERROR GOTO 30000 & ! Print the totals; reset standard error trap & 12120 SELECTIVE% = 0% & \ EOF% = 0% & \ PRINT & \ PRINT "Input files: "; & \ INPUT LINE INFILES$ & ! Reset selective and EOF flags; get input files; default is input & ! from all files on tape & 12125 IF INSTR(1%,INFILES$,'/M') THEN PRINT "More> "; & \ INPUT LINE #1% MORE$ & \ INFILES$ = INFILES$ + ';' + MORE$ & \ GOTO 12125 & ! Check to see if the '/M' switch was used; handle as necessary & 12127 INFILES$ = CVT$$(INFILES$,2%+4%+32%+64%) & \ GOTO 12130 UNLESS LEN(INFILES$) & \ SELECTIVE% = -1% & ! Squish out all garbage from file string; if default not used, & ! set SELECTIVE%, the selective file processing flag & 12130 GOTO 12900 & ! Return & 12140 ! & & & ! C h e c k F l a g F i l e n a m e & & & 12150 GOTO 12180 UNLESS LEN(INFILES$) & \ FIL$ = CVT$$(FIL.OUT$,2%+4%+32%+64%) & \ I% = INSTR(1%,INFILES$,FIL$) & \ GOTO 4055 UNLESS I% & ! Skip out if no string to search; squish out garbage bytes from the & ! filename to be checked; look for filename within string of files & ! specified for transferral; skip out if no match & 12160 INFILES$ = '' IF INFILES$ = FIL$ & \ GOTO 12170 UNLESS LEN(INFILES$) & \ INFILES$ = LEFT(INFILES$,I%-2%) + RIGHT(INFILES$,I%+LEN(FIL$)+1%) & ! Do null string checking; cut filename out of specification string & 12170 GOTO 4070 & ! Skip back to old processing routine & 12180 I% = MAGTAPE(3%,0%,2%) & \ GOTO 14060 & ! Rewind the tape and go print transfer complete message & 12900 RETURN & 14000 ! & & & ! E O F H a n d l e r R o u t i n e & & & 14010 GOTO 14060 IF EOF% & \ EOF% = -1% & ! Let's close up shop if this is the second successive tapemark, & ! else set EOF flag and continue & 14015 CLOSE #3% IF OPN% & \ GOTO 14020 UNLESS OPN% & \ OPN% = 0% & \ COUNTER% = COUNTER% + 1% & \ PRINT "File";COUNTER%;"transferred to ";FIL.OUT$;" -";RECS%; & "block";FNS$(RECS%);" long" & \ TOTL% = TOTL% + RECS% & \ RECS% = 0% & ! Close the output file if one was open; skip ahead if no file & ! was transferred else reset open file flag, increment counter, & ! log transfer and update totals & 14020 FIL.OUT$ = '' & \ GOTO 4040 & ! Reset output filename; go back for more data & 14060 PRINT & \ PRINT "MAGINT transfer complete" & \ CLOSE #3% IF OPN% & \ OPN%, EOF% = 0% & \ PRINT & \ PRINT "Total of";COUNTER%;"file";FNS$(COUNTER%); & " comprising";TOTL%;"block";FNS$(TOTL%); & " transferred" & \ PRINT & \ TOTL% = 0% & ! Do cleanup at end of transfer & 14070 GOTO 14900 UNLESS FLAG% & \ IF LEN(INFILES$) THEN PRINT & "? The following input file string was not processed:" & \ PRINT & \ PRINT INFILES$ & \ PRINT & \ PRINT "? No matching files on tape" & \ INFILES$ = '' & ! Take care of undigested file specs & 14100 GOTO 14900 & 14200 LSET BUFFER$ = STRING$(BUF.SIZ%,0%) & \ GOTO 14015 & 14900 PRINT & \ GOTO 4000 IF FLAG% & \ GOTO 1045 & 18000 ! & & & ! D o T a p e L a b e l l i n g H e r e & & & 18010 STATS% = MAGTAPE(7%,0%,2%) & ! Get the statistics of the tape & 18015 START% = 1% & ! Set up loop start point & 18020 GOTO 18050 IF (STATS% AND 256%) & ! Dispatch to routine if tape at BOT & 18030 IF FLAG% THEN LSET BUFFER$ = FNCONVERT$(FLAG$+FIL.IN$) & \ START% = 2% & \ GOTO 18900 & ! If we will be labelling the tape with flag records, do the & ! conversions on the flag record and set up a start point one & ! record into the buffer & 18040 I% = MAGTAPE(2%,0%,2%) & \ GOTO 18900 & ! We are not at BOT (checked at 18020) and tape will be unlabelled & ! Write an EOF to the tape to separate files & 18050 GOTO 18030 IF FLAG% & ! Tape is at BOT; if flag records are to be written, then go write & ! one else exit (no spacing EOFs at BOT for unlabelled tapes) & 18900 RETURN & 19000 ! & & & ! M u l t i - V o l u m e H a n d l i n g & & & 19010 ON ERROR GOTO 19500 & \ LSET BUFFER$ = STRING$(BUF.SIZ%,0%) & \ E1% = ERL & ! Set a modular error trap; zero buffer; store error line & 19020 I% = MAGTAPE(2%,0%,2%) FOR I% = 1% TO 3% & ! Write a LEOT & 19030 I% = MAGTAPE(3%,0%,2%) & \ ON ERROR GOTO 30000 & \ GOTO 19700 IF E1% = 6080% & ! Rewind the tape; reset standard error trap; dispatch to cleanup & ! routine if we finished last file & 19040 CLOSE #2% & \ PRINT & \ PRINT BEEP$; & \ PRINT "End of tape reached - please mount a new tape" & \ PRINT & \ PRINT "Type RETURN to continue" & \ GET & \ PRINT "Are you sure the tape now mounted is the one you wish to"; & \ INPUT " use";QUERY$ & \ IF QUERY$ <> "YES" THEN Y% = 0% & \ PRINT & \ GOSUB 10030 & ! Ding the user; tell him to mount a new tape for we've run out & ! of room on this tape; confirm tape is right one & 19050 Y% = 0% & \ GOSUB 10040 & \ SET.TAPE% = MAGTAPE(6%,E%+(D%*4%)+P%+S%,2%) & \ PRINT "Tape is now mounted - resuming processing..." & \ PRINT & \ FIELD #2%, BUF.SIZ% AS BUFFER$ & \ GOTO 6030 IF E1% = 6080% & ! Go to tape mounting subroutine; set tape characteristics & ! previously desired; notify user; re-field buffer & ! Dispatch properly if end of last file was reached & 19060 GOTO 6040 UNLESS FLAG% & \ GOSUB 18000 & \ GOTO 6040 & ! Skip out if we don't have to bother with flag records; & ! go label tape if necessary; go continue processing & 19500 RESUME 19030 & ! On any error, just go rewind the tape & 19700 CLOSE #3% & \ RECS% = RECS% + 1% UNLESS LOOP% = 1% & \ COUNTER% = COUNTER% + 1% & \ PRINT FIL.IN$;" transferred to tape -";RECS%;"block";FNS$(RECS%); & " used" & \ TOTL% = TOTL% + RECS% & \ RECS% = 0% & \ GOTO 19040 & ! Close the input file; do cleanup; tell user end of tape reached & 20000 ! & & & ! F u n c t i o n s & & & 20010 DEF* FNYES.OR.NO%(DEFAULT$) & ! Define the function to check responses & 20020 FNYES.OR.NO% = -1% & \ FNYES.OR.NO% = 0% IF DEFAULT$ = "NO" & \ RESPONSE$ = CVT$$(QUERY$,2%+4%+32%) & \ GOTO 20060 UNLESS LEN(RESPONSE$) & \ IF LEFT("NO",LEN(RESPONSE$)) = RESPONSE$ THEN 20050 & ! Compare the response against "NO" & 20030 IF RESPONSE$ <> LEFT("YES",LEN(RESPONSE$)) AND & RESPONSE$ <> LEFT("NO",LEN(RESPONSE$)) THEN FNYES.OR.NO% = 2% & \ PRINT & \ PRINT "Please answer [Y]es or [N]o" & \ PRINT & \ GOTO 20060 & ! If response is neither YES or NO, then print an error message, & ! set the function name to indicate an entry error, and go back & ! for another response & 20040 FNYES.OR.NO% = -1% & \ GOTO 20060 & ! YES was the response & 20050 FNYES.OR.NO% = 0% & ! Set function name to indicate "NO" was the response to the & ! question & 20060 FNEND & 20070 DEF* FNCONVERT$(DUMMY$) & ! Define the function to perform all the necessary conversions & ! on DUMMY string passed & 20080 GOTO 20230 IF NOT DISK.TO.TAPE% & ! Dispatch to tape to disk processing routine & 20090 GOTO 20210 IF OVR% & \ I% = INSTR(1%,DUMMY$,CHR$(13%)+CHR$(10%)) & \ GOTO 20110 IF I% < 2% & \ IF SAVE.NULLS% THEN DUMMY$ = LEFT(DUMMY$,I%-1%) ELSE & DUMMY$ = CVT$$(DUMMY$,4%) & ! Look for a carriage return; if there and we must preserve nulls, & ! cut off the line terminator with string functions else use CVT$$ & 20100 IF LEN(DUMMY$) > REC.LEN% THEN & OVERLENGTH$ = RIGHT(DUMMY$,REC.LEN%+1%) & \ DUMMY$ = LEFT(DUMMY$,REC.LEN%) & \ OVR% = -1% & ! If last line processed was over length, dispatch accordingly; & ! otherwise, check length; if too long, put over length data & ! into OVERLENGTH$ (clever name) and set flag to indicate over & ! length processing is in effect & 20110 IF NOT TB.TO.SP% THEN 20170 ELSE START% = 1% & ! If no tab to space conversion, then skip this bit else set variable & ! to indicate where to start looking in the string for a tab & 20120 I% = INSTR(START%,DUMMY$,CHR$(9%)) & \ GOTO 20170 UNLESS I% & ! Start the search at character number START%; exit this routine if & ! no tab characters are found & 20130 TEMP$ = LEFT(DUMMY$,I%-1%) & ! Put the string up to the tab into temporary storage & 20140 FOR LOUPE% = 1% UNTIL TB.TO.SP%(LOUPE%) > I% & \ NEXT LOUPE% & \ POSTN% = TB.TO.SP%(LOUPE%) & \ DUMMY$ = TEMP$ + SPACE$(POSTN%-I%)+RIGHT(DUMMY$,I%+1%) & ! Go searching through the tab to space conversion tables for the & ! next highest tab position; add correct amount of spaces string and & ! reformat DUMMY$ & 20150 START% = I% + 1% & \ GOTO 20120 & ! Start next search at character position following last found tab & 20170 DUMMY$ = DUMMY$ + SPACE$(REC.LEN%-LEN(DUMMY$)) & \ RESULT$ = DUMMY$ & ! Pad to REC.LEN% bytes with spaces if necessary & 20180 GOTO 20400 IF NOT ASCII.TO.EBCDIC% & \ RESULT$ = '' & \ GOTO 20190 IF SAVE.NULLS% & \ RESULT$ = XLATE(DUMMY$,ASCII.TO.EBCDIC$) & \ GOTO 20400 & ! Skip this routine if no code conversion is to be performed; skip & ! to next routine if null characters must be preserved; translate & ! via the XLATE function the string to EBCDIC code; exit routine & 20190 FOR LUPE% = 1% TO REC.LEN% & \ V% = ASCII(MID(DUMMY$,LUPE%,1%))+1% & \ RESULT$ = RESULT$ + CHR$(ASCII.TO.EBCDIC%(V%)) & ! Do the conversion character by character to preserve null characters & ! Put the result into RESULT$ (another clever name) & 20200 NEXT LUPE% & \ GOTO 20400 & ! Continue the loop; exit when done & 20210 ! & & & ! T a k e C a r e O f O v e r l e n g t h & & & 20220 DUMMY$ = OVERLENGTH$ & \ OVERLENGTH$ = '' & \ OVR% = 0% & \ GOTO 20090 & ! Go process overage as if it were a line passed; nullify temporary & ! storage variable; reset flag; go process & 20230 ! & & & ! E B C D I C T o A S C I I C o n v e r s i o n & & & 20240 GOTO 20270 IF NOT EBCDIC.TO.ASCII% & \ RESULT$ = '' & \ GOTO 20250 IF SAVE.NULLS% & \ RESULT$ = XLATE(DUMMY$,EBCDIC.TO.ASCII$) & \ GOTO 20280 & ! Skip this if no conversion requested; skip to next routine if null & ! characters are to be preserved else translate with XLATE and exit & 20250 FOR LUPE% = 1% TO REC.LEN% & \ V% = ASCII(MID(DUMMY$,LUPE%,1%))+1% & \ RESULT$ = RESULT$ + CHR$(EBCDIC.TO.ASCII%(V%)) & ! Translate character by character to preserve null characters & 20260 NEXT LUPE% & \ GOTO 20280 & ! Continue loop; skip next line when through & 20270 RESULT$ = DUMMY$ & 20280 RESULT$ = CVT$$(RESULT$,128%) & \ I% = ASCII(RIGHT(RESULT$,LEN(RESULT$))) & \ IF I% > 31% AND I% < 127% THEN RESULT$=RESULT$+CHR$(13%)+CHR$(10%) & ! Get rid of all trailing spaces & ! Look for some form of line terminator within the string; if found, & ! skip this routine else add a carriage return terminator & 20400 FNCONVERT$ = RESULT$ & \ RESULT$ = '' & ! Set function value equal to converted string; nullify result & ! holding string & 20410 FNEND & 20420 DEF* FNFIP$ & ! Define the file processor function & 20432 GOTO 20540 IF WILD.PPN% OR WILD.NAME% & ! Dispatch to proper routine if processing wildcards & 20435 FIL$ = "*END*" UNLESS LEN(F.IN$) & \ GOTO 20600 UNLESS LEN(F.IN$) & \ CHANGE SYS(CHR$(6%)+CHR$(-23%)+F.IN$) TO DIR.LU% & \ I% = LEN(F.IN$) - RECOUNT & \ I% = 0% UNLESS RECOUNT <> 0% & \ FIL$ = LEFT(F.IN$,I%) IF I% & \ F.IN$ = RIGHT(F.IN$,I%+2%) IF I% & \ FIL$ = F.IN$ UNLESS I% & \ F.IN$ = '' UNLESS I% & ! If we have run out of filespecs, set variable to generate an error; & ! Go set function name to illegal name if we are out of filespecs; & ! Process the command line with the terminating file name string scan; & ! Put the file processed into FIL$, the remainder of string into & ! F.IN$. If string is one filespec, set the file processed to the & ! string itself. If that was done, nullify the string variable & 20437 FLAG1% = DIR.LU%(27%)+SWAP%(DIR.LU%(28%)) & \ FLAG2% = DIR.LU%(29%)+SWAP%(DIR.LU%(30%)) & ! Get the two flag words returned by the file name string scan & 20440 IF (FLAG1% AND 256%)=0% THEN PRINT "? ";FIL$; & " is an illegal filename - ignored" & \ GOTO 20435 & ! If the filename specified was null, notify user of an illegal & ! filename error and tell him that specification will be ignored & 20445 TEMP.FIL$ = FIL$ & ! Store the filespec being processed into a temporary variable & 20450 IF FLAG1% >= 0% THEN 20600 & ! If no wildcards in filespec, go exit with FNFIP set to filespec & 20455 COUNTR% = 0% & \ CNT% = 0% & ! Reset our processing counters & 20460 IF DIR.LU%(6%) <> 255% AND DIR.LU%(5%) <> 255% THEN 20560 ELSE & WILD.PPN% = -1% & \ PROJ% = DIR.LU%(6%) & \ PROG% = DIR.LU%(5%) & ! If neither PPN specification was a '*', then go do the lookup & ! else set a flag indicating a wild PPN was entered and processing & ! for it is in progress & 20470 DIR.LU%(0%) = 30% & \ DIR.LU%(1%) = 6% & \ DIR.LU%(2%) = 25% & \ DIR.LU%(3%) = CNT% & \ DIR.LU%(4%) = SWAP%(CNT%) & \ DIR.LU%(5%) = PROG% & \ DIR.LU%(6%) = PROJ% & \ CHANGE DIR.LU% TO PPN.LU$ & \ CHANGE SYS(PPN.LU$) TO DIR.LU% & \ CNT% = CNT% + 1% & ! Set up array for wildcard PPN lookup SYS call (new with V7.0) & ! Execute it and increment the PPN index & 20540 ! & & & ! D o D i r e c t o r y L o o k u p & & & 20560 DIR.LU%(0%) = 30% & \ DIR.LU%(1%) = 6% & \ DIR.LU%(2%) = 17% & \ DIR.LU%(3%) = INDEX% & \ DIR.LU%(4%) = SWAP%(INDEX%) & \ INDEX% = INDEX% + 1% & \ WILD.NAME% = -1% & ! Set up for the directory lookup on index with wildcards; increment & ! the index pointer; set the wild name flag & 20570 CHANGE DIR.LU% TO DIR.LU$ & \ CHANGE SYS(DIR.LU$) TO DIR.LU% & ! Execute the directory lookup SYS call & 20575 COUNTR% = COUNTR% + 1% & ! Increment the counter for successful lookups & 20580 FIL$ = RAD$(DIR.LU%(7%)+SWAP%(DIR.LU%(8%)))+ & RAD$(DIR.LU%(9%)+SWAP%(DIR.LU%(10%)))+'.'+ & RAD$(DIR.LU%(11%)+SWAP%(DIR.LU%(12%))) & \ FIL$ = "["+NUM1$(DIR.LU%(6%))+","+NUM1$(DIR.LU%(5%))+"]"+FIL$ & \ P1% = DIR.LU%(5%) \ P2% = DIR.LU%(6%) & ! Set up the filename; add an account specification & ! Save the account numbers & 20590 CHANGE SYS(CHR$(6%)+CHR$(-23%)+TEMP.FIL$) TO DIR.LU% & \ DIR.LU%(5%) = P1% \ DIR.LU%(6%) = P2% & ! Put the old data for the filespec back into the matrix; & ! It was destroyed by the directory lookup call return so & ! the matrix must be fixed so that the call can be made again & ! Put current PPN back into matrix & 20600 FNFIP$ = CVT$$(FIL$,4%) & ! Remove garbage bytes from the input filename & 20610 FNEND & 20620 DEF* FNS$(DUMMY%) & ! Define a function to add an 's' if needed & 20630 IF DUMMY% = 1% THEN FNS$ = "" ELSE FNS$ = "s" & ! If equal to one, don't add an 's' else add an 's' & 20640 FNEND & 20650 DEF* FNP$(X$) & ! Define the routine to print filenames for tape directory section & 20655 X$ = CVT$$(X$,4%+8%+128%) & ! Squish out garbage & 20660 GOTO 20690 IF CCPOS(0%) & ! Skip ahead if print head is not at left margin & 20670 PRINT X$; & \ IF WIDTH% < 44% THEN PRINT & \ GOTO 20720 & ! Print the item at the left margin; if no room for another item, & ! skip ahead & 20680 PRINT TAB(22%); & \ GOTO 20720 & ! Tab over to the next printing position and exit & 20690 POSITION% = CCPOS(0%) & ! Put the printer position into POSITION% & 20700 PRINT X$; & \ IF (POSITION% + 22% + 19%) > WIDTH% THEN PRINT & \ GOTO 20720 & ! Print the item somewhere in the middle of the page; if old position & ! plus another item would overshoot the width, return the carriage & 20710 PRINT TAB(POSITION% + 22%); & ! Tab over to the next printing position & 20720 FNEND & 30000 ! & & & ! E r r o r H a n d l i n g & & & 30020 IF ERR = 28% THEN CLOSE #1%,2%,3% & \ RESUME 32767 & ! Go to the end if a CTRL/C combination was typed & 30030 IF ERL=1040% THEN PRINT & "? Magtape drive is unavailable - try again later" & \ PRINT & \ RESUME 32000 & ! If someone else has ASSIGNed or OPENed the tape, tell user & ! and abort & 30040 IF ERL = 3010% THEN Y% = 0% & \ GOSUB 10030 & \ RESUME 3030 & ! If tape not mounted, go to the subroutine that tells the user & ! to do so & 30050 IF ERL = 1090% THEN PRINT & "? Blocking factor must be an INTEGER from 1 to 20" & \ PRINT & \ RESUME 1090 & ! If user typed something other than a number, tell him what to do & 30060 IF ERL = 6030% THEN PRINT "? ";FIL.IN$; UNLESS ERR<>5% AND ERR<>10% & \ PRINT " not found - ignored" IF ERR = 5% & \ PRINT " cannot be opened - protection error" IF ERR=10% & \ RESUME 6030 UNLESS ERR<>5% AND ERR<>10% & ! Take care of errors occurring on file opening & 30065 IF ERL = 6030% THEN PRINT & \ PRINT "MAGINT transfer complete" & \ PRINT & \ PRINT "Total of";COUNTER%;"file";FNS$(COUNTER%); & " comprising";TOTL%;"block";FNS$(TOTL%); & " transferred to tape" & \ PRINT & \ I% = MAGTAPE(2%,0%,2%) FOR J% = 1% TO 3% & \ I% = MAGTAPE(5%,1%,2%) & \ I% = MAGTAPE(5%,1%,2%) & \ I% = MAGTAPE(5%,1%,2%) & \ COUNTER%,TOTL% = 0% & \ RESUME 6000 & ! When finished, write LEOT, backspace 3 records for further & ! processing; reset counters and go back for more input files & 30070 IF ERL = 6050% THEN RESUME 6080 & ! If EOF on input, go see if it needs to & ! be written to the tape as a 'short block' & 30080 IF ERL = 6060% AND ERR = 4% THEN RESUME 19000 & ! Take care of multi-volume processing & 30090 IF ERL = 20435% THEN PRINT "? Illegal file specification - "; & \ I% = INSTR(1%,F.IN$,',') & \ I% = INSTR(1%,F.IN$,';') UNLESS I% & \ FIL$ = LEFT(F.IN$,I%-1%) IF I% & \ FIL$ = F.IN$ UNLESS I% & \ F.IN$ = RIGHT(F.IN$,I%+1%) IF I% & \ PRINT FIL$;" - ignored" & \ RESUME 20435 & ! Process illegal file name errors on specs entered & 30095 IF ERL = 20470% AND ERR = 5% THEN & WILD.NAME%, WILD.PPN% = 0% & \ PRINT "? No files matching ";FIL$ UNLESS COUNTR% & \ COUNTR% = 0% & \ RESUME 20435 & ! We are finished with wildcard processing if PPN lookup fails & 30100 IF ERL = 20570% AND ERR = 5% THEN INDEX% = 0% & \ RESUME 20470 IF WILD.PPN% & \ PRINT "? No files matching ";FIL$ UNLESS COUNTR% & \ COUNTR% = 0% & \ WILD.PPN%,WILD.NAME% = 0% & \ RESUME 20435 & ! Trap errors resulting from no matching filespec in a wildcard & ! SYS lookup; go increment PPN counters if wildcard PPN processing & ! is in effect; if no wild PPN's and no matches were found on a & ! wildcard specification (the counter of matches = 0) then print & ! a message notifying the user of such a case; whatever the case, & ! reset all flags and variables and go process another filespec & 30110 IF ERL = 10040% THEN RESUME 10030 & ! If user has not mounted the tape, go tell him to again & 30120 IF ERR = 11% AND ERL = 4040% THEN RESUME 14000 & ! If we hit an EOF on input (tapemark detected) go to proper & ! handler routine at line 14000 & 30130 IF ERR = 2% AND (ERL = 4070% OR ERL = 4085% OR ERL = 4100%) THEN PRINT & "? Illegal filename specification - "; & \ PRINT FIL.OUT$ & \ PRINT & \ OPN% = 0% & \ I% = 0% & \ PRINT "To what file should this data be written"; & \ INPUT LINE FIL.OUT$ & \ FIL.OUT$ = CVT$$(FIL.OUT$,4%) & \ I% = -1% IF FIL.OUT$ = "CONTINUE" & \ PRINT "% 'CONTINUE' option unavailable with supersede" IF & I% = -1% AND M% = 0% & \ GOTO 30130 IF I% = -1% AND M% = 0% & \ FIL.OUT$ = TEMP.FIL$ IF I% & \ RESUME 4085 UNLESS (ERL = 4100%) OR (I% = -1%) & \ RESUME 4100 & ! We got an illegal filename somewhere; tell user and get a proper & ! name; handle misinterpreted flag headers & 30145 IF ERR = 14% AND ERL = 4500% THEN PRINT BEEP$; & \ PRINT "Line printer hung - please fix it" UNLESS LP.ERROR% & \ PRINT UNLESS LP.ERROR% & \ LP.ERROR% = -1% & \ SLEEP 10% & \ RESUME 4500 & ! Take care of line printer errors & 30150 IF ERR = 39% OR ERR = 14% THEN PRINT & \ PRINT BEEP$; & \ PRINT "Tape drive has gone offline - put ONLINE to continue" & ! Magtape select error - ding user and say what's what & 30160 IF ERR = 39% OR ERR = 14% THEN & GOTO 30160 IF (MAGTAPE(7%,0%,2%) AND 32%) <> 0% & \ PRINT & \ PRINT "Continuing..." & \ PRINT & \ RESUME & ! Loop until tape comes back on line then resume where we were & ! so RUDELY interrupted & 30170 IF ERR = 13% AND (ERL = 12030% OR ERL = 4040%) THEN PRINT & \ PRINT "? No LEOT - aborting transfer in progress" & \ RESUME 14000 & ! Take care of user data errors & 30200 IF ERR = 40% THEN RESUME 8000 & ! Handle magtape record length errors & 30850 IF ERR = 11% THEN RESUME 32000 & 30900 PRINT "? Unexpected error - "; & CVT$$(RIGHT(SYS(CHR$(6%)+CHR$(9%)+CHR$(ERR)),3%),4%); & " - (ERR=";NUM1$(ERR);") at line";ERL & \ RESUME 32767 & ! On an unexpected error, tell user what happened and exit & 31000 ! & & & ! D a t a I n i t i a l i z a t i o n & & & 31010 ASCII.TO.EBCDIC%(0%)=256% & \ READ ASCII.TO.EBCDIC%(I%) FOR I% = 1% TO 128% & \ RESTORE & \ READ ASCII.TO.EBCDIC%(I%) FOR I% = 129% TO 256% & \ CHANGE ASCII.TO.EBCDIC% TO ASCII.TO.EBCDIC$ & ! Initialize the ASCII to EBCDIC code conversion tables & 31020 EBCDIC.TO.ASCII%(0%)=256% & \ READ EBCDIC.TO.ASCII%(I%) FOR I% = 1% TO 256% & \ CHANGE EBCDIC.TO.ASCII% TO EBCDIC.TO.ASCII$ & ! Read to EBCDIC to ASCII conversion data & 31030 READ TB.TO.SP%(I%) FOR I% = 1% TO 17% & ! Initialize the tab to space conversion tables & 31090 RETURN & 31095 ! & ! Data for ASCII to EBCDIC conversions & ! 31100 DATA 0,1,2,3,55,45,46,47,22,5,37,11,12,13,14,15 31110 DATA 16,17,18,19,60,61,50,38,24,25,63,39,28,29,30,31 31120 DATA 64,79,127,123,91,108,80,125,77,93,92,78,107,96,75,97 31130 DATA 240,241,242,243,244,245,246,247,248,249,122,94,76,126,110,111 31140 DATA 124,193,194,195,196,197,198,199,200,201,209,210,211,212,213,214 31150 DATA 215,216,217,226,227,228,229,230,231,232,233,74,224,90,95,109 31160 DATA 121,129,130,131,132,133,134,135,136,137,145,146,147,148,149,150 31170 DATA 151,152,153,162,163,164,165,166,167,168,169,192,106,208,161,7 31180 ! & ! Data for EBCDIC to ASCII conversions & ! 31190 DATA 0,1,2,3,24,9,24,127,24,24,24,11,12,13,14,15 31200 DATA 16,17,18,19,24,24,8,24,24,25,24,24,28,29,30,31 31210 DATA 24,24,24,24,24,10,23,27,24,24,24,24,24,5,6,7 31220 DATA 24,24,22,24,24,24,24,4,24,24,24,24,20,21,24,26 31230 DATA 32,24,24,24,24,24,24,24,24,24,91,46,60,40,43,33 31240 DATA 38,24,24,24,24,24,24,24,24,24,93,36,42,41,59,94 31250 DATA 45,47,24,24,24,24,24,24,24,24,124,44,37,95,62,63 31260 DATA 24,24,24,24,24,24,24,24,24,96,58,35,64,39,61,34 31270 DATA 24,97,98,99,100,101,102,103,104,105,24,24,24,24,24,24 31280 DATA 24,106,107,108,109,110,111,112,113,114,24,24,24,24,24,24 31290 DATA 24,126,115,116,117,118,119,120,121,122,24,24,24,24,24,24 31300 DATA 24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24 31310 DATA 123,65,66,67,68,69,70,71,72,73,24,24,24,24,24,24 31320 DATA 125,74,75,76,77,78,79,80,81,82,24,24,24,24,24,24 31330 DATA 92,24,83,84,85,86,87,88,89,90,24,24,24,24,24,24 31340 DATA 48,49,50,51,52,53,54,55,56,57,24,24,24,24,24,24 31345 ! & ! End of code conversion data & & & ! Beginning of tab to space conversion data & ! 31350 DATA 9,17,25,33,41,49,57,65,73,80,89,97,105,113,121,129,132 31500 ! & ! End of data for tab to space conversions & ! & ! Originally only 10 pieces of data, this list was & ! expanded to 17 items with the advent of variable & ! record lengths. & ! 32000 ! & & & ! E x i t & & & 32020 S$ = SYS(CHR$(6%)+CHR$(11%)+STRING$(20%,0%)+"MM"+CHR$(0%)+CHR$(255%)) & ! Deassign the tape after the session is over & 32030 CLOSE #1%,2%,3% & 32500 NO EXTEND ! Disable EXTEND mode processing 32760 S$ = SYS(CHR$(9%)) ! Clear core and exit fast 32767 END