*DECK S$MGDSN 
          PROC S$MGDSN(STRTBL$, IMTBL$, FMTBL$, SPEC$, REC$); 
  
  
#**       S$MGDSN -  MERGE DESIGN                                      #
#                                                                      #
#     CALLING SEQUENCE-                                                #
#         S$MGDSN(STRTBL$, IMTBL$, FMTBL$, SPEC$):                     #
#                                                                      #
#     GIVEN-                                                           #
#         STRTBL$ = DESCRIPTION OF STRINGS WRITTEN BY LONG-CODE.       #
#                                                                      #
#     DOES-                                                            #
#         SETS IMTBL$ = SET OF INTERMEDIATE MERGE PASSES, IF ANY.      #
#         SETS FMTBL$ = FINAL MERGE PASS.                              #
#                                                                      #
#     NOTE-                                                            #
#         THIS ROUTINE HAS BEEN HARD-CODED WITHOUT USE OF MNEMONICS    #
#         TO RESTRICT THE MAXIMUM NUMBER OF INPUT FILES TO ANY MERGE   #
#         TO 14.  REFERENCE TO THIS NUMBER IS MADE IN S$STREC (TO SET  #
#         SPEC$LWSA) AND IN S$ALCS.                                    #
  
          BEGIN 
  
*CALL A 
  
*CALL STRTBL$ 
  
*CALL IMTBL$
  
*CALL FMTBL$
  
*CALL SPEC$ 
  
  
*CALL REC$
  
  
*CALL MACHINE 
  
*CALL DEBUG 
  
          XREF
              BEGIN 
              PROC S$ABORT;            # HANDLE INTERNAL ERROR         #
              END 
  
#                                                                      #
#     THIS ARRAY SHOWS WHICH FILE HAS MULTIPLE STRINGS                 #
#                                                                      #
          ARRAY [1:72] S(1);
              BEGIN 
              ITEM  FILEUSED   B( 0, 0,60);  # TRUE IF NOT FIRST       #
                                             # STRING ON FILE          #
              END 
  
  
  
          ITEM  INDEX        I;      # SCRATCH INDEX                   #
          ITEM  INDEX2       I; 
          ITEM  AVAIL        I; 
  
          # VARIABLES USED TO MASSAGE BFS-S                            #
         #ITEM  AVAIL        I           WORDS AVAILABLE FOR BUFFERS   #
          ITEM  BFSI         I;        # TENTATIVE BFS FOR INPUT BUFS  #
          ITEM  BFSO         I;        # TENTATIVE BFS FOR OUTPUT BUF  #
          ITEM  GOODBFSI     I;        # LAST GOOD BFSI                #
          ITEM  GOODBFSO     I;        # LAST GOOD BFSO                #
          ITEM  I            I;        # SCRATCH                       #
          ITEM  IP           I;        # INDEX TO IMTBL$ FOR THIS PASS #
          ITEM  LKEY         I;        # LENGTH OF ALL KEYS (OR LARGER)#
          ITEM  MRLWORDS     I;        # MAXIMUM RECORD LENGTH IN WORDS#
          ITEM  NIFILES      I;        # NUMBER OF INPUT FILES FOR PASS#
          ITEM  P            I;        # PASS NUMBER (1..IMTBL$PASSES) #
          ITEM  USED         I;        # NUMBER OF WORDS USED FOR BUFS #
  
  
          ITEM  IMPTR        I;      # PTR TO IMTBL$ ENTRY             #
          ITEM  FMPTR        I;      # PTR TO FMTBL$ ENTRY             #
          ITEM  IPTR         I;      # SCRATCH POINTERS                #
          ITEM  JPTR         I; 
          ITEM  KPTR         I; 
          ITEM  FILE         I; 
          ITEM  FILENUM      I; 
          ITEM  LEVEL        I; 
          ITEM  NLEVEL       I; 
          ITEM  MAXMO        I=10;     # MAX. INTER-MERGE ORDER        #
          ITEM  IMAXMO       I;        # INTER-MERGE ORDER             #
          ITEM  NISTR        I;        # NO OF INTER-MERGE STRINGS     #
          ITEM  TABLE1INDEX  I;        # INDEX TO INTERNAL TABLE 1     #
          ITEM  TABLE2INDEX  I;        # INDEX TO INTERNAL TABLE 2     #
          ITEM  TABLE3INDEX  I;        # INDEX TO INTERNAL TABLE 3     #
          ITEM  STRPTR       I;        # PTR TO STRTBL$ TO READ        #
          ITEM  M1           I;        # SCRATCH                       #
          ITEM  M2           I;        # SCRATCH                       #
          ITEM  M3           I;        # SCRATCH                       #
          ITEM  MAXFL        I;        # MAXIMUM FIELD LENGTH          #
  
          XREF
               BEGIN
               PROC  S$GTMFL;          # GET MAXIMUM FIELD LENGTH      #
               END
  
  
