CONSTSTRING  (20) VERSION = "FIX 14  13/3/81"
CONSTINTEGER  SEGSIZE = X'00040000'
!**** RECORD FORMATS ****
RECORDFORMAT  DIRINFF(STRING  (6) USER,  C 
   STRING  (31) BATCHFILE,  C 
   INTEGER  MARK, FSYS, PROCNO, ISUFF, REASON, BATCHID,  C 
   SESSICLIM, SCIDENSAD, SCIDENS, OPERNO, MSGFAD, SCDATE,  C 
   SYNC1DEST, SYNC2DEST, ASYNCDEST)
RECORDFORMAT  TABF(STRING  (31) NAME, INTEGER  I, J)
RECORDFORMAT  RF(INTEGER  AREALOC, BASELOC)
RECORDFORMAT  RELF(INTEGER  LINK, N, RECORDARRAY  R(1 : 2000)(RF))
RECORDFORMAT  OFMF(INTEGER  START, L, PROP)
RECORDFORMAT  RRF(INTEGER  CONAD, FILETYPE, DATASTART, DATAEND)
RECORDFORMAT  CENTF(INTEGER  LINK, LOC, STRING  (31) IDEN)
RECORDFORMAT  DENTF(INTEGER  LINK, DISP, L, A, STRING  (31) IDEN)
RECORDFORMAT  CREFF(INTEGER  LINK, REFLOC, STRING  (31) IDEN)
RECORDFORMAT  DREFF(INTEGER  LINK, REFARRAY, L, STRING  (31) IDEN)
!**** SYSTEM AND EXTERNAL SPECS******
DYNAMICINTEGERFNSPEC  BUILDSCT(INTEGER  OUTBASE, INBASE)
EXTERNALINTEGERFNSPEC  OUTSTREAM
EXTERNALSTRINGFNSPEC  TIME
EXTERNALSTRINGFNSPEC  DATE
EXTERNALINTEGERFNSPEC  UINFI(INTEGER  N)
EXTERNALROUTINESPEC  DEFINE(STRING  (255) S)
SYSTEMROUTINESPEC  PSYSMES(INTEGER  ROOT, FLAG)
SYSTEMROUTINESPEC  TRIM(STRING  (31) FILE, INTEGERNAME  FLAG)
SYSTEMROUTINESPEC  DISCONNECT(STRING  (31) S, INTEGERNAME  FLAG)
SYSTEMROUTINESPEC  SETPAR(STRING  (255) S)
SYSTEMSTRINGFNSPEC  SPAR(INTEGER  N)
SYSTEMROUTINESPEC  CONNECT(STRING  (31) FILE,  C 
   INTEGER  MODE, HOLE, PROT, RECORDNAME  RR, INTEGERNAME  FLAG)
SYSTEMROUTINESPEC  OUTFILE(STRING  (31) FILE,  C 
   INTEGER  SIZE, HOLE, PROT, INTEGERNAME  CONAD, FLAG)
SYSTEMROUTINESPEC  MOVE(INTEGER  LEN, FROM, TO)
SYSTEMROUTINESPEC  PHEX(INTEGER  I)

STRINGFN  ITOS(INTEGER  N)
                                        !RETURNS STRING CONTAINING
                                        ! CHARACTER VALUE OF N WITH
                                        ! NO LEADING SPACE
                                        !N SHOULD BE POSITIVE OR
                                        ! NEGATIVE INTEGER
CONSTINTEGERARRAY  TENS(0 : 9) =                   C 
 1, 10, 100, 1000, 10000, 100000 C 
        , 1000000, 10000000, 100000000, 1000000000
STRING  (11) RES
INTEGER  M, R, I, STARTED
   IF  N = 0 THEN  RESULT  = "0";       !SPECIAL CASE
   IF  N < 0 THEN  N = -N AND  RES = "-" ELSE  RES = ""
   STARTED = 0;                         !INDICATES THAT NO CHAS PUT
                                        ! OUT SO FAR
   CYCLE  I = 9,-1,0
      R = TENS(I)
      IF  N >= R OR  STARTED # 0 START 
         STARTED = 1;                   !TO INDICATE THAT CHAR
                                        ! ALREADY FOUND
         M = N//R
         RES = RES.TOSTRING(M+'0')
         N = N-M*R
      FINISH 
   REPEAT 
   RESULT  = RES
