*DECK RGTABLE 
USETEXT TAREATB 
USETEXT TBASCTB 
USETEXT TEXPRES 
USETEXT TPSTACK 
USETEXT TSBASIC 
      PROC RGTABLE;         BEGIN 
        #THIS PROC BUILDS THE RANGE TABLE USED IN IF-KEY LOGIC# 
                                                                         RGTABLE
      DEF IKPSTKOFFSET #17#;       # OFFSET WITHIN IFKEYLOC WHERE      #
                                   # RGTABLE PREPARES PROGRAM STACK    #
                                   # TO BE USED FOR COMPARING KEYS     #
          XREF PROC EXPEV20;
         XREF PROC CONVERT; 
         ITEM I;
         ITEM RC; 
      ITEM WORDPTR I;              # WORD INDEX                        #
      ITEM BITPTR I;               # BIT WITHIN WORD AT WORDPTR        #
      ITEM CHAR I;                 # HIGH OR LOW CHARACTER, DEPENDING  #
                                   # ON FUNCTION                       #
      XREF ITEM RECDORD I;         # RECORD ORDINAL USED BY THIS XMISSN#
      XREF ITEM RSTKPTR;
      XREF ITEM RSTKERROR B;
      XREF ITEM BLDRANGETBL B;
      XREF FUNC CMM$ALF I;         # ALLOCATES CM BLOCKS               #
      XREF ITEM POINTKNT; 
      XREF ITEM AREACOL;           # ADDRESS OF AREA TABLE             #
      XREF ITEM HIGHCHAR;          # CHAR WITH HIGHEST COLLATE VALUE   #
      XREF ITEM LOWCHAR;           # CHAR WITH LOWEST COLLATE VALUE    #
      XREF PROC HIGHLOW;           # CALCULATE HIGH AND LOW CHARACTER  #
      XREF ITEM DUMMY;                                                   RGTABLE
      XREF ITEM RTBLCALL; 
      XREF BASED ARRAY SAVDAREA;
        BEGIN 
        ITEM AREAINUSE  B(0,0,1); 
        ITEM RELORD     U(0,6,12);
        ITEM AREASAVE   I(0,42,18);  # AREA TABLE ADDRESS              #
        ITEM AREASAVEWD I(0,0,60);   # ENTIRE WORD                     #
        END 
      XREF ITEM LOWAREA;
      STATUS CODE LSTHAN, GRTHAN,GEQL, LEQL, EQL, , NEQL, 
                 ANDLOG, ORLOG, ALL;
      STATUS POS LOWER, EQUAL,HIGHER; 
      ITEM BASICCODE, 
           LITERALBITS, 
           STKINDEX,
           TABLINDEX, 
           PRIORIFXISTS B,
           RSLTSCRATCH, 
           RVALPTR, 
           KEYLENW, 
           CHARPOS, 
           WORDPOS, 
           CHARIND, 
           STRINGLGTH,
           SCRATCH1,
           SCRATCH2,
           LOWKEYV, 
           CURRENTKEY,
           PREVIOUSKEY, 
           OPERATOR,
           CHAR1 ,
           CHAR2 ,
           ORDINAL, 
           FIRSTONE,
           LASTONE, 
           PREVIOUS I,
           RELPOS S:POS;
      ITEM OP1, 
           OP2; 
      ITEM PAKLENGTH I;            # LENGTH IN CHARS OF PRIMARY OR     #
                                   # ALTERNATE KEY TO ACCESS BY        #
      ITEM PAKTYPE I;              # TYPE OF PRIMARY OR ALTERNATE KEY  #
                                   # TO ACCESS BY                      #
      ITEM TDSIGN B;               # TEMP SAVE LOCATION FOR DSIGN      #
      ITEM TDPOINT B;        # TEMP SAVE LOCATION FOR DPOINT           #
      ITEM TDPTLOC I;        # TEMP SAVE LOCATION FOR DPTLOC           #
  
      ARRAY MOCKUP [2]; 
        ITEM WORD1 I(0,0,60), 
             NCHARS U(0,12,12), 
             OPND1 I(0,24,18);
      ARRAY EXPRSTACK [9];    # HOLDING AREA #
        ITEM STACKADDR I (0,42,18), 
             PSTKPTR I (0,24,18); 
      ARRAY CVTCODES [0:0]; 
        BEGIN 
        ITEM CCODES I(0,0,60) = [O"01333435360000000000"];
        END 
      BASED ARRAY CVTPARAMS [0:0] S(2);  # E. E. FOR CONVERT #
        ITEM NBCHAR U(0,12,12),     # FROM FLD LENGTH IN BYTES #
             FROMCHAR U(0,4,4),    # RELATIVE FROM CHAR POS            #
             FROMWORD U(0,24,18),   # ADDR. OF SOURCE FLD      #
             TOWORD U(0,42,18),     # ADDR. OF SINK FLD  OR    #
                                    # ADDR. OF ATTRIB. ENTRY   #
             CONVRTCODE  U(1,0,6); #CONVERSION REQUESTED               # RGTABLE
                                    # CF. -CONVERT- FOR LIST   #
                                    # OF CODES                 #
      BASED ARRAY ATTRIBENTRY [0:0] S(3); 
        BEGIN 
        ITEM DEWPOS  I(01,18,18);   # ADDRESS OF SINK FIELD            #
        ITEM DECLSLG I(01,42,18);   # LENGTH OF SINK FIELD (BYTES)     #
        ITEM DSIGN   B(02,15,01);  # TRUE IF SIGN OVERPUNCH            #
        ITEM DPOINT  B(02,20,01);   # TRUE = DECIMAL POINT ACTUALLY    #
                                    # PRESENT, FALSE = ASSUMED POINT   #
        ITEM DPTLOC  I(02,21,06);   # CHAR POS OF POINT RELATIVE TO    #
                                    # THE END OF THE FIELD             #
                                    # >0 = POINT TO LEFT               #
                                    # <0 = POINT TO RIGHT              #
        END 
      XREF ARRAY RGSTACK[0:62] S(3);  # ARRAY DEFINED IN EXPEV20       #
        ITEM RSTKTYPE U(0,0,2), 
             RSTKOP U(0,2,4), 
             RSTKCODE U(0,0,6), 
             RSTKOPND0 I(0,6,18), 
             RSTKOPND1 I(0,24,18),
             RSTKRSLT I(0,42,18), 
             NUMCHARS U(0,12,12), 
             DUPVAL B(1,0,1), 
             UNIVORMAJKEY B(1,1,1),  # TRUE IF RGTABLE SHOULD PAD KEY  #
                                     # STARTING AT FIRST UNIVERSAL CHAR#
                                     # OR PAD MAJOR KEY UP TO FULL KEY #
                                     # LENGTH WITH HIGH OR LOW CHARACTE#
             RFROMCHAR U(1,6,6),   # RELATIVE BEGINNING CHAR POS OPND1 #
             PADCHARPOS U(1,15,9),   # CHARACTER POSITION TO START     #
                                     # PADDING WITH HIGH OR LOW CHAR   #
             STKORD I(1,24,18), 
             NEXTPTR I(1,42,18),
             KEYLOC U(2,42,18),    # ADDR OF THIS KEY"S PSTACK ENTRY   #
             RSTKWORD1 I(0,0,60), 
             RSTKWORD2 U(1,0,60), 
             RSTKWORD3 U(2,0,60); 
  
      XREF ARRAY AKT$TBL [0:0] S(1);  # DESCRIPTION OF SINGLE ALTERNATE#
                                      # KEY USED FOR RECORD RETRIEVAL  #
        BEGIN 
        ITEM AKT$ITEMORD   U(00,00,15);  # ITEM ORDINAL IF CDCS, ELSE 0#
        ITEM AKT$TYPE      U(00,15,06);  # KEY TYPE:  0 = ALPHANUMERIC #
                                         #            1 = NUMERIC, COMP#
                                         #            2 = INTEGER      #
                                         #            3 = COMP-1       #
                                         #            4 = COMP-2       #
                                         #            5 = DOUBLE       #
                                         #            6 = COMPLEX      #
                                         #            7 = LOGICAL      #
        ITEM AKT$LENGTH    U(00,21,09);  # KEY LENGTH IN CHARACTERS    #
        ITEM AKT$CPOS      U(00,30,06);  # CHAR POSITION OF KEY IN WORD#
                                         # POINTED TO BY AKT$WPOS      #
        ITEM AKT$WPOS      I(00,42,18);  # WORD POSITN OF KEY IN RECORD#
        END 
  
      BASED ARRAY OPERAND1; 
        ITEM I1 I(0,0,60),
             R1 R(0,0,60);
      BASED ARRAY OPERAND2; 
        ITEM I2 I(0,0,60),
             R2 R(0,0,60);
      BASED ARRAY RESULT; 
        ITEM IR I(0,0,60);
      BASED ARRAY RANGETABLE; 
        ITEM RTBLWORD I(0,0,60);
        SWITCH PATTERN LT,
                       GT,
                       GE,
                       LE,
                       EQUALPATTN,
                       ,
                       ALL, 
                       BOOLEAN, 
                       BOOLEAN, 
                       ALL; 