# THESE ARE THE INTERNAL TABLES.                    # 
# TABLE 1 ENTRIES WILL BE THE INTER-MERGE OUTPUT FILE DESC. FOR FIRST  #
# MERGE LEVEL. THESE WILL IN TURN BE INPUT FILE DESCRIPTORS TO SECOND  #
# MERGE LEVEL. THE OUTPUT FILE DESCRIPTORS FOR SECOND MERGE LEVEL ARE  #
# ENTRIES IN TABLE 2. THESE WILL ALSO BE INPUT FILE DESCRIPTORS FOR    #
# THIRD MERGE LEVEL. TABLE 0 IS A TEMPLATE TO PUT ON THE HIGHEST TABLE #
# USED OF TABLE 1,2 OR 3. IT HELPS CREATE THE FINAL-MERGE TABLE.       #
  
          ARRAY TABLE1[0:14]; 
              BEGIN 
              ITEM TABLE1ENTRY I(0,0,60); 
              ITEM TABLE1ORD   I(0,0,30); 
              ITEM TABLE1FILENO I(0,30,12); 
              ITEM TABLE1BFS I(0,42,18);
              END 
  
          ARRAY TABLE2[0:10]; 
              BEGIN 
              ITEM TABLE2ENTRY I(0,0,60); 
              ITEM TABLE2ORD   I(0,0,30); 
              ITEM TABLE2FILENO I(0,30,12); 
              ITEM TABLE2BFS I(0,42,18);
              END 
  
          ARRAY TABLE3[0:10]; 
              BEGIN 
              ITEM TABLE3ENTRY I(0,0,60); 
              ITEM TABLE3ORD   I(0,0,30); 
              ITEM TABLE3FILENO I(0,30,12); 
              ITEM TABLE3BFS I(0,42,18);
              END 
  
          BASED ARRAY TABLE0[0:0];
              BEGIN 
              ITEM TABLE0ENTRY I(0,0,60); 
              ITEM TABLE0ORD I(0,0,30); 
              ITEM TABLE0FILENO I(0,30,12); 
              ITEM TABLE0BFS I(0,42,18);
              END 
  
          DEF TABLE0LEN #TABLE0ENTRY[0]#; 
          DEF TABLE1LEN #TABLE1ENTRY[0]#; 
          DEF TABLE2LEN #TABLE2ENTRY[0]#; 
          DEF TABLE3LEN #TABLE3ENTRY[0]#; 
CONTROL EJECT;
  