END ;                                   !OF ITOS

INTEGERFN  ROUNDUP(INTEGER  N, ROUND)
                                        !RESULT IS N ROUNDED UP TO
                                        ! MULTIPLE OF ROUND >=N
   ROUND = ROUND-1
   RESULT  = (N+ROUND)&(¬ROUND);        ! AND WITH NOT ROUND
END ;                                   !OF ROUNDUP

ROUTINE  FIX(STRING  (31) IN, OUT, LIST,  C 
   INTEGER  MODE, CODESTART, GLASTART)
!BITS IN MODE -
!2**0 COPY LOAD DATA
!2**1 FILL REFS FROM CURRECT SC TABLE
!2**2 SUPERVISOR - PUT DESCRIPTOR TO "ENTER" ADDRESS IN WORD 8 OF HEADER
!    ALSO ALIGN GLAP ON PAGE BOUNDARY
!2**3 PUT JUMP IN WORD 5 OF HEADER - TEMPORARY ARRANGEMENT TILL
!SUPERVISOR AND DIRECTOR CHANGED
INTEGER  AREACODE, AREADISP, BASECODE, BASEDISP, N, DR0, DR1
INTEGER  UNSATCODE, UNSATDATA, CUROUTSTREAM, OLDSTART,  C 
      NEWSTART, BLOCKS, GLEN
INTEGER  FLAG, INBASE, OUTBASE, LOC, I, LINK, LEN, OUTLEN, AD
INTEGER  RLINK, REFARRAY
INTEGERARRAY  BASE(1 : 7);              !AREA START ADDRESSES IN  FILE 'OUT'
INTEGERARRAY  LBASE(1 : 7);             !AREA START ADDRESSES WHEN LOADED
INTEGERARRAYFORMAT  LDATAAF(0 : 14)
INTEGERARRAYFORMAT  REFLOCAF(1 : 1000)
INTEGERARRAYNAME  LDATA, REFLOC
RECORDNAME  CENT(CENTF)
RECORDNAME  DENT(DENTF)
RECORDARRAYFORMAT  OFMAF(1 : 7)(OFMF)
RECORDARRAYNAME  OFM(OFMF)
RECORDNAME  CREF(CREFF)
RECORDNAME  DREF(DREFF)
RECORDNAME  REL(RELF)
RECORD  RR(RRF)
STRING  (31) IDEN

   ROUTINE  PRINTBOTH(STRING  (255) S)
