*DECK DB$UAWS 
USETEXT UTMPTTX 
USETEXT UTCDFTX 
USETEXT CUGBATX 
      PROC DB$UAWS((LOCPOINT),(AMOUNT));
 #
  *   DB$UAWS - ADJUST WORK SPACE IN A BLOCK     PAGE  1
  *   STEVEN P. LEVIN                            DATE  10/27/75 
  *   BOB MCALLESTER                             DATE  03/30/84 
  
  DC  PURPOSE 
  
      ADJUST THE WORK SPACE USABLE IN A MANAGED MEMORY BLOCK, USING 
      CMM TO INCREASE OR DECREASE THE MANAGED MEMORY BLOCK LENGTH ONLY
      IF THE WORK SPACE ADJUSTMENT WARRANTS A CMM BLOCK LENGTH CHANGE.
  
  DC  ENTRY CONDITIONS
  
      THE PARAMETER LOCPOINT IS THE LOCATION OF A MANAGED MEMORY BLOCK
      POINTER WORD FOR AN EXISTING (ALLOCATED, BUT NOT FREED) BLOCK.
      THE PARAMETER AMOUNT IS THE AMOUNT OF SPACE IN USE IN THE BLOCK 
      TO BE DECREASED (NEGATIVE AMOUNT) OR TO BE INCREASED (POSITIVE
      AMOUNT), OR INDICATES THE BLOCK LENGTH IS TO BE TRIMMED TO
      EXACTLY THAT NEEDED FOR THE CURRENT SPACE IN USE (ZERO AMOUNT). 
      COMMON ITEM OVERFLOW IS TRUE IF OVERFLOW WAS DAMAGING TO BLOCKS.
  
  DC  EXIT CONDITIONS 
  
      UPON NORMAL RETURN FROM DB$UAWS, THE SPACE IN USE IN THE BLOCK
      WHOSE POINTER WORD IS LOCATED AT LOCPOINT WILL BE DECREASED OR
      INCREASED, IF AMOUNT IS NEGATIVE OR POSITIVE, RESPECTIVELY.  IF 
      THE ADJUSTMENT OF SPACE IN USE WARRANTS A CMM BLOCK LENGTH
      CHANGE, OR IF AMOUNT IS ZERO AND THERE IS BLOCK TRIMMING TO BE
      DONE, CMM WILL BE USED TO CHANGE THE BLOCK LENGTH.  IF CMM IS 
      USED TO CHANGE BLOCK LENGTH, BLOCK FIRST-USABLE-ADDRESS WORDS 
      WILL BE RESET TO REFLECT THE CURRENT CORE LAYOUT, AS NEEDED.
      FIELDS IN THE ADJUSTED MEMORY BLOCK"S HEADER WORD WILL BE RESET.
      IF SPACE IN USE IS DECREASED, "UNUSED" WORDS LEFT IN THE BLOCK
      WILL BE ZEROED, AND IF THE BLOCK LENGTH INCREASES FOR AN
      INCREASE IN SPACE IN USE, NEW WORDS ALLOCATED WILL BE ZEROED. 
  
      CERTAIN BLOCKS THAT ARE DEFINED WITH A HEADER THAT IS GREATER 
      THAN ONE WORD IN LENGTH WILL NOT BE ALLOWED TO GROW THEIR USED
      SPACE BEYOND A MAXIMUM THAT IS SPECIFIED IN THE EXPANDED HEADER.
      WHEN ADDITIONAL SPACE IS REQUESTED FOR THESE TABLES, A PORTION
      OF THIER CONTENTS WILL BE STORED ON DISK. 
  
      IF DB$UAWS DOES NOT RETURN NORMALLY, IT WILL BE BECAUSE IT CALLS
      DB$UABN TO HANDLE A PARAMETER OR OVERFLOW ABNORMALITY, CMM CALLS
      AN OVERFLOW ACTION ROUTINE WHICH DOES NOT RETURN NORMALLY, OR 
      CMM ITSELF ABORTS.  IF DB$UABN IS CALLED TO HANDLE AN OVERFLOW
      ABNORMALITY, THE BLOCK HEADER WORD WILL LIKELY CONTAIN INVALID
      INFORMATION AND OTHER BLOCK WORDS CAN NOT BE ASSUMED TO BE
      ZEROED.  SUCH A BLOCK SHOULD BE FREED IF DB$UABN DOES NOT ABORT.
  
  DC  CALLING ROUTINES
  
      DB$CARE - CST BUILDER PROC TO BUILD AN AREA WORK BLOCK IN CORE
      DB$CBLD - CONDENSED SCHEMA/SUBSCHEMA TABLE BUILDER MAIN MODULE
      DB$CCHK - CST BUILDER PROC TO COMPARE MD/(SUB)SCHEMA CHECKSUMS
      DB$CCON - CST BUILDER PROC TO BUILD A CONSTRAINT WORK BLOCK 
      DB$CCPP - CST BUILDER PROC TO PREPROCESS FOR CONSTRAINT INFO
      DB$CEND - CST BUILDER PROC TO END CST BUILDING BY WRITING PARTS 
      DB$CLOK - CST BUILDER PROC TO BUILD A PRIVACY LOCK TABLE IN CORE
      DB$COPT - CST BUILDER PROC TO BUILD A PROCEDURE OPTION TABLE
      DB$CPRE - CST BUILDER PROC TO PREPARE TO BUILD WORK BLOCKS
      DB$CREC - CST BUILDER PROC TO BUILD A RECORD WORK BLOCK IN CORE 
      DB$CREL - CST BUILDER PROC TO BUILD RELATION WORK BLOCK IN CORE 
  
  DC  CALLED ROUTINES 
  
      DB$MVG  - CALL CMM TO GROW A VARYING-POSITION BLOCK AT LWA
      DB$MVS  - CALL CMM TO SHRINK A VARYING-POSITION BLOCK AT LWA
      DB$UABN - HANDLE ABNORMALITIES IN MANAGED MEMORY BLOCK MODULES
      DB$UADR - UPDATE MANAGED MEMORY BLOCK FIRST-USABLE-ADDRESS WORDS
      DB$UTLC - DUMP PART OF THE TABLE TO DISK TO MAKE ROOM FOR GROWTH
  
  DC  NON-LOCAL VARIABLES 
  
      THE MODIFIED BLOCK"S HEADER WORD IS CHANGED AS FOLLOWS: 
      HEADER WORD SPACE IN USE - WILL CHANGE BY AMOUNT (A PARAMETER)
      HEADER WORD BLOCK LENGTH - WILL CHANGE IF BLOCK LENGTH CHANGES
      IN ADDITION, IF BLOCK LENGTH IS CHANGED USING CMM, BLOCK
      FIRST-USABLE-ADDRESS WORDS WILL BE RESET BY DB$UADR, AS NEEDED. 
      IF SPACE IN USE DECREASES, "UNUSED" BLOCK WORDS WILL BE ZEROED. 
      IF BLOCK LENGTH INCREASES, NEW WORDS ALLOCATED WILL BE ZEROED.
  
  DC  DESCRIPTION 
  
      IF THE POINTER WORD IS 0 OR NEW SPACE IN USE < 0, CALL DB$UABN. 
      DEPENDING ON AMOUNT INCREASE OR DECREASE BLOCK LENGTH IF NEEDED.
      IF AMOUNT IS POSITIVE, HAVE CMM INCREASE BLOCK LENGTH IF NEEDED.
      IF AMOUNT IS NONPOSITIVE HAVE CMM SHRINK BLOCK LENGTH IF NEEDED.
      IF CMM IS CALLED, CALL DB$UADR AND RESET BLOCK LENGTH IN HEADER.
      RESET SPACE IN USE IN THE HEADER WORD TO ITS OLD VALUE + AMOUNT.
      IF SPACE IN USE IS DOWN OR BLOCK LENGTH GREW, ZERO NEEDED WORDS.
      RETURN FROM DB$UAWS WITH THE BLOCK USABLE WORK SPACE ADJUSTED.
 #
  
  
        BEGIN                # DB$UAWS #
  
