!**************************
!* LINK6S/LINK *
!* DATE: 10.APR.80 *
!* 4TH PASS FOR IMP COMP. *
!**************************
CONTROL K'101011'; ! 11/45 & TRUSTED
RECORDFORMAT DFGH(INTEGER G)
CONSTRECORD (DFGH) NAME NULL = 0
BEGIN
!! STK = 27200
CONSTBYTEINTEGERNAME ID = K'160030'
CONSTBYTEINTEGERNAME FSYS = K'160055'
CONSTINTEGER EXAMINE = 0
CONSTINTEGER OUT = 2; ! 'MAP' OUTPUT STREAM
INTEGER CKSM, BC, LOADPT, STK, STR, I, J
INTEGER LOAD, N, STK STRT, CODEL, GLAL, LDL
INTEGER STK GAP, TSTK, CODE STRT
OWNINTEGER GLA STRT = K'20'; ! LEAVES 20 BYTES FOR ME
OWNINTEGER CODE BASE = K'40000'
CONSTINTEGER SUPER CODE BASE = K'1400'
OWNINTEGER U REF = 0
OWNINTEGER PROG FILE = 0
OWNINTEGER F BLOCK =- 1
RECORDFORMAT SEGDF(INTEGER TYPE, LEN)
RECORDFORMAT FBF(INTEGER S, BC, LD, BYTEINTEGERARRAY C
NAME(0:3), INTEGER SP, RECORD (SEGDF) ARRAY SEGDEF(0:7))
OWNRECORD (FBF)FB
CONSTINTEGER NO ACCESS = 4
CONSTINTEGER READ ONLY = 5
CONSTINTEGER READ WRITE = 6
CONSTINTEGER SHARED = 7
CONSTINTEGER GLA MAX = 11000, GLA MAXI = 5500
RECORDFORMAT GF(INTEGERARRAY C(0:GLA MAXI))
RECORDFORMAT GBF(BYTEINTEGERARRAY C(0:GLA MAX))
RECORD (GF) NAME GLAI
RECORD (GBF)GLA
RECORDFORMAT LFMF(STRING (8)NAME, BYTEINTEGER FLAG, INTEGER C
REF)
RECORDFORMAT R1F(RECORD (LFMF) NAME LFM)
RECORDFORMAT R2F(BYTEINTEGERNAME N)
RECORDFORMAT R3F(INTEGER X)
RECORD (R1F)R1
RECORD (R2F) NAME R2
RECORD (R3F) NAME R3
RECORDFORMAT GLA HEADF(INTEGERARRAY A(0:4), INTEGER CODES, C
STK LM, GLA END)
RECORD (GLA HEADF) NAME GLA HEAD
RECORDFORMAT REFF(INTEGER PT, INTEGER CODE, GLA)
RECORD (REFF) NAME REF
RECORDFORMAT STRDF(INTEGER R, N, G, BYTEINTEGER S, RP, UNIT, C
FSYS, BYTEINTEGERARRAY NAME(0:5), INTEGER BLOCK)
RECORDFORMAT STRPF(RECORD (STRDF) NAME STRD)
RECORD (STRDF) NAME STRD
CONSTRECORD (STRPF) NAME STRP1 = K'160034'
CONSTRECORD (STRPF) NAME STRP5 = K'160044'
CONSTINTEGERNAME STRP2 = K'160036'
RECORDFORMAT UNDEFF(STRING (8)NAME, BYTEINTEGER FLAG, C
INTEGER REF)
CONSTINTEGER LIB END = 2
CONSTINTEGER LIB FILE = 1
RECORDFORMAT P2F(BYTEINTEGER SERVICE, REPLY, INTEGER A1, C
BYTEINTEGERNAME A2, INTEGER A3)
OWNRECORD (UNDEFF) ARRAY UNDEFA(0:100)
OWNINTEGER UND PT = 0
CONSTINTEGER LIB ENTRIES = 41
RECORD (LFMF) ARRAY LIBA(0:LIB ENTRIES+1)
ROUTINESPEC FIX GLA HEADER
ROUTINESPEC DO REFS(INTEGER PT)
ROUTINESPEC CHECK REFS
ROUTINESPEC GET LIB(BYTEINTEGER FSYS)
ROUTINESPEC LOAD FILE
ROUTINESPEC FIX EXTERNALS(BYTEINTEGER FSYS)
ROUTINESPEC STUFF SEGS
ROUTINESPEC PUT BLOCK(RECORD (GBF) NAME C, INTEGER INIT, C
MAX)
ROUTINESPEC START BLOCK
ROUTINESPEC DIGEST(RECORD (GBF) NAME C)
ROUTINESPEC PUT DUMMY HEADER
ROUTINESPEC COPY HEADER(RECORD (FBF) NAME FB)
ROUTINE OCTAL(INTEGER N)
INTEGER I
SPACE
CYCLE I = 15, -3, 0
PRINTSYMBOL((N >> I)&7+'0')
REPEAT
END
INTEGERFN SYM
INTEGER N
READSYMBOL(N)
RESULT = N
END
INTEGERFN WORD
INTEGER N
N = SYM
RESULT = SYM << 8!(N&X'FF')
END
ROUTINE PUT(INTEGER I)
PRINTSYMBOL(I)
CKSM = CKSM+I
END
ROUTINE PUT WORD(INTEGER I)
PUT(I&X'FF'); PUT(I >> 8)
END
ROUTINE PLANT(INTEGER QUANT, ACCESS, INTEGERNAME SEGS)
INTEGER LEN, N
N = 0
UNTIL QUANT <= 0 CYCLE
N = N+1; LEN = QUANT
IF LEN > K'17777' THEN LEN = K'17777'
FB_SEGDEF(SEGS)_TYPE = ACCESS
FB_SEGDEF(SEGS)_LEN = LEN
QUANT = QUANT-LEN-1; SEGS = SEGS+1
REPEAT
END
INTEGERFN ROCTAL
INTEGER SUM, N, I
SUM = 0
SKIPSYMBOL WHILE NEXTSYMBOL = ' ' OR NEXTSYMBOL = NL
CYCLE
N = NEXTSYMBOL-'0'
RESULT = SUM IF N < 0 OR N > 7
SUM = SUM << 3+N
SKIPSYMBOL
REPEAT
END
GLAI == GLA
R2 == R1; R3 == R2
FB_NAME(I) = ' ' FOR I = 0, 1, 3
IF STRP2 = 0 START
STRD == STRP5_STRD
UNLESS STRD == NULL START
FB_NAME(I) = STRD_NAME(I) FOR I = 0, 1, 3
FINISH
STK = K'14000'
STR = K'5000'
ELSE
PROMPT('NAME?')
CYCLE I = 0, 1, 3
READSYMBOL(J)
EXITIF J = NL
FB_NAME(I) = J
REPEAT
PROMPT('STACK:')
STK = ROCTAL
IF STK = 0 THEN CODE BASE = SUPER CODE BASE
PROMPT('STREAMS:'); STR = ROCTAL
STR = STR*K'1030'+K'500'
NEWLINE
FINISH
CODE STRT = 0
SELECT OUTPUT(1)
PUT DUMMY HEADER
STRD == STRP5_STRD
F BLOCK = STRD_BLOCK UNLESS STRD == NULL
SELECTOUTPUT(OUT)
PRINTSTRING('PROG:'); PRINTSYMBOL(FB_NAME(I)) FOR I = 0, 1, 3
NEWLINE
LOAD FILE
DO REFS(GLAL)
FIX EXTERNALS(FSYS)
FIX EXTERNALS(0)
STUFF SEGS
GLAI_C(0) = GLA HEAD_GLA END; ! ACTUAL TOP-OF-STACK WORD
IF STK = 0 THEN STK STRT = K'140000'; ! SPECIAL FOR SUPERVISOR
PUT BLOCK(GLA, STK STRT, GLAL)
START BLOCK
CHECK REFS
STOP
ROUTINE FIX GLA HEADER
R2_N == GLA_C(GLA STRT)
GLA HEAD == R1_LFM; ! POINT GLA RECORD AT GLA
GLA HEAD_CODES = CODE BASE+CODE STRT
GLA HEAD_STK LM = STK STRT
GLA HEAD_GLA END = STK STRT+GLAL
END
ROUTINE QUIT(STRING (20)S)
SELECT OUTPUT(0)
PRINTSTRING(S); NEWLINE
STOP
END
RECORD (UNDEFF) MAP GET LINK(RECORD (LFMF) NAME LFM)
INTEGER N
N = 0
IF UND PT # 0 START
CYCLE N = 0, 1, UND PT
RESULT == UNDEFA(N) IF UNDEFA(N)_NAME = LFM_NAME
REPEAT
FINISH
UNDEFA(N)_NAME = LFM_NAME; UND PT = UND PT+1
RESULT == UNDEFA(N)
END
ROUTINE FILL CHAIN(RECORD (LFMF) NAME LFM, INTEGER RADD)
INTEGERNAME LINK
RECORD (UNDEFF) NAME UNDEF
UNDEF == GET LINK(LFM); ! GET EXISTING, OR A NEW, CHAIN
IF UNDEF_FLAG = 1 START
PRINTSTRING(LFM_NAME); WRITE(UNDEF_FLAG, 2)
WRITE(LFM_FLAG, 2); SPACE
QUIT('*DOUBLE DEF?')
FINISH
WHILE UNDEF_REF # 0 CYCLE ; ! SEARCH THE ENTRIES
LINK == GLAI_C(UNDEF_REF >> 1)
UNDEF_REF = LINK; ! REMEMBER NEXT LINK
LINK = RADD; ! AND FILL IN THIS ONE
REPEAT
UNDEF_FLAG = 1
UNDEF_REF = RADD; ! REMEMBER ADDRESS FOR FUTURE USE
IF UNDEF_NAME = '#GO' THEN GLAI_C(1) = RADD
END
ROUTINE DO REFS(INTEGER PT)
CONSTSTRING (5) ARRAY TYPE(0:3) = C
'XDEF:', 'XREF:', 'DDEF:', 'DREF:'
RECORD (R2F) NAME R2
RECORD (R1F)R1
RECORD (LFMF) NAME LFM
RECORD (UNDEFF) NAME UNDEF
INTEGER I, N, P, Q, C, CTY, TYP, SHSF, PR
INTEGERNAME LINK
R2 == R1
C = 0; CTY = 0; ! FORMATTING VARIABLE FOR 'REFS'
SHSF = 0; ! SHARED CODE FLAG
CYCLE
R2_N == GLA_C(PT)
LFM == R1_LFM
EXITIF LENGTH(LFM_NAME) = 0
TYP = LFM_FLAG
IF TYP&1 # 0 START
!! REFERENCE
U REF = U REF+1
LFM_REF = LFM_REF+GLA STRT
! ADD IN BASE OF LOCAL GLA
UNDEF == GET LINK(LFM)
GLAI_C(LFM_REF >> 1) = UNDEF_REF
UNDEF_REF = LFM_REF IF UNDEF_FLAG = 0
! IE, NOT ALREDY DEFINED
!! IF IT EAS DEFINED, THEN FILL IN THE REFERENCE
!! OTHERWISE: CONSTRUCT LINKS THROUGH THE REFERENCES
IF C = 0 OR CTY # TYP START
C = 0; CTY = TYP
SPACES(2); PRINTSTRING(TYPE(TYP))
FINISH
PRINTSTRING(LFM_NAME); SPACES(10-LENGTH(LFM_NAME))
IF C = 4 THEN C = 0 AND NEWLINE ELSE C = C+1
ELSE
!! DEFINITION
NEWLINE IF C # 0; C = 0
P = LFM_REF+GLA STRT; ! P IS THE ARRAY INDEX OF ITEM
Q = P+STK STRT+(2-TYP&127); ! Q IS THE REAL ADDRESS OF ITEM
PR = Q
R2_N == GLA_C(P)
REF == R1_LFM; ! REF POINTS TO BEGINNING OF
! THE 3 WORDS
IF TYP&127 = 0 START ; ! FOR ROUTINE REFS ONLY
REF_PT = Q
IF TYP = 0 START
REF_CODE = REF_CODE+CODE BASE+CODE STRT
PR = REF_CODE
ELSE
SHSF = 1
FINISH
REF_GLA = GLA STRT+STK STRT
FINISH
FILL CHAIN(LFM, Q); ! DEAL WITH UNDEFINEDS
SPACES(2)
PRINTSTRING(TYPE(TYP&127)); OCTAL(PR); SPACES(2)
PRINTSTRING(LFM_NAME); NEWLINE
FINISH
PT = PT+12
REPEAT
NEWLINE IF C # 0
FIX GLA HEADER IF SHSF = 0; ! NOT IN CASE OF SHARED FILE
END
ROUTINE CHECK REFS
INTEGER N
RECORD (UNDEFF) NAME UNDEF
SELECT OUTPUT(0)
N = 0
WHILE N <= UNDPT-1 CYCLE
UNDEF == UNDEFA(N)
IF UNDEF_FLAG = 0 START
PRINTSTRING(UNDEF_NAME); PRINTSTRING(' UNDEFINED!
')
FINISH
N = N+1
REPEAT
END
ROUTINE GET LIB(BYTEINTEGER FSYS)
CONSTBYTEINTEGERARRAY LIB(0:5) =
'L', 'I', 'B', '0', '0', '0'
RECORD (P2F)P2, P3
RECORDFORMAT FILEF(BYTEINTEGER UNIT, FSYS, C
BYTEINTEGERARRAY NAME(0:5))
RECORD (FILEF)FILE
RECORDFORMAT F1F(BYTEINTEGER X)
RECORD (F1F) NAME F1
F1 == LIBA(0)
FILE_NAME(I) = LIB(I) FOR I = 0, 1, 5
FILE_FSYS = FSYS; FILE_UNIT = 0
LIBA(0)_FLAG = LIB END; ! PROTECTION AGAINST NO LIB
P2_SERVICE = 4; P2_REPLY = ID
P2_A1 = EXAMINE; P2_A2 == FILE_UNIT
PONOFF(P2)
IF P2_A1 = 0 THENRETURN
P3_SERVICE = 3; P3_REPLY = ID
P3_A1 = 0; ! READ BLOOCK
P3_A2 == F1_X
P3_A3 = P2_A1
PONOFF(P3)
END
ROUTINE LOAD FILE
INTEGER PHY ADD, LINO
SELECT INPUT(1)
READSYMBOL(I) UNTIL I = 1; SKIPSYMBOL
BC = WORD; LOAD PT = WORD
CODEL = WORD+CODE STRT; GLAL = WORD+GLA STRT; LDL = WORD
IF PROG FILE = 0 START
TSTK = STK+GLAL+K'100'; ! WITH EXTRA FOR EXT GLAS
STK GAP = K'160000'-TSTK
STK STRT = STK GAP&K'160000'
IF STK STRT = K'40000' START
SELECT OUTPUT(0); PRINTSTRING('STACK OVERFLOW?
')
SELECT OUTPUT(OUT)
STK STRT = K'60000'
FINISH
IF STK = 0 THEN STK STRT = (CODE BASE+CODEL+K'77')&K'177700'
!! SUPERVISOR GLA ON END OF CODE
FINISH
PROG FILE = PROG FILE+1
PHY ADD = CODE STRT+CODE BASE
PRINTSTRING(' CODE:'); OCTAL(PHY ADD)
PRINTSTRING(' GLA:'); OCTAL(GLA STRT+STK STRT)
NEWLINE
IF GLAL > GLA MAX THEN QUIT('GLA BUFFER OVERFLOW')
SKIPSYMBOL AND BC = BC-1 UNTIL BC = 11
! INCLUDE CKSM
CYCLE
READSYMBOL(I) UNTIL I = 1; SKIPSYMBOL
BC = WORD
EXITIF BC = 6
LOAD = WORD
IF BC < 6 THEN QUIT('FILE FORMAT ERROR')
IF LOAD >= 0 START
SELECT OUTPUT(1)
CKSM = 0
PUT WORD(1); PUT WORD(BC)
PUT WORD(LOAD+PHY ADD)
DIGEST(NULL)
PRINTSYMBOL(-CKSM)
LINO = WORD; PUT WORD(LINO)
PRINTSYMBOL(0); PRINTSYMBOL(0)
SELECT OUTPUT(OUT)
ELSE
LOAD = LOAD&K'77777'+GLA STRT
DIGEST(GLA)
FINISH
REPEAT
END
ROUTINE ARRANGE FOR LOAD(RECORD (LFMF) NAME LIB)
RECORD (STRDF) NAME STRD
SELECT INPUT(1)
CLOSE INPUT
STRD == STRP1_STRD
STRD_FSYS = LIB_REF; ! COPY FILE SYSTEM NUMBER
STRD_NAME(I) = CHARNO(LIB_NAME, I+1) FOR I = 0, 1, 5
END
ROUTINE FIX EXTERNALS(BYTEINTEGER FSYS)
INTEGER FLAG, I
RECORD (LFMF) NAME LIB, LIBN
RECORD (UNDEFF) NAME UNDEF
RETURNIF UREF = 0
GET LIB(FSYS)
FLAG = 1; N = 0
WHILE N <= UND PT-1 CYCLE
UNDEF == UNDEFA(N)
IF UNDEF_FLAG = 0 START
CYCLE I = 0, 1, LIB ENTRIES
LIB == LIBA(I)
EXITIF LIB_FLAG = LIB END
IF LIB_FLAG = LIB FILE START
LIBN == LIB
CONTINUE
FINISH
IF UNDEF_NAME = LIB_NAME START
IF LIB_FLAG&128#0 START ; ! SHARED ENTRY
FILL CHAIN(LIB, LIB_REF); ! DEAL WITH IT NOW
CONTINUE
FINISH
PRINTSTRING('FILE:'); PRINTSTRING(LIBN_NAME)
NEWLINE
ARRANGE FOR LOAD(LIBN)
! SET THE STREAM UP
CODE STRT = CODEL
IF STK=0 AND PROG FILE=1 THEN C
CODE STRT=K'61000'-SUPER CODE BASE
GLA STRT = GLAL
LOAD FILE
DO REFS(GLAL)
EXIT
FINISH
REPEAT
FINISH
N = N+1
REPEAT
END
ROUTINE STUFF SEGS
INTEGER SS, SEGPT, TSTK, SEG, DIFF, SS2
TSTK = STK+GLAL; ! WORK IT OUT AGAIN
IF TSTK+STK STRT > K'160000' THEN TSTK = K'160000'-STK STRT
SS = (K'160000'-TSTK)>>13; SS2 = STK STRT>>13
PRINTSTRING('
TOTALS: CODE =')
OCTAL(CODEL)
PRINTSTRING(' GLA/STACK ='); OCTAL(TSTK); NEWLINE
SEGPT = 1
FB_SEGDEF(0)_TYPE = 4
FB_SEGDEF(1)_TYPE = SHARED; FB_SEGDEF(1)_LEN = 0
SEG = 2
PLANT(CODEL+4, READ ONLY, SEG)
IF SEG > SS2 AND STK # 0 THEN QUIT("VIRTUAL MEMORY TOO SMALL")
WHILE SEG < SS2 CYCLE
FB_SEGDEF(SEG)_TYPE = NO ACCESS
SEG = SEG+1
REPEAT
PLANT(TSTK, READ WRITE, SEG)
IF SS # SS2 START
FB_SEGDEF(SEG)_TYPE = NO ACCESS; SEG = SEG+1
FINISH
PLANT(STR, READ WRITE, SEG)
FB_S = 1
FB_BC = 8*4+6+4+2
FB_LD = 0
FB_SP = STK STRT+TSTK-2
COPY HEADER(FB)
END
ROUTINE PUT BLOCK(RECORD (GBF) NAME C, INTEGER INIT, MAX)
INTEGER I
SELECT OUTPUT(1)
CKSM = 0
PUT(1); PUT(0); PUT WORD(MAX+6)
PUT WORD(INIT)
CYCLE I = 0, 1, MAX-1
PUT(C_C(I))
REPEAT
PUT(-CKSM)
PUT WORD(0)
SELECT OUTPUT(OUT)
END
ROUTINE START BLOCK
SELECT OUTPUT(1)
CKSM = 0
PUT WORD(1); PUT WORD(6); PUT WORD(-1)
PUT(-CKSM)
SELECT OUTPUT(OUT)
END
ROUTINE DIGEST(RECORD (GBF) NAME C)
INTEGER N
CYCLE BC = BC-7, -1, 0
READSYMBOL(N)
IF C == NULL START
PRINTSYMBOL(N); CKSM = CKSM+N
ELSE
C_C(LOAD) = N; LOAD = LOAD+1
FINISH
REPEAT
SKIPSYMBOL; ! THE CHECKSUM
END
ROUTINE PUT DUMMY HEADER
INTEGER I
PRINTSYMBOL(0) FOR I = 1, 1, 47
END
ROUTINE COPY HEADER(RECORD (FBF) NAME FB)
RECORDFORMAT RX2F(BYTEINTEGER X)
RECORD (RX2F) NAME RX2
RECORD (FBF) NAME RX
RECORD (P2F)P3
RX == LIBA(0)
RX2 == RX
QUIT('NO OUTPUT FILE') IF FBLOCK = -1
SELECT OUTPUT(1)
PRINTSYMBOL(0) FOR I = 1, 1, 512-60
SELECT OUTPUT(OUT)
P3_SERVICE = 3; P3_REPLY = ID
P3_A1 = 0
P3_A2 == RX2_X
P3_A3 = F BLOCK
PONOFF(P3); ! READ THE FIRST BLOCK AGAIN
QUIT('READ DISC FAILS') IF P3_A1 # 0
RX = FB; ! COPY NEW HEADER
P3_SERVICE = 3; P3_REPLY = ID
P3_A1 = 1; ! WRITE
P3_A2 == RX2_X
P3_A3 = FBLOCK
PONOFF(P3); ! AND WRITE THE BLOCK OUT
QUIT('WRITE DISC FAILS') IF P3_A1 # 0
END
ENDOFPROGRAM