!PRINTS MESSAGE TERMINATED BY NEWLINE ON BOTH STREAMS CUROUTSTREAM AND 1
      PRINTSTRING(S)
      NEWLINE
      SELECTOUTPUT(CUROUTSTREAM)
      PRINTSTRING(S)
      NEWLINE
      SELECTOUTPUT(1)
   END ;                                !OF PRINT BOTH

   ROUTINE  FAIL(STRING  (100) S)
      SELECTOUTPUT(0)
      PRINTSTRING("FAILURE IN FIX - ".S)
      STOP 
   END ;                                !OF FAIL

   ROUTINE  FINDCODEEP(STRING  (31) ENTRY,  C 
      INTEGERNAME  DR0, DR1, FLAG)
   INTEGER  LINK, P
   RECORDARRAYFORMAT  TABLEAF(1 : 1000)(TABF)
   RECORDARRAYNAME  TABLE(TABF)
   RECORDNAME  DIRINF(DIRINFF)
   RECORDNAME  CENT(CENTF)
      LINK = LDATA(1)
      WHILE  LINK # 0 CYCLE 
         CENT == RECORD(INBASE+LINK)
         IF  ENTRY = CENT_IDEN START 
            DR0 = X'B1000000'
            DR1 = LBASE((CENT_LOC>>24)&X'F')+CENT_LOC&X'FFFFFF'
            FLAG = 0
            RETURN 
         FINISH 
         LINK = CENT_LINK
      REPEAT 
      IF  MODE&2 = 2 START ;            !FILL UNSAT REFS FROM SC TABLE
         DIRINF == RECORD(UINFI(10))
         TABLE == ARRAY(DIRINF_SCIDENSAD,TABLEAF)
         CYCLE  P = 1,1,DIRINF_SCIDENS; !NO OF ENTRIES IN SC TABLE
            IF  TABLE(P)_NAME = ENTRY START ;!ENTRY FOUND
               DR0 = X'E3000000'!TABLE(P)_I
               DR1 = TABLE(P)_J
               RETURN 
            FINISH 
         REPEAT 
      FINISH 
      PRINTSTRING("UNSAT REF ".ENTRY)
      NEWLINE
      FLAG = 1
      DR0 = M'NORT';                    !USEFUL FOR DIAGNOSING FAULTS
      MOVE(4,ADDR(ENTRY)+1,ADDR(DR1));  !FIRST FOUR BYTES OF ENTRY NAME
      DR1 = X'54524546'
      UNSATCODE = UNSATCODE+1
   END ;                                !OF FINDCODEEP

   ROUTINE  FINDDATAEP(STRING  (31) ENTRY,  C 
      INTEGERNAME  AD, FLAG)
   INTEGER  LINK
   RECORDNAME  DENT(DENTF)
      LINK = LDATA(4)
      WHILE  LINK # 0 CYCLE 
         DENT == RECORD(INBASE+LINK)
         IF  ENTRY = DENT_IDEN START 
            AD = LBASE(DENT_A)+DENT_DISP
            FLAG = 0
            RETURN 
         FINISH 
         LINK = DENT_LINK
      REPEAT 
      PRINTSTRING("UNSAT DATA REF ".ENTRY)
      NEWLINE
      AD = 0;                           !NULL VALUE
      FLAG = 1
      UNSATDATA = UNSATDATA+1
   END ;                                !OF FINDDATAEP
   IF  LIST = "" THEN  LIST = "T#LIST"; !DEFAULT LISTING FILE
   CUROUTSTREAM = OUTSTREAM
   DEFINE("1,".LIST)
   SELECTOUTPUT(1)
   PRINTBOTH(VERSION)
   NEWLINES(2)
   PRINTSTRING("FIX CALLED AT ".TIME." ON ".DATE)
   NEWLINES(2)
   PRINTSTRING("INPUT: ".IN)
   NEWLINE
   PRINTSTRING("OUTPUT: ".OUT)
   NEWLINE
   PRINTSTRING("CODESTART: ")
   PHEX(CODESTART)
   NEWLINE
   PRINTSTRING("GLASTART: ")
   PHEX(GLASTART)
   NEWLINES(2)
   UNSATCODE = 0
   UNSATDATA = 0
   CONNECT(IN,0,0,0,RR,FLAG);           !CONNECT INPUT FILE - READ
   -> ERR IF  FLAG # 0
   IF  INTEGER(RR_CONAD+12) # 1 THEN  FAIL("INVALID FILETYPE")
   INBASE = RR_CONAD
   LEN = RR_DATAEND
   IF  MODE&16 = 16 THEN  OUTLEN = LEN+8192 ELSE  OUTLEN = LEN
                                        !DIRECTOR NEEDS ROOM FOR SC TABLE
   OUTFILE(OUT,OUTLEN+4096,0,0,OUTBASE,FLAG);!ALLOW FOR ALIGNMENT IN SUPERVISOR - A BIT GENEROUS
   -> ERR IF  FLAG # 0
   MOVE(LEN,INBASE,OUTBASE);            !COPY FILE TO 'OUT'
   LDATA == ARRAY(INBASE+INTEGER(INBASE+24),LDATAAF)
                                        !LOAD DATA
   OFM == ARRAY(INBASE+INTEGER(INBASE+28)+4,OFMAF)
                                        !OBJECT FILE MAP
   CYCLE  I = 1,1,5
      BASE(I) = OUTBASE+OFM(I)_START
   REPEAT 
   LBASE(1) = OFM(1)_START+CODESTART;   !START OF LOADED CODE
   LBASE(2) = GLASTART;                 !START OF LOADED GLA
   LBASE(4) = OFM(4)_START+CODESTART;   !START OF LOADED SST
   LBASE(5) = OFM(2)_L+GLASTART;        !START OF LOADED UST
!NOW GO THROUGH CODE REFS FILLING IN INFO
   LINK = LDATA(7);                     !STATIC CODE REFS
   WHILE  LINK # 0 CYCLE 
      CREF == RECORD(LINK+INBASE)
      FINDCODEEP(CREF_IDEN,DR0,DR1,FLAG)
      LOC = BASE(CREF_REFLOC>>24)+CREF_REFLOC&X'FFFFFF'
      INTEGER(LOC) = DR0
      INTEGER(LOC+4) = DR1
      LINK = CREF_LINK
   REPEAT 