*CALL MDABTDCLS 
  
# THE FOLLOWING ARE FORMAL PARAMETERS, IN THE ORDER THEY ARE PASSED # 
  
        ITEM LOCPOINT U;     # LOCATION OF MEMORY BLOCK POINTER WORD #
        ITEM AMOUNT I;       # AMOUNT OF CHANGE OF BLOCK SPACE IN USE#
  
# THE FOLLOWING ARE EXTERNALLY REFERENCED PROCEDURES #
  
        XREF PROC DB$CALL;   # CALL A VARIABLE PROCEDURE             #
        XREF PROC DB$MABI;   # DBMSTRD INTERNAL ERROR,  ABORT        #
        XREF PROC DB$MABT;   # DBMSTRD ABORT, MEMORY OVERFLOW        #
        XREF PROC DB$MVG;    # CALL CMM TO GROW A VARY-POSITION BLOCK#
        XREF PROC DB$MVS;    # CALL CMM TO SHRINK VARY-POSITION BLOCK#
        XREF PROC DB$UADR;   # UPDATE MANAGED MEMORY USABLE ADDRESSES#
        XREF PROC DB$UTLC;   # TABLE LENGTH CONTROL, DUMP TO DISK.   #
  
        XREF ARRAY DB$RA0;
          BEGIN 
          ITEM ABSWORD   (00,00,60);  # WORD SUBSCRIPTED WITH ABS ADDR #
          END 
  