*CALL SETPSL
CONTROL EJECT;               # BEGINNING OF RGTABL EXECUTABLE CODE.    #
        P<AREA$TABLE> = AREASAVE[LOWAREA];
        P<KEY$TBL> = AT$PKEYDPTR;  # POSITION TO KEY DESC TABLE        #
        AREAORG = AT$FITFO;                                              RGTABLE
         P<BASICTABLE> = BASTABLOC; 
        BITINDEX = 0; 
        SCANALLAREA=FALSE;
        BLDRANGETBL=TRUE; 
        TABLINDEX = 0;
        LOGICALRESLT=FALSE; 
        PRIORIFXISTS = FALSE; 
        RSTKPTR=-1; 
        POINTKNT=0; 
        SCRATCH1 = LOC(WORD1[0]); 
        SCRATCH2 = LOC(WORD1[1]); 
        RSLTSCRATCH = LOC(WORD1[2]);
  
 #                                                           #
 #  INITIALIZATION OF POINTERS IS DONE.  NOW LOOP THROUGH    #
 #  THE BASICTABLE(S), PAUSING AT EACH -IF- FOR A QUICK      #
 #  SWING THROUGH EXPEV20 TO BUILD THE RANGE STACK.          #
 #                                                           #
       FOR TABLINDEX = 0 STEP 1 WHILE BLDRANGETBL 
          DO
          BEGIN 
          BASICCODE = BASCODE[TABLINDEX]; 
          IF BASICCODE EQ IFCODE
            THEN
            BEGIN 
            B<0,60>PROGSTACKLOC = BASCADDR[TABLINDEX];                   QU30296
            EXPEV20;               # CALL TO EXPEV20 TO BUILD RSTACK.  #
                                   # POINTER TO AREA TABLE IS ALSO SET #
                                   # THERE.                            #
            BITINDEX = -2;              # USED BY -NEXTGET- # 
