C LAST UPDATE: 
C+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
C
C**************************
C**     LDM_PARSE        **
C**************************
C
CD-Routine: Parse Line Containing LDM Data - LDM_PARSE
C This routine parses a given line of data, examining it for the presence
C of LDM data. Any such data found is automatically checked and, if valid,
C stored in the Laue Data Module. If the line does not contain LDM data,
C then it is merely passed back to the calling program to allow further
C interpretation by that program. LDM and non-LDM data must not be given
C in the same line of data and a line of data containing any valid LDM
C keyword will be assumed to be an LDM parameter line. The calling program 
C should also take account of the fact that incorrectly specified LDM 
C keyords may result in the line being returned to the calling program.
CD-end
CD-Fortran:
      SUBROUTINE LDM_PARSE (LINE, IFLAG, BADTOK, ERRSTR)
CD-end
      INCLUDE 'implicit_none.finc'
C
C Purpose: Parse line for laue_module data and store any found.
C
C Author:  John W. Campbell, May 1993
C
C Arguments:
C
      CHARACTER*(*) LINE
      INTEGER IFLAG
      CHARACTER*(*) BADTOK
      CHARACTER*(*) ERRSTR

CD-Parameters:
C LINE     c (R)   Character string containing line to be parsed
C                  (Assume comments & continuations already removed)
C IFLAG    i (W)   Return flag = 0,  Laue module data found & OK
C                              = 1,  Not Laue module data
C                              = 2,  No non-blank tokens
C                              < 0,  Laue module data but error(s)
C                              =-1,  Invalid or inappropriate pack 
C                                    specification
C                              =-2,  Invalid or inappropriate plate 
C                                    specification
C                              =-3,  Syntax error in pack/plate 
C                                    specification
C                              =-4,  Invalid code/string value or syntax 
C                                    error
C                              =-5,  Invalid value - must be >=0.0 (>=0)
C                              =-6,  Invalid value - must be >0.0 (>0)
C                              =-7,  Other out of range value
C                              =-8,  Non-LDM data mixed with LDM data
C                                    (Possibly miss-spelt keyword)
C                             -100,  Coding error in LDM routines, 
C                                    information supposedly already 
C                                    checked is found later to be invalid! 
C BADTOK   c (W)   Returns the token string for an invalid token
C ERRSTR   c (W)   Error string (max 80 chars) if IFLAG<0
CD-end
C
C====== Parameter statements
C 

C
C====== GLOBALS:
C
      INCLUDE 'ldm_data.finc'
      INCLUDE 'ldm_extended.finc'
      EXTERNAL LDM_BDAT
C
C====== FUNCTION TYPES:
C
      INTEGER NXTTOK
      INTEGER KDMSTR
      INTEGER LENSTR
C
C====== LOCALS:
C
      LOGICAL EXTRA_PAR
      INTEGER I
      INTEGER LL
      INTEGER IL
      INTEGER M1
      INTEGER M2
      INTEGER ITYP
      INTEGER IERR
      INTEGER IPACK
      INTEGER IPLATE
      INTEGER NVALS
      INTEGER IPKPL
      INTEGER IPAR
      INTEGER II
      INTEGER MDUM
      INTEGER IVAL
      REAL FVAL
      CHARACTER*20 KEYWORD
      CHARACTER*50 FULLNAME
      CHARACTER*4 SEP

C     LOGICAL EXTRA_PAR    !Additionally defined parameter
C     INTEGER I            !Return flag from NXTTOK routine
C     INTEGER LL           !Length of input line
C     INTEGER IL           !Last character accessed in line being parsed
C     INTEGER M1           !First character in token field
C     INTEGER M2           !Final character in token field
C     INTEGER ITYP         !LDM parameter type flag from LDM_PARSEITEM
C                           or extended parameter type from KDMF_CHECKPAR
C     INTEGER IERR         !Error flag
C     INTEGER IPACK        !Pack number decoded from LDM keyword (0=all packs)
C     INTEGER IPLATE       !Plate number decoded from LDM keyword (0=all plates)
C     INTEGER NVALS        !No. of values for KDM defined extra item
C     INTEGER IPKPL        !Pack/plate specification found for KDM parameter
C     INTEGER IPAR         !KDM parameter number
C     INTEGER II           !Temp/loop variable
C     INTEGER MDUM         !Dummy character position index
C     INTEGER IVAL         !Integer parameter value
C     REAL FVAL            !Real parameter value
C     CHARACTER*20 KEYWORD !Keyword string
C     CHARACTER*50 FULLNAME !Full KDM parameter name
C     CHARACTER*4 SEP      !Token separator characters

      DATA SEP /'  ,='/