# THE FOLLOWING ITEMS ARE LOCAL TO DB$UAWS #
  
        ITEM CHANGE I;       # CHANGE IN THE PHYSICAL LENGTH OF BLOCK#
        ITEM HEADL  I;       # HEADER LENGTH OF BLOCK                  #
        ITEM LOWER I;        # LOWER BOUND ON WORDS TO BE ZEROED #
        ITEM USED I;         # NEW VALUE FOR WORK SPACE USED IN BLOCK#
        ITEM INDEX I;        # A GENERAL INDEX AND INDUCTION VARIABLE#
  
  
  
  
#     B E G I N   D B $ U A W S   E X E C U T A B L E   C O D E .      #
  
  
# IF THE POINTER WORD IS 0 OR THE NEW SPACE IN USE < 0, CALL DB$UABN #
  
        P<TLC> = B<42,18>ABSWORD[LOCPOINT];  # POINT TO TLC HEADER     #
        IF LOC(TLC) EQ 0
        THEN
          BEGIN 
          DB$MABI("DB$UAWS 1");    # ABORT IF POINTER IS ZERO          #
  
          END 
        USED = TLCUSED[0] + AMOUNT;    # NEW WORK SPACE USED IN BLOCK#
        IF USED LS 0
        THEN
          BEGIN 
          DB$MABI("DB$UAWS 2");    # ABORT IF REDUCED TO NEGATIVE SIZE #
  
          END 
        HEADL = 1;                 # ESTABLISH TLC HEADER LENGTH       #
        IF TLCCT[0] 
        THEN
          BEGIN 
          HEADL = TLCHLEN[0]; 
          END 
  
# DEPENDING ON AMOUNT, INCREASE OR DECREASE BLOCK LENGTH, IF NEEDED # 
  
        CHANGE = 0;          # DEFAULT CHANGE IN THE LENGTH OF BLOCK #
        IF AMOUNT GR 0       # CHECK IF SPACE IN USE IS TO INCREASE # 
  
# IF AMOUNT > 0 INCREASE BLOCK LENGTH (AND CHECK OVERFLOW), IF NEEDED#
  
          THEN               # AMOUNT OF SPACE IN USE IS TO INCREASE #
            BEGIN 
            LOWER = TLCLEN[0] + 1;  # (CURRENT BLOCK LENGTH) + 1       #
  
                                   # IF USED MEMORY EXTENTS BEYOND     #
                                   # THE END OF THE BLOCK              #
                                   # INCREASE THE BLOCK SIZE           #
            IF HEADL + USED GR TLCLEN[0]
                                   # OR IF A LIMITED TABLE REACHES ITS #
                                   # LIMIT, DUMP TO DISK.              #
              OR (TLCCT[0]
                AND USED GR TLCTMXL[0]) 
            THEN
              BEGIN 
              IF TLCCT[0] 
                AND USED GR TLCTMXL[0]
              THEN
                                   # A LIMITED TABLE IS GROWING BEYOND #
                                   # ITS LIMIT                         #
                BEGIN 
                DB$UTLC(LOCPOINT);  # DUMP A SEGMENT TO DISK           #
                HEADL = TLCHLEN[0]; 
                                   # CLEAR THE RELEASED AREA           #
                LOWER = TLCHLEN[0] + TLCBSBW[0];
  
                                   # RE-EVALUATE THE MEMORY USAGE      #
                USED = TLCBSBW[0] + AMOUNT; 
                END 
  
              IF HEADL + USED GR TLCLEN[0]
              THEN                 # AN INCREASE IS STILL IN ORDER     #
                BEGIN 
                IF TLCCT[0] 
                  AND USED + TLCPAD[0] GR TLCTMXL[0]
                THEN               # A LIMITED TABLE HAS REACHED ITS   #
                                   # LIMIT.                            #
                                   # LIMIT THE PADDING TO DFTLCPAD.    #
                                   # THE ONLY REQUIRED GROWTH IS FOR   #
                                   # THE TLC HEADER (SEGMENT CONTROLS).#
                  BEGIN 
                  CHANGE = HEADL + TLCTMXL[0] + DFTLCPAD - TLCLEN[0]; 
                  END 
                ELSE
                  BEGIN 
                  CHANGE = HEADL + USED + TLCPAD[0] - TLCLEN[0];
                  END 
                DB$MVG(B<42,18>ABSWORD[LOCPOINT],CHANGE); 
                IF OVERFLOW 
                THEN
                  BEGIN 
                  IF OVLLEVEL EQ 3
                  THEN
                    BEGIN 
                    DB$CALL(OVERFERR,"7202UAWS",LOCPOINT);
                    END 
                  DB$MABT(DFMMOVER,"DB$UAWS");
                  END 
                END 
              END 
            END 
  