#   THE RANGE STACK IS BUILT BY RSTACKR IN EXPEV20                     #
            IF RSTKERROR THEN TEST TABLINDEX; 
            IF PRIORIFXISTS 
              THEN       # -OR- THE CURRENT BIT PATTERN # 
              BEGIN      # WITH THE CUMULATIVE PATTERN  # 
              RSTKPTR = RSTKPTR + 1;
              IF RSTKPTR GQ 63
              THEN
                BEGIN 
                SCANALLAREA = TRUE; 
                RETURN; 
                END 
              RSTKCODE[RSTKPTR] = CODE"ORLOG";
              RSTKOPND0[RSTKPTR] = RSLTSCRATCH; 
              RSTKOPND1[RSTKPTR] = RSTKRSLT[RSTKPTR - 1]; 
              RSTKRSLT[RSTKPTR] = RSLTSCRATCH;
              END 
  
              ELSE
              BEGIN 
              PRIORIFXISTS = TRUE;
              RSTKRSLT[RSTKPTR] = RSLTSCRATCH;
              END 
            END 
            ELSE
            IF BASICCODE EQ ENDCODE 
              THEN BLDRANGETBL = FALSE; 
              ELSE IF BASICCODE EQ CONTCODE 
                     THEN 
                     BEGIN
                     BASCPTR = BASCLAST[TABLINDEX]; 
                     P<BASICTABLE> = BASCPTR; 
                     TABLINDEX = -1;
                     END
          END 
        IF ONEAKEY                 # IF ACCESSING BY SINGLE ALT KEY    #
        THEN
          BEGIN 
          PAKLENGTH = AKT$LENGTH[0];  # LENGTH OF ALT KEY              #
          PAKTYPE = AKT$TYPE[0];   # TYPE OF ALT KEY                   #
          END 
  
        ELSE                       # IF ACCESSING BY PRIMARY KEY       #
          BEGIN 
          PAKLENGTH = KT$LENGTH[RECDORD];  # LENGTH OF PRIMARY KEY     #
          PAKTYPE = KT$TYPE[RECDORD];  # TYPE OF PRIMARY KEY           #
          END 
  
        IF RSTKERROR OR (BITINDEX EQ 0) THEN   # EXIT IF OVERFLOW,# 
          BEGIN                           # ERROR, OR NO -IF-     # 
          SCANALLAREA = TRUE; 
          RETURN; 
          END 
  
                # WE CAN HANDLE 28 KEY VALUES WITH   #
                # A 60-BIT PATTERN                   #
                # MAJOR CONSTRAINT COULD BE KEY SIZE #
                # OF SYMBOLIC KEYS (UP TO 255 CHARS) #
                #  -- A LOT OF CM IF THERE ARE 28!   #
        IF POINTKNT GR 28 
          THEN SCANALLAREA = TRUE;
          ELSE
          BEGIN 
          LOGKEYSIZE = ((PAKLENGTH + 9) / 10) * 10; 
                                                     # RACTERS, ROUNDED#
                                                     # UP TO NEAREST   #
                                                     # MULTIPLE OF 10. #
          KEYLENW = LOGKEYSIZE/10;
          IFKEYLOC = CMM$ALF((((POINTKNT + 1) * KEYLENW) + 40), 0, 0);
          IF IFKEYLOC EQ 0
            THEN SCANALLAREA = TRUE;
          END 
  
        IF RSTKOPND1[0] EQ 0       # IF KEY IS COMPARING TO ITSELF, # 
                                   # NO RANGETABLE IS NEEDED.       # 
                                   # JUST HAVE A FULL FILE PASS.    # 
          THEN
            BEGIN 
            SCANALLAREA = TRUE; 
            END 
  
        IF SCANALLAREA THEN RETURN; 
  
 ############################################################ 
 # THIS IS THE LAST EARLY TERMINATION.  FROM HERE ON, WE    # 
 # CRUNCH NUMBERS, BUILDING THE RANGETABLE (IE.,BIT PATTERN)# 
 # FROM THE ARRAY -RANGESTACK-.                             # 
 #   PROCESSING STEPS ARE:                                  # 
 #     1) PICK UP ENTRY FROM RANGESTACK.                    # 
 #        IF NO MORE ENTRIES, GO TO STEP 7.                 # 
 #     2) IF ENTRY IS FOR A RELATION,THEN PROCEED.          # 
 #        OTHERWISE IT IS FOR A BOOLEAN AND DOES NOT REF-   # 
 #        A KEY VALUE DIRECTLY -- THEREFORE LOOP BACK TO    # 
 #        STEP 1.(WE ARE LOOKING FOR KEY VALUES)            # 
 #     3) MOVE KEY VALUE INTO STORAGE SPACE FOLLOWING THE   # 
 #        RECEIVING FIELD FOR THE FINAL BIT PATTERN. ALLOW  # 
 #        ROOM TO EXPAND SYMBOLIC KEYS TO FULL FIELD LENGTH # 
 #     4) FOR SYMBOLIC KEYS, PAD THE KEY VALUE CHARACTER    # 
 #        STRING UP TO LENGTH OF THE KEY FIELD.             # 
 #        PADDING IS EITHER WITH BLANKS OR WITH THE HIGHEST # 
 #        OR LOWEST CHARACTERS IN THE COLLATING SEQUENCE.   # 
 #     5) DETERMINE RANK OF KEY VALUE RELATIVE TO THE       # 
 #        KEY VALUES PROCESSED PREVIOUSLY.  AN ORDERED      # 
 #        CHAIN IS MAINTAINED FOR THIS PURPOSE.             # 
 #        THIS ALLOWS CREATION OF BIT PATTERNS.             # 
 #        CREATE INDEX TO THE KEY VALUES -- USED BY         # 
 #        NEXTGET TO RELATE BIT PATTERN TO VALUES           # 
 #     6) LOOP TO STEP 1 TO PICK UP THE NEXT ENTRY          # 
 #     7) ACTUAL PROCESSING OF -RANGESTACK-.                # 
 #         A) RELATIONAL OPERATOR ENTRIES RESULT IN THE     # 
 #            FORMATION OF INPUT BIT PATTERNS.              # 
 #         B) BOOLEAN OPERATOR ENTRIES OPERATE ON THESE     # 
 #            INPUT PATTERNS TO PRODUCE A CUMULATIVE        # 
 #            PATTERN.                                      # 
 ############################################################ 
  