C
C-------------------------------------------------------------------------------
C
      IFLAG = 2
      SEP(2:2) = CHAR(9)
      BADTOK = ' '
      ERRSTR = ' '
      IL = 0
      LL = LEN(LINE)
C
C====== Get next token
C
100   I = NXTTOK (LINE, SEP, IL, M1, M2)
      IF (I.EQ.-1) RETURN
      IF (I.EQ.0) GO TO 100
C
C====== See if laue module parameter name
C
      EXTRA_PAR = .FALSE.
      CALL LDM_PARSEITEM (LINE(M1:M2), KEYWORD, IPACK, IPLATE,
     +                     ITYP, IERR)
      IF (IERR.EQ.1.AND.EXTENDED) THEN
         CALL LDM_PARSEKDM (LINE(M1:M2), KEYWORD, IPACK, IPLATE, IPKPL, 
     +                       IERR)
         IF (IERR.EQ.0) THEN
            CALL KDMF_CHECKPAR (KDX_EXT, KDMSTR(KEYWORD), 
     +                          LENSTR(KEYWORD), IPACK, IPLATE, IPKPL,
     +                          KDMSTR(FULLNAME), 50, ITYP, NVALS, IPAR, 
     +                          IERR)
            EXTRA_PAR = .TRUE.
         END IF
      END IF
      IF (IERR.LE.0) THEN
         IFLAG = 0
         IF (IERR.LT.0) THEN
            BADTOK = LINE(M1:M2)
            IFLAG = IERR
            IF (IERR.EQ.-1) 
     +         ERRSTR = 'Invalid or inappropriate pack specification'
            IF (IERR.EQ.-2) 
     +         ERRSTR = 'Invalid or inappropriate plate specification'
            IF (IERR.EQ.-3) 
     +         ERRSTR = 'Syntax error in pack/plate specification'
            RETURN
         END IF
         I = NXTTOK (LINE, SEP, IL, M1, M2)
         IF (I.LE.0) THEN
            IF (EXTRA_PAR) THEN
               CALL KDMF_RESET (KDX_EXT,  KDMSTR(FULLNAME), 
     +                          LENSTR(FULLNAME), IPACK, IPLATE, 
     +                          KDMSTR(ERRSTR), LEN(ERRSTR), IERR)
            ELSE 
               CALL LDM_RESET (KEYWORD, IPACK, IPLATE, IERR, ERRSTR)
            END IF
            IF (IERR.LT.0) THEN
               IFLAG = IERR
C
C====== Note: IERR=-3 should not occur as keyword already checked
C
               IF (IERR.EQ.-3) IFLAG = -100
               RETURN
            END IF
            IF (I.LT.0) RETURN
         ELSE
            IF (EXTRA_PAR) THEN
               IF (ITYP.GT.9) THEN
                      M2 = LL
                      IL = LL
               END IF
               IF (ITYP.LT.7.AND.NVALS.GT.1) THEN
                  DO 120 II = 2, NVALS
                     I = NXTTOK (LINE, SEP, IL, MDUM, M2)
                     IF (I.LE.0) THEN
                        ERRSTR = 
     +                     'Too few values given for the parameter'     
                        IFLAG = -4
                        RETURN
                     END IF
 120              CONTINUE
               END IF
               CALL KDMF_SETVALUE (KDX_EXT, KDMSTR(FULLNAME), 
     +                          LENSTR(FULLNAME),
     +                          IPACK, IPLATE, KDMSTR(LINE(M1:M2)), 
     +                          M2-M1+1, IVAL, FVAL, 0,
     +                          KDMSTR(ERRSTR), LEN(ERRSTR), IERR)
               IF (IERR.GT.0) THEN
                  BADTOK = LINE(M1:M2)
                  IFLAG = - 4
                  RETURN
               END IF
            ELSE
               IF (KEYWORD(1:4).EQ.'CRYS'.OR.KEYWORD(1:4).EQ.'TITL'
     +            .OR.KEYWORD(1:4).EQ.'SYMM') THEN
                      M2 = LL
                      IL = LL
               END IF
               CALL LDM_SET (KEYWORD, IPACK, IPLATE, LINE(M1:M2), 
     +                       IERR, ERRSTR)
               IF (IERR.GT.0) THEN
                  BADTOK = LINE(M1:M2)
                  IFLAG = - 3 - IERR
                  RETURN
               END IF
            END IF
C
C====== Note: Pack/plate already checked so should not get IERR<0
C
            IF (IERR.LT.0) THEN
               IFLAG = -100
               RETURN
            END IF
         END IF
      ELSE
C
C====== Non-LDM (or extended LDM) keyword found
C
         IF (IFLAG.EQ.0) THEN
            BADTOK = LINE(M1:M2)
            IFLAG = -8
            RETURN
         ELSE
            IFLAG = 1
            RETURN
         END IF
      END IF
      GO TO 100
      END
