*DECK RELSCAN 
USETEXT TCMMDEF 
USETEXT TENVIRN 
USETEXT TRELTBL 
      PROC RELSCAN; 
      BEGIN 
#                                                                      #
#     R E L S C A N                                                    #
#                                                                      #
# RELSCAN CONTAINS TWO PROCS, GETRELATION AND SCANRELSTK. REFER TO     #
# THE DESCRIPTION PRECEDING EACH OF THESE PROCS FOR DETAILS.           #
#                                                                      #
      XREF ITEM LOWAREA;           # ORDINAL OF LOWEST AREA            #
      XREF ITEM LOWRELATION;       # ORDINAL OF LOWEST RELATION        #
      XREF ITEM LOWSTKENTRY;       # ORDINAL OF PROGSTAK LOW AREA ENTRY#
      XREF ITEM VIAPOINT; 
      XREF ITEM RELATBLPTR;         # ADDRESS OF FIRST RELATION TABLE. #
      XREF PROC CMOVE;
      XREF PROC DIAG; 
      XREF PROC READ; 
      XREF PROC WRITE;
      XREF BASED ARRAY SAVDAREA;   # ARRAY TO SAVE INFO ABOUT AREAS.   #
        BEGIN 
        ITEM AREASAVE    U(0,42,18);  # ADDRESS OF AREA TABLE.         #
        ITEM AREAINUSE   B(0,0,1);    # TRUE--THIS AREA WILL BE USED.  #
        ITEM RELORD      U(0,6,12);   # ORDINAL OF RELATION ENTRY FOR  #
        ITEM AREASAVEWD  U(0,0,60);   # THIS AREA.                     #
        END 
      XREF ITEM CURRVIANUM;        # PATH BIT NUMBER OF CURRENT -VIA-  #
      XREF ITEM CURRELLOC;         # ADDRESS OF CURRENT REL TABLE.     #
      XREF ITEM CURRELATION;       # ACCUMULATED BIT PATH FLAGS.       #
      BASED ARRAY SAVEREL S(5);    # SAVES INFO ABOUT RELATION.        #
        BEGIN                      # RELATIONS--TEMPORARY.             #
        ITEM RELSAVE  U(0,0,6); 
        ITEM RELADDR  U(0,42,18); 
        ITEM RELNAME  C(1,0,40);   # RELATION NAME.                    #
        END 
      ITEM LOOPCON B;              # LOOP CONTROL VARIABLE.            #
      ITEM INDEX; 
      ITEM DUMMY; 
      ITEM DUMMY1;
      ITEM RC;                     # RETURN CODE.                      #
      ARRAY READBUF [0:0] S(5);    # INPUT BUFFER FOR READING A RELA-  #
        BEGIN                      # TION NAME.                        #
        ITEM CARRCTL C(0,0,1);     # CARRIAGE CONTROL CHARACTER        #
        ITEM RESPNAME C(0,0,40);
        ITEM FILLER C(4,0,10);
        END 
      XDEF PROC GETRELATION;
      PROC GETRELATION (RCG); 
      BEGIN 