$BEGIN
  
          FUNC  OCT(VALUE) C(20); 
  
              ITEM  VALUE        U;    # VALUE TO BE CONVERTED         #
              ITEM  C20          C(20); 
              ITEM  I            I; 
              BEGIN 
              FOR I = 0 STEP 1 UNTIL 19 DO
                  C<I,1>C20 = B<3*I,3>VALUE + O"33";
              OCT = C20;
              END  # OCT #
  
          FUNC  DEC(VALUE) C(10); 
              ITEM  VALUE       I;     # VALUE TO BE CONVERTED         #
              ITEM  C10PLUS     C(20);
              ITEM  I            I; 
              ITEM  N            I; 
              BEGIN 
              C10PLUS = "         0          "; 
              N = VALUE;
              IF N LS 0  THEN 
                  N = -N; 
              IF N GR 999999999 THEN
                  BEGIN 
                  C10PLUS = " *********          "; 
                  I = 0;
                  END 
              ELSE
                  BEGIN 
                  FOR I = 9 WHILE N NQ 0  DO
                      BEGIN 
                      C<I,1>C10PLUS = N - (N/10)*10 + 27; 
                      N = N/10; 
                      I = I - 1;
                      END 
                  END 
              IF VALUE LS 0 THEN
                  C<I,1>C10PLUS = "-";
              DEC = C<I,10>C10PLUS; 
              END  # DEC #
  
          XREF
              BEGIN 
              PROC S$PRTCD; 
              END 
  
          ITEM  LINE         C(60); 
          ITEM  C20          C(20); 
  
$END
CONTROL EJECT;
          $BEGIN
          LINE = " STRTBL$";
          S$PRTCD(LINE);
          FOR INDEX=0 STEP 1 UNTIL STRTBL$LEN DO
              BEGIN 
              C<0,20>LINE = OCT(STRTBL$ENTRY[INDEX]); 
              S$PRTCD(LINE);
              END 
          FLUSH;
          $END
  
          IMTBL$NSECTS = 0;    # ASSUME NO INTER-MERGE #
          IMTBL$PASSES = 0; 
          IMTBL$MXNFIL = 0; 
  
          IF STRTBL$LEN LQ 14 THEN
              BEGIN 
              M1 = STRTBL$LEN;
              M2 = 1; 
              M3 = 1; 
              TABLE1LEN = 0;
              FOR IPTR = 1 STEP 1 UNTIL STRTBL$LEN DO 
                  BEGIN 
                  TABLE1ENTRY[IPTR] = STRTBL$ENTRY[IPTR]; 
                  IF TABLE1BFS[IPTR] LS 0 THEN
                      TABLE1BFS[IPTR] = 131071; 
                  TABLE1LEN = TABLE1LEN + 1;
                  END 
              END 
          ELSE
              BEGIN # INTER-MERGE # 
              IMTBL$NSECTS = 1; 
              IMPTR = 2;    # SKIP NSECTS AND PASSES WORDS #
              STRPTR = 1; 
              FILENUM = 14; # START FILE NUMBER FOR INTER-MERGE # 
              TABLE3LEN = 0;
              TABLE3INDEX = 1;
  
              NISTR = (STRTBL$LEN/14);
              IF (NISTR*14 LS STRTBL$LEN) THEN
                  NISTR = NISTR + 1;
  
              # FIND THE MINIMUM MERGE LEVEL WITH MAXMO OF 10          #
  
              NLEVEL = 1; 
              FOR INDEX = 1 STEP 1
                WHILE (MAXMO**INDEX LS NISTR) DO
                  NLEVEL = INDEX + 1; 
  
              # FIND MINIMUM INTER-MERGE ORDER WITH NLEVEL             #
  
              FOR INDEX = MAXMO STEP -1 
                WHILE (INDEX**NLEVEL GQ NISTR) DO 
                  IMAXMO = INDEX; 
  
              IF NLEVEL EQ 1 THEN 
                  BEGIN 
                  M1 = IMAXMO;
                  M2 = 1; 
                  M3 = 1; 
                  END 
              ELSE IF NLEVEL EQ 2 THEN
                       BEGIN
                       M1 = IMAXMO; 
                       M2 = IMAXMO; 
                       M3 = 1;
                       END
              ELSE IF NLEVEL EQ 3 THEN
                       BEGIN
                       M1 = IMAXMO; 
                       M2 = IMAXMO; 
                       M3 = IMAXMO; 
                       END
              ELSE
                  S$ABORT("S$MGDSN-1"); 
  
              $BEGIN
              LINE = "  IMAXMO         NLEVEL"; 
              S$PRTCD(LINE);
              LINE = " "; 
              C<0,10>LINE = DEC(IMAXMO);
              C<15,10>LINE = DEC(NLEVEL); 
              S$PRTCD(LINE);
              LINE = "    M1             M2             M3";
              S$PRTCD(LINE);
              LINE = " "; 
              C<4,10>LINE = DEC(M1);
              C<19,10>LINE = DEC(M2); 
              C<34,10>LINE = DEC(M3); 
              S$PRTCD(LINE);
              FLUSH;
              $END
  