!NOW DEAL WITH DATA REFS
   LINK = LDATA(9)
   WHILE  LINK # 0 CYCLE 
      DREF == RECORD(LINK+INBASE)
      REFARRAY = (DREF_REFARRAY&X'7FFFFFFF')+INBASE
                                        !AND OFF COMMON BIT
      N = INTEGER(REFARRAY)
      REFLOC == ARRAY(REFARRAY+4,REFLOCAF)
      FINDDATAEP(DREF_IDEN,AD,FLAG)
      CYCLE  N = 1,1,N
         LOC = BASE(REFLOC(N)>>24)+REFLOC(N)&X'FFFFFF'
         INTEGER(LOC) = INTEGER(LOC)+AD
      REPEAT 
      LINK = DREF_LINK
   REPEAT 
! NOW DEAL WITH RELOCATION REQUESTS
   LINK = LDATA(14)
   WHILE  LINK # 0 CYCLE 
      REL == RECORD(LINK+INBASE)
      CYCLE  N = 1,1,REL_N;             !NO OF RELOCATION ENTRIES IN THIS BLOCK
         AREACODE = REL_R(N)_AREALOC>>24
         AREADISP = REL_R(N)_AREALOC&X'FFFFFF'
         BASECODE = REL_R(N)_BASELOC>>24
         BASEDISP = REL_R(N)_BASELOC&X'FFFFFF'
         LOC = BASE(AREACODE)+AREADISP
         INTEGER(LOC) = INTEGER(LOC)+LBASE(BASECODE)+BASEDISP
      REPEAT 
      LINK = REL_LINK
   REPEAT 
!NOW FILL IN JUMP TO BYTE 32 BECAUSE DIRECTOR ALWAYS SET
!PC TO 16
   IF  MODE&8 = 8 THEN  INTEGER(OUTBASE+16) = X'1B800008'
                                        !JUMP 8 HALF WORDS(16 BYTES)
!NOW PRINT MAP OF ENTRY POINTS
   NEWLINES(2)
   PRINTSTRING("NAME                          ENTRY POINT")
   NEWLINES(2)
   LINK = LDATA(1);                     !HEAD OF CODE EP LIST
   WHILE  LINK # 0 CYCLE 
      CENT == RECORD(INBASE+LINK)
      PRINTSTRING(CENT_IDEN)
      SPACES(32-LENGTH(CENT_IDEN))
      LOC = BASE((CENT_LOC>>24)&X'F')+CENT_LOC&X'FFFFFF'
      PHEX(INTEGER(LOC+4))
      NEWLINE
      LINK = CENT_LINK
   REPEAT 