#                                                                      #
#     G E T R E L A T I O N                                            #
#                                                                      #
# THIS PROC FINDS THE PROPER RELATION TABLE BY EXAMINING -CURRELATION- #
# AND -VIA$POINT-. VIA$POINT IS THE ADDRESS OF THE RELATION TABLE      #
# SPECIFIED IN A -VIA- DIRECTIVE. CURRELATION IS THE RESULT OF -ANDING-#
# THE BIT PATHS ASSOCIATED WITH EACH AREA.  AT LEAST ONE BIT SHOULD BE #
# ONE BIT TURNED ON. THE POSITION OF THE BIT(S) THAT IS ON SHOULD BE   #
# THE SAME AS THE BIT NUMBER ASSOCIATED WITH A RELATION TABLE.  IF     #
# MORE THAN ONE BIT IS ON, THE USER WILL SELECT THE PROPER RELATION.   #
# -CURRVIANUM- AND -CURRELLOC- WILL BE SET TO THE BIT NUMBER AND THE   #
#  ADDRESS OF THE RELATION TABLE, RESPECTIVELY, ON EXIT.               #
#                                                                      #
      ITEM RCG;                    # RETURN CODE.                      #
      CURRELLOC = 0;
      CURRVIANUM = 0; 
      IF VIAPOINT NQ 0 THEN        # VIA HAS BEEN SPECIFIED. SET UP    #
        BEGIN                      # POINTERS ACCORINGLY.              #
        P<REL$TABLE> = VIAPOINT;
        CURRVIANUM = RT$PATHBIT;
        END 
      INDEX = -1; 
      P<SAVEREL> = CMM$ALF(59*2, 0, 0);  # GET SPACE FOR HOLDING INFO. #
      LOOPCON = TRUE; 
      FOR DUMMY = 1 STEP 1 UNTIL 59 DO       # LOOK FOR BIT PATH FLAGS.#
        BEGIN 
        IF B<DUMMY,1>CURRELATION  EQ 1 THEN  # BIT IS SET--CHECK THIS  #
          BEGIN                              # PATH.                   #
          INDEX = INDEX + 1;
          RELSAVE[INDEX] = DUMMY; 
          IF CURRVIANUM NQ 0 THEN  # IF THERE IS A -VIA-, CHECK TO SEE #
            BEGIN 
                                   # IF THIS IS THE -VIA- PATH.        #
            IF DUMMY EQ CURRVIANUM THEN 
              BEGIN 
              DUMMY = 60; 
              INDEX = -1;          # EXIT GETRELATION                  #
              CURRELLOC = VIAPOINT; 
              TEST DUMMY; 
              END 
            END 
          END 
        END                        # END OF -DUMMY- LOOP.              #
      IF INDEX EQ 0 THEN           # ONLY ONE PATH WAS FOUND. THIS IS  #
        BEGIN                      # THE PATH TO BE USED. LOCATE THE   #
                                   # TABLE ASSOCIATED WITH THIS PATH.  #
        LOOPCON = TRUE; 
        CURRVIANUM = RELSAVE[0];
        P<REL$TABLE> = RELATBLPTR;
        FOR DUMMY = DUMMY WHILE LOOPCON DO
          BEGIN 
          IF RT$PATHBIT[0] EQ CURRVIANUM THEN 
            BEGIN 
            CURRELLOC = P<REL$TABLE>;  # HAVE LOCATED THE TABLE. EXIT  #
            LOOPCON = FALSE;           # LOOP.                         #
            TEST DUMMY; 
            END 
          ELSE
            BEGIN 
            IF RT$FORWARD[0] NQ 0 THEN   # MOVE TO THE NEXT TABLE IN   #
              BEGIN                      # THE CHAIN.                  #
              P<REL$TABLE> = RT$FORWARD[0]; 
              TEST DUMMY; 
              END 
            ELSE
              BEGIN 
              LOOPCON = FALSE;
              TEST DUMMY; 
              END 
            END 
          END                      # END OF -DUMMY- LOOP.              #
        END 
        IF INDEX GR 0 THEN         # MORE THAN 1 PATH EXISTS. USER WILL#
          BEGIN                    # CHOOSE THE CORRECT RELATION, DIAGS#
                                   # 1011, 1012, AND 1013 PRINT OUT    #
                                   # RELATION INFO FOR USER.           #
          DIAG (1011);
          DIAG (1012);
          CARRCTL[0] = " ";        # CARRIAGE CONTROL CHARACTER        #
          FOR DUMMY = 0 STEP 1 WHILE RELSAVE[DUMMY] NQ 0 DO 
            BEGIN 
            P<REL$TABLE> = RELATBLPTR;
            LOOPCON = TRUE; 
            FOR DUMMY1 = DUMMY1 WHILE LOOPCON DO
              BEGIN 
              IF RT$PATHBIT[0] EQ RELSAVE[DUMMY] THEN 
                BEGIN 
                RELNAME[DUMMY] = RT$RELNAME[0]; 
                RELADDR[DUMMY] = P<REL$TABLE>;
                CMOVE(RELNAME[DUMMY], 0, 40, READBUF, 1); 
                WRITE(READBUF, 41, RC);  # WRITE RELATION NAME         #
                TEST DUMMY; 
                END 
              ELSE
                BEGIN 
                IF RT$FORWARD[0] NQ 0 THEN   # MOVE TO NEXT TABLE IN   #
                  BEGIN                      # CHAIN.                  #
                P<REL$TABLE> = RT$FORWARD[0]; 
                TEST DUMMY1;
                END 
                ELSE
                  BEGIN 
                  LOOPCON = FALSE;
                  TEST DUMMY1;
                  END 
                END 
              END                  # END OF -DUMMY1- LOOP.             #
            END                    # END OF -DUMMY- LOOP.              #
          IF TERMINAL EQ 0 THEN    # IF BATCH MODE                     #
            BEGIN 
            DIAG (364);            # NO PROMPT UNDER BATCH MODE        #
            RCG=1;                 # IGNORE THIS COMMAND               #
            RETURN; 
            END 
          DIAG (1013, ">>");       # >> IS PRINTED OUT.                #
          DUMMY = 40; 
          DUMMY1 = 40;
          C<0,40>RESPNAME[0] = " ";           # BLANK OUT BUFFER       #
          READ (READBUF, DUMMY1, DUMMY, RC);  # READ USER RESPONSE.    #
          LOOPCON = TRUE; 
          FOR DUMMY = 0 STEP 1 WHILE LOOPCON DO 
            BEGIN 
            IF C<0,40>RELNAME[DUMMY] EQ C<0,40>RESPNAME[0]
            THEN
              BEGIN 
                                           # FOUND A MATCH. THIS IS    #
              CURRELLOC = RELADDR[DUMMY];  # USER SPECIFIED RELATION.  #
              CURRVIANUM = RELSAVE[DUMMY];
              LOOPCON = FALSE;
              TEST DUMMY; 
              END 
            IF RELNAME[DUMMY] EQ 0 THEN  # NO MORE RELATION NAMES.     #
              BEGIN 
              RCG = 1;
              DIAG (340);          # NO MATCH ON RELATION NAME.        #
              RETURN; 
              END 
            END                    # END OF -DUMMY- LOOP.              #
          END 
      DUMMY = P<SAVEREL>; 
      CMM$FRF (DUMMY);             # RELEASE TEMPORARY SPACE.          #
      END                          # END OF GETRELATION.               #
 CONTROL EJECT; 
      XDEF PROC SCANRELSTK; 
      PROC SCANRELSTK;
      BEGIN 