# RESET INTER-MERGE FILE NUMBERS TO NOT USED                           #
  
              FOR INDEX = 15 STEP 1 UNTIL 42 DO 
                  FILEUSED[INDEX] = FALSE;
  
# READ STRTBL$ AND CREATE INTERNAL TABLES AND IMTBL$                   #
  
              FOR IPTR = M3 STEP -1 
                WHILE (IPTR GQ 1 AND STRPTR LQ STRTBL$LEN) DO 
                  BEGIN 
  
              $BEGIN
              LINE = "IPTR      STRPTR    M3";
              S$PRTCD(LINE);
              C<0,10>LINE = DEC(IPTR);
              C<11,10>LINE = DEC(STRPTR); 
              C<21,10>LINE = DEC(M3); 
              S$PRTCD(LINE);
              FLUSH;
              $END
  
                  TABLE2LEN = 0;
                  TABLE2INDEX = 1;
  
                  FOR JPTR = M2 STEP -1 
                    WHILE (JPTR GQ 1 AND STRPTR LQ STRTBL$LEN) DO 
                      BEGIN 
  
              $BEGIN
              LINE = "JPTR      STRPTR    M2";
              S$PRTCD(LINE);
              C<0,10>LINE = DEC(JPTR);
              C<11,10>LINE = DEC(STRPTR); 
              C<21,10>LINE = DEC(M2); 
              S$PRTCD(LINE);
              FLUSH;
              $END
  
                      TABLE1LEN = 0;
                      TABLE1INDEX= 1; 
  
                      FOR KPTR = M1 STEP -1 
                        WHILE (KPTR GQ 1
                                 AND STRPTR LQ STRTBL$LEN) DO 
                          BEGIN 
  
              $BEGIN
              LINE = "KPTR      STRPTR    M1";
              S$PRTCD(LINE);
              C<0,10>LINE = DEC(KPTR);
              C<11,10>LINE = DEC(STRPTR); 
              C<21,10>LINE = DEC(M1); 
              S$PRTCD(LINE);
              FLUSH;
              $END
  
                          FOR LEVEL = 1 STEP 1
                            WHILE ( LEVEL LQ 14 
                                      AND STRPTR LQ STRTBL$LEN) DO
                              BEGIN 
  
              $BEGIN
              LINE = "LEVEL     STRPTR    IMPTR"; 
              S$PRTCD(LINE);
              C<0,10>LINE = DEC(LEVEL); 
              C<11,10>LINE = DEC(STRPTR); 
              C<21,10>LINE = DEC(IMPTR);
              S$PRTCD(LINE);
              FLUSH;
              $END
  
                              STRTBL$NPRUS[STRPTR] = O"1001"; 
                              IF (SPEC$MRL / 10) GR 300 THEN
                                 STRTBL$NPRUS[STRPTR] = O"1501";
                              IMTBL$PASSE$[IMPTR+LEVEL] = 
                                           STRTBL$ENTRY[STRPTR];
                              STRPTR = STRPTR + 1;
                              END 
                          IMTBL$NIFILS[IMPTR] = LEVEL - 1;
  
                          # SEARCH FOR A NOT-USED FILE NUMBER # 
                          FOR FILENUM = 15
                            WHILE FILEUSED[FILENUM] DO
                              FILENUM = FILENUM + 1;
                          IMTBL$FILENO[IMPTR] = FILENUM;
                          FILEUSED[FILENUM] = TRUE; 
                          IMTBL$BFS[IMPTR] = O"2001"; 
                          TABLE1ENTRY[TABLE1INDEX] =
                                          IMTBL$PASSE$[IMPTR];
  
                  $BEGIN
                  LINE = "KPTR = "; 
                  C<10,10>LINE = DEC(KPTR); 
                  S$PRTCD(LINE);
                  FOR INDEX2 = IMPTR STEP 1 UNTIL IMPTR+LEVEL DO
                      BEGIN 
                      C<0,20>LINE = OCT(IMTBL$PASSE$[INDEX2]);
                      S$PRTCD(LINE);
                      END 
                  $END
  
                          TABLE1ORD[TABLE1INDEX] = 1; 
                          TABLE1INDEX = TABLE1INDEX + 1;
                          TABLE1LEN = TABLE1LEN + 1;
                          IMTBL$PASSES = IMTBL$PASSES + 1;
                          IMPTR = IMPTR + LEVEL;
                          END 
  
                      IF M2 LQ 1 THEN 
                          TEST JPTR;
                      FOR LEVEL = 1 STEP 1 UNTIL TABLE1LEN DO 
                          BEGIN 
                          TABLE1BFS[LEVEL] = O"1001"; 
                          IF (SPEC$MRL / 10) GR 300 THEN
                              TABLE1BFS[LEVEL] = O"1501"; 
                          IMTBL$PASSE$[IMPTR+LEVEL] = 
                                          TABLE1ENTRY[LEVEL]; 
                          END 
                      IMTBL$NIFILS[IMPTR] = TABLE1LEN;
  
                      AVAIL = TABLE1FILENO[1] + TABLE1LEN;#NEXT FILENO# 
                      FOR FILENUM = AVAIL WHILE FILEUSED[FILENUM] DO
                          FILENUM = FILENUM + 1;
                      IMTBL$FILENO[IMPTR] = FILENUM;
                      FILEUSED[FILENUM] = TRUE; 
                      IMTBL$BFS[IMPTR] = O"2001"; 
  
                  $BEGIN
                  LINE = "JPTR = "; 
                  C<10,10>LINE = DEC(JPTR); 
                  S$PRTCD(LINE);
                  FOR INDEX2 = IMPTR STEP 1 UNTIL IMPTR+LEVEL DO
                      BEGIN 
                      C<0,20>LINE = OCT(IMTBL$PASSE$[INDEX2]);
                      S$PRTCD(LINE);
                      END 
                  $END
  
                      TABLE2ENTRY[TABLE2INDEX] = IMTBL$PASSE$[IMPTR]; 
                      TABLE2ORD[TABLE2INDEX] = 1; 
                      TABLE2INDEX = TABLE2INDEX + 1;
                      TABLE2LEN = TABLE2LEN + 1;
                      IMTBL$PASSES = IMTBL$PASSES + 1;
                      IMPTR = IMPTR + TABLE1LEN + 1;
                      # RESET FILE NUMBERS USED IN LAST LEVEL TO FALSE# 
                      FOR INDEX = 15 STEP 1 UNTIL AVAIL-1 DO
                          FILEUSED[INDEX] = FALSE;
                      END 
  
                  IF M3 LQ 1 THEN 
                      TEST IPTR;
                  FOR LEVEL = 1 STEP 1 UNTIL TABLE2LEN DO 
                      BEGIN 
                      TABLE2BFS[LEVEL] = O"1001"; 
                      IF (SPEC$MRL / 10) GR 300 THEN
                          TABLE2BFS[LEVEL] = O"1501"; 
                      IMTBL$PASSE$[IMPTR+LEVEL] = TABLE2ENTRY[LEVEL]; 
                      END 
                  IMTBL$NIFILS[IMPTR] = TABLE2LEN;
  
                  # SEARCH FOR A NOT-USED FILE NUMBER # 
                  FOR FILENUM = AVAIL 
                    WHILE FILEUSED[FILENUM] DO
                      FILENUM = FILENUM + 1;
                  IMTBL$FILENO[IMPTR] = FILENUM;
                  FILEUSED[FILENUM] = TRUE; 
                  IMTBL$BFS[IMPTR] = O"2001"; 
  
                  $BEGIN
                  LINE = "IPTR = "; 
                  C<10,10>LINE = DEC(IPTR); 
                  S$PRTCD(LINE);
                  FOR INDEX2 = IMPTR STEP 1 UNTIL IMPTR+LEVEL DO
                      BEGIN 
                      C<0,20>LINE = OCT(IMTBL$PASSE$[INDEX2]);
                      S$PRTCD(LINE);
                      END 
                  $END
  
                  TABLE3ENTRY[TABLE3INDEX] = IMTBL$PASSE$[IMPTR]; 
                  TABLE3INDEX = TABLE3INDEX + 1;
                  TABLE3LEN = TABLE3LEN + 1;
                  IMPTR = IMPTR + TABLE2LEN + 1;
                  IMTBL$MXNFIL = IMPTR - 1; 
                  IMTBL$PASSES = IMTBL$PASSES + 1;
                  # RESET FILE NUMBERS IN LAST LEVEL TO FALSE # 
                  FOR INDEX = AVAIL STEP 1 UNTIL TABLE3FILENO[1]-1 DO 
                      FILEUSED[INDEX] = FALSE;
                  END 
  
