! THIS VERSION HAS TWO VERSIONS OF CHECKTAPE - PAGE BY PAGE
! AND BULK MOVE, OBTAINED BY 'CHECKTAPE' AND 'FCHECKTAPE'
! RESPECTIVELY. BOTH OF THEM COPE WITH 4/75 TAPES AND 2900 TAPES
! CDM - 20/JUNE/80
!
CONSTSTRING  (1) SNL = "
"
CONSTBYTEINTEGERARRAY  HEX(0 : 15) =             C 
'0','1','2','3','4','5','6','7',
'8','9','A','B','C','D','E','F'
CONSTINTEGER  READING = 1
CONSTINTEGER  WRITING = 2
CONSTINTEGER  IN = 1
CONSTINTEGER  OUT = 2
CONSTINTEGER  EOT = 4
CONSTINTEGER  PAGE SIZE = 4096
!*
EXTERNALROUTINESPEC  DEFINE(STRING  (63) S)
EXTERNALSTRINGFNSPEC  INTERRUPT
SYSTEMROUTINESPEC  FILL(INTEGER  LENGTH, FROM, PATTERN)
EXTERNALROUTINESPEC  PROMPT(STRING  (15) S)
EXTERNALROUTINESPEC  OPEN TAPE(INTEGER  NO, MODE, RLEV,  C 
   STRING  (6) TAPE, INTEGERNAME  FLAG)
EXTERNALROUTINESPEC  CLOSE TAPE(INTEGER  NO, INTEGERNAME  FLAG)
EXTERNALROUTINESPEC  READ PAGE( C 
   INTEGER  NO, CHAP, ADDRESS, INTEGERNAME  FLAG)
EXTERNALROUTINESPEC  WRITE PAGE( C 
   INTEGER  NO, CHAP, ADDRESS, INTEGERNAME  FLAG)
EXTERNALROUTINESPEC  WRITE TRAILER(INTEGER  NO, INTEGERNAME  FLAG)
EXTERNALROUTINESPEC  BULK MOVE(INTEGER  FROM,TO,PGS,INTEGERNAME  FLAG)
!*
!*
RECORDFORMAT  FP(STRING  (6) USER, BYTEINTEGER  PERM)
RECORDFORMAT  TFHF(STRING  (6) TAPENAME, USERNAME,  C 
   STRING  (15) FILENAME,  C 
 STRING  (8) DATE, TIME, TYPE, BYTEINTEGER  SPARE0, SPARE1, SPARE2,  C 
   INTEGER  CHAPTER, E PAGES, FSYS, PERMS, OWNP, EEP, ARCH,  C 
   CODES, SSBYTE, CCT, SPARE3, SPARE4, SPARE5, RECORDS,  C 
   STRING  (6) OFFERED TO, RECORDARRAY  PERMLIST(1 : 16)(FP))
!*
!*
!*

STRING  (15) FN  I TO S(INTEGER  N)
!**********************************************************************
!*                                                                    *
!*  TURNS AN INTEGER INTO A STRING USES MACHINE CODE                  *
!*                                                                    *
!**********************************************************************
STRING  (16) S
INTEGER  D0, D1, D2, D3
   *LSS_N;  *CDEC_0
   *LD_S;  *INCA_1;                     ! PAST LENGTH BYTE
   *CPB_B ;                             ! SET CC=0
   *SUPK_L =15,0,32;                    ! UNPACK 15 DIGITS SPACE FILL
   *STD_D2;                             ! FINAL DR FOR LENGTH CALCS
   *JCC_8,<WASZERO>;                    ! N=0 CASE
   *LSD_TOS ;  *ST_D0;                  ! SIGN DESCRIPTOR STKED BY SUPK
   *LD_S;  *INCA_1
   *MVL_L =15,15,48;                    ! FORCE IN ISO ZONE CODES
   IF  N < 0 THEN  BYTEINTEGER(D1) = '-' AND  D1 = D1-1
   BYTEINTEGER(D1) = D3-D1-1
   RESULT  = STRING(D1)
WASZERO:

   RESULT  = "0"
END ;                                   !OF STRINGFN I TO S
!*
!*