#                                                                      #
#     S C A N R E L S T K                                              #
# THIS PROC SCANS THE RELATION TABLE AND ARRAY SAVDAREA, LOOKING FOR A #
# MATCH BETWEEN THE AREA TABLE ADDRESS IN THE RELATION TABLE AND THE   #
# AREA TABLE ADDRESS IN SAVDAREA. ALSO, THE LOWEST AREA IN THE CHAIN   #
# WILL BE LOCATED, AS WELL AS THE LOWEST RELATION ORDINAL.             #
#                                                                      #
      P<REL$TABLE> = CURRELLOC;    # PICK UP ADDRESS OF RELATION TABLE.#
      LOWRELATION = 100;
      LOOPCON = TRUE; 
      LOWAREA = 0;
# THIS LOOP FINDS A MATCH BETWEEN THE AREA ADDRESS IN SAVDAREA- AND    #
# THE AREA ADDRESS IN RR$AREAPTR, WHICH IS PART OF THE RELATION, OR    #
# RANK, INFORMATION. THE RELATION ORDINAL IS PUT IN SAVDAREA- FOR      #
# FUTURE USE.                                                          #
      FOR DUMMY = 1 STEP 1 UNTIL RT$NORANKS + 1 DO
        BEGIN 
        DUMMY1 = LOC(RT$RANKPOS[0]);
        IF DUMMY LQ 2 THEN
          BEGIN 
          P<REL$RANKINFO> = DUMMY1 + ((DUMMY - 1) * RANKSIZE);
          END 
        ELSE
          BEGIN 
          P<REL$RANKINFO> = P<REL$RANKINFO> + (RANKSIZE * 2); 
          END 
        FOR DUMMY1 = 1 STEP 1 
          WHILE AREASAVE[DUMMY1] NQ 0 
        DO
          BEGIN 
          IF AREASAVE[DUMMY1] EQ RR$AREAPTR[0] THEN 
            BEGIN 
            RELORD[DUMMY1] = DUMMY; 
            IF DUMMY LS LOWRELATION THEN
              BEGIN 
              LOWRELATION = DUMMY;
              LOWAREA = DUMMY1; 
              END 
            TEST DUMMY; 
            END 
          ELSE
            BEGIN 
            TEST DUMMY1;
            END 
          END                      # END OF DUMMY1 LOOP.               #
        END                        # END OF DUMMY LOOP.                #
                                   # LOOK THROUGH THE ARRAY -SAVDAREA- #
                                   # TO MAKE SURE THAT ALL REQUIRED    #
                                   # AREAS ARE MARKED AS -IN USE-. IF  #
                                   # AN AREA IN A RELATION IS NOT DIR- #
                                   # ECTLY SPECIFIED IN A QUERY, IT    #
                                   # WILL NOT BE -IN USE-, EVEN IF IT  #
                                   # IS NEEDED TO COMPLETE THE RECORD  #
                                   # SET.                              #
      FOR DUMMY = 1 STEP 1 WHILE AREASAVE[DUMMY] NQ 0 DO
        BEGIN 
        IF NOT AREAINUSE[DUMMY] AND RELORD[DUMMY] NQ 0 THEN 
          BEGIN 
                                   # FOUND A POSSIBLE MISSING AREA.    #
          FOR DUMMY1 = 1 STEP 1 WHILE AREASAVE[DUMMY1] NQ 0 DO
            BEGIN 
            IF RELORD[DUMMY1] GR RELORD[DUMMY] AND
               AREAINUSE[DUMMY1] THEN 
                                   # THIS IS A MISSING AREA. TURN ON   #
                                   # THE AREAINUSE FLAG.               #
              BEGIN 
              AREAINUSE[DUMMY] = TRUE;
              TEST DUMMY; 
              END 
            END 
          END 
        END 
      END                          # END OF SCANRELSTACK.              #
      END                          # END OF -RELSCAN-                  #
      TERM