$BEGIN
LINE = "SPEC$LWSA=";
C<11,10>LINE = DEC(SPEC$LWSA);
C20 = OCT(SPEC$LWSA); 
C<20,6>LINE = C<14,6>C20; 
S$PRTCD(LINE);
$END
  
$BEGIN
LINE = " IMTBL$ ";
C<10,20>LINE = OCT(IMTBL$PASSE$[0]);
S$PRTCD(LINE);
LINE = " "; 
  
FOR INDEX2 = 1 STEP 1 WHILE IMTBL$PASSE$[INDEX2] GR 0 
 AND INDEX2 LQ IMTBL$LEN DO 
    BEGIN 
    C<1,20>LINE = OCT(IMTBL$PASSE$[INDEX2]);
    S$PRTCD(LINE);
    END # FOR INDEX2 #
S$PRTCD(0); 
$END
  
  
                S$GTMFL(MAXFL); 
                IF MAXFL GQ 65536 THEN    # IF WE HAVE ENOUGH SPACE    #
                BEGIN 
                  # ALLOCATE BUFFERS BETTER FOR INTERMEDIATE MERGE     #
  
                  # DURING INTERMEDIATE MERGE SPEC$LWSA WDS ARE USABLE #
                  #   TOURNAMENT      1 WORD PER INPUT FILE            #
                  #   FET-S           7 WORDS PER FILE                 #
                  #   OUTPUT BUFFER   BFS WORDS LONG                   #
                  #   INPUT BUFFERS   BFS + LKEY WORDS PER INPUT FILE  #
                  #                  (RECORDS ARE COMPARED WHILE IN THE#
                  #                   BUFFER.  SO KEY COMPARISON DOES  #
                  #                   NOT HAVE TO WORRY ABOUT WRAP-    #
                  #                   AROUND THE FIRST LKEY WORDS IN   #
                  #                   THE BUFFER ARE COPIED TO THE END)#
  
                  LKEY =(REC$LK2 + REC$LS2 + REC$LO2)/(WORD*BYTE) + 1;
                  IP = 2;           # INDEX TO IMTBL$ PASS HEADER WORD #
                  FOR P = 1 STEP 1 UNTIL IMTBL$PASSES DO
                      BEGIN # MASSAGE BFS-S IN PASS P IN IMTBL$        #
                      NIFILES = IMTBL$NIFILS[IP]; 
                      USED = NIFILES
                           + 7 * (NIFILES + 1)
                           + NIFILES * LKEY;
                      AVAIL = SPEC$LWSA - USED; # AVAILABLE FOR BUFFERS#
                      # MINIMUM BFS HOLDS MAX (PRU+1, MRLWORDS+1)      #
                      MRLWORDS = REC$IRRL + 1;
                      BFSI = MRLWORDS + 1;
                      IF BFSI LS 65 THEN
                          BFSI = 65;
                      USED = (NIFILES + 1) * BFSI;
                      IF USED GR AVAIL THEN 
                          S$ABORT ("S$MGDSN-2");
                      GOODBFSI = BFSI;    # SAVE GOOD VALUES FOR BFSI  #
                      GOODBFSO = BFSI;    # AND BFSO (SAME AS INPUT)   #
  
                      # NOW TRY FOR TWO RECORDS PER BUFFER             #
                      BFSI = 2 * MRLWORDS + 1;
                      IF BFSI LS 65 THEN
                          BFSI = 65;
                      USED = (NIFILES + 1) * BFSI;
                      IF USED LQ AVAIL THEN 
                          BEGIN                # OK, NOW FOR NEXT TRY! #
                          GOODBFSI = BFSI;
                          GOODBFSO = BFSI;
  
                          # NOW TRY FOR 1001B WORDS PER BUFFER         #
                          BFSI = 2 * MRLWORDS + 1; # STILL NEED 2 RECS #
                          IF BFSI LS 513 THEN 
                              BFSI = 513; 
                          USED = (NIFILES + 1) * BFSI;
                          END 
                      IF USED LQ AVAIL THEN 
                          BEGIN 
                          GOODBFSI = BFSI;
                          GOODBFSO = BFSI;
  
                          # NOW TRY FOR 4001B WORDS FOR OUTPUT BUFFER  #
                          BFSO = BFSI;
                          IF BFSO LS 2049 THEN
                              BFSO = 2049;
                          USED = NIFILES * BFSI + BFSO; 
                          END 
                      IF USED LQ AVAIL THEN 
                          BEGIN 
                          # NOW ALLOCATE REST ACCORDING TO RATIO       #
                          GOODBFSI = BFSI + (AVAIL - USED)/(NIFILES+4); 
                          GOODBFSO = AVAIL - NIFILES * GOODBFSI;
                          USED = NIFILES * GOODBFSI + GOODBFSO; 
                          END 
                      IF USED LQ AVAIL THEN 
                      GOODBFSO = GOODBFSO + (AVAIL - USED); 
  
                      USED =   NIFILES
                             + 7 * (NIFILES + 1)
                             + GOODBFSO 
                             + NIFILES * (GOODBFSI + LKEY); 
                      IF USED GR SPEC$LWSA THEN 
                          S$ABORT("S$MGDSN-3"); 
  
                      # NOW SET BFS-S IN IMTBL$ FOR THIS PASS          #
                      IMTBL$BFS[IP] = GOODBFSO; 
                      FOR I = 1 STEP 1 UNTIL NIFILES DO 
                          IMTBL$BFS[IP+I] = GOODBFSI; 
                      IP = IP + 1 + IMTBL$NIFILS[IP]; # SET NEXT INDEX #
                      END # FOR P # 
                END # IF MAXFL #
  
