C-----------------------------------------------------------------------

      SUBROUTINE IXGB2(LUGB,LSKIP,LGRIB,CBUF,NUMFLD,MLEN,IRET) 1,22
C$$$  SUBPROGRAM DOCUMENTATION BLOCK
C
C SUBPROGRAM: IXGB2          MAKE INDEX RECORDS FOR FIELDS IN A GRIB2 MESSAGE
C   PRGMMR: GILBERT          ORG: W/NP11      DATE: 2001-12-10
C
C ABSTRACT: THIS SUBPROGRAM GENERATES AN INDEX RECORD FOR EACH FIELD IN A
C           GRIB2 MESSAGE.  THE INDEX RECORDS ARE WRITTEN TO INDEX BUFFER
C           POINTED TO BY CBUF.
C
C           EACH INDEX RECORD HAS THE FOLLOWING FORM:
C       BYTE 001 - 004: LENGTH OF INDEX RECORD
C       BYTE 005 - 008: BYTES TO SKIP IN DATA FILE BEFORE GRIB MESSAGE
C       BYTE 009 - 012: BYTES TO SKIP IN MESSAGE BEFORE LUS (LOCAL USE)
C                       SET = 0, IF NO LOCAL USE SECTION IN GRIB2 MESSAGE.
C       BYTE 013 - 016: BYTES TO SKIP IN MESSAGE BEFORE GDS
C       BYTE 017 - 020: BYTES TO SKIP IN MESSAGE BEFORE PDS
C       BYTE 021 - 024: BYTES TO SKIP IN MESSAGE BEFORE DRS
C       BYTE 025 - 028: BYTES TO SKIP IN MESSAGE BEFORE BMS
C       BYTE 029 - 032: BYTES TO SKIP IN MESSAGE BEFORE DATA SECTION
C       BYTE 033 - 040: BYTES TOTAL IN THE MESSAGE
C       BYTE 041 - 041: GRIB VERSION NUMBER ( CURRENTLY 2 )
C       BYTE 042 - 042: MESSAGE DISCIPLINE
C       BYTE 043 - 044: FIELD NUMBER WITHIN GRIB2 MESSAGE
C       BYTE 045 -  II: IDENTIFICATION SECTION (IDS) 
C       BYTE II+1-  JJ: GRID DEFINITION SECTION (GDS) 
C       BYTE JJ+1-  KK: PRODUCT DEFINITION SECTION (PDS)
C       BYTE KK+1-  LL: THE DATA REPRESENTATION SECTION (DRS)
C       BYTE LL+1-LL+6: FIRST 6 BYTES OF THE BIT MAP SECTION (BMS)
C
C PROGRAM HISTORY LOG:
C   95-10-31  IREDELL
C   96-10-31  IREDELL   AUGMENTED OPTIONAL DEFINITIONS TO BYTE 320
C 2001-12-10  GILBERT   MODIFIED FROM IXGB TO CREATE GRIB2 INDEXES
C 2002-01-31  GILBERT   ADDED IDENTIFICATION SECTION TO INDEX RECORD
C
C USAGE:    CALL IXGB2(LUGB,LSKIP,LGRIB,CBUF,NUMFLD,MLEN,IRET)
C   INPUT ARGUMENTS:
C     LUGB         INTEGER LOGICAL UNIT OF INPUT GRIB FILE
C     LSKIP        INTEGER NUMBER OF BYTES TO SKIP BEFORE GRIB MESSAGE
C     LGRIB        INTEGER NUMBER OF BYTES IN GRIB MESSAGE
C   OUTPUT ARGUMENTS:
C     CBUF         CHARACTER*1 POINTER TO A BUFFER THAT CONTAINS INDEX RECORDS.
C                  USERS SHOULD FREE MEMORY THAT CBUF POINTS TO
C                  USING DEALLOCATE(CBUF) WHEN CBUF IS NO LONGER NEEDED.
C     NUMFLD       INTEGER NUMBER OF INDEX RECORDS CREATED.
C                  = 0, IF PROBLEMS
C     MLEN         INTEGER TOTAL LENGTH OF ALL INDEX RECORDS
C     IRET         INTEGER RETURN CODE
C                  =0, ALL OK
C                  =1, NOT ENOUGH MEMORY TO ALLOCATE INITIAL INDEX BUFFER
C                  =2, I/O ERROR IN READ
C                  =3, GRIB MESSAGE IS NOT EDITION 2
C                  =4, NOT ENOUGH MEMORY TO ALLOCATE EXTENT TO INDEX BUFFER
C                  =5, UNIDENTIFIED GRIB SECTION ENCOUNTERED...PROBLEM 
C                      SOMEWHERE.
C
C SUBPROGRAMS CALLED:
C   GBYTE        GET INTEGER DATA FROM BYTES
C   SBYTE        STORE INTEGER DATA IN BYTES
C   BAREAD       BYTE-ADDRESSABLE READ
C   REALLOC      RE-ALLOCATES MORE MEMORY
C
C ATTRIBUTES:
C   LANGUAGE: FORTRAN 90
C
C$$$
      USE RE_ALLOC          ! NEEDED FOR SUBROUTINE REALLOC
      CHARACTER(LEN=1),POINTER,DIMENSION(:) :: CBUF
      PARAMETER(LINMAX=5000,INIT=50000,NEXT=10000)
      PARAMETER(IXSKP=4,IXLUS=8,IXSGD=12,IXSPD=16,IXSDR=20,IXSBM=24,
     &          IXDS=28,IXLEN=36,IXFLD=42,IXIDS=44)
      PARAMETER(MXSKP=4,MXLUS=4,MXSGD=4,MXSPD=4,MXSDR=4,MXSBM=4,
     &          MXDS=4,MXLEN=4,MXFLD=2,MXBMS=6)
      CHARACTER CBREAD(LINMAX),CINDEX(LINMAX)
      CHARACTER CVER,CDISC
      CHARACTER CIDS(LINMAX),CGDS(LINMAX),CBMS(6)
      CHARACTER(LEN=4) :: CTEMP
      INTEGER LOCLUS,LOCGDS,LENGDS,LOCBMS
C - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      LOCLUS=0
      IRET=0
      MLEN=0
      NUMFLD=0
      IF (ASSOCIATED(CBUF)) NULLIFY(CBUF)
      MBUF=INIT
      ALLOCATE(CBUF(MBUF),STAT=ISTAT)    ! ALLOCATE INITIAL SPACE FOR CBUF
      IF (ISTAT.NE.0) THEN
         IRET=1
         RETURN
      ENDIF
C - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
C  READ SECTIONS 0 AND 1 FOR VERSIN NUMBER AND DISCIPLINE
      IBREAD=MIN(LGRIB,LINMAX)
      CALL BAREAD(LUGB,LSKIP,IBREAD,LBREAD,CBREAD)
      IF(LBREAD.NE.IBREAD) THEN
         IRET=2
         RETURN
      ENDIF
      IF(CBREAD(8).NE.CHAR(2)) THEN          !  NOT GRIB EDITION 2
         IRET=3
         RETURN
      ENDIF
      CVER=CBREAD(8)
      CDISC=CBREAD(7)
      CALL GBYTE(CBREAD,LENSEC1,16*8,4*8)
      LENSEC1=MIN(LENSEC1,IBREAD)
      CIDS(1:LENSEC1)=CBREAD(17:16+LENSEC1)
      IBSKIP=LSKIP+16+LENSEC1
C - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
C  LOOP THROUGH REMAINING SECTIONS CREATING AN INDEX FOR EACH FIELD
      IBREAD=MAX(5,MXBMS)
      DO
         CALL BAREAD(LUGB,IBSKIP,IBREAD,LBREAD,CBREAD)     
         CTEMP=CBREAD(1)//CBREAD(2)//CBREAD(3)//CBREAD(4)
         IF (CTEMP.EQ.'7777') RETURN        ! END OF MESSAGE FOUND
         IF(LBREAD.NE.IBREAD) THEN
            IRET=2
            RETURN
         ENDIF
         CALL GBYTE(CBREAD,LENSEC,0*8,4*8)
         CALL GBYTE(CBREAD,NUMSEC,4*8,1*8)

         IF (NUMSEC.EQ.2) THEN                 ! SAVE LOCAL USE LOCATION
            LOCLUS=IBSKIP-LSKIP
         ELSEIF (NUMSEC.EQ.3) THEN                 ! SAVE GDS INFO
            LENGDS=LENSEC
            CGDS=CHAR(0)
            CALL BAREAD(LUGB,IBSKIP,LENGDS,LBREAD,CGDS)     
            IF(LBREAD.NE.LENGDS) THEN
               IRET=2
               RETURN
            ENDIF
            LOCGDS=IBSKIP-LSKIP
         ELSEIF (NUMSEC.EQ.4) THEN                 ! FOUND PDS
            CINDEX=CHAR(0)
            CALL SBYTE(CINDEX,LSKIP,8*IXSKP,8*MXSKP)    ! BYTES TO SKIP
            CALL SBYTE(CINDEX,LOCLUS,8*IXLUS,8*MXLUS)   ! LOCATION OF LOCAL USE
            CALL SBYTE(CINDEX,LOCGDS,8*IXSGD,8*MXSGD)   ! LOCATION OF GDS
            CALL SBYTE(CINDEX,IBSKIP-LSKIP,8*IXSPD,8*MXSPD)  ! LOCATION OF PDS
            CALL SBYTE(CINDEX,LGRIB,8*IXLEN,8*MXLEN)    ! LEN OF GRIB2
            CINDEX(41)=CVER
            CINDEX(42)=CDISC
            CALL SBYTE(CINDEX,NUMFLD+1,8*IXFLD,8*MXFLD)   ! FIELD NUM
            CINDEX(IXIDS+1:IXIDS+LENSEC1)=CIDS(1:LENSEC1)
            LINDEX=IXIDS+LENSEC1
            CINDEX(LINDEX+1:LINDEX+LENGDS)=CGDS(1:LENGDS)
            LINDEX=LINDEX+LENGDS
            ILNPDS=LENSEC
            CALL BAREAD(LUGB,IBSKIP,ILNPDS,LBREAD,CINDEX(LINDEX+1))     
            IF(LBREAD.NE.ILNPDS) THEN
               IRET=2
               RETURN
            ENDIF
            !   CINDEX(LINDEX+1:LINDEX+ILNPDS)=CBREAD(1:ILNPDS)
            LINDEX=LINDEX+ILNPDS
         ELSEIF (NUMSEC.EQ.5) THEN                 ! FOUND DRS
            CALL SBYTE(CINDEX,IBSKIP-LSKIP,8*IXSDR,8*MXSDR)  ! LOCATION OF DRS
            ILNDRS=LENSEC
            CALL BAREAD(LUGB,IBSKIP,ILNDRS,LBREAD,CINDEX(LINDEX+1))     
            IF(LBREAD.NE.ILNDRS) THEN
               IRET=2
               RETURN
            ENDIF
            !   CINDEX(LINDEX+1:LINDEX+ILNDRS)=CBREAD(1:ILNDRS)
            LINDEX=LINDEX+ILNDRS
         ELSEIF (NUMSEC.EQ.6) THEN                 ! FOUND BMS
            INDBMP=MOVA2I(CBREAD(6))
            IF ( INDBMP.LT.254 ) THEN
               LOCBMS=IBSKIP-LSKIP
               CALL SBYTE(CINDEX,LOCBMS,8*IXSBM,8*MXSBM)  ! LOC. OF BMS
            ELSEIF ( INDBMP.EQ.254 ) THEN
               CALL SBYTE(CINDEX,LOCBMS,8*IXSBM,8*MXSBM)  ! LOC. OF BMS
            ELSEIF ( INDBMP.EQ.255 ) THEN
               CALL SBYTE(CINDEX,IBSKIP-LSKIP,8*IXSBM,8*MXSBM)  ! LOC. OF BMS
            ENDIF
            CINDEX(LINDEX+1:LINDEX+MXBMS)=CBREAD(1:MXBMS)
            LINDEX=LINDEX+MXBMS
            CALL SBYTE(CINDEX,LINDEX,0,8*4)    ! NUM BYTES IN INDEX RECORD
         ELSEIF (NUMSEC.EQ.7) THEN                 ! FOUND DATA SECTION
            CALL SBYTE(CINDEX,IBSKIP-LSKIP,8*IXDS,8*MXDS)   ! LOC. OF DATA SEC.
            NUMFLD=NUMFLD+1
            IF ((LINDEX+MLEN).GT.MBUF) THEN        ! ALLOCATE MORE SPACE IF
                                                   ! NECESSARY
               NEWSIZE=MAX(MBUF+NEXT,MBUF+LINDEX)
               CALL REALLOC(CBUF,MLEN,NEWSIZE,ISTAT)
               IF ( ISTAT .NE. 0 ) THEN
                  NUMFLD=NUMFLD-1
                  IRET=4
                  RETURN
               ENDIF
               MBUF=NEWSIZE
            ENDIF
            CBUF(MLEN+1:MLEN+LINDEX)=CINDEX(1:LINDEX)
            MLEN=MLEN+LINDEX
         ELSE                           ! UNRECOGNIZED SECTION
            IRET=5
            RETURN
         ENDIF
         IBSKIP=IBSKIP+LENSEC
      ENDDO

C - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      RETURN
      END