CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      SUBROUTINE STRUCTURE_EDB(EDB, EDB_START, EDB_HEADER, EDB_RECORD, QUALITY_FLAG)
C+
C
C FUNCTIONAL DESCRIPTION:
C
C     This routine uses the information in the first 30 bytes of EDB (i.e. the
C     EDB header) to recover the various data items in that EDB.  Both the
C     header and the data itself are placed in structures.
C
C FORMAL ARGUMENTS:
C
C     EDB:
C	BYTE	  I	BYTE array of length 3056 containing the EDB to be
C			analyzed.
C
C     EDB_START:
C	/EDB_STRT/  O	Upon return will contain the sync, length, and counter
C			information from EDB.
C
C     EDB_HEADER:
C	/EDB_HDR/  O	Upon return will contain the length fields for the
C			various data types included in EDB.  If QUALITY_FLAG is
C			set to -1 it is possible that one or more of these
C			length fields is invalid.
C
C     EDB_RECORD:
C	/EDB_REC/  O	Upon return will contain the extracted data from EDB.
C			If QUALITY_FLAG is set to -1 it is possible that one or
C			more of these data types is invalid or was never
C			extracted.
C
C     QUALITY_FLAG:
C	I*4	  O	Upon return will contain a -1 if any of the quality
C			checks failed.  If all the checks passed this flag is
C			left unchanged.  Its valid values are -1 and 0.
C
C INTERFACE:
!
!	INTERFACE STRUCTURE_EDB
!	  SUBROUTINE STRUCTURE_EDB (EDB, EDB_START, EDB_HEADER, EDB_RECORD,
!	1			    QUALITY_FLAG) 
!	    BYTE, INTENT(IN) :: EDB(3056)
!	    RECORD /EDB_STRT/ EDB_START
!	    RECORD /EDB_HDR/ EDB_HEADER
!	    RECORD /EDB_REC/ EDB_RECORD
!	    INTENT(OUT) EDB_START, EDB_HEADER, EDB_RECORD
!	    INTEGER(KIND=4), INTENT(OUT) :: QUALITY_FLAG
!	  END SUBROUTINE STRUCTURE_EDB
!	END INTERFACE STRUCTURE_EDB
C
C COMMON BLOCKS:
C
C     None
C
C INCLUDE FILES:
C
C     EDBDEF.INC
C
C DESIGN:
C
C     An EDB can be bad in several ways, so all must be checked.  All length
C     fields must be within the allowable range for that data item.  Further,
C     make sure that we don't access beyond the end of the EDB when copying
C     the data; this can happen even if all length fields are okay.
C
C     Since EDB is a BYTE array it is treated as a signed entity by Fortran.
C     Use ZEXT to extract and assemble bytes to avoid sign extension problems.
C
C     Make sure byte ordering (endian) is taken into account, since Alpha
C     and Motorola architectures differ.
C
C     extract length fields for the various data types
C     validate length field for each possible data type, set quality flag to
C      bad if any are bad 
C     if quality flag set to bad return early
C     for each possible data type
C       check if entire item, as specified by its length field, fits within EDB
C       if not set quality flag to bad and return early
C       if so copy bytes into proper structure field
C
C IMPLICIT INPUTS:
C
C     None
C
C IMPLICIT OUTPUTS:
C
C     None
C
C SIDE EFFECTS:
C
C     If EDB is good QUALITY_FLAG is left unchanged; it is *not* set to 0.
C
C This version:   1.5   27-FEB-1996
C
C CREATED:
C
C     13-SEP-1995    John Paquette
C
C DEVELOPMENT HISTORY:
C
C  Author       Date		Description of Change
C  --------	-----------	---------------------
C  J. PAQUETTE  13-SEP-1995     Added structure name to length fields
C  J. PAQUETTE  12-OCT-1995     Added comments
C  J. PAQUETTE  16-JAN-1996     Check to see that we're not going out of bounds
C                               (due to bogus length fields in the EDB header)
C  J. PAQUETTE  24-JAN-1996     Changed to use IOR operation instead of
C                               arithmetic for 2-byte length fields; check to
C                               make certain that they don't exceed listed
C                               maxima
C  J. PAQUETTE  27-FEB-1996     QUALITY_FLAG no longer set to 0 upon entering
C                               this routine; the whole EDB is zeroed in the
C                               routine that calls this one, and that routine
C                               may also set the quality flag 
C  L. Bleau	10-NOV-1999	added comments
C-
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CDEC$ IDENT	'1.5'
      INCLUDE 'INC_DIR:EDBDEF.INC'
      BYTE EDB(3056)
      RECORD /EDB_STRT/ EDB_START
      RECORD /EDB_HDR/ EDB_HEADER
      RECORD /EDB_REC/ EDB_RECORD
      INTEGER*4 OFFSET, I, QUALITY_FLAG