$BEGIN
LINE = " IMTBL$ ";
C<10,20>LINE = OCT(IMTBL$PASSE$[0]);
S$PRTCD(LINE);
LINE = " "; 
FOR INDEX2 = 1 STEP 1 WHILE IMTBL$PASSE$[INDEX2] GR 0 
    AND INDEX2 LQ IMTBL$LEN DO
    BEGIN 
    C<1,20>LINE = OCT(IMTBL$PASSE$[INDEX2]);
    S$PRTCD(LINE);
    END 
S$PRTCD(0); 
$END
              END 
CONTROL EJECT;
  
FNLMRG: 
  
#     HERE WE ARE DONE WITH IMTBL$                                     #
#     WE WILL FORM FMTBL$ FROM THE BOTTOM PART OF THE INTERNAL TABLE   #
  
#    NOTE THAT BUFFER SIZES ARE EFFICIENTLY SET IN S$ALCF              #
  
  
          IF M3 GR 1 THEN 
              P<TABLE0> = LOC(TABLE3);
          ELSE IF M2 GR 1 THEN
                   P<TABLE0> = LOC(TABLE2); 
          ELSE
              P<TABLE0> = LOC(TABLE1);
  
              $BEGIN
              LINE = " TABLE3"; 
              S$PRTCD(LINE);
              FOR INDEX = 0 STEP 1 UNTIL 10 DO
                  BEGIN 
                  C<0,20>LINE = OCT(TABLE3ENTRY[INDEX]);
                  S$PRTCD(LINE);
                  END 
              LINE = " TABLE2"; 
              S$PRTCD(LINE);
              FOR INDEX = 0 STEP 1 UNTIL 10 DO
                  BEGIN 
                  C<0,20>LINE = OCT(TABLE2ENTRY[INDEX]);
                  S$PRTCD(LINE);
                  END 
              LINE = " TABLE1"; 
              S$PRTCD(LINE);
              FOR INDEX=0 STEP 1 UNTIL 10 DO
                  BEGIN 
                  C<0,20>LINE = OCT(TABLE1ENTRY[INDEX]);
                  S$PRTCD(LINE);
                  END 
              LINE = " TABLE0"; 
              S$PRTCD(LINE);
              FOR INDEX = 0 STEP 1 UNTIL 10 DO
                  BEGIN 
                  C<0,20>LINE = OCT(TABLE0ENTRY[INDEX]);
                  S$PRTCD(LINE);
                  END 
              FLUSH;
              $END
