*DECK S$GNREV 
          PROC  S$GNREV(SPEC$, OREC, ORSA, REC$); 
  
#**       S$GNREV -  GENERATE- REVERT RECORD                           #
#                                                                      #
#     CALLING SEQUENCE-                                                #
#         S$GNREV(SPEC$, <OREC>, <ORSA>, REC$):                        #
#                                                                      #
#     GIVEN-                                                           #
#         SPEC$ = USER SPECIFICATION.                                  #
#         <OREC>  = WSAF$OREC OR WSAS$OREC, WHICH IS                   #
#                    OFFSET IN WSA$ FOR EXTERNAL RECORD                #
#          AND PUT IT AT <OREC>.                                       #
#         <OREC> = WSAF$OREC OR WSAS$OREC, WHICH IS                    #
#          THE WORD OFFSET IN WSA$ FOR THE RECORD STORAGE AREA.        #
#                                                                      #
#     DOES-                                                            #
#         GENERATES CODE TO REVERT THE RECORD                          #
#          AND PUT IT AT WSAS$OREC.                                    #
#                                                                      #
#     GENERATED CODE ASSUMES-                                          #
#         CERTAIN REGISTERS ARE ALWAYS TO BE PRESERVED.                #
  
  
          BEGIN 
          ITEM  OREC         I;        # OFFSET FOR EXTERNAL RECORD    #
          ITEM  ORSA         I;        # OFFSET FOR REC STOR AREA      #
  
*CALL A 
  
*CALL REC$
  
*CALL SPEC$ 
  
*CALL MACHINE 
  
*CALL KT$ 
  
          XREF
              BEGIN 
              PROC  S$ABORT;           # INTERNAL ERROR                #
              PROC  S$SKIP;     # SKIP AN INTERNAL FIELD  # 
              PROC  S$GNCNE;           # GEN- COPY NON-KEY TO EXTERNAL #
              PROC  S$GNCVE;           # GEN- COPY VAR. PART TO EXT.   #
              PROC  S$GNRVK;           # GEN- REVERT A SINGLE KEY      #
              PROC  S$GNRZR;           # GEN- ZERO EXTERNAL RECORD     #
              PROC  S$GNXLN;           # GEN- EXTRACT LENGTH           #
              PROC  S$STLEN;           # SET REC LEN IN ORECLEN        #
              END 
  
          XREF
              BEGIN 
              ITEM  S$IRRL   I;        # REC$IRRL                      #
              ITEM  S$LK     I;        # NUMBER OF USED KEY BITS       #
              ITEM  S$LR     I;        # NUMBER OF BITS FOR REC. NUM.  #
              ITEM  S$OREC   I;        # WSA$ OFFSET TO EXTERNAL REC   #
              ITEM  S$ORSA   I;        # WSA$ OFFSET TO REC STOR AREA  #
              END 
  
               ARRAY KEY$ [1:200] S(2); 
              BEGIN 
                    ITEM  KEY$LENGTH    I( 0, 0,30);
                    ITEM  KEY$OFFSET    I( 0,30,30);
                    ITEM  KEY$OVERLAP   B( 1, 0,30);
                    ITEM  KEY$CONTAIN   B( 1,30,30);
              END 
  
                   ARRAY OVER[1:200]; 
                       ITEM OVERLAP$OFLN   I( 0, 0,60); 
                    ITEM OVERLAP$PNTR    I; 
                    ITEM LASTONE         I; 
          ITEM  I;           # INDEX TO SPEC$ KEY ENTRY                #
          ITEM  SI                     I; # INDEX TO SPEC$SUM ENTRY    #
          ITEM  K            I;        # INDEX TO SPEC$ OR KEY$        #
          ITEM  LENGTH       I;        # LENGTH OF A NON-KEY FIELD     #
          ITEM  NKEYS        I;        # NUMBER OF KEYS                #
          ITEM  OFFSET       I;        # OFFSET OF A NON-KEY FIELD     #
          ITEM  SORTED       B;        # FLAG TO HELP SORT             #
          ITEM SUM       B = TRUE;
          ITEM KEY       B= FALSE;
          ITEM REP           I;# TEMP. REPETITION COUNTER              #
          ITEM TEMPSUMBIT    I;# CALCULATE OFFSET FOR                  #
                               # REPEATED SUM FIELDS                   #
  
  
          CONTROL DISJOINT; 
  
          CONTROL INERT ; 
  
CONTROL EJECT;
  
#         AS A GENERAL PRINCIPLE IT DOES NOT MATTER WHETHER WE COPY    #
#          SEQUENTIALLY FROM THE INTERNAL RECORD TO VARIOUS FIELDS     #
#          IN THE EXTERNAL RECORD, OR COPY SEQUENTIALLY TO THE         #
#          EXTERNAL RECORD FROM VARIOUS FIELDS IN THE INTERNAL RECORD. #
#          HOWEVER THE LATTER METHOD REQUIRES THE ABILITY TO DETERMINE #
#          THE OFFSET IN AN INTERNAL RECORD OF AN INTERNAL KEY FIELD   #
#          FROM THE EXTERNAL KEY SPECIFICATION, AND THIS ABILITY IS NOT#
#          READILY AVAILABLE.                                          #
  