STRING  (8) FN  H TO S(INTEGER  VALUE, PLACES)
!**********************************************************************
!*                                                                    *
!*  TURNS AN INTEGER INTO A HEXIDECIMAL STRING OF GIVEN LENGTH        *
!*  USES MACHINE CODE                                                 *
!*                                                                    *
!**********************************************************************
STRING  (8) S
INTEGER  I
   I = 64-4*PLACES
   *LD_S;  *LSS_PLACES;  *ST_(DR )
   *INCA_1;  *STD_TOS ;  *STD_TOS 
   *LSS_VALUE;  *LUH_0;  *USH_I
   *MPSR_X'24';                         ! SET CC=1
   *SUPK_L =8
   *LD_TOS ;  *ANDS_L =8,0,15;          ! THROW AWAY ZONE CODES
   *LSS_HEX+4;  *LUH_X'18000010'
   *LD_TOS ;  *TTR_L =8
   RESULT  = S
END ;                                   !OF STRINGFN H TO S
!*
!*

ROUTINE  READ LINE(STRINGNAME  LINE)
!***********************************************************************
!*                                                                     *
!*  READS A LINE OF TEXT TERMINATED BY A NEWLINE. SKIPPING LEADING     *
!*  NEWLINES AND SPACES.                                               *
!*                                                                     *
!***********************************************************************
INTEGER  SYM
   LINE = ""
   SKIP SYMBOL WHILE  NEXT SYMBOL = ' ' OR  NEXT SYMBOL = NL
   READ SYMBOL(SYM)
   WHILE  SYM # NL CYCLE 
      LINE = LINE.TO STRING(SYM)
      READ SYMBOL(SYM)
   REPEAT 
END ;                                   !OF ROUTINE READ LINE
!*
!*
!*
!*

EXTERNALROUTINE  COPYARCH(STRING  (63) S)
!***********************************************************************
!*                                                                     *
!*               EMAS BACKUP/ARCHIVE TAPE COPY PROGRAM.                *
!*  USED ONLY WHEN A TAPE IS LOST, DESTROYED OR UNREADABLE             *
!*  THEREFORE USES FULL ERROR RECOVERY PROCEDURES TO COPY THE TAPE.    *
!*                                                                     *
!***********************************************************************
BYTEINTEGERARRAY  DATA AREA(0 : PAGE SIZE-1)
RECORDNAME  HDR(TFHF)
STRING  (6) RTAPE, WTAPE, USER
STRING  (15) FILE
INTEGER  FLAG, BUFFA, CHAP, PAGE, NOP, RLEV, EFLAG
!ROUTINES

   ROUTINE  WFAIL
      PRINT STRING("WRITE PAGE ".ITOS(PAGE-1))
      PRINT STRING(" CHAPTER ".ITOS(CHAP))
      PRINT STRING("   FILE:- ".USER.".".FILE." FAILS ".ITOS( C 
         FLAG).SNL)
      EFLAG = 1
   END ;                                !OF ROUTINE WFAIL
!*
!*

   ROUTINE  RETRY MESS
      PRINT STRING("READ PAGE ".ITOS(PAGE-1))
      PRINT STRING(" CHAPTER ".ITOS(CHAP))
      PRINT STRING("  AFTER ".ITOS(RLEV))
      PRINT STRING(" RETRIES!"."  FAILS ".ITOS(FLAG).SNL)
   END ;                                !OF ROUTINE RETRY MESS
