*DECK CBCKBUF 
      PROC CBCKBUF(BLOCK,WANT); 
      BEGIN 
 #
* *   CBCKBUF--DDL PASS 2 BUFFER MANAGER
* *   C O GIMBER                                 10.14.74 
* 
* DC  PURPOSE 
* 
*     CBCKBUF PROVIDES BUFFER MANAGEMENT FOR BASED ARRAYS.  IT WILL 
*     INCREASE THE SIZE OR DECREASE THE SIZE OF ARRAYS AND MOVE THEM
*     IN MANAGED MEMORY SPACE.
*     IF IT IS CALLED FOR AN ARRAY WHICH IT IS NOT CURRENTLY MANAGING,
*     IT WILL ALLOCATE SPACE FOR IT AND SET THE BASED ARRAY POINTER 
*     TO THE SPACE ALLOCATED. 
*     IF IT IS CALLED TO INCREASE OR DECREASE THE SIZE OF AN ARRAY, 
*     IT WILL DO IT KEEPING THE INTEGRITY OF THE DATA IN THE ARRAY. 
*     IT MAY BE NECESSARY FOR IT TO MOVE ARRAYS WHEN IT PERFORMS
*     ITS OPERATION ON ANOTHER ARRAY. 
* 
*     SPECIAL CONSIDERATION IS MADE FOR THE FIRST TWO CALLS.
*     THE FIRST CALL IS FOR THE REALM LIST BUFFER, IT IS NOT ALTERED
*     DURING THIS PASS, SO ITS POSITION AND LENGTH ARE RECORDED.
*     IT ALREADY IS LOCATED IN A GOOD POSITION, SO NO ATTEMPT IS MADE 
*     TO MOVE IT. 
*     THE SECOND TABLE TO BE DEFINED IS THE SUBSCHEMA DIRECTORY THAT
*     IS BEING BUILT.  THIS IS LOCATED DIRECTLY ADJACENT TO THE REALM 
*     LIST TABLE WHICH HAS A FIXED LENGTH DURING THIS PASS, SO THERE IS 
*     NO NEED TO MOVE THE SUBSCHEMA DIRECTORY.
*     CONSEQUENTLY, THESE FIRST TWO TABLES ARE NOT INCLUDED IN THE LOOP 
*     TO MOVE TABLES. 
* 
* DC  ENTRY CONDITIONS
* 
*     PARAMETERS
*       BLOCK = BASED ARRAY POINTER 
*       WANT = LENGTH OF ARRAY DESIRED
 #
  
# PASSED PARAMTERS# 
      ITEM BLOCK;            #BASED ARRAY POINTER#
      ITEM WANT;             #LENGTH DESIRED# 
  
# EXTERNAL REFERENCES#
      XREF ITEM DDLMEM;      #LWA+1 OF MEMORY#
      XREF ITEM DDLSU ;      # STORAGE USED (MIN FL NEEDED)            #
      XREF ITEM MAXFL ;      # MAX FIELD LENGTH ALLOWED                #
      XREF PROC ABRT1 ;      # ABORT RUN WITH INSUFF FIELD LENGTH MSG. #
      XREF PROC CBERROR;       #DDL PASS 2 ERROR HANDLER# 
      XREF PROC MEMORY ;     # ISSUE FIELD LENGTH REQUEST              #
  