#     SET GLOBAL VARIABLES FOR THE LOW-LEVEL CODE GENERATORS           #
  
          S$IRRL = REC$IRRL;
          S$LK = 0; 
          S$LR = REC$LR;
          S$OREC = OREC;
  
#     ZERO OUT THE EXTERNAL RECORD FOR EASIER INSERTION OF FIELDS      #
  
          S$GNRZR(BYTE*SPEC$MRL);#(S$OREC)# 
  
#     REVERT KEY FIELDS TO THEIR ORIGINAL FORM                         #
  
          FOR I = SPEC$1STKEY WHILE I NQ 0 DO 
            BEGIN 
          IF ( SPEC$KEYTYPE[I] EQ KT$T"DISPLAY" ) 
                    AND 
             ( NOT SPEC$KEYALT[I] )    # WE HAVE EQUATES WITH          #
                                       # NO ALTER                      #
            THEN
                S$SKIP((SPEC$KEYNBYT[I]*BYTE)+SPEC$KEYNBIT[I]); 
            ELSE
              BEGIN 
              S$GNRVK(SPEC$KEYTYPE[I],
                  BYTE*SPEC$KEYNBYT[I]+SPEC$KEYNBIT[I], 
                  BYTE*SPEC$KEYBYTE[I]+SPEC$KEYBIT[I],
                  SPEC$KEYASC[I], 
                      LOC(SPEC$CSORDER[SPEC$KEYCS[I]]), 
                      KEY); 
              END 
            I = SPEC$NEXTKEY[I];
            END 
  
          $BEGIN
          IF S$LK GR (REC$LK1 + REC$LK2) THEN 
              S$ABORT("S$GNREV-1"); 
          $END
  
          # IF THE RETAIN OPTION WAS SPECIFIED, SKIP                   #
          # OVER THE RECORD ORDINAL IN THE INTERNAL RECORD             #
          # AND DO NOT REVERT IT                                       #
  
          IF SPEC$RETAIN THEN S$SKIP(REC$LO1+REC$LO2);
  
  
#     IF SUM FIELD OPTION CHOSEN, REVERT SUM FIELDS                   # 
  
          IF SPEC$1STSUM NQ 0 THEN
              BEGIN 
              FOR SI = SPEC$1STSUM WHILE SI NQ 0 DO 
                  BEGIN 
                  # HANDLE THE REPETITION FACTOR FOR SUM FIELDS        #
  
                  FOR REP = 1 STEP 1 UNTIL SPEC$SUMREP[SI] DO 
                      BEGIN 
                      TEMPSUMBIT = SPEC$SUMBIT[SI] +
                         ( SPEC$SMLENE[SI] * ( REP - 1 ));
                      S$GNRVK(SPEC$SUMTYPE[SI], 
                              SPEC$SMLENE[SI],
                              TEMPSUMBIT, 
                              TRUE, 
                              0,
                              SUM); 
                      END  # HANDLING OF REPETITION FACTOR             #
                  SI = SPEC$NEXTSUM[SI];
                  END 
              END 
  
#         IF THIS IS A VARIABLE-LENGTH RECORD,                         #
#         EXTRACT THE NUMBER OF EXCESS CHARACTERS                      #
  
          IF NOT SPEC$FIXED THEN
              S$GNXLN(REC$LL1+REC$LL2,SPEC$MNR);#(S$IRRL,S$LK,S$ORSA)#
          ELSE
              S$STLEN(SPEC$FIXLEN); 
  
#         THE NEXT TASK IS TO DISTRIBUTE THE NON-KEY FIELDS FROM       #
#          THE FIXED-LENGTH PART OF THE INTERNAL RECORD TO THEIR       #
#          VARIOUS FIELDS IN THE EXTERNAL RECORD.  THE INTERNAL FIELDS #
#          ARE ASSOCIATED WITH THE EXTERNAL DESCRIPTION BY REPEATING   #
#          THE SAME COMPUTATION IN S$GNINV THAT SET THE INTERNAL FIELDS#
  
#     ***NOTE***                                                       #
#     ANY CHANGES BELOW MUST BE REFLECTED IN THE CORRESPONDING CODE    #
#      IN S$GNINV.                                                     #
  
          NKEYS = 0;
          FOR K = SPEC$1STKEY WHILE K NQ 0 DO 
              BEGIN 
              IF ((SPEC$KEYTYPE[K] EQ KT$T"DISPLAY") AND SPEC$KEYALT[K])
                        OR (SPEC$KEYTYPE[K] NQ KT$T"DISPLAY")  THEN 
                        # ALTER HAS BEEN SPECIFIED                     #
                  BEGIN 
                  NKEYS = NKEYS + 1;
                  KEY$LENGTH[NKEYS] = BYTE * SPEC$KEYNBYT[K] +
                      SPEC$KEYNBIT[K];
                  KEY$OFFSET[NKEYS] = BYTE * SPEC$KEYBYTE[K] +
                      SPEC$KEYBIT[K]; 
                  END 
              K = SPEC$NEXTKEY[K];
              END 