# IF AMOUNT IS NONPOSITIVE, HAVE CMM DECREASE BLOCK LENGTH, IF NEEDED#
  
        IF AMOUNT LQ 0
          THEN
            BEGIN 
                             # HEADER + (NEW SPACE IN USE) +1          #
              LOWER = HEADL + USED + 1; 
              IF AMOUNT LS 0 # CHECK IF SPACE IN USE IS TO DECREASE # 
                THEN         # CHECK IF BLOCK LENGTH MIGHT DECREASE # 
                  BEGIN 
                             # IF A REDUCTION RETURNS A PORTION        #
                             # OF A DISK SEGMENT - ABORT               #
                    IF TLCCT[0] 
                      AND TLCHLEN[0] GR DFTLCHL 
                      AND USED LS TLCBSBW[0]
                    THEN
                      BEGIN 
                      DB$MABI("DB$UAWS 3"); 
                      END 
  
                    IF HEADL + USED + 2 * TLCPAD[0] LQ TLCLEN[0]
                      THEN   # COMPUTE POSSIBLE BLOCK LENGTH CHANGE # 
                        BEGIN 
                        CHANGE = TLCLEN[0] - (HEADL + USED + TLCPAD[0]);
                        END 
                  END 
                ELSE         # AMOUNT IS ZERO # 
                  CHANGE = TLCLEN[0] - (HEADL + USED);
              IF CHANGE NQ 0 # CHECK IF BLOCK LENGTH IS TO DECREASE # 
                THEN         # HAVE CMM DECREASE LENGTH OF THE BLOCK #
                  BEGIN 
                    DB$MVS(B<42,18>ABSWORD[LOCPOINT],CHANGE); 
                    CHANGE = -CHANGE;  # MAKE CHANGE NEGATIVE # 
                  END 
            END 
  
# IF CMM IS CALLED, CALL DB$UADR AND RESET HEADER WORD BLOCK LENGTH # 
  
        IF CHANGE NQ 0       # IF BLOCK LENGTH WAS CHANGED USING CMM #
          THEN               # CALL DB$UADR. SET HEADER BLOCK LENGTH.#
            BEGIN 
              XCALL DB$UADR; # UPDATE MANAGED MEMORY USABLE ADDRESSES#
              P<TLC> = B<42,18>ABSWORD[LOCPOINT];     # HEADER         #
              TLCLEN[0] = B<12,18>ABSWORD[LOCPOINT];  # NEW LENGTH     #
            END 
  
# RESET SPACE IN USE IN THE HEADER WORD TO ITS OLD VALUE PLUS AMOUNT #
  
        TLCUSED[0] = USED;   # SPACE IN USE = OLD VALUE PLUS AMOUNT # 
  
# IF SPACE IN USE DECREASED OR BLOCK LENGTH GREW, ZERO NEEDED WORDS # 
  
        IF LOWER LQ TLCLEN[0]         # IF THERE ARE WORDS TO ZERO #
          THEN               # ZERO ALL WORDS FROM LOWER TO BLOCK END#
            BEGIN 
              P<PUTENTRY> = B<42,18>ABSWORD[LOCPOINT] - 1;  # POINT # 
              FOR INDEX = LOWER THRU TLCLEN[0] DO         # FOR LOOP# 
                PUTUNSIG[INDEX] = 0;   # ZERO WORDS TO END OF BLOCK # 
            END 
  
        RETURN;              # BLOCK USABLE WORK SPACE ADJUSTED NOW # 
  
        END                  # DB$UAWS #
  
      TERM