#    SET UP BASED ARRAYS.  #
        P<CVTPARAMS> = IFKEYLOC;
        RTBLLOC = IFKEYLOC + 33;   # SAVE START OF RANGE TABLE         #
        P<RANGETABLE> = RTBLLOC;
        RVALPTR = RTBLLOC + 7;    # WE START COPYING KEY VALUES # 
                                  # BEGINNING A WORD 4 OF RTBL  # 
                                  # FINAL BIT PATTERN GOES IN WORD 0 #
                                  # INDEX IS IN WDS 1 THRU 3    # 
        LOWKEYV = -1; 
        PREVIOUS = -1;
        SETPSL;                    # SET *PROGSTACKLOC*                #
        P<PROGRAMSTACK> = PROGSTACKLOC;    # SAVE ORIGINAL LITERAL #
        LITERALBITS = 0;                   #FLAGS FOR USE LATER   # 
# THE FOLLOWING CODE SEARCHES THE PROGRAMSTACK TO FIND A NON-NUMERIC #
# LITERAL.  THIS IS DONE BY CHECKING THE LITERAL FLAGS FOUND IN   # 
# AN ENTRY WHICH IS AN OPERATOR.  IF THERE IS A -SPECIFY- REFERENCED #
# IN THE PROGRAMSTACK, THE -SPECIFY- TABLE IS ALSO SEARCHED.    # 
        FOR DUMMY=DUMMY                                                  RGTABLE
          WHILE LITERALBITS EQ 0                                         RGTABLE
        DO                                                               RGTABLE
          BEGIN 
          FOR STKINDEX = 0 STEP 1 WHILE LITERALBITS EQ 0 DO 
            BEGIN 
            IF OPCODE[STKINDEX] EQ O"70" THEN 
              IF PREVIOUS GQ 0 THEN 
                BEGIN 
                P<PROGRAMSTACK> = STACKADDR[PREVIOUS]; #RESET ADDRESS#
                STKINDEX = PSTKPTR[PREVIOUS]; #RESET POINTER# 
                PREVIOUS = PREVIOUS - 1;
                TEST STKINDEX;
                END 
              ELSE GOTO ENDLOOP;
              IF ENTRYTYPE[STKINDEX] EQ 3 OR ENTRYTYPE[STKINDEX] EQ 6 
                THEN
                BEGIN 
                PREVIOUS = PREVIOUS + 1;
                STACKADDR[PREVIOUS] = P<PROGRAMSTACK>; #SAVE ADDRESS# 
                PSTKPTR[PREVIOUS] = STKINDEX;   # SAVE POINTER# 
                P<PROGRAMSTACK> = EXPRESSTACK[STKINDEX];                 RGTABLE
                TEST DUMMY; 
                END 
              IF ENTRYTYPE[STKINDEX] NQ 7 THEN TEST STKINDEX; 
              ELSE LITERALBITS = LITBITS[STKINDEX]; 
            END 
          END 