C
C Transfer header information into EDB_HEADER structure.  Because some of the
C quantities are (unsigned) bytes, the ZEXT (ZEro eXTend) function is used to
C convert them to positive integers.  If it were not used, any byte with a
C value > 127 would result in an erroneously negative integer value due to sign
C extension.  Those quantities that are not bytes are already integer*2, BUT,
C they have an endianity of Motorola, which is the opposite of the endianity
C used by VMS systems.  Therefore, byte swapping is neccesary.
C
      DO 100 I=1, 3
        EDB_START.SYNC(I) = EDB(I)
 100  CONTINUE
      EDB_START.LENGTH = IOR(ISHFT(ZEXT(EDB(4)), 8), ZEXT(EDB(5)))
      EDB_START.COUNTER = EDB(6)
C
      EDB_HEADER.DPU_HEADER_LEN            = ZEXT(EDB(7))
      EDB_HEADER.DPU_STATUS_LEN            = IIOR(IISHFT(IZEXT(EDB(8)), 8), IZEXT(EDB(9)))
      IF((EDB_HEADER.DPU_STATUS_LEN .GT. 3024) .OR. (EDB_HEADER.DPU_STATUS_LEN .LT. 0))QUALITY_FLAG = -1
      EDB_HEADER.STOF_HSTOF_PHA_LEN        = IIOR(IISHFT(IZEXT(EDB(10)), 8), IZEXT(EDB(11)))
      IF((EDB_HEADER.STOF_HSTOF_PHA_LEN .GT. 3024) .OR. (EDB_HEADER.STOF_HSTOF_PHA_LEN .LT. 0))QUALITY_FLAG = -1
      EDB_HEADER.MTOF_PHA_LEN              = IIOR(IISHFT(IZEXT(EDB(12)), 8), IZEXT(EDB(13)))
      IF((EDB_HEADER.MTOF_PHA_LEN .GT. 3024) .OR. (EDB_HEADER.MTOF_PHA_LEN .LT. 0))QUALITY_FLAG = -1
      EDB_HEADER.CTOF_PHA_LEN              = IIOR(IISHFT(IZEXT(EDB(14)), 8), IZEXT(EDB(15)))
      IF((EDB_HEADER.CTOF_PHA_LEN .GT. 3024) .OR. (EDB_HEADER.CTOF_PHA_LEN .LT. 0))QUALITY_FLAG = -1
      EDB_HEADER.STOF_DIAGNOSTIC_LEN       = ZEXT(EDB(16))
      EDB_HEADER.STOF_STATUS_LEN           = ZEXT(EDB(17))
      EDB_HEADER.STOF_MATRIX_RATES_LEN     = IIOR(IISHFT(IZEXT(EDB(18)), 8), IZEXT(EDB(19)))
      IF((EDB_HEADER.STOF_MATRIX_RATES_LEN .GT. 3024) .OR. (EDB_HEADER.STOF_MATRIX_RATES_LEN .LT. 0))QUALITY_FLAG = -1
      EDB_HEADER.STOF_MATRIX_ELEMENTS_LEN  = ZEXT(EDB(20))
      EDB_HEADER.STOF_HSTOF_SEM_RATES_LEN  = ZEXT(EDB(21))
      EDB_HEADER.HSTOF_MATRIX_RATES_LEN    = IIOR(IISHFT(IZEXT(EDB(22)), 8), IZEXT(EDB(23)))
      IF((EDB_HEADER.HSTOF_MATRIX_RATES_LEN .GT. 3024) .OR. (EDB_HEADER.HSTOF_MATRIX_RATES_LEN .LT. 0))QUALITY_FLAG = -1
      EDB_HEADER.HSTOF_MATRIX_ELEMENTS_LEN = ZEXT(EDB(24))
      EDB_HEADER.MTOF_STATUS_LEN           = ZEXT(EDB(25))
      EDB_HEADER.MTOF_TOF_SPECTRA_LEN      = ZEXT(EDB(26))
      EDB_HEADER.MTOF_RATES_LEN            = ZEXT(EDB(27))
      EDB_HEADER.PM_R_VS_THETA_LEN         = ZEXT(EDB(28))
      EDB_HEADER.PM_THETA_SPECT_LEN        = ZEXT(EDB(29))
      EDB_HEADER.PM_R_SPECT_LEN            = ZEXT(EDB(30))
      EDB_HEADER.PM_RATES_LEN              = ZEXT(EDB(31))
      EDB_HEADER.CTOF_STATUS_LEN           = ZEXT(EDB(32))
      EDB_HEADER.CTOF_MATRIX_RATES_LEN     = IIOR(IISHFT(IZEXT(EDB(33)), 8), IZEXT(EDB(34)))
      IF((EDB_HEADER.CTOF_MATRIX_RATES_LEN .GT. 3024) .OR. (EDB_HEADER.CTOF_MATRIX_RATES_LEN .LT. 0))QUALITY_FLAG = -1
      EDB_HEADER.CTOF_MATRIX_ELEMENTS_LEN  = ZEXT(EDB(35))
      EDB_HEADER.CTOF_RATES_LEN            = ZEXT(EDB(36))