#     ADD SUM FIELDS TO KEY FIELD ARRAY                               # 
  
          IF SPEC$1STSUM NQ 0 THEN
              BEGIN 
              FOR SI = SPEC$1STSUM WHILE SI NQ 0 DO 
                  BEGIN 
                  NKEYS = NKEYS+1;
                  KEY$OFFSET[NKEYS] = SPEC$SUMBIT[SI];
                  KEY$LENGTH[NKEYS] = SPEC$SMLENE[SI] * 
                      SPEC$SUMREP[SI];
                  SI = SPEC$NEXTSUM[SI];
                  END 
              END 
  
          IF NKEYS GQ 2 THEN
              BEGIN 
              SORTED = FALSE; 
              FOR I=I WHILE NOT SORTED DO 
                  BEGIN 
                  SORTED = TRUE;
                  FOR I = 1 STEP 1 UNTIL NKEYS-1 DO 
                      BEGIN 
                IF (KEY$OFFSET[I] GR KEY$OFFSET[I+1]) OR
                   ((KEY$OFFSET[I] EQ KEY$OFFSET[I+1]) AND
                    (KEY$LENGTH[I] LS KEY$LENGTH[I+1])) THEN
                          BEGIN 
                          KEY$OFFSET[I] == KEY$OFFSET[I+1]; 
                          KEY$LENGTH[I] == KEY$LENGTH[I+1]; 
                          SORTED = FALSE; 
                          END 
                      END 
                  END 
              END 
  
                FOR I = 1 STEP 1 UNTIL 200 DO 
                 BEGIN
                    OVERLAP$OFLN[I] = 0;
                    KEY$OVERLAP[I] = FALSE; 
                    KEY$CONTAIN[I] = FALSE; 
                 END
                IF NKEYS GQ 2 THEN
                BEGIN 
                    FOR I = 1 STEP 1 UNTIL NKEYS DO 
                     OVERLAP$OFLN[I]= KEY$OFFSET[I] + KEY$LENGTH[I]-1;
                    FOR I = 1 STEP 1 UNTIL NKEYS-1 DO 
                    BEGIN 
                       IF (OVERLAP$OFLN[I] GQ OVERLAP$OFLN[I+1]) AND
                          (KEY$OFFSET[I] LQ KEY$OFFSET[I+1]) THEN 
                           KEY$CONTAIN[I+1] = TRUE; 
                    END 
                    FOR I = 1 STEP 1 UNTIL NKEYS-1 DO 
                    BEGIN 
                      IF NOT(KEY$CONTAIN[I]) THEN 
                      BEGIN 
                       FOR K= I+1 STEP 1 UNTIL NKEYS DO 
                       BEGIN
                         IF NOT( KEY$CONTAIN[K])THEN
                         BEGIN
                         IF KEY$OFFSET[K] LQ OVERLAP$OFLN[I] THEN 
                            KEY$OVERLAP[K] = TRUE;
                         IF (OVERLAP$OFLN[I] GQ OVERLAP$OFLN[K]) AND
                            (KEY$OFFSET[I] LQ KEY$OFFSET[K]) THEN 
                            BEGIN 
                            KEY$CONTAIN[K] = TRUE;
                            KEY$OVERLAP[K] = FALSE; 
                            END 
                         END
                       END
                      END 
                    END 
                END 
          OFFSET = 0; 
          FOR K = 1 STEP 1 UNTIL NKEYS DO 
              BEGIN 
                  IF NOT KEY$CONTAIN[K] THEN
                  BEGIN 
                  IF NOT KEY$OVERLAP[K] THEN
                  BEGIN 
                  LENGTH = KEY$OFFSET[K] - OFFSET;
                  # GENERATE- COPY NON-KEY FIELD TO EXTERNAL RECORD    #
          S$GNCNE(OFFSET,LENGTH);#(S$IRRL,S$LK,S$LR,S$OREC,S$ORSA)# 
                  OFFSET = OFFSET + LENGTH + KEY$LENGTH[K]; 
                  END 
                  ELSE
                  OFFSET = KEY$OFFSET[K] + KEY$LENGTH[K]; 
                  END 
              END 
          IF SPEC$FIXED THEN
              LENGTH = BYTE*SPEC$FIXLEN - OFFSET; 
          ELSE
              LENGTH = BYTE*SPEC$MNR - OFFSET;
          S$GNCNE(OFFSET,LENGTH);#(S$IRRL,S$LK,S$LR,S$OREC,S$ORSA)# 
  
#     ***NOTE***                                                       #
#     END OF CHANGES NEEDING TO BE REFLECTED IN S$GNINV.               #
  
#     THE FINAL TASK IS TO COPY THE REMAINDER OF THE VARIABLE-LENGTH   #
#      PART OF THE INTERNAL RECORD TO THE EXTERNAL RECORD.             #
  
          IF NOT SPEC$FIXED THEN
              S$GNCVE(SPEC$MNR);#(S$IRRL,S$LK,S$LR,S$OREC,S$ORSA)#
  
          END  # S$GNREV #
          TERM