!*
!*
   RLEV = 10;  EFLAG = 0;  CHAP = 1;  BUFFA = ADDR(DATA AREA(0))
   HDR == RECORD(BUFFA);                !DEFAULTS
   RTAPE = "";  WTAPE = ""
   UNLESS  S -> RTAPE.(",").WTAPE START 
      PROMPT("READ TAPE:")
      READ LINE(RTAPE);                 !GET INPUT TAPE NAME
   FINISH 
   OPEN TAPE(IN,READING,RLEV,RTAPE,FLAG)
   IF  FLAG = 0 START 
      IF  WTAPE = "" START 
         PROMPT("WRITE TAPE:")
         READ LINE(WTAPE)
      FINISH 
      OPEN TAPE(OUT,WRITING,RLEV,WTAPE,FLAG)
      IF  FLAG = 0 START ;              !FAILED TO OPEN OUTPUT TAPE
         CHAP = 0;  FILE = "";  USER = ""
         CYCLE ;                        !CYCLE THROUGH EACH CHAPTER TILLE O T
            CHAP = CHAP+1;  PAGE = 1;   !NEXT CHAPTER FIRST PAGE
            READ PAGE(IN,CHAP,BUFFA,FLAG);    !READ CHAPTER HEADER
            EXIT  IF  FLAG = EOT;       !E O T ?!
            IF  FLAG # 0 START ;        !DID WE SUCCEED
               RETRY MESS;              !NO THEN TELL THE USER
               FILL(PAGE SIZE,BUFFA,X'81');  !SET UP DUMMY CHAPTER
               HDR_PERMS = 0
               HDR_TAPENAME = WTAPE
               HDR_USERNAME = "NONAME"
               HDR_FILENAME = "DUMMYEMPTY"
               HDR_CHAPTER = CHAP
               HDR_FSYS = -1
               HDR_E PAGES = 1
               WRITE PAGE(OUT,CHAP,BUFFA,FLAG)
                                        !WRITE OUT THE DUMMMY HEADER
               WFAIL AND  EXIT  IF  FLAG # 0
               FILL(PAGE SIZE,BUFFA,X'81')
               PAGE = PAGE+1;           !SET UP DUMMY PAGE IN CHAPTER
               WRITE PAGE(OUT,CHAP,BUFFA,FLAG)
                                        !WRITE OUT THE DUMMY PAGE
               WFAIL AND  EXIT  IF  FLAG # 0
               PRINT STRING( C 
                  "DUMMY CHAPTER WRITTEN TO REPLACE CHAPTER ". C 
                  ITOS(CHAP).SNL)
            FINISH  ELSE  START 
               NOP = HDR_E PAGES;       !GET NUMBER OF PAGES
               USER = HDR_USERNAME
               FILE = HDR_FILENAME;     !GET FILE NAME
               HDR_TAPENAME = WTAPE;    !INSERT NEW TAPE NAME
               IF  CHAP = HDR_CHAPTER START 
                  WRITE PAGE(OUT,CHAP,BUFFA,FLAG)
                                        !WRITE THE HEADER
                  WFAIL AND  EXIT  IF  FLAG # 0
                  CYCLE  PAGE = 2,1,NOP+1
                                        !CYCLE THROUGH PAGES IN THE CHAPTER
                     READ PAGE(IN,CHAP,BUFFA,FLAG)
                                        !READ PAGE IN CHAPTER
                     IF  FLAG # 0 START ;    !WAS IT OK?
                        RETRY MESS;     !NO THEN TELL THE USER
                        PRINT STRING("PAGE ".ITOS(PAGE-1))
                        PRINT STRING(" IN CHAPTER ".ITOS(CHAP))
                        PRINT STRING(" FILE:- ".USER.".".FILE)
                        PRINT STRING( C 
                           " WRITTEN WITH ERRORS!!!!".SNL)
                     FINISH 
                     WRITE PAGE(OUT,CHAP,BUFFA,FLAG)
                                        !WRITE PAGE IN CHAPTER
                     WFAIL AND  EXIT  IF  FLAG # 0
                  REPEAT 
               FINISH  ELSE  START 
                  PRINT STRING( C 
                     "CHAPTER IN HEADER NOT AS EXPECTED".SNL)
                  PRINT STRING("ACTUAL ".I TO S(HDR_CHAPTER). C 
                     " EXPECTED ".I TO S(CHAP).SNL)
                  CHAP = HDR_CHAPTER
               FINISH 
            FINISH 
            EXIT  IF  EFLAG # 0 OR  INTERRUPT = "STOP"
                                        !STOP GRACIOUSLY IF USERS ASKS FOR IT
         REPEAT 
         WRITE TRAILER(OUT,FLAG)
         PRINT STRING("WRITE TRAILER FAILS ".I TO S(FLAG).SNL) C 
            IF  FLAG # 0
         CLOSE TAPE(OUT,FLAG)
      FINISH 
      CLOSE TAPE(IN,FLAG)
   FINISH 
   PRINT STRING(ITOS(CHAP-1)." CHAPTERS COPIED".SNL)
END ;                                   !OF EXTERNALROUTINE COPYARCH
!*
!*
!*
!*