C
C If we had a bad length field, this EDB was marked as bad. If it is, RETURN.
C
      IF(QUALITY_FLAG .EQ. -1)RETURN
C
C Transfer the actual data into the EDB_RECORD structure, using the LEN values
C as indices. Set OFFSET to point to the first data area after the header
C
      OFFSET = 6 + EDB_HEADER.DPU_HEADER_LEN
C
C First, get the DPU Status (60 bytes)
C
      IF((OFFSET + EDB_HEADER.DPU_STATUS_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 200 I = 1, EDB_HEADER.DPU_STATUS_LEN
        EDB_RECORD.DPU_STATUS(I) = EDB( OFFSET + I)
 200  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.DPU_STATUS_LEN
C
C Next, get STOF/HSTOF PHA words. There are EDB_HEADER.STOF_HSTOF_PHA_LEN bytes
C
      IF((OFFSET + EDB_HEADER.STOF_HSTOF_PHA_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 300 I = 1, EDB_HEADER.STOF_HSTOF_PHA_LEN
        EDB_RECORD.STOF_HSTOF_PHA(I) = EDB( OFFSET + I)
 300  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.STOF_HSTOF_PHA_LEN
C
C Then, get MTOF PHA words. There are EDB_HEADER.MTOF_PHA_LEN bytes
C
      IF((OFFSET + EDB_HEADER.MTOF_PHA_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 400 I = 1, EDB_HEADER.MTOF_PHA_LEN
        EDB_RECORD.MTOF_PHA(I) = EDB( OFFSET + I)
 400  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.MTOF_PHA_LEN
C
C Then, get CTOF PHA words. There are EDB_HEADER.CTOF_PHA_LEN bytes
C
      IF((OFFSET + EDB_HEADER.CTOF_PHA_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 500 I = 1, EDB_HEADER.CTOF_PHA_LEN
        EDB_RECORD.CTOF_PHA(I) = EDB( OFFSET + I)
 500  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.CTOF_PHA_LEN
C
C The next item is STOF diagnostic data. There are STOF_DIAGNOSTIC_LEN bytes
C
      IF((OFFSET + EDB_HEADER.STOF_DIAGNOSTIC_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 600 I = 1, EDB_HEADER.STOF_DIAGNOSTIC_LEN
        EDB_RECORD.STOF_DIAGNOSTIC(I) = EDB( OFFSET + I)
 600  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.STOF_DIAGNOSTIC_LEN
C
C STOF status is next. There are STOF_STATUS_LEN bytes of it.
C
      IF((OFFSET + EDB_HEADER.STOF_STATUS_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 700 I = 1, EDB_HEADER.STOF_STATUS_LEN
        EDB_RECORD.STOF_STATUS(I) = EDB( OFFSET + I)
 700  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.STOF_STATUS_LEN
C
C Next are STOF matrix rates. There are STOF_MATRIX_RATES_LEN bytes
C
      IF((OFFSET + EDB_HEADER.STOF_MATRIX_RATES_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 800 I = 1, EDB_HEADER.STOF_MATRIX_RATES_LEN
        EDB_RECORD.STOF_MATRIX_RATES(I) = EDB( OFFSET + I)
 800  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.STOF_MATRIX_RATES_LEN
C
C Next are STOF matrix elements. There are STOF_MATRIX_ELEMENTS_LEN bytes
C
      IF((OFFSET + EDB_HEADER.STOF_MATRIX_ELEMENTS_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 900 I = 1, EDB_HEADER.STOF_MATRIX_ELEMENTS_LEN
        EDB_RECORD.STOF_MATRIX_ELEMENTS(I) = EDB( OFFSET + I)
 900  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.STOF_MATRIX_ELEMENTS_LEN
C
C Next are STOF/HSTOF/SEM rates. There are STOF_HSTOF_SEM_RATES_LEN bytes
C
      IF((OFFSET + EDB_HEADER.STOF_HSTOF_SEM_RATES_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 1000 I = 1, EDB_HEADER.STOF_HSTOF_SEM_RATES_LEN
        EDB_RECORD.STOF_HSTOF_SEM_RATES(I) = EDB( OFFSET + I)
1000  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.STOF_HSTOF_SEM_RATES_LEN
C
C Next are HSTOF matrix rates. There are HSTOF_MATRIX_RATES_LEN bytes
C
      IF((OFFSET + EDB_HEADER.HSTOF_MATRIX_RATES_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 1100 I = 1, EDB_HEADER.HSTOF_MATRIX_RATES_LEN
        EDB_RECORD.HSTOF_MATRIX_RATES(I) = EDB( OFFSET + I)
1100  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.HSTOF_MATRIX_RATES_LEN
C
C Next are HSTOF matrix elements. There are HSTOF_MATRIX_ELEMENTS_LEN bytes
C
      IF((OFFSET + EDB_HEADER.HSTOF_MATRIX_ELEMENTS_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 1200 I = 1, EDB_HEADER.HSTOF_MATRIX_ELEMENTS_LEN
        EDB_RECORD.HSTOF_MATRIX_ELEMENTS(I) = EDB( OFFSET + I)
1200  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.HSTOF_MATRIX_ELEMENTS_LEN
C
C Next is the MTOF status. There are MTOF_STATUS_LEN bytes
C
      IF((OFFSET + EDB_HEADER.MTOF_STATUS_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 1300 I = 1, EDB_HEADER.MTOF_STATUS_LEN
        EDB_RECORD.MTOF_STATUS(I) = EDB( OFFSET + I)
1300  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.MTOF_STATUS_LEN
C
C The next block is the MTOF Time of Flight spectra.  There are
C MTOF_TOF_SPECTRA_LEN bytes.
C
      IF((OFFSET + EDB_HEADER.MTOF_TOF_SPECTRA_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 1400 I = 1, EDB_HEADER.MTOF_TOF_SPECTRA_LEN
        EDB_RECORD.MTOF_TOF_SPECTRA(I) = EDB( OFFSET + I)
1400  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.MTOF_TOF_SPECTRA_LEN
C
C Next is the MTOF rates. There are MTOF_RATES_LEN bytes
C
      IF((OFFSET + EDB_HEADER.MTOF_RATES_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 1500 I = 1, EDB_HEADER.MTOF_RATES_LEN
        EDB_RECORD.MTOF_RATES(I) = EDB( OFFSET + I)
1500  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.MTOF_RATES_LEN
C
C The next block contains the PM R vs Theta. There are PM_R_VS_THETA_LEN bytes
C
      IF((OFFSET + EDB_HEADER.PM_R_VS_THETA_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 1600 I = 1, EDB_HEADER.PM_R_VS_THETA_LEN
        EDB_RECORD.PM_R_VS_THETA(I) = EDB( OFFSET + I)
1600  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.PM_R_VS_THETA_LEN
C
C The next block holds the PM theta spectrum. There are PM_THETA_SPECT_LEN bytes
C
      IF((OFFSET + EDB_HEADER.PM_THETA_SPECT_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 1700 I = 1, EDB_HEADER.PM_THETA_SPECT_LEN
        EDB_RECORD.PM_THETA_SPECT(I) = EDB( OFFSET + I)
1700  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.PM_THETA_SPECT_LEN
C
C Next is the PM R spectrum. There are PM_R_SPECT_LEN bytes
C
      IF((OFFSET + EDB_HEADER.PM_R_SPECT_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 1800 I = 1, EDB_HEADER.PM_R_SPECT_LEN
        EDB_RECORD.PM_R_SPECT(I) = EDB( OFFSET + I)
1800  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.PM_R_SPECT_LEN
C
C Next is the PM rates. There are PM_RATES_LEN bytes
C
      IF((OFFSET + EDB_HEADER.PM_RATES_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 1900 I = 1, EDB_HEADER.PM_RATES_LEN
        EDB_RECORD.PM_RATES(I) = EDB( OFFSET + I)
1900  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.PM_RATES_LEN
C
C Next is the CTOF status. There are CTOF_STATUS_LEN bytes
C
      IF((OFFSET + EDB_HEADER.CTOF_STATUS_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 2000 I = 1, EDB_HEADER.CTOF_STATUS_LEN
        EDB_RECORD.CTOF_STATUS(I) = EDB( OFFSET + I)
2000  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.CTOF_STATUS_LEN
C
C The next item is  the CTOF matrix rates. There are CTOF_MATRIX_RATES_LEN bytes
C
      IF((OFFSET + EDB_HEADER.CTOF_MATRIX_RATES_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 2100 I = 1, EDB_HEADER.CTOF_MATRIX_RATES_LEN
        EDB_RECORD.CTOF_MATRIX_RATES(I) = EDB( OFFSET + I)
2100  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.CTOF_MATRIX_RATES_LEN
C
C Next are the CTOF matrix elements. There are CTOF_MATRIX_ELEMENTS_LEN bytes
C
      IF((OFFSET + EDB_HEADER.CTOF_MATRIX_ELEMENTS_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 2200 I = 1, EDB_HEADER.CTOF_MATRIX_ELEMENTS_LEN
        EDB_RECORD.CTOF_MATRIX_ELEMENTS(I) = EDB( OFFSET + I)
2200  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.CTOF_MATRIX_ELEMENTS_LEN
C
C Next are the CTOF rates. There are CTOF_RATES_LEN bytes
C
      IF((OFFSET + EDB_HEADER.CTOF_RATES_LEN).GT.3056)THEN
        QUALITY_FLAG = -1
        RETURN
      ENDIF
C
      DO 2300 I = 1, EDB_HEADER.CTOF_RATES_LEN
        EDB_RECORD.CTOF_RATES(I) = EDB( OFFSET + I)
2300  CONTINUE
      OFFSET = OFFSET + EDB_HEADER.CTOF_RATES_LEN
C
C The header and data for an EDB have now been transferred to structure. Return.
C
      RETURN
      END