$BEGIN
LINE = " FMTBL$ ";
S$PRTCD(LINE);
$END
          FMPTR = 1;
          FMTBL$MO = 0; 
  
          FOR INDEX = 1 STEP 1 UNTIL TABLE0LEN DO 
              BEGIN 
              FMTBL$FILE[FMPTR] = "ZZZZZ1*";
              FILE = TABLE0FILENO[INDEX]; 
  
              IF FILE GQ 15 THEN
                  FMTBL$PRUNUM[FMPTR] = 1;
              ELSE
                  FMTBL$PRUNUM[FMPTR] = TABLE0ORD[INDEX]; 
  
              FOR INDEX2 = INDEX2 WHILE FILE GR 26 DO 
                  BEGIN 
                  FILE = FILE - 26; 
                  B<30,6>FMTBL$FILE[FMPTR] =
                      B<30,6>FMTBL$FILE[FMPTR] + 1; 
                  END 
              B<36,6>FMTBL$FILE[FMPTR] = FILE;
  
              FMTBL$RELBFS[FMPTR] = TABLE0BFS[INDEX]; 
              IF (SPEC$MRL /10) GR 300 THEN 
                  FMTBL$RELBFS[FMPTR] = O"1501";
              FMPTR = FMPTR + 1;
              FMTBL$MO = FMTBL$MO + 1;
              END 
  
  
$BEGIN
LINE = " "; 
FOR INDEX = 0 STEP 1 UNTIL FMTBL$MO DO
    BEGIN 
    C<1,10>LINE = DEC(INDEX); 
    C<15,20>LINE = OCT(FMTBL$MO$[INDEX]); 
    C<39,20>LINE = OCT(FMTBL$RELBFS[INDEX]);
    S$PRTCD(LINE);
    END 
S$PRTCD(0); 
$END
          END 
  
          TERM