!NOW PRINT MAP OF DATA ENTRIES IF ANY
   LINK = LDATA(4);                     !HEAD OF DATA EP LIST
   IF  LINK # 0 START 
      NEWLINES(2)
      PRINTSTRING( C 
         "NAME                        LENGTH              ADDRESS")
      NEWLINES(2)
      WHILE  LINK # 0 CYCLE 
         DENT == RECORD(INBASE+LINK)
         PRINTSTRING(DENT_IDEN)
         SPACES(32-LENGTH(DENT_IDEN))
         WRITE(DENT_L,10)
         SPACES(5)
         PHEX(LBASE(DENT_A)+DENT_DISP)
         NEWLINE
         LINK = DENT_LINK
      REPEAT 
   FINISH 
   IF  MODE&16 = 16 START ;             !SPECIAL ACTIONS FOR DIRECTOR
      INTEGER(OUTBASE+24) = OFM(2)_START;    !START OF GLAP
      INTEGER(OUTBASE+8) = INTEGER(OUTBASE+24);   !TEMP
      INTEGER(OUTBASE) = ROUNDUP(INTEGER(INBASE+24),4096)
                                        !ALLOW ROM FOR CODE AND GLA AND THEN ROUND UP TO PAGE BOUNDARY
      INTEGER(OUTBASE+28) = INTEGER(OUTBASE);!START OF SC TABLE
      INTEGER(OUTBASE+12) = INTEGER(OUTBASE);!TEMPORARY UNTIL DIRECTOR CORRECTED
      FLAG = BUILDSCT(OUTBASE,INBASE);  !NEED INBASE TO GET AT LOAD DATA
      IF  FLAG # 0 THEN  START 
         PRINTBOTH("NUMBER OF SCT FAULTS: ".ITOS(FLAG))
      FINISH 
   FINISH ;                             !END OF DIRECTOR SECTION
   IF  MODE&4 = 4 START ;               !SPECIAL ACTIONS FOR SUPERVISORS
      FINDCODEEP("ENTER",DR0,DR1,FLAG)
      IF  FLAG # 0 THEN  FAIL( C 
         "NO ENTRY POINT ""ENTER"" FOR SUPERVISOR")
      INTEGER(OUTBASE+28) = DR1-GLASTART;    !DISPLACEMENT OF PLT DESCRIPTOR FOR "ENTER"
      OLDSTART = BASE(2)
      NEWSTART = ROUNDUP(BASE(2),4096); !ROUND UP TO NEXT PAGE
      GLEN = OFM(2)_L+OFM(5)_L;         !TOTAL LENGTH OF GLAP
      IF  NEWSTART # OLDSTART START ;   !DONT MOVE IF ALREADY ALIGNED
         CYCLE  I = GLEN-1,-1,0;        !FIELDS MIGHT OVERLAP - DONT USE MOVE
            BYTEINTEGER(NEWSTART+I) = BYTEINTEGER(OLDSTART+I)
         REPEAT 
      FINISH 
      INTEGER(OUTBASE) = NEWSTART+GLEN-OUTBASE;   !NEW LENGTH OF FILE
      INTEGER(OUTBASE+24) = NEWSTART-OUTBASE
!NOW CHECK FOR UN-USED ENTRIES
      LINK = LDATA(1);                  !LIST HEAD OF CODE ENTRIES
      WHILE  LINK # 0 CYCLE 
         CENT == RECORD(INBASE+LINK)
         IDEN = CENT_IDEN
         RLINK = LDATA(7);              !HEAD OF CODE REF LIST
         WHILE  RLINK # 0 CYCLE 
            CREF == RECORD(INBASE+RLINK)
            EXIT  IF  IDEN = CREF_IDEN; !ENTRY IS USED
            RLINK = CREF_LINK
         REPEAT 
         IF  RLINK = 0 AND  IDEN # "ENTER" START ;!ENTRY IS NOT REFERENCED
            PRINTBOTH("**WARNING - PROCEDURE ".IDEN. C 
               " NOT USED")
         FINISH 
         LINK = CENT_LINK
      REPEAT 
!NOW CHECK FOR UNUSED DATA ENTRIES
      LINK = LDATA(4);                  !HEAD OF DATA ENTRY LIST
      WHILE  LINK # 0 CYCLE 
         DENT == RECORD(INBASE+LINK)
         IDEN = DENT_IDEN
         RLINK = LDATA(9);              !HEAD OF DATA REF LIST
         WHILE  RLINK # 0 CYCLE 
            DREF == RECORD(INBASE+RLINK)
            EXIT  IF  IDEN = DREF_IDEN
            RLINK = DREF_LINK
         REPEAT 
         IF  RLINK = 0 START 
            PRINTBOTH("**WARNING - DATA ENTRY ".IDEN. C 
               " NOT USED")
         FINISH 
         LINK = DENT_LINK
      REPEAT 
   FINISH 
   BLOCKS = ROUNDUP(INTEGER(OUTBASE),4096)>>12;   !NO OF 4K BLOCKS
   TRIM(OUT,FLAG)
   DISCONNECT(OUT,FLAG)
   IF  UNSATCODE = 0 = UNSATDATA START 
      PRINTBOTH("ALL REFS FILLED")
   FINISH  ELSE  START 
      IF  UNSATCODE > 0 START 
         PRINTBOTH(ITOS(UNSATCODE). C 
            "  UNSATISFIED CODE REFERENCES")
      FINISH 
      IF  UNSATDATA > 0 THEN  START 
         PRINTBOTH(ITOS(UNSATDATA). C 
            "  UNSATISFIED DATA REFERENCES")
      FINISH 
   FINISH 
   NEWLINE
   PRINTBOTH("NUMBER OF 4K BLOCKS: ".ITOS(BLOCKS))
   RETURN 
