CONSTSTRING  (20) VERSION = "FIX 16  24/10/83"
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, RECORD (RF)ARRAY  R(1 : 2000))
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, RECORD (RRF)NAME  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
   FOR  I = 9,-1,0 CYCLE 
      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
!2**5 Fix up subsystem dynamic refs (shareable basegla)
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
RECORD (CENTF)NAME  CENT
RECORD (DENTF)NAME  DENT
RECORD (OFMF)ARRAYFORMAT  OFMAF(1 : 7)
RECORD (OFMF)ARRAYNAME  OFM
RECORD (CREFF)NAME  CREF
RECORD (DREFF)NAME  DREF
RECORD (RELF)NAME  REL
RECORD (RRF) RR
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
   RECORD (TABF)ARRAYFORMAT  TABLEAF(1 : 1000)
   RECORD (TABF)ARRAYNAME  TABLE
   RECORD (DIRINFF)NAME  DIRINF
   RECORD (CENTF)NAME  CENT
      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)
         FOR  P = 1,1,DIRINF_SCIDENS CYCLE ; !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
   RECORD (DENTF)NAME  DENT
      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
   FOR  I = 1,1,5 CYCLE 
      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 
   ! Subsystem dynamic refs.
   ! If we want a shareable basegla then must fix up ss dynamic refs with
   ! escape descriptors to escape tables on the unshared basegla. The escape
   ! tables are located at known addresses at the start of T#BGLA and constructed
   ! at ss startup
   IF  MODE&32#0 THEN  START 
      LINK=LDATA(8)
      AD=X'00880000';  ! Start of basegla
      WHILE  LINK#0 CYCLE 
         CREF==RECORD(LINK+INBASE)
         LOC=BASE(CREF_REFLOC>>24)+CREF_REFLOC&X'00FFFFFF'
         INTEGER(LOC)=X'E5000000';   ! Escape descriptor
         INTEGER(LOC+4)=AD
         LINK=CREF_LINK
         AD=AD+16
      REPEAT 
   FINISH 
!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)
      FOR  N = 1,1,N CYCLE 
         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)
      FOR  N = 1,1,REL_N CYCLE ;             !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
         FOR  I = GLEN-1,-1,0 CYCLE ;        !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  SSFIX16(STRING  (255) S)
RECORD (RRF) RR
STRING (31) IN,OUT,LIST,UNSH
RECORD (OFMF)ARRAYFORMAT  OFMAF(1:7)
RECORD (OFMF)ARRAYNAME  OFM
CONSTINTEGER  CODESTART = X'00800020'
CONSTINTEGER  OPTFILESIZE=X'1000'
CONSTINTEGER  BASEDIRSIZE=X'3000' { to the nearest page}
INTEGER  FLAG,GLASTART,MODE
   SETPAR(S)
   IN = SPAR(1)
   OUT = SPAR(2)
   LIST = SPAR(3)
   UNSH=SPAR(4)
   CONNECT(IN,0,0,0,RR,FLAG)
   IF  FLAG = 0 START 
      IF  UNSH="U" THEN  START 
         MODE=11
         PRINTSTRING(">>> Unshared basegla <<<
")
         GLASTART = ROUNDUP(CODESTART+RR_DATAEND+BASEDIRSIZE+ 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  START 
         MODE=43
         PRINTSTRING(">>> Shared basegla <<<
")
         OFM==ARRAY(RR_CONAD+INTEGER(RR_CONAD+28)+4,OFMAF)
         GLASTART=CODESTART+OFM(2)_START
      FINISH 
   FINISH  ELSE  GLASTART = 0;          !FIX WILL PRODUCE FAILURE MESSAGE
   FIX(IN,OUT,LIST,MODE,CODESTART,GLASTART)
END ;                                   !OF SSFIX

ENDOFFILE