ENDLOOP:  
        P<PROGRAMSTACK> = IFKEYLOC + IKPSTKOFFSET;
        ENTRYTYPE[0] = 1;               # SET UP PROGRAMSTACK TO BE # 
        ENTRYTYPE[1] = 1;               # USED BY EXPEVALUATE TO      # 
        ENTRYTYPE[2] = 7;               # DETERMINE THE RANK OF   THE # 
        ENTRYTYPE[3] = 7;               # KEYS.                    #
        NBRCHARS[0] = PAKLENGTH;   # LENGTH OF KEY                     #
        NBRCHARS[1] = PAKLENGTH;
        IF PAKTYPE NQ DT$NUM       # IF KEY IS NOT NUMERIC             #
        THEN
          BEGIN 
          AREAORD[0] = LOWAREA;    # STORE AREA ORDINAL IN PROGRAMSTACK#
                                   # SO EXPEVAL CAN GET CORRECT        #
                                   # COLLATING SEQUENCE TABLE.  NUMERIC#
                                   # KEYS ARE UNCOLLATED SYMBOLIC      #
          END 
  
        OPCODE[3] = O"70";
        LITBITS[2] = B<58,2>LITERALBITS;
        IF PAKTYPE LQ DT$NUM       # IF SYMBOLIC KEY                   #
        THEN
          BEGIN 
          OPCODE[2] = O"56";
          END 
        ELSE
          BEGIN 
          IF PAKTYPE EQ DT$INTEGER # INTEGER KEY                       #
          THEN
            BEGIN 
            OPCODE[2] = O"12";
            END 
          ELSE
            BEGIN 
            OPCODE[2] = O"32";        # FLOATING POINT KEY             #
            END 
          END 
        FOR STKINDEX = 0 STEP 1 UNTIL RSTKPTR 
          DO
          BEGIN 
          IF RSTKTYPE[STKINDEX] EQ 0 THEN TEST STKINDEX;
          P<OPERAND1> = RSTKOPND1[STKINDEX];
          STRINGLGTH = NUMCHARS[STKINDEX];
          NBCHAR[0] = STRINGLGTH; 
          FROMWORD[0] = P<OPERAND1>;
          FROMCHAR[0] = RFROMCHAR[STKINDEX];  # FROM IS ITEM OCC BCP   #
        P<PROGRAMSTACK> = KEYLOC[STKINDEX];  # USE ORIG PSTACK ENTRY   #
                                             # FOR THIS KEY            #
      IF PAKTYPE EQ DT$NUM         # IF NUMERIC                        #
        AND R1[0] LS 0             # IF NEGATIVE                       #
      THEN
        BEGIN 
        P<ATTRIBENTRY> = FROMWORDADDR[0];  # POSITION TO ATTRIB TABLE  #
        IF NOT DSIGN[0]            # IF NO SIGN OVER PUNCH             #
        THEN
          BEGIN 
                                   # CONVERSION WOULD YIELD A POSITIVE #
                                   # NUMBER WHICH WOULD GIVE WRONG     #
                                   # RECORD RETRIEVAL, SO WRITE -ALL-  #
          RSTKCODE[STKINDEX] = CODE"ALL"; 
          TEST STKINDEX;
          END 
        END 
  
      IF KEYTYPE[0] EQ 2           # IF INTEGER                        #
        AND ENTRYTYPE[0] LQ 1      # IF NO CONVERSION REQUIRED         #
      THEN
        BEGIN 
        P<RESULT> = RVALPTR;       # POSITION TO RESULT FIELD          #
        IR[0] = I1[0];             # MOVE INTEGER                      #
        P<PROGRAMSTACK> = IFKEYLOC + IKPSTKOFFSET;
        END 
      ELSE
        BEGIN 
        IF KEYTYPE[0] LQ 3         # IF NUMERIC, INTEGER, OR UNNORM    #
          AND KEYTYPE[0] GQ 1 
        THEN                       # SAVE ITS DEC POINT INFO           #
          BEGIN 
          P<ATTRIBENTRY> = FROMWORDADDR[0]; 
          TDSIGN = DSIGN[0];
          TDPOINT = DPOINT[0];
          TDPTLOC = DPTLOC[0];
          END 
        ELSE                       # ELSE SET TO 0                     #
          BEGIN 
          TDSIGN = FALSE; 
          TDPOINT = FALSE;
          TDPTLOC = 0;
          END 
        P<ATTRIBENTRY> = IFKEYLOC+2;
        DECLSLG[0] = NBRCHARS[0];  # LENGTH OF KEY                     #
        DSIGN[0] = TDSIGN;
        DPOINT[0] = TDPOINT;   # SET DEC PT INFO IN NEW ATTRIBENTRY    #
        DPTLOC[0] = TDPTLOC;
                             # SET CONVRTCODE BY KEYTYPE               #
        CONVRTCODE[0] = B<KEYTYPE[0]*6,6>CCODES[0]; 
        P<PROGRAMSTACK> = IFKEYLOC + IKPSTKOFFSET;
                                   # RESET PSTACK TO CURRENT ADDRESS   #
          IF PAKTYPE LQ DT$FIXED   # IF ALPHA, NUM, INTEGER, FIXED     #
            THEN
            BEGIN 
            TOWORD[0] = P<ATTRIBENTRY>; 
            DEWPOS[0] = RVALPTR;
            END 
            ELSE TOWORD[0] = RVALPTR; 
          CONVERT(CVTPARAMS,RC);  # MOVE KEY VALUES TO HIGH CORE #
          IF RC NQ 0  # CHECK FOR ERRORS IN CONVERSION #
            THEN IF RC EQ 54
                   THEN  # OVERFLOWED RECEIVING FLD # 
                   BEGIN
                   RSTKCODE[STKINDEX] = CODE"ALL";
                   TEST STKINDEX; 
                   END
                   ELSE  # UNKNOWN ERROR - PASS WHOLE FILE #
                   BEGIN
                   SCANALLAREA = TRUE;
                   RETURN;
                   END
        END 
          RSTKOPND1[STKINDEX] = RVALPTR;
          P<OPERAND1> = RVALPTR;
          IF UNIVORMAJKEY[STKINDEX]  # IF WE MUST REPLACE CHARACTERS   #
          THEN
            BEGIN 
            WORDPTR = PADCHARPOS[STKINDEX] / 10;
            BITPTR = (PADCHARPOS[STKINDEX] - (WORDPTR * 10)) * 6; 
            AREACOL = P<AREA$TABLE>;  # GIVE HIGHLOW THE AREA TBL ADDR #
            HIGHLOW;               # CALCULATE LOW AND HIGH CHARACTER  #
            IF RSTKOP[STKINDEX] EQ CODE"GRTHAN"  # IF *GT*             #
              OR RSTKOP[STKINDEX] EQ CODE"LEQL"  # IF *LE*             #
            THEN
              BEGIN 
              CHAR = HIGHCHAR;     # PAD WITH HIGHEST CHAR             #
              END 
            ELSE                   # FOR *GE* AND *LT*                 #
              BEGIN 
              CHAR = LOWCHAR;      # PAD WITH LOWEST CHAR              #
              END 
            FOR I = PADCHARPOS[STKINDEX] STEP 1 
              UNTIL PAKLENGTH - 1 
            DO
              BEGIN 
              B<BITPTR,6>I1[WORDPTR] = CHAR;  # STORE HIGH OR LOW CHAR #
              IF BITPTR EQ 54      # IF END OF WORD                    #
              THEN
                BEGIN 
                BITPTR = 0;        # POSITION TO NEXT WORD             #
                WORDPTR = WORDPTR + 1;
                END 
              ELSE
                BEGIN 
                BITPTR = BITPTR + 6;  # POSITION TO NEXT CHARACTER     #
                END 
              END 
            END 
  
          IF LOWKEYV LS 0 
            THEN
            BEGIN 
            LOWKEYV = STKINDEX; 
            RVALPTR = RVALPTR + KEYLENW;
            END 
            ELSE
            BEGIN 
            RELPOS = POS"HIGHER"; 
            PREVIOUSKEY = -1; 
            CURRENTKEY = LOWKEYV; 
  
 # LINK THE NEW KEY VALUE INTO IT-S APPROPRIATE POINT IN  # 
 # THE ORDERED CHAIN OF KEY VALUES PROCESSED PREVIOUSLY   # 
 # DUPLICATE VALUES ARE LINKED IN FRONT OF THEIR DUP.     # 
 # -LOWKEYV- POINTS TO THE RANGESTACK ENTRY WHERE THE     # 
 # LOWEST KEY VALUE IS REFERENCED.  THAT STACK ENTRY      # 
 # POINTS TO THE STACK ENTRY WHERE THE NEXT HIGHER (OR    # 
 # POSSIBLY DUPLICATE) KEY VALUE IS REFERENCED.           # 
 # THE ENTRY REFERENCING THE HIGHEST VALUE HAS A NEGATIVE # 
 # ONE IN ITS POINTER FIELD.                              # 
            TOWORDADDR[0] = RSTKOPND1[STKINDEX];
  
            FOR I = 0 WHILE RELPOS EQ POS"HIGHER" AND CURRENTKEY GQ 0 
              DO
              BEGIN 
              P<OPERAND2> = RSTKOPND1[CURRENTKEY];
              TOWORDADDR[1] = RSTKOPND1[CURRENTKEY];
              PROGSTACKLOC = IFKEYLOC + IKPSTKOFFSET; 
              RTBLCALL = 1; 
              BLDRANGETBL = FALSE;
              EXPEV20;             # CALL EXPEV20 TO DETERMINE THE     #
                                   # RELATIONSHIP.                     #
                             # RELATIONSHIP.                    # 
              IF RTBLCALL LQ 0 THEN 
                BEGIN 
                IF RTBLCALL EQ 0 THEN RELPOS = POS"EQUAL";
                ELSE RELPOS = POS"LOWER"; 
                TEST I; 
                END 
  