ERR:

   SELECTOUTPUT(0)
   IF  FLAG # 0 THEN  PSYSMES(1000,FLAG)
END ;                                   !OF FIX

EXTERNALROUTINE  SJFIX(STRING  (255) S)
!FIX FOR SCIENTIFIC JOBBER
RECORD  RR(RRF)
STRING  (31) IN, OUT, LIST
CONSTINTEGER  CODESTART = X'00800000'
INTEGER  FLAG, GLASTART
   SETPAR(S)
   IN = SPAR(1)
   OUT = SPAR(2)
   LIST = SPAR(3)
   CONNECT(IN,0,0,0,RR,FLAG)
   IF  FLAG = 0 START 
      GLASTART = ROUNDUP(CODESTART+RR_DATAEND,SEGSIZE)
                                        !GLA STARTS AT NEXT FREE SEGMENT AFTER BASEFILE
   FINISH  ELSE  GLASTART = 0;          !FIX WILL PRODUCE FAILURE MESSAGE
   FIX(IN,OUT,LIST,11,CODESTART,GLASTART)
END ;                                   !OF SJFIX

EXTERNALROUTINE  SSFIX(STRING  (255) S)
RECORD  RR(RRF)
STRING  (31) IN, OUT, LIST
CONSTINTEGER  CODESTART = X'00800020'
CONSTINTEGER  SESSDIRSIZE = X'4000'
CONSTINTEGER  OPTFILESIZE = 4096
INTEGER  FLAG, GLASTART
   SETPAR(S)
   IN = SPAR(1)
   OUT = SPAR(2)
   LIST = SPAR(3)
   CONNECT(IN,0,0,0,RR,FLAG)
   IF  FLAG = 0 START 
      GLASTART = ROUNDUP(CODESTART+RR_DATAEND+SESSDIRSIZE+ C 
         OPTFILESIZE+96,SEGSIZE)
                                        !THE 96 ALLOWS FOR 
                                        !3*32 BYTE ENTRIES IN THE PD FILE DIRECTORY FOR THE THREE
                                        !MEMBERS INVOLVED
                                        !GLA STARTS AT NEXT FREE SEGMENT AFTER BASEFILE
   FINISH  ELSE  GLASTART = 0;          !FIX WILL PRODUCE FAILURE MESSAGE
   FIX(IN,OUT,LIST,11,CODESTART,GLASTART)
END ;                                   !OF SSFIX

EXTERNALROUTINE  SPFIX(STRING  (255) S)
RECORD  RR(RRF)
CONSTINTEGER  CODESTART = X'00800000'
STRING  (31) IN, OUT, LIST
INTEGER  GLASTART, FLAG
   SETPAR(S)
   IN = SPAR(1)
   OUT = SPAR(2)
   LIST = SPAR(3)
   CONNECT(IN,0,0,0,RR,FLAG)
   IF  FLAG = 0 START 
      GLASTART = ROUNDUP(CODESTART+RR_DATAEND,SEGSIZE)
                                        !ALLOWS FOR MORE THAN 1 SEGMENT
   FINISH  ELSE  GLASTART = 0
   FIX(IN,OUT,LIST,9,CODESTART,GLASTART)
END ;                                   !OF SPFIX

EXTERNALROUTINE  DIRFIX(STRING  (255) S)
STRING  (31) IN, OUT, LIST
CONSTINTEGER  CODESTART = X'00080000'
CONSTINTEGER  GLASTART = X'000C0000'
   SETPAR(S)
   IN = SPAR(1)
   OUT = SPAR(2)
   LIST = SPAR(3)
   FIX(IN,OUT,LIST,24,CODESTART,GLASTART)
END ;                                   !OF DIRFIX

EXTERNALROUTINE  SUPFIX(STRING  (255) S)
CONSTINTEGER  CODESTART = X'80200000'
CONSTINTEGER  GLASTART = X'80240000'
STRING  (31) IN, OUT, LIST
   SETPAR(S)
   IN = SPAR(1)
   OUT = SPAR(2)
   LIST = SPAR(3)
   FIX(IN,OUT,LIST,4,CODESTART,GLASTART)
END ;                                   !OF SUPFIX
ENDOFFILE