ROUTINE  CHECKTAPE1(STRING  (63) S,INTEGER  BM)
!**********************************************************************
!*                                                                    *
!*       STANDARD EMAS BACKUP OR ARCHIVE TAPE CHECK PROGRAM.          *
!*  IF S = "TAPE" THE FILES ARE READ AND EACH HEADER IS VALIDATED.    *
!*  IF S = "TAPE,LIST" A LIST OF ALL THE FILES ON TAPE IS OUTPUT TO   *
!*  THE FILE "LIST".                                                  *
!*                                                                    *
!**********************************************************************
BYTEINTEGERARRAY  DATA AREA(0 : PAGE SIZE-1)
RECORDNAME  HDR(TFHF)
STRING  (6) TAPE, USER,S1,S2
STRING  (15) FILE, LIST
INTEGER  FLAG, BUFFA, CHAP, PAGE, NOP
!ROUTINES

   ROUTINE  READ FAIL
      PRINT STRING("READ PAGE ".ITOS(PAGE-1))
      PRINT STRING(" CHAPTER ".ITOS(CHAP))
      PRINT STRING(" FILE ".USER.".".FILE)
      PRINT STRING("  FAILS ".ITOS(FLAG).SNL)
   END ;                                !OF ROUTINE READ FAIL
!*
!*
   LIST = "";                           !DEFAULTS
   TAPE = S UNLESS  S -> TAPE.(",").LIST
   IF  TAPE = "" START 
      PROMPT("TAPE:")
      READ LINE(TAPE)
   FINISH 
   IF  LIST # "" START 
      DEFINE("1,".LIST.",1024")
      SELECT OUTPUT(1)
      NEWPAGE
      SPACES(15)
      PRINT STRING("CHECK LIST OF ".TAPE.SNL)
      NEWLINES(4)
      PRINT STRING( C 
"CHAPTER   USERNAME FILENAME    E PAGES DATE AND TIME WRITTEN". C 
"  TYPE    FSYS OWNP EEP ARCH CODE SSBYTE CCT OFF TO INDIV PERMS". C 
         SNL.SNL)
      SELECT OUTPUT(0)
   FINISH 
   CHAP = 1
   OPEN TAPE(IN,READING,0,TAPE,FLAG)
   IF  FLAG = 0 START ;                 ! FAILED TO OPEN INPUT TAPE
      CHAP = 0;  FILE = "";  USER = ""
      BUFFA = ADDR(DATA AREA(0))
      HDR == RECORD(BUFFA)
      IF  (TAPE->S1.("EST").S2 OR  TAPE->S1.("NRS").S2) AND  S1="" START 
        ! SECURE TAPE
        CHAP=1;  ! TO SKIP SYSTEM DUMP AT CHAP 1
        IF  LIST#"" START 
          SELECTOUTPUT(1)
          PRINTSTRING("SYSTEM DUMP ASSUMED AT CHAPTER 1")
          NEWLINE
          SELECTOUTPUT(0)
        FINISH 
      FINISH 
      CYCLE ;                           !CYCLE THROUGH EACH CHAPTER TILLE O T
         CHAP = CHAP+1;  PAGE = 1;      !NEXT CHAPTER FIRST PAGE
         READ PAGE(IN,CHAP,BUFFA,FLAG); !READ CHAPTER HEADER IF SKIP OK
         EXIT  IF  FLAG = EOT;          !E O T ?!
         IF  FLAG # 0 START ;           !DID WE SUCCEED
            READ FAIL;                  !NO THEN TELL THE USER
            EXIT 
         FINISH  ELSE  START 
            IF  TAPE = HDR_TAPENAME START 
               IF  LENGTH(HDR_USERNAME) = 6 START 
                  IF  1 <= LENGTH(HDR_FILENAME) <= 11 START 
                     IF  1 <= HDR_E PAGES <= 4096 START 
                        IF  CHAP = HDR_CHAPTER START 
                           NOP = HDR_E PAGES;!GET NUMBER OF PAGES
                           FILE = HDR_FILENAME
                                        !GET FILE NAME
                           USER = HDR_USERNAME
                           IF  LIST # "" START 
                              SELECT OUTPUT(1)
                              WRITE(CHAP,4)
                              SPACES(6)
                              PRINT STRING(USER."  ")
                              PRINT STRING(FILE)
                              SPACES(12-LENGTH(FILE))
                              WRITE(NOP,5)
                              PRINT STRING("    ".HDR_DATE. C 
                                 " ".HDR_TIME."    ".HDR_TYPE. C 
                                "   ".ITOS(HDR_FSYS))
                              IF  HDR_PERMS#0 START 
                                PRINT STRING("   ".H TO S(HDR_OWNP,2 C 
                                   )."   ".H TO S(HDR_EEP,2). C 
                                   "   ".H TO S(HDR_ARCH,2). C 
                                   "   ".H TO S(HDR_CODES,2). C 
                                   "    ".H TO S(HDR_SSBYTE,2). C 
                                   "  ".H TO S(HDR_CCT,2))
                                IF  HDR_OFFERED TO = "" THEN   C 
                                   PRINT STRING("        ") C 
                                   ELSE  PRINT STRING(" ".HDR_ C 
                                   OFFERED TO." ")
                                IF  HDR_RECORDS > 0 START 
                                   CYCLE  FLAG = 1,1,HDR_RECORDS
                                      SPACES(123) IF  FLAG > 1
                                      PRINT STRING(HDR_PERMLIST C 
                                         (FLAG)_USER." ".H TO S C 
                                         (HDR_PERMLIST(FLAG)_ C 
                                         PERM,2))
                                   REPEAT 
                                FINISH 
                              FINISH 
                              NEWLINE
                              SELECT OUTPUT(0)
                           FINISH 
                           IF  BM=0 START 
                             CYCLE  PAGE = 2,1,NOP+1
                                        !CYCLE THROUGH PAGES IN THE CHAPTER
                                READ PAGE(IN,CHAP,BUFFA,FLAG)
                                        !READ PAGE IN CHAPTER
                                IF  FLAG # 0 START ;!WAS IT OK?
                                   READ FAIL;  !NO THEN TELL THE USER
                                   EXIT 
                                FINISH 
                             REPEAT 
                             EXIT  IF  FLAG # 0
                           FINISHELSESTART ;  ! BULK MOVE#0
                             BULK MOVE(IN,-1,NOP+1,FLAG)
                             ! PAGES TO SINK. DRIVE INTO TM
                             UNLESS  FLAG=X'01040000'!(NOP+1) START 
                               PRINT STRING("BULK MOVE FAILS X". C 
                                     H TO S(FLAG,8)." AT CHAPTER ")
                               WRITE(CHAP,0)
                               NEWLINE
                             FINISH 
                           FINISH 
                        FINISH  ELSE  START 
                           PRINT STRING( C 
                              "CHAPTER IN HEADER NOT AS EXPECTED" C 
                              .SNL)
                           PRINT STRING("ACTUAL ".I TO S(HDR_ C 
                              CHAPTER)." EXPECTED ".I TO S( C 
                              CHAP).SNL)
                        FINISH 
                     FINISH  ELSE  START 
                        PRINT STRING( C 
                           "PAGES IN HEADER NOT AS EXPECTED". C 
                           SNL)
                        PRINT STRING("PAGES = ".I TO S(HDR_ C 
                           E PAGES).SNL)
                     FINISH 
                  FINISH  ELSE  START 
                     PRINT STRING( C 
                        "FILENAME IN HEADER NOT AS EXPECTED". C 
                        SNL)
                     PRINT STRING("FILENAME = ".HDR_FILENAME. C 
                        SNL)
                  FINISH 
               FINISH  ELSE  START 
                  PRINTSTRING( C 
                     "USERNAME IN HEADER NOT AS EXPECTED".SNL)
                  PRINT STRING("USERNAME = ".HDR_USERNAME.SNL)
               FINISH 
            FINISH  ELSE  START 
               PRINT STRING( C 
                  "TAPENAME IN HEADER NOT AS EXPECTED".SNL)
               PRINT STRING("ACTUAL ".HDR_TAPENAME. C 
                  " EXPECTED ".TAPE.SNL)
            FINISH 
         FINISH 
         EXIT  IF  INTERRUPT = "STOP";  !STOP GRACIOUSLY IF USERS ASKS FOR IT
      REPEAT 
      CLOSE TAPE(IN,FLAG)
   FINISH 
   PRINT STRING(ITOS(CHAP-1)." CHAPTERS CHECKED".SNL)
END ;                                   !OF ROUTINE CHECKTAPE1
!*
!*
EXTERNALROUTINE  CHECKTAPE(STRING (63) S)
CHECKTAPE1(S,0);      ! PAGE BY PAGE
END ;       ! EXTERANLROUTINE CHECKTAPE
!*
!*
EXTERNALROUTINE  FCHECKTAPE(STRING (63) S)
CHECKTAPE1(S,1);    ! BULK MOVE
END ;       ! EXTERNALROUTINE FCHECKTAPE
!*
ENDOFFILE