RESETPTRS:  
                PREVIOUSKEY = CURRENTKEY; 
                CURRENTKEY = NEXTPTR[CURRENTKEY]; 
              END       # END OF THE -I- LOOP # 
            IF RELPOS EQ POS"EQUAL" 
              THEN    # WE DON-T NEED TWO COPIES OF THE SAME KEY VALUE #
              BEGIN   # WASTING CENTRAL MEMORY. READJUST POINTERS.     #
              RSTKOPND1[STKINDEX] = RSTKOPND1[CURRENTKEY];
              DUPVAL[CURRENTKEY] = TRUE;
              END 
              ELSE RVALPTR = RVALPTR + KEYLENW; 
            IF PREVIOUSKEY LS 0 
              THEN    # VALUE WILL BE THE NEW LOWKEYV                  #
              BEGIN 
              NEXTPTR[STKINDEX] = LOWKEYV;
              LOWKEYV = STKINDEX; 
              END 
              ELSE    # LINK TO CHAIN IN THE NORMAL FASHION            #
              BEGIN 
              NEXTPTR[STKINDEX] = CURRENTKEY; 
              NEXTPTR[PREVIOUSKEY] = STKINDEX;
              END 
  
            END  #END OF THE IF LOWKEYV LS 0 ELSE BRANCH  # 
          END 
  
 # END OF THE -FOR STKINDEX- LOOP THAT MOVES, SUBSTITUTES # 
 # FOR UNIVERSAL CHARS, PADS, AND ORDERS KEY VALUES.      # 
 # NOW WE CAN ACTUALLY BUILD THE RANGETABLE BIT PATTERNS  # 
 # -- BUT FIRST WE WILL QUICKLY WRITE AN INDEX TO THE LIST# 
 # OF KEY VALUES WE HAVE SITTING IN HIGH CORE.            # 
  
        RTBLCALL = 0; 
        CURRENTKEY = LOWKEYV; 
        ORDINAL = -1; 
        CHARPOS = 0;
        WORDPOS = 1;
        FOR I=0 WHILE CURRENTKEY GQ 0 
          DO
          BEGIN 
          IF NOT DUPVAL[CURRENTKEY] 
            THEN
            BEGIN 
            ORDINAL = ORDINAL + 1;