#     LOCAL DECLARATIONS# 
  
      DEF RESERVEP2 #O"1000"#;         #EXCESS MEMORY TO BE REQUESTED  #
      DEF RESMAXP2  #O"2000"#;         #MAXIMUM EXCESS MEMORY, PASS 2  #
      DEF RESMINP2  #O"0200"#;         #MINIMUM EXCESS MEMORY          #
  
      ITEM DELTA;                      #WORDS BETWEEN ARRAYS# 
      BASED ARRAY FROM;                #FROM ADDRESS FOR ARRAY MOVE#
        ITEM FROMWORD;
      ITEM I;                          #FOR LOOP INDEX# 
      ITEM INDEX;                      #INDEX INTO INFO ARRAY#
      ITEM INDEXI;                     #INDEX INTO INFO ARRAY OF# 
                                       #ARRAY BEING CHANGED#
      ITEM INDEXL = 0;                 #INDEX OF LAST ENTRY IN INFO ARR#
      BASED ARRAY INFO;                #CONTAINS INFO FOR MANAGED ARRAY#
                                       #THIS IS THE FIRST MANAGED ARRAY#
                                       #(FWA[INDEXL+1])=LWA+1 OF# 
                                       #  MANAGED MEMORY# 
        BEGIN 
        ITEM LENGTH (0,0,18);          #LENGTH OF ARRAY#
        ITEM POINTER (0,18,18);        #LOCATION OF POINTER#
        ITEM FWA (0,42,18);            #FWA OF ARRAY# 
        END 
      BASED ARRAY RA;                  #ARRAY FOR REFERENCING MEMORY# 
        BEGIN 
        ITEM WORD ; 
        ITEM RA65 U(O"65",42,18); 
        END 
      BASED ARRAY TO;                  #TO ADDRESS FOR ARRAY MOVES# 
        ITEM TOWORD;
  
  
  
#     B E G I N   C B C K B U F   E X E C U T A B L E   C O D E .      #
  
  
      P<RA> = 0;
 #
*     FIND ARRAY IN INFO TABLE
*     INCREASE ARRAY SIZE IF IT CAN BE DONE WITHOUT REDISTRIBUTION
 #
      FOR INDEXI=1 STEP 1 UNTIL INDEXL DO 
        IF POINTER[INDEXI] EQ LOC(BLOCK) THEN 
          BEGIN 
          IF FWA[INDEXI]+WANT GR FWA[INDEXI+1] THEN 
            GOTO REDISTRIBUTE;
          IF  WANT LS LENGTH[INDEXI]    # IF DECREASE IN SIZE          #
          THEN ASU ;                    # ACCUMULATE STORAGE USED      #
          LENGTH[INDEXI] = WANT;
          RETURN; 
          END 
 #
*     IF ARRAY NOT IN INFO TABLE THEN ADD IT
 #
      INDEXL = INDEXL+1;
      INDEXI = INDEXL;
      P<INFO> = RA65[0] - 10; 
      FWA[0] = LOC(INFO); 
      LENGTH[0] = INDEXL + 2; 
      FWA[INDEXL+1] = B<0,30>DDLMEM;
      POINTER[INDEXI] = LOC(BLOCK); 
      FWA[INDEXI] = BLOCK;
      IF INDEXL LQ 2 THEN 
 #
*     THE FIRST TWO TABLES ARE ALREADY ALLOCATED, THEY ARE ONLY 
*     BEING RECORDED IN THE INFO TABLE. 
 #
        BEGIN 
        LENGTH[INDEXL] = WANT;
        RETURN; 
  
        END 
      ELSE
        LENGTH[INDEXL] = 0; 
 #
*     COMPACT ALL ARRAYS IN UPPER PART OF MANAGED MEMORY
*     THE FIRST TWO TABLES ARE ALREADY COMPACTED. 
 #
REDISTRIBUTE: 
      FOR INDEX=3 STEP 1 UNTIL INDEXL DO
        BEGIN 
        P<TO> = FWA[INDEX-1]+LENGTH[INDEX-1]; 
        P<FROM> = FWA[INDEX]; 
        FWA[INDEX] = LOC(TO); 
        WORD[POINTER[INDEX]] = FWA[INDEX] ; 
        FOR I=0 STEP 1 WHILE I LS LENGTH[INDEX] DO
          TOWORD[I] = FROMWORD[I];
        END 
 #
*     CALCULATE DELTA=WORDS BETWEEN ARRAYS
 #
      LENGTH[0] = INDEXL + 3; 
      DELTA = FWA[INDEXL+1]-(FWA[INDEXL]+LENGTH[INDEXL])
        -(WANT-LENGTH[INDEXI]) - 1; 
 #
*     IF THE EXCESS MEMORY EXCEEDS THE MAXIMUM RESERVE ALLOWED
*     THEN REDUCE THE FIELD LENGTH. 
 #
      IF DELTA GR RESMAXP2 THEN 
        BEGIN 
        DELTA = RESERVEP2;
        INDEX = FWA[INDEXL] + LENGTH[INDEXL] + RESERVEP2
                 + (WANT - LENGTH[INDEXI]); 
        INDEX = (INDEX +63) /64 *64;
        MEMORY(INDEX);
        FWA[INDEXL +1] = B<0,30>DDLMEM; 
        END 
 #
*       IF RESERVE MEMORY HAS FALLEN BELOW THE MINIMUM THEN 
*       REQUEST MORE. 
 #
      IF DELTA LS RESMINP2
      THEN
        BEGIN 
 #
*         IF INSUFFICIENT MEMORY WITHIN MAXIMUM FIELD LENGTH
*         THEN ERROR. 
*         THIS TEST IS ONLY SIGNIFICANT IF DELTA IS NEGATIVE. 
*         IN THAT CASE THE ADDITIONAL MEMORY MUST BE ACQUIRED IN ORDER
*         TO CONTINUE.
 #
          INDEX = ((B<0,30>DDLMEM - DELTA + 63) / 64) * 64 ;
          IF  INDEX GR MAXFL THEN 
            BEGIN 
              DDLSU = INDEX ;          # FIELD LENGTH NEEDED           #
              CBERROR (310,0) ;        # EXCEEDS MAX ALLOWED           #
              ABRT1 ;                  # SO ABORT JOB                  #
            END 
 #
*         ADD A RESERVE TO THE REQUEST, BUT DO NOT EXCEED MAX FL. 
 #
          INDEX = INDEX + RESERVEP2;
          IF INDEX GR MAXFL THEN
            BEGIN 
            INDEX = MAXFL;
            END 
          MEMORY (INDEX) ;             # REQUEST FIELD LENGTH          #
          FWA[INDEXL +1] = B<0,30>DDLMEM; 
          DELTA = FWA[INDEXL +1] - ( FWA[INDEXL] + LENGTH[INDEXL] ) 
                   - ( WANT - LENGTH[INDEXI] ) -1;
        END 
      LENGTH[INDEXI] = WANT;
      DELTA = DELTA / (INDEXL -1);
 #
*     EXPAND ARRAYS IN MANAGED MEMORY, BUT DO NOT MOVE THE FIRST
*     TWO TABLES. 
 #
      FOR INDEX=INDEXL STEP -1 UNTIL 3 DO 
        BEGIN 
        P<FROM> = FWA[INDEX]; 
        P<TO> = FWA[INDEX+1]-LENGTH[INDEX]-DELTA; 
        FWA[INDEX] = LOC(TO); 
        WORD[POINTER[INDEX]] = FWA[INDEX] ; 
        FOR I=LENGTH[INDEX]-1 STEP -1 UNTIL 0 DO
          TOWORD[I] = FROMWORD[I];
        END 
      RETURN; 
  
  
  
      XDEF PROC ASU ; 
      PROC ASU ;
      BEGIN 
 #
* *   ASU - ACCUMULATE STORAGE USED . 
* *   R H GOODELL.                               77/05/24.
* 
* DC  PURPOSE.
* 
*     *ASU* TOTALS THE LENGTHS OF ALL OF THE TABLES MANAGED 
*     BY *CBCKBUF* AND UPDATES *DDLSU* (STORAGE USED).
 #
  
        ITEM S ;
  
        S = FWA[0] ;
        FOR INDEX = 0 STEP 1 UNTIL INDEXL DO
          S = S + LENGTH[INDEX];
        IF S GR DDLSU THEN
          DDLSU = S ; 
        RETURN ;
      END 
  
      END 
      TERM; 