#  STORE THE ADDRESSES OF KEY VALUES IN THE RANGE TABLE.    # 
#  THE ORDINAL IS THE POINTER TO EACH ADDRESS.              # 
            B<CHARPOS,12>RTBLWORD[WORDPOS] =
               RSTKOPND1[CURRENTKEY] - RTBLLOC; 
            IF CHARPOS EQ 48
              THEN
              BEGIN 
              CHARPOS = 0;
              WORDPOS = WORDPOS + 1;
              END 
              ELSE CHARPOS = CHARPOS + 12;
            END 
          STKORD[CURRENTKEY] = ORDINAL; 
          CURRENTKEY = NEXTPTR[CURRENTKEY]; 
          END 
  
 # THE INDEX IS COMPLETE. NOW BUILD AND PROCESS THE BIT PATTERNS #
  
        FOR STKINDEX = 0 STEP 1 UNTIL RSTKPTR 
          DO
          BEGIN 
          IF RSTKWORD1[STKINDEX] EQ 0 THEN TEST STKINDEX; 
          FIRSTONE = 0; 
          LASTONE = 0;
          P<RESULT> = RSTKRSLT[STKINDEX]; 
          OPERATOR = RSTKOP[STKINDEX];
          GOTO PATTERN[OPERATOR]; 
#  BUILD THE BIT PATTERN DEPENDING ON THE OPCODE.          #
#  A BIT VALUE OF 1 INDICATES THE BEGINNING OF A RANGE.    #
  
LE: 
            LASTONE = 1;
LT: 
            LASTONE = LASTONE + (2 * STKORD[STKINDEX]); 
            GOTO SETBITS; 
GT: 
            FIRSTONE = 1; 
GE: 
            FIRSTONE = FIRSTONE + (2 * STKORD[STKINDEX]) + 1; 
            LASTONE = 57; 
            GOTO SETBITS; 
EQUALPATTN: 
            FIRSTONE = 1 + (2 * STKORD[STKINDEX]);
            LASTONE = FIRSTONE; 
SETBITS:  
            IR[0] = 2;      # INITIALIZE TO A NON-ZERO, NON-ONE VAL # 
            FOR I = FIRSTONE STEP 1 UNTIL LASTONE 
              DO B<I,1>IR[0] = 1; 
            TEST STKINDEX;
BOOLEAN:  
          P<OPERAND1> = RSTKOPND1[STKINDEX];
          P<OPERAND2> = RSTKOPND0[STKINDEX];
          OP1 = I1[0];
          OP2 = I2[0];
          IF OP1 EQ 0 OR OP1 EQ 1 THEN OP1 = -1;
          IF OP2 EQ 0 OR OP2 EQ 1 THEN OP2 = -1;
          IF OPERATOR EQ CODE"ANDLOG" 
            THEN IR[0] = OP1 LAN OP2; 
            ELSE IR[0] = OP1 LOR OP2; 
          TEST STKINDEX;
ALL:  
            IR[0] = -1; 
          END 
  
 # SIGH... WE-RE DONE   # 
  
        RTBLWORD[0] = IR[0]; # THE LAST RESULT IS THE CUMULATIVE #
                             # PATTERN WE NEED.                  #
        IF RTBLWORD[0] EQ -1       # IF FINAL BIT PATTERN IS -ALL-     #
        THEN
          BEGIN 
          SCANALLAREA = TRUE;      # FULL FILE PASS                    #
          END 
  
        P<PROGRAMSTACK> = IFKEYLOC + IKPSTKOFFSET;  # PREPARE PSTACK   #
                                                    # FOR NEXTGET      #
  
        IF AT$KEYEXCL[0]           # IF KEY OUTSIDE RECORD             #
          OR ONEAKEY               # IF ACCESSING BY SINGLE ALT KEY    #
        THEN
          BEGIN 
          TOWORDADDR[0] = P<AREA$TABLE> + AT$CURRKEY[0];
                                   # KEY LOCATION                      #
          RELTOCHAR[0] = 0; 
          END 
  
        ELSE                       # KEY IS INSIDE RECORD              #
          BEGIN 
          RELTOCHAR[0] = KT$CPOS[RECDORD];  # KEY CHARACTER POSITION   #
                                   # NEXTGET WILL STORE KEY WORD       #
                                   # POSITION AFTER FITWSA ASSIGNED    #
          END 
  
        RETURN; 
        END 
     TERM 
