Use this in Makefile, with $(FC) set to your Fortran compiler (e.g. gfortran or g77), $(LDIR) set to the directory where libbufr.a is located, and $(FCFLAGS) set to -fbackslash for gfortran. Note that code for comfilter.f is found at the end of this page (below the code for bufrdump.F).

bufrdump: bufrdump.F comfilter.f
	$(FC) $(FCFLAGS) -o bufrdump  $< -L $(LDIR) -lbufr
bufrdump.F
C (C) Copyright 2010-2016 MET Norway
C
C This program is free software; you can redistribute it and/or modify
C it under the terms of the GNU General Public License as published by
C the Free Software Foundation; either version 2 of the License, or
C (at your option) any later version.
C
C This program is distributed in the hope that it will be useful, but
C WITHOUT ANY WARRANTY; without even the implied warranty of
C MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
C General Public License for more details.
C
C You should have received a copy of the GNU General Public License
C along with this program; if not, write to the Free Software
C Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
C 02110-1301, USA.
 
 
C Extract BUFR messages from bufr file(s) and print the data as
C 'parameter=value' lines. See usage_verbose for explanation of the
C options allowed.
C
C Usage: bufrdump <bufr file>
C        [--help]
C        [--filter <filter file>]
C        [--obstype] <amdar|ocea|surface|sounding|sounding->
C        [--stop_on_error]
C        [--rectangle x1 y1 x2 y2]
C        or one or more of
C        [--lon1 x1]
C        [--lat1 y1]
C        [--lon2 x2]
C        [--lat2 y2]
C
C Extract BUFR messages from bufr file and print the data as
C 'parameter = value' lines. See subroutine get_arguments for
C explanation of the options and DokIT for more documentation.
C
C Probably you should set
C export PRINT_TABLE_NAMES=false
C export BUFR_TABLES=/usr/local/lib/bufrtables/
C
C Author: P.Sannes, MET Norway
 
 
      PROGRAM BUFRDUMP
 
      IMPLICIT NONE
 
      CHARACTER(LEN=200) bufr_file       ! Bufr file to read from
      LOGICAL data_only                  ! TRUE if only data section is to be printed
      LOGICAL filter                     ! TRUE if observations should be filtered
      LOGICAL rectangle                  ! TRUE if observations are wanted for a rectangle only
      LOGICAL stop_on_error              ! TRUE if program should stop if a libbufr call returns an error
      CHARACTER(LEN=10) obstype
      CHARACTER(LEN=200) filter_file     ! File containing the filter criteria
      CHARACTER(LEN=200) descriptor_file ! File containing the descriptors requested for partial expansion
      INTEGER verbose                    ! Level of verbose output: 0 - 3 (default 1)
      INTEGER nlibbufr_errors            ! Number of errors encountered in libbufr calls
 
C     Dimensions of arrays used by libbufr routines are the same as those used in
C     example program decode_bufr.F in bufr_000280/example/
 
      INTEGER ibuff(512000)               ! Buffer to hold BUFR message
      INTEGER ibflen                      ! Size in BYTES of the array ibuff
      INTEGER ilen                        ! Size in BYTES of the BUFR message read
      INTEGER wlen                        ! Size in WORDS of the BUFR message read
      INTEGER iunit,iret
      INTEGER iloop
      LOGICAL eof
 
      PARAMETER (ibflen=4*512000)
 
      INCLUDE 'comfilter.f'     ! contains variables used when --filter is set
 
      verbose = 1
 
      CALL get_arguments(bufr_file,filter,filter_file,rectangle,
     +     stop_on_error,obstype)
 
      IF (filter) CALL read_filter(filter,filter_file,verbose)
 
C     Open bufr file - for read
      CALL PBOPEN(iunit,bufr_file,'r',iret)
      IF (iret.NE.0) CALL err_msg('PBOPEN failed for ' // bufr_file)
 
      nlibbufr_errors = 0
      iloop = 0
      DO WHILE (.TRUE.)
         iloop = iloop + 1
 
C     Get the next BUFR message
         CALL get_next_bufr_message(iunit,ibuff,ibflen,ilen,
     +        iloop,verbose,eof)
         IF (eof) GOTO 900
 
C     Decode Bufr message
         wlen = ilen/4 + 1   ! shouldn't really add 1 when ilen is divisible with 4,
                             ! but copy how it is done in decode_bufr in libbufr
         CALL BUFRdecode(ibuff,wlen,filter,rectangle,verbose,
     +        stop_on_error,obstype,nlibbufr_errors)
      END DO
 900  CONTINUE
 
      IF (nlibbufr_errors.GT.0) THEN
         WRITE(*,*) '\n\n  NOTE: At least ',nlibbufr_errors,
     +        ' BUFR message(s) skipped due to errors in libbufr calls',
     +        ' Check output for details of the errors encountered!',
     +        ' (Search on "ERROR")'
      END IF
 
      END PROGRAM BUFRDUMP
 
 
C     -----------------------------------------------------------------
 
      SUBROUTINE get_next_bufr_message(iunit,ibuff,ibflen,ilen,
     +        iloop,verbose,eof)
      IMPLICIT none
      INTEGER ibuff(*)
      INTEGER iunit,ibflen,ilen,iloop,iret,verbose
      LOGICAL eof
 
      eof = .FALSE.
      iret = 0
      CALL PBBUFR(iunit,ibuff,ibflen,ilen,iret)
      IF (iret .EQ. -1 ) THEN
         eof = .TRUE.
         RETURN
      ELSEIF (iret .EQ. -2 ) THEN
         CALL err_msg('ERROR: File handling problem')
      ELSEIF (iret .EQ. -3 ) THEN
         CALL err_msg('ERROR: Array too small')
      END IF
      IF (verbose .GT. 2) THEN
         WRITE (*,'(1X,A,I10)') 'BUFR message number= ',iloop
         WRITE (*,'(1X,A,I10)') 'Length of BUFR message = ',ilen
      END IF
      END SUBROUTINE get_next_bufr_message
 
C     -----------------------------------------------------------------
 
      SUBROUTINE BUFRdecode(ibuff,ilen,filter,rectangle,
     +     verbose,stop_on_error,obstype,nlibbufr_errors)
      IMPLICIT NONE
      INTEGER ibuff(*)
      INTEGER ilen              ! size in WORDS (not bytes) of the BUFR message read
      LOGICAL filter
      LOGICAL rectangle
      LOGICAL stop_on_error
      CHARACTER(LEN=*) obstype
      INTEGER nlibbufr_errors   ! Number of errors encountered in libbufr calls
      INTEGER verbose
 
      LOGICAL metar             ! Set to TRUE if metar (data subcategory 5)
 
      INTEGER kelem,kxelem      ! expected (max) number of expanded elements
      INTEGER kvals             ! expected (max) number of data values
 
C     Dimensions of arrays used by libbufr routines are the same as those used in
C     example program decode_bufr.F in bufr_000310/example/
      PARAMETER (kelem = 160000,kvals = 4096000)
 
C     BUFREX variables
      INTEGER ksup(9)           ! Integer array containing suplementary information
      INTEGER ksec0(3)          ! Bufr section 0 information
      INTEGER ksec1(40)
      INTEGER ksec2(4096)
      INTEGER ksec3(4)
      INTEGER ksec4(2)
      CHARACTER*64 cnames(kelem) ! Bufr Table B element names
      CHARACTER*24 cunits(kelem) ! Bufr Table B units
      CHARACTER*80 cvals(kelem) ! Bufr code table or CCITTIA5 Bufr elements entries
                                ! Using kelem as dimension seems somewhat arbitrary,
                                ! - just copying from decode_bufr.F in libbufr
      REAL*8 values(kvals)      ! expanded data values
 
C     BUSEL variables
      INTEGER ktdlst(2*kelem)     ! array containing data descriptors in section 3
      INTEGER ktdexp(2*kelem)     ! array containing expanded data descriptors
                                  ! Use 2*kelem, not kelem; copied from decode_bufr.F in libbufr
      INTEGER ktdlen            ! number of data descriptors in section 3
      INTEGER ktdexl            ! number of entries in list of expanded data descriptors
      INTEGER kerr              ! returned error code - but note that some libbufr
                                ! routines will return immediately if this is not 0 on input
      INTEGER ksub,ksub1,ksub2
 
C     BUSQR variables
      INTEGER kreq(2)
      INTEGER krql
      INTEGER krq(kelem)
      REAL*8 rqv(kelem)
      INTEGER rqd(101)           ! Requested descriptors
 
C     BUUKEY variables
      INTEGER key(46)
 
      INTEGER found_list(10000),num_found
 
      INTEGER i
 
      kerr = 0
      metar = .FALSE.
 
C     Do a partial expansion without quality control
      kreq(1) = 1               ! All original elements without quality control
      kreq(2) = 0
      krql = 0
 
C     Partial expansion
      CALL BUSRQ(kreq,krql,rqd,rqv,kerr)
      IF (kerr.NE.0) THEN
         IF (stop_on_error) STOP 1
         WRITE(*,*) 'ERROR IN BUSRQ: KERR= ',kerr
         nlibbufr_errors = nlibbufr_errors + 1
         RETURN
      END IF
C
C     Decode BUFR message into fully decoded form.
C
 
C     Using parameter kelem in call to BUFREX might be too big for some
C     multisubset messages (or too small for other messages). Have
C     copied the method used in decode_bufr.F in libbufr, first calling
C     BUS012 in order to get number of subsets ksup(6)
      CALL BUS012(ilen,ibuff,ksup,ksec0,ksec1,ksec2,kerr)
      IF (kerr.NE.0) THEN
         IF (stop_on_error) STOP 1
         WRITE(*,*) 'ERROR IN BUS012: KERR= ',kerr
         nlibbufr_errors = nlibbufr_errors + 1
         RETURN
      END IF
      kxelem = kvals/ksup(6)
C     The second IF-condition is not in decode_bufr.F, but else I get 'KELEM
C     ARGUMENT TOO SMALL' from BUUPWT when decoding large radiosondefiles
      IF (kxelem.GT.kelem .AND. ksup(6).GT.10) kxelem = kelem
 
      CALL BUFREX (ilen,ibuff,ksup,ksec0,ksec1,ksec2,
     +     ksec3,ksec4,kxelem,cnames,cunits,kvals,values,
     +     cvals,kerr)
      IF (kerr.EQ.45) RETURN      ! No requested elements in data
      IF (kerr.NE.0) THEN
         IF (stop_on_error) STOP 1
         WRITE(*,*) 'ERROR IN BUFREX: KERR= ',kerr
         nlibbufr_errors = nlibbufr_errors + 1
         RETURN
      END IF
      IF (verbose .GT. 2) WRITE (*,'(1X,A,I10)')
     +     'Number of subsets:',ksup(6)
 
C     Convert messages with data category (BUFR table A) 0-2,4,6 and 31 only.
C     0 = Surface data - land, 1 = Surface data - sea, 2 = Vertical
C     sounding (other than satellite) 4 = Single level upper-air data
C     (other than satellite) 6 = Radar data 31 = Oceanographic data
      IF (ksec1(6).GT.2 .AND. ksec1(6).NE.4 .AND. ksec1(6).NE.6
     +     .AND. ksec1(6).NE.31) RETURN
 
C     MET (and perhaps also other ECMWF based software?) uses local
C     subcategory 5 for metar (and BUFR edition 3)
      IF (KSEC1(2).EQ.3 .AND. KSEC1(6).EQ.0 .AND. KSEC1(7).EQ.5) THEN
         metar = .TRUE.
      END IF
 
      IF (filter) THEN
C     Return list of Data Descriptors from Section 3 of Bufr message,
C     and total/requested list of elements. BUFREX must have been called
C     before BUSEL. If filter is set, BUSEL2 will later be called to be
C     used for printing each subset, but for filter we need to know the
C     first members of ktdlst and ktdexl already now, to be able to call
C     find_stations.
         CALL BUSEL(ktdlen,ktdlst,ktdexl,ktdexp,kerr)
         IF (kerr .GT. 0) THEN
            IF (stop_on_error) STOP 1
            WRITE(*,*) 'ERROR IN BUSEL: KERR= ',kerr
            nlibbufr_errors = nlibbufr_errors + 1
            RETURN
         END IF
      END IF
 
      IF (filter) THEN
         CALL find_stations(ktdexp,ktdexl,values,cvals,ksup(6),
     +         kxelem,found_list,num_found)
      ENDIF
      IF (filter .AND. num_found.GT.0) THEN
         DO i=1,num_found
            ksub = found_list(i)
            CALL BUSEL2(ksub,kxelem,ktdlen,ktdlst,ktdexl,ktdexp,
     +           cnames,cunits,kerr)
            IF (kerr.NE.0) THEN
               IF (stop_on_error) STOP 1
               WRITE(*,*) 'ERROR IN BUSEL2: KERR= ',kerr
               nlibbufr_errors = nlibbufr_errors + 1
               RETURN
            END IF
 
            IF (obstype.EQ.'surface') THEN
               CALL print_surface_values(ksub,kxelem,ktdexl,ktdexp,
     +              values,cvals,rectangle,metar,verbose)
            ELSE IF (obstype(1:8).EQ.'sounding') THEN
               CALL print_sounding_values(ksub,kxelem,ktdexl,ktdexp,
     +              values,cvals,rectangle,obstype,verbose)
            ELSE IF (obstype.EQ.'amdar') THEN
               CALL print_amdar_values(ksub,kxelem,ktdexl,ktdexp,
     +              values,cvals,rectangle,verbose)
            ELSE IF (obstype.EQ.'ocea') THEN
               CALL print_oceanographic_values(ksub,kxelem,ktdexl,
     +              ktdexp,values,cvals,rectangle,verbose)
            ELSE IF (ksec1(6).LE.1) THEN
               CALL print_surface_values(ksub,kxelem,ktdexl,ktdexp,
     +              values,cvals,rectangle,metar,verbose)
            ELSE IF (ksec1(6).EQ.2) THEN
               CALL print_sounding_values(ksub,kxelem,ktdexl,ktdexp,
     +              values,cvals,rectangle,obstype,verbose)
            ELSE IF (ksec1(6).EQ.4) THEN
               CALL print_amdar_values(ksub,kxelem,ktdexl,ktdexp,
     +              values,cvals,rectangle,verbose)
            ELSE IF (ksec1(6).EQ.6) THEN
               CALL print_radar_profiler_values(ksub,kxelem,ktdexl,
     +              ktdexp,values,cvals,rectangle,verbose)
            ELSE IF (ksec1(6).EQ.31) THEN
               CALL print_oceanographic_values(ksub,kxelem,ktdexl,
     +              ktdexp,values,cvals,rectangle,verbose)
            END IF
         ENDDO
      ELSE IF (.NOT. filter) THEN
         DO ksub=1,ksup(6)
            CALL BUSEL2(ksub,kxelem,ktdlen,ktdlst,ktdexl,ktdexp,
     +           cnames,cunits,kerr)
            IF (kerr.NE.0) THEN
               IF (stop_on_error) STOP 1
               WRITE(*,*) 'ERROR IN BUSEL2: KERR= ',kerr
               nlibbufr_errors = nlibbufr_errors + 1
               RETURN
            END IF
 
            IF (obstype.EQ.'surface') THEN
               CALL print_surface_values(ksub,kxelem,ktdexl,ktdexp,
     +              values,cvals,rectangle,metar,verbose)
            ELSE IF (obstype(1:8).EQ.'sounding') THEN
               CALL print_sounding_values(ksub,kxelem,ktdexl,ktdexp,
     +              values,cvals,rectangle,obstype,verbose)
            ELSE IF (obstype.EQ.'amdar') THEN
               CALL print_amdar_values(ksub,kxelem,ktdexl,ktdexp,
     +              values,cvals,rectangle,verbose)
            ELSE IF (obstype.EQ.'ocea') THEN
               CALL print_oceanographic_values(ksub,kxelem,ktdexl,
     +              ktdexp,values,cvals,rectangle,verbose)
            ELSE IF (ksec1(6).LE.1) THEN
               CALL print_surface_values(ksub,kxelem,ktdexl,ktdexp,
     +              values,cvals,rectangle,metar,verbose)
            ELSE IF (ksec1(6).EQ.2) THEN
               CALL print_sounding_values(ksub,kxelem,ktdexl,ktdexp,
     +              values,cvals,rectangle,obstype,verbose)
            ELSE IF (ksec1(6).EQ.4) THEN
               CALL print_amdar_values(ksub,kxelem,ktdexl,ktdexp,
     +              values,cvals,rectangle,verbose)
            ELSE IF (ksec1(6).EQ.6) THEN
               CALL print_radar_profiler_values(ksub,kxelem,ktdexl,
     +              ktdexp,values,cvals,rectangle,verbose)
            ELSE IF (ksec1(6).EQ.31) THEN
C     For ocea files at met.no data category is 31. But note that IOB
C     bulletins all have data category 1 (and sub-category 25 or 255),
C     so for these we end up calling print_surface_values (unless
C     --obstype ocea is used)
               CALL print_oceanographic_values(ksub,kxelem,ktdexl,
     +              ktdexp,values,cvals,rectangle,verbose)
            END IF
         END DO
      END IF
 
      END SUBROUTINE BUFRdecode
 
C     -----------------------------------------------------------------
 
      SUBROUTINE get_arguments(bufr_file,filter,filter_file,
     +     rectangle,stop_on_error,obstype)
 
      IMPLICIT NONE
 
      CHARACTER(LEN=*) bufr_file ! Bufr file to read from
      LOGICAL data_only          ! TRUE if only data section is to be printed
      LOGICAL filter             ! TRUE if observations should be filtered
      LOGICAL rectangle          ! TRUE if observations are wanted for a rectangle only
      LOGICAL stop_on_error      ! TRUE if program should stop if a libbufr call returns an error
      CHARACTER(LEN=*) filter_file ! File containing the filter criteria
      CHARACTER(LEN=*) obstype
 
      CHARACTER(LEN=200) argument ! Buffer for next argument
      CHARACTER(LEN=1350) Usage
      CHARACTER(LEN=950) Help
      INTEGER iargc,iarg
 
C     Variables used for geographical filtering av observations
      REAL*8 x1,y1,x2,y2
      COMMON /COM_RECTANGLE/  x1,y1,x2,y2
      x1 = -180.00001
      y1 = -90.00001
      x2 = 180.00001
      y2 = 90.00001
 
      Usage = '\nUsage: bufrdump <bufr file> [options]\n\n'
     +     // 'Will print section 4 in BUFR messages in <bufr file>'
     +     // ' as "parameter=value" lines.'
     +     // '\nOptions (may be abbreviated to one character)'
     +     // ' are:\n'
     +     // '\t--help\t\tPrint this Usage plus some more help\n'
     +     // '\t--filter <filter file>\n'
     +     // '\t\t\tDecode observations meeting criteria in '
     +     // '<filter file> only\n'
     +     // '\t--obstype <amdar|ocea|surface|sounding|sounding->\n'
     +     // '\t\t\tForce observation type. If this option '
     +     // 'is not set, bufrdump\n\t\t\twill make an '
     +     // 'educated guess of observation type based on\n'
     +     // '\t\t\tmetadata in section 1 of each BUFR message. '
     +     // 'The special value\n\t\t\t"sounding-" results in '
     +     // 'levels with no vss being skipped\n'
     +     // '\t--stop_on_error\tIf a libbufr call returns an '
     +     // 'error, bufrdump will return\n\t\t\timmediately with '
     +     // 'exit status 1\n'
     +     // '\t--rectangle x1 y1 x2 y2\n'
     +     // '\t\t\tDecode observations inside rectangle with lower '
     +     // 'left coordinates\n\t\t\t(x1,y1) (i.e.lon,lat) '
     +     // 'and upper right coordinates (x2,y2) only\n'
     +     // 'As an alternative to --rectangle you can use one or '
     +     // 'more of\n'
     +     // '\t--lon1 x1'
     +     // '\tDecode observations with longitude >= x1 only\n'
     +     // '\t--lat1 y1'
     +     // '\tDecode observations with latitude >= y1 only\n'
     +     // '\t--lon2 x2'
     +     // '\tDecode observations with longitude <= x2 only\n'
     +     // '\t--lat2 y2'
     +     // '\tDecode observations with latitude <= y2 only\n'
     +     // '\t\t\tx1,y1,x2,y2 should be degrees or decimal degrees'
 
      Help = '\nYou should probably set\n'
     +     // '\texport BUFR_TABLES=/usr/local/lib/bufrtables/\n'
     +     // '\texport PRINT_TABLE_NAMES=false\n'
     +     // '\nUsing --filter will decode only those observations '
     +     // 'that meet the criteria in\n<filter file>. An example '
     +     // 'of a filter file is\n\n'
     +     // 'D: 001001 I2.2\n'
     +     // '01\n'
     +     // 'D: 001001 I2.2 001002 I3.3\n'
     +     // '03 895\n'
     +     // '06 252\n'
     +     // 'D: 001011 A9\n'
     +     // 'LMEL     \n\n'
     +     // 'which decodes all observations with block number 01, '
     +     // 'two other specific wmo\nstations and one ship. '
     +     // 'So far only filtering on exact matches on integer and\n'
     +     // 'character valued BUFR descriptors has been implemented.'
     +     // ' But note that the\nclosely related program bufrdump.pl'
     +     // ' has a lot more options for filtering.'
     +     // '\n\nIf an error occurs during decoding (typically '
     +     // 'because the required BUFR table\nis missing or message '
     +     // 'is corrupt) the message is skipped, and the number '
     +     // 'of\nerrors is reported at end of output - unless '
     +     // 'option --stop_on_error has been\napplied (note that '
     +     // 'some error messages from libbufr might still have been '
     +     // 'sent\nto STDOUT).\n'
 
C     Default values
      filter = .FALSE.
      obstype = ''
      rectangle = .FALSE.
      stop_on_error = .FALSE.
      bufr_file = ''
      iarg = 0
 
      IF (iargc() .LT. 1) THEN
         WRITE(*,*) Usage
         CALL EXIT(0)
      END IF
 
C     Loop: reading of command options
 100  CONTINUE
      iarg = iarg + 1
      CALL getarg(iarg,argument)
      IF (argument .EQ. '--help' .OR.
     +     argument .EQ. '--h' .OR. argument .EQ. '-h') THEN
         WRITE(*,*) Usage
         WRITE(*,*) Help
         CALL EXIT(0)
      ELSE IF (argument .EQ. '--filter' .OR.
     +     argument .EQ. '--f' .OR. argument .EQ. '-f') THEN
         filter = .TRUE.
         iarg = iarg + 1
         CALL getarg(iarg,filter_file)
      ELSE IF (argument .EQ. '--obstype' .OR.
     +     argument .EQ. '--o' .OR. argument .EQ. '-o') THEN
         iarg = iarg + 1
         CALL getarg(iarg,obstype)
      ELSE IF (argument .EQ. '--stop_on_error') THEN
         stop_on_error = .TRUE.
      ELSE IF (argument .EQ. '--rectangle' .OR.
     +     argument .EQ. '--r' .OR. argument .EQ. '-r') THEN
         rectangle = .TRUE.
         iarg = iarg + 1
         CALL getarg(iarg,argument)
         READ (argument,*) x1
         iarg = iarg + 1
         CALL getarg(iarg,argument)
         READ (argument,*) y1
         iarg = iarg + 1
         CALL getarg(iarg,argument)
         READ (argument,*) x2
         iarg = iarg + 1
         CALL getarg(iarg,argument)
         READ (argument,*) y2
      ELSE IF (argument .EQ. '--lon1') THEN
         rectangle = .TRUE.
         iarg = iarg + 1
         CALL getarg(iarg,argument)
         READ (argument,*) x1
      ELSE IF (argument .EQ. '--lat1') THEN
         rectangle = .TRUE.
         iarg = iarg + 1
         CALL getarg(iarg,argument)
         READ (argument,*) y1
      ELSE IF (argument .EQ. '--lon2') THEN
         rectangle = .TRUE.
         iarg = iarg + 1
         CALL getarg(iarg,argument)
         READ (argument,*) x2
      ELSE IF (argument .EQ. '--lat2') THEN
         rectangle = .TRUE.
         iarg = iarg + 1
         CALL getarg(iarg,argument)
         READ (argument,*) y2
      ELSE IF (argument(1:2) .EQ. '--' .OR.
     +     argument .EQ. '--d' .OR. argument .EQ. '-d') THEN
         WRITE(*,*) 'Unknown option ',argument
         WRITE(*,*) Usage
         CALL EXIT(1)
      ELSE
C     Read in Bufr file to decode
         bufr_file = argument
      END IF
      IF (iarg .LT. iargc()) GOTO 100
 
      IF (bufr_file .EQ. '') THEN
         WRITE(*,*) 'No BUFR file given'
         CALL EXIT(1)
      END IF
 
      IF (obstype.NE.'' .AND. obstype.NE.'amdar' .AND. obstype.NE.'ocea'
     +     .AND. obstype.NE.'surface' .AND. obstype.NE.'sounding'
     +     .AND. obstype.NE.'sounding-') THEN
         WRITE(*,*) 'Argument to --obstype must be one of amdar, ocea,',
     +   ' surface, sounding or sounding-'
         CALL EXIT(1)
      END IF
 
      END SUBROUTINE get_arguments
 
C     -----------------------------------------------------------------
 
      SUBROUTINE err_msg(msg)
      IMPLICIT NONE
      CHARACTER(LEN=*) msg
      WRITE(*,*) msg
      STOP
      END SUBROUTINE err_msg
 
C     -----------------------------------------------------------------
 
      SUBROUTINE err_msg1(msg,kerr)
      IMPLICIT NONE
      CHARACTER(LEN=*) msg
      INTEGER kerr
      WRITE(*,*) msg,kerr
      STOP
      END SUBROUTINE err_msg1
 
C     -----------------------------------------------------------------
 
      SUBROUTINE read_filter(filter,filter_file,verbose)
C
C     Reads the content of filter file into matrices fid and fidformat,
C     arrays nd_fid and nvl_fid for the descriptors, into matrices fivI
C     and fivC for the values to filter on. Also sets nfidlines and
C     nfidvalues. See comfilter.f for explanation of variables. See Help
C     in get_arguments for an example of filter file.
C
      IMPLICIT NONE
      LOGICAL filter            ! TRUE on input. Might be changed to FALSE on output
                                ! if no filter condition is found in filter file
      CHARACTER(LEN=200) filter_file
      INTEGER verbose,ios,inplen,i1,i2,i3,ifid,jfid,lenstr,fmt_len
      CHARACTER*100 inpline,readformat
      CHARACTER*10 fmt
      LOGICAL new_fid
 
      INCLUDE 'comfilter.f'
 
      OPEN (UNIT = 11,FILE = filter_file,STATUS = 'OLD',
     +     IOSTAT = ios)
      IF (ios.NE.0) CALL err_msg('Cannot open ' // filter_file)
 
      nfidlines = 0
      nfivlines = 0
      ifid = 0
      filter_loop: DO WHILE (.TRUE.)
C     Note: a line consisting of blanks or the new line character only
C     marks end of filter conditions
         READ (11,'(A100)',END=11) inpline
         IF (verbose.GT.2) WRITE (*,*) inpline
         inplen = lenstr(inpline,1)
         IF (inplen.EQ.0) EXIT filter_loop
         i1 = 0
         i2 = 0
         CALL advance_word(inpline,inplen,i1,i2)
         IF (i1 .EQ. 0) EXIT filter_loop
         IF (inpline(i1:i1).EQ.'#') CYCLE filter_loop ! Comment line
 
         IF (inpline(i1:i1+1).EQ.'D:') THEN
C     Descriptor line (e.g. D: 001001 I2.2 001002 I3.3)
            ifid = ifid + 1
            IF (ifid.GT.dim1_fid) CALL err_msg(
     +      'bufrread: dimension 1 limit exeeded for array fid')
            jfid = 0
            DO WHILE (i1 .NE. 0)
               CALL advance_word(inpline,inplen,i1,i2)
               IF (i1 .NE. 0) THEN
                  jfid = jfid + 1
                  IF (jfid.GT.dim1_fid) CALL err_msg(
     +                 'bufrread: dimension 2 exeeded for array fid')
C     Read descriptor
                  READ (inpline(i1:i2),*) fid(ifid,jfid)
                  CALL advance_word(inpline,inplen,i1,i2)
                  IF (i1 .EQ. 0)
     +                 CALL err_msg('Wrong format in filter file')
C     Read format
                  READ (inpline(i1:i2),*) fidformat(ifid,jfid)
               END IF
            END DO
            nd_fid(ifid) = jfid
            nfidlines = ifid
         ELSE
 
C     Value line (e.g. 03 895 or: North Shields)
            nfivlines = nfivlines + 1
            IF (nfivlines.GT.dim_fiv) CALL err_msg(
     +      'bufrread: dimension limit exeeded for array fivI/C')
            nvl_fid(ifid) =  nvl_fid(ifid) + 1
C     Read in value field, descriptor for descriptor:
            DO jfid = 1,nd_fid(ifid)
               fmt = fidformat(ifid,jfid)
               IF (fmt(1:1).EQ.'I') THEN
                  READ (inpline(i1:i2),*) fivI(nfivlines,jfid)
                  IF (verbose.GT.2) WRITE(*,*) 'nfivlines,jfid,fivI=',
     +                 nfivlines,jfid,fivI(nfivlines,jfid)
               ELSE IF (fmt(1:1).EQ.'A') THEN
C                 String may include space, therefore i2 may need to be adjusted
                  READ (fmt(2:lenstr(fmt,0)),*) fmt_len
                  i2 = i1 + fmt_len
                  READ (inpline(i1:i2),*) fivC(nfivlines,jfid)
                  IF (verbose.GT.2) WRITE(*,*) 'nfivlines,jfid,fivC=',
     +                 nfivlines,jfid,' ',fivC(nfivlines,jfid)
               ELSE
                  CALL err_msg('Wrong value format in filter file')
               END IF
               CALL advance_word(inpline,inplen,i1,i2)
            END DO
         ENDIF
      END DO filter_loop
 
 11   CONTINUE
      CLOSE(11)
 
      IF (verbose.GT.2) WRITE(*,*) 'nfidlines=',nfidlines
      IF (nfivlines.EQ.0) filter = .FALSE.
 
      END SUBROUTINE read_filter
 
C     -----------------------------------------------------------------
 
      subroutine advance_word(str,length,beginp,endp)
C
C     The character variable 'str' contains words of non-blank
C     characters separated by blanks. 'beginp' and 'endp' points to the
C     beginning and end of a word (char indices within 'str'). This
C     subroutine advances these pointers to point to the next word
C     within 'str'. 'length' is the length of 'str'. Initially, 'beginp'
C     and 'endp' is set to 0 (outside this subroutine). The first call
C     to 'advance_word' will then set these pointers to the first word
C     within 'str'. When no more words are found, 'beginp' and 'endp'
C     are again set to 0.
C
      implicit none
      character*(*) str
      integer length,beginp,endp
      integer i1,i2
      i1 = endp+1
      do while (i1 .le. length)
         if (str(i1:i1) .ne. ' ') then
            beginp = i1
            i2 = index(str(i1:length),' ')
            if (i2 .eq. 0) then
               endp = length
               return
            else
               endp = i1 + i2 - 2
               return
            end if
         else
            i1 = i1 + 1
         end if
      end do
      beginp = 0
      endp = 0
      end subroutine advance_word
 
C     -----------------------------------------------------------------
 
      SUBROUTINE find_stations(ktdexp,ktdexl,values,cvals,num_subsets,
     +        kxelem,found_list,num_found)
C
C     Return the number of subsets in BUFR message which contain an
C     observation matching one of the criteria in filter file as
C     num_found, the subset numbers in found(list(i)), i=1,...,num_found
C
      IMPLICIT NONE
      INTEGER found_list(10000),num_found
      INTEGER ktdexp(*)         ! array containing expanded data descriptors
      INTEGER ktdexl            ! number of entries in list of expanded data descriptors
      INTEGER kxelem            ! number of data elements for each section 4 report
      CHARACTER*80 cvals(*)     ! Bufr code table or CCITTIA5 Bufr elements entries
      REAL*8 values(*)          ! expanded data values
      INTEGER num_subsets
 
      INTEGER i1,i2,nsub,ifvl,itd,iv,icv,ifiv
      LOGICAL match             ! Set to true if a value in data matches value in
                                ! filter, for a single descriptor
      LOGICAL int_fid           ! Set to true if filter descriptor is integer type
      LOGICAL char_fid          ! Set to true if filter descriptor is character type
 
      INCLUDE 'comfilter.f'
 
      REAL*8 rvind              ! missing value for real*8 data
      PARAMETER (rvind=1.7E38)
 
      num_found = 0
C     loop through all subsets:
      DO nsub = 1,num_subsets
C     loop through all different conditions:
         ifiv = 0
         DO i1 = 1,nfidlines
C     loop through all filter value lines (for given) condition:
            DO ifvl = 1,nvl_fid(i1)
               ifiv = ifiv + 1
C     loop through all descriptors in condition:
               DO i2 = 1,nd_fid(i1)
                  match = .FALSE.
                  int_fid = .FALSE.
                  char_fid = .FALSE.
                  IF (fidformat(i1,i2)(1:1).EQ.'I') THEN
                     int_fid = .TRUE.
                  ELSE IF (fidformat(i1,i2)(1:1).EQ.'A') THEN
                     char_fid = .TRUE.
                  END IF
C     loop through all data in subset:
                  DO itd = 1,ktdexl
                     IF (ktdexp(itd).EQ.fid(i1,i2)) THEN
                        iv = (nsub-1)*kxelem + itd
                        IF (values(iv).EQ.rvind)
     +                       GOTO 400 ! next condition, no point in checking
                                      ! other filter value lines
                        IF (int_fid) THEN
                           IF (nint(values(iv)).EQ.fivI(ifiv,i2)) THEN
                              match = .TRUE.
                              EXIT ! exit innermost loop
                           END IF
                        ELSE IF (char_fid) THEN
                           icv = nint(values(iv))/1000
                           IF (cvals(icv).EQ.fivC(ifiv,i2)) THEN
                              match = .TRUE.
                              EXIT ! exit innermost loop
                           END IF
                        END IF
                     END IF
                   END DO       ! all data in subset
                   IF (.NOT.match) ! there is one descriptor in condition which
     +                  EXIT       ! subset does not match, so go to next
                                   ! value line
                END DO          ! all descriptors in condition
                IF (match) THEN
                   num_found = num_found + 1
                   found_list(num_found) = nsub
                   GO TO 500    ! next subset
                END IF
            END DO              ! all filter value lines (for given) condition
 400        CONTINUE
         END DO                 ! all different conditions
 500     CONTINUE
      END DO                    ! all subsets
 
      END SUBROUTINE find_stations
 
C     -----------------------------------------------------------------
 
C     Identify pressure, temperature etc and print parameter=value to
C     screen. Note: have seen high resolution data with 7002 HEIGHT OR
C     ALTITUDE and wind profiler data with 007009 GEOPOTENTIAL HEIGHT
C     used as vertical coordinate instead of 7004 PRESSURE (10004 was
C     used for pressure in the first case). Not able to handle that in
C     present code.
      SUBROUTINE print_sounding_values(ksub,kxelem,ktdexl,ktdexp,values,
     +     cvals,rectangle,obstype,verbose)
      IMPLICIT NONE
 
      INTEGER ksub              ! Input: number of subset currently processed
      INTEGER kxelem            ! Input: expected (max) number of expanded elements
      INTEGER ktdexl            ! Input: number of entries in list of expanded data descriptors
      INTEGER ktdexp(*)         ! Input: array containing expanded data descriptors
      REAL*8 values(*)          ! Input: expanded data values (one subset)
      CHARACTER*80 cvals(*)     ! Input: CCITTIA5 Bufr elements entries (one subset)
      LOGICAL rectangle         ! Input: TRUE if observations are wanted for a rectangle only
      CHARACTER(LEN=*) obstype  ! Input: influence flow if set to 'sounding-'
      INTEGER verbose           ! Input: verbose level
 
      REAL*8 rvind              ! missing value for real*8 data
      PARAMETER (rvind=1.7E38)
 
      REAL*8 II,iii,ix,year,month,day,hour,minute,
     +     longitude,latitude,height,wigos_series
      CHARACTER*5 wigos_issuer,wigos_issueno,missing5
      CHARACTER*9 call_sign,missing9
      CHARACTER*8 flight_number,missing8
      CHARACTER*16 wigos_localid,missing16
 
      CHARACTER one_bits
      REAL*8 value
      INTEGER idx,cidx,desc,n,maxlevel,numlevels,i,ind,ind2,ind3
      PARAMETER(maxlevel=100000)
 
      REAL*8 P(maxlevel),D(maxlevel),F(maxlevel),
     +     T(maxlevel),TD(maxlevel),h(maxlevel),
     +     la(maxlevel),lo(maxlevel),tp(maxlevel), ! displacements (lat, lon, time)
     +     wsb(maxlevel),wsa(maxlevel) ! absolute wind shear in 1 km layer below/above
      CHARACTER*8 vss(maxlevel) ! Vertical sounding significance
      CHARACTER*8 vss_missing
      LOGICAL reduce ! Set to TRUE if we should skip levels with
                     ! vertical sounding significance missing or equal
                     ! to 0
 
C     Variables used for geographical filtering av observations
      REAL*8 x1,y1,x2,y2
      COMMON /COM_RECTANGLE/  x1,y1,x2,y2
 
C     Functions
      INTEGER lenstr
      CHARACTER*9 ctrim  ! length must be >= longest variable ctrim is used for
 
      IF (obstype.EQ.'sounding-') THEN
         reduce = .TRUE.
      ELSE
         reduce = .FALSE.
      END IF
 
      one_bits = CHAR(255)
      WRITE(missing5,'(5A)') one_bits,one_bits,one_bits,one_bits,
     +     one_bits
      WRITE(missing8,'(8A)') one_bits,one_bits,one_bits,one_bits,
     +     one_bits,one_bits,one_bits,one_bits
      missing9 = missing8 // one_bits
      missing16 = missing8 // missing8
      vss_missing = '       '
 
C     Initialize all parameters to missing values
      call_sign = missing9
      flight_number = missing8
      wigos_issuer = missing5
      wigos_issueno = missing5
      wigos_localid = missing16
      wigos_series = rvind
      II = rvind
      iii= rvind
      year = rvind
      month = rvind
      day = rvind
      hour = rvind
      minute = rvind
      latitude = rvind
      longitude = rvind
      height = rvind
      DO n=1,maxlevel
         P(n) = rvind
         D(n) = rvind
         F(n) = rvind
         T(n) = rvind
         TD(n) = rvind
         h(n) = rvind
         la(n) = rvind
         lo(n) = rvind
         tp(n) = rvind
         vss(n) = vss_missing
         wsb(n) = rvind
         wsa(n) = rvind
      END DO
 
C     Loop through all expanded descriptors
      n = 0 ! Numbering the pressure levels
      DO idx=1,ktdexl
         desc = ktdexp(idx)
         value = values(idx + (ksub-1)*kxelem)
 
C     Nothing to do if value is missing (note that the missing value
C     returned from libbufr might not be exactly equal to rvind)
         IF (ABS(value - rvind)/rvind.LE.0.001) THEN
            CYCLE
         END IF
 
         IF (desc.EQ.1001) THEN ! WMO block number
            II = value
         ELSE IF (desc.EQ.1002) THEN ! WMO station number
            iii = value
         ELSE IF (desc.EQ.1011.OR.   ! Ship or mobile land station identifier
     +           desc.EQ.1195) THEN  ! Mobil land station identifier
               cidx = int(value/1000)
               call_sign = cvals(cidx) ! CCITTIA5 data
               call_sign = ctrim(call_sign,9,missing9)
         ELSE IF (desc.EQ.1006) THEN ! Aircraft flight number, used for dropsondes
            cidx = int(value/1000)
            flight_number = cvals(cidx) ! CCITTIA5 data
            flight_number = ctrim(flight_number,8,missing8)
         ELSE IF (desc.EQ.1125) THEN ! WIGOS identifier series
            wigos_series = value
         ELSE IF (desc.EQ.1126) THEN ! WIGOS issuer of identifier
            i = NINT(value)
            WRITE(wigos_issuer,'(I5)') i
            wigos_issuer = ADJUSTL(wigos_issuer)
         ELSE IF (desc.EQ.1127) THEN ! WIGOS issue number
            i = NINT(value)
            WRITE(wigos_issueno,'(I5)') i
            wigos_issueno = ADJUSTL(wigos_issueno)
         ELSE IF (desc.EQ.1128) THEN  ! WIGOS local identifier
            cidx = int(value/1000)
            wigos_localid = cvals(cidx) ! CCITTIA5 data
            wigos_localid = ctrim(wigos_localid,16,missing16)
         ELSE IF (desc.EQ.2001) THEN ! Type of station
            ix = value
         ELSE IF (desc.EQ.4001) THEN ! Year
            year = value
         ELSE IF (desc.EQ.4002) THEN ! Month
            month = value
         ELSE IF (desc.EQ.4003) THEN ! Day
            day = value
         ELSE IF (desc.EQ.4004) THEN ! Hour
            hour = value
         ELSE IF (desc.EQ.4005) THEN ! Minute
            minute = value
C     Seen 5002 and 6002 used for each level in high resolution data
         ELSE IF (desc.EQ.5001 .AND. latitude.EQ.rvind) THEN ! Latitude (high accuracy)
            latitude = value
         ELSE IF (desc.EQ.5002 .AND. latitude.EQ.rvind) THEN ! Latitude (coarse accuracy)
            latitude = value
         ELSE IF (desc.EQ.6001 .AND. longitude.EQ.rvind) THEN ! Longitude (high accuracy)
            longitude = value
         ELSE IF (desc.EQ.6002 .AND. longitude.EQ.rvind) THEN ! Longitude (coarse accuracy)
            longitude = value
         ELSE IF (desc.EQ.7001.OR.  ! Height of station
     +           desc.EQ.7030.OR.   ! Height of station ground above mean sea level
     +           desc.EQ.7031.OR.   ! Height of barometer above mean sea level
     +           desc.EQ.7007) THEN ! Height (i.e. of release of sonde above mean sea level)
            IF (height.EQ.rvind) THEN
               height = value
            END IF
         ELSE IF (desc.EQ.4086.AND.n.LT.maxlevel) THEN ! Long time period or displacement [second]
C     In WMO template (309052) descriptors 004086 and 008042 comes BEFORE 7004 pressure
            tp(n+1) = value
         ELSE IF (desc.EQ.8042.AND.n.LT.maxlevel) THEN ! Extended vertical sounding significance
            CALL vss_8042(NINT(value),vss(n+1))
         ELSE IF (desc.EQ.7004) THEN ! Pressure
            n = n + 1           ! new level
            IF (n.GT.maxlevel) THEN
               n = maxlevel
               WRITE(*,*) 'Too many levels! Skipping rest of message'
               GOTO 110
            END IF
            P(n) = value
C     All following descriptors come after pressure in 309052 (or Hirlam template)
         ELSE IF (n.GT.0 .AND. n.LE.maxlevel) THEN
            IF (desc.EQ.11001) THEN ! Wind direction
               D(n) = value
            ELSE IF (desc.EQ.11002) THEN ! Wind speed
               F(n) = value
            ELSE IF (desc.EQ.12101) THEN ! Temperature/dry bulb temperature (16 bits)
               T(n) = value
            ELSE IF (desc.EQ.12001) THEN ! Temperature/dry bulb temperature (12 bits)
               T(n) = value
            ELSE IF (desc.EQ.12103) THEN ! Dew-point temperature (16 bits)
               TD(n) = value
            ELSE IF (desc.EQ.12003) THEN ! Dew-point temperature (12 bits)
               TD(n) = value
            ELSE IF (desc.EQ.10003.AND.value.NE.rvind) THEN ! Geopotential
               h(n) = value/9.81
            ELSE IF (desc.EQ.10009) THEN ! Geopotential height
               h(n) = value
            ELSE IF (desc.EQ.5015) THEN ! Latitude displacement
               la(n) = value
            ELSE IF (desc.EQ.6015) THEN ! Longitude displacement
               lo(n) = value
            ELSE IF (desc.EQ.8001 .AND. value.NE.rvind) THEN ! Vertical sounding significance
C     In HIRLAM template (309007) 008001 comes AFTER 7004 pressure
               CALL vss_8001(NINT(value),vss(n))
            ELSE IF (desc.EQ.11061) THEN ! Absolute wind shear in 1 km layer below
               wsb(n) = value
            ELSE IF (desc.EQ.11062) THEN ! Absolute wind shear in 1 km layer above
               wsa(n) = value
            END IF
         END IF
      END DO
 110  CONTINUE
      numlevels = n
 
      IF (rectangle) THEN
         IF (longitude.EQ.rvind .OR. latitude.EQ.rvind
     +        .OR. longitude.LT.x1 .OR. longitude.GT.x2
     +        .OR. latitude.LT.y1 .OR. latitude.GT.y2) RETURN
      END IF
 
 
      IF (II.NE.rvind .AND. iii.NE.rvind) THEN
         WRITE(*,*)
         WRITE(*,'(A,I5.5)') 'wmonr=',NINT(II)*1000 + NINT(iii)
      ELSE IF (wigos_series.NE.rvind .AND. wigos_issuer.NE.missing5
     +        .AND. wigos_issueno.NE.missing5
     +        .AND. wigos_localid.NE.missing16) THEN
         ind = index(wigos_issuer,' ') - 1
         IF (ind.EQ.-1) ind = 5
         ind2 = index(wigos_issueno,' ') - 1
         IF (ind2.EQ.-1) ind2 = 5
         ind3 = index(wigos_localid,' ') - 1
         IF (ind3.EQ.-1) ind3 = 16
         WRITE(*,*)
         WRITE(*,'(A,I1.1,A1,A,A1,A,A1,A)')
     +        'wigosid=',NINT(wigos_series),
     +        '-',wigos_issuer(1:ind),
     +        '-',wigos_issueno(1:ind2),
     +        '-',wigos_localid(1:ind3)
      ELSE IF (call_sign.NE.missing9) THEN
         WRITE(*,*)
         WRITE(*,'(A,A)') 'call_sign=',call_sign(1:lenstr(call_sign,1))
      ELSE IF (flight_number.NE.missing8) THEN
         WRITE(*,*)
         WRITE(*,'(A,A)') 'aircraft=',
     +        flight_number(1:lenstr(flight_number,1))
      ELSE
         IF (verbose .GT. 1) THEN
            WRITE(*,*)
            WRITE(*,*) 'Both wmonr, wigosid, call sign and aircraft'
     +           // ' flight number are missing !!!'
         END IF
         RETURN
      END IF
 
      IF (year.NE.rvind.AND.month.NE.rvind.AND.day.NE.rvind
     +     .AND.hour.NE.rvind.AND.minute.NE.rvind) THEN
         WRITE(*,900),NINT(year),NINT(month),NINT(day),
     +        NINT(hour),NINT(minute)
 900     FORMAT('obstime=',I4,'-',I2.2,'-',I2.2,' ',I2.2,':',I2.2,':00')
      ELSE
         IF (verbose .GT. 1) THEN
            WRITE(*,*) 'obstime is missing!!!'
            RETURN
         END IF
      ENDIF
      IF (ix.NE.rvind) THEN
         IF (NINT(ix).EQ.0) THEN
            WRITE(*,'(A,A)') 'type=Automatic'
         ELSE IF (NINT(ix).EQ.1) THEN
            WRITE(*,'(A,A)') 'type=Manned'
         ELSE IF (NINT(ix).EQ.2) THEN
            WRITE(*,'(A,A)') 'type=Hybrid'
         END IF
      END IF
      IF (latitude.NE.rvind) THEN
         WRITE(*,'(A,F10.5)') 'lat=',latitude
      END IF
      IF (longitude.NE.rvind) THEN
         WRITE(*,'(A,F10.5)') 'lon=',longitude
      END IF
      IF (height.NE.rvind) THEN
         WRITE(*,'(A,I7)') 'height=',NINT(height)
      END IF
 
      DO n=1,numlevels
         IF (reduce .AND. vss(n).EQ.vss_missing) CYCLE
         WRITE(*,'(A,I12)'),'n=',n
C     The following 3 parameters are not found in TAC TEMP
         IF (tp(n).NE.rvind) THEN
            WRITE(*,'(A,I12)') 't=',NINT(tp(n))
         END IF
         IF (la(n).NE.rvind) THEN
            WRITE(*,'(A,F11.5)') 'la=',la(n)
         END IF
         IF (lo(n).NE.rvind) THEN
            WRITE(*,'(A,F11.5)') 'lo=',lo(n)
         END IF
C     Choose to display vss even when it is empty
         WRITE(*,'(A,A10)') 'vss=',vss(n)
         IF (P(n).NE.rvind) THEN
            WRITE(*,'(A,F11.1)') 'PP=',P(n)/100 ! hPa
         END IF
         IF (h(n).NE.rvind) THEN
            WRITE(*,'(A,I11)') 'gh=',NINT(h(n))
         END IF
         IF (D(n).NE.rvind) THEN
            WRITE(*,'(A,I11)') 'DD=',NINT(D(n))
         END IF
         IF (F(n).NE.rvind) THEN
            WRITE(*,'(A,F11.1)') 'FF=',F(n)
         END IF
         IF (T(n).NE.rvind) THEN
            WRITE(*,'(A,F11.1)') 'TT=',T(n)-273.15
         END IF
         IF (TD(n).NE.rvind) THEN
            WRITE(*,'(A,F11.1)') 'TD=',TD(n)-273.15
         END IF
         IF (wsb(n).NE.rvind) THEN
            WRITE(*,'(A,F10.1)') 'wsb=',wsb(n)
         END IF
         IF (wsa(n).NE.rvind) THEN
            WRITE(*,'(A,F10.1)') 'wsa=',wsa(n)
         END IF
      END DO
 
      END SUBROUTINE print_sounding_values
 
C     -----------------------------------------------------------------
 
C     Identify height, wind and data quality parameters and print parameter=value to
C     screen for the given heights.
      SUBROUTINE print_radar_profiler_values(ksub,kxelem,ktdexl,ktdexp,
     +     values,cvals,rectangle,verbose)
      IMPLICIT NONE
 
      INTEGER ksub              ! Input: number of subset currently processed
      INTEGER kxelem            ! Input: expected (max) number of expanded elements
      INTEGER ktdexl            ! Input: number of entries in list of expanded data descriptors
      INTEGER ktdexp(*)         ! Input: array containing expanded data descriptors
      REAL*8 values(*)          ! Input: expanded data values (one subset)
      CHARACTER*80 cvals(*)     ! Input: CCITTIA5 Bufr elements entries (one subset)
      LOGICAL rectangle         ! Input: TRUE if observations are wanted for a rectangle only
      INTEGER verbose           ! Input: verbose level
 
      REAL*8 rvind              ! missing value for real*8 data
      PARAMETER (rvind=1.7E38)
 
      REAL*8 II,iii,ix,year,month,day,hour,minute,
     +     longitude,latitude,height
      CHARACTER*9 call_sign,missing9
      CHARACTER one_bits
      REAL*8 value
      INTEGER idx,cidx,desc,n,maxlevel,numlevels,ind
      PARAMETER(maxlevel=1000)
 
      REAL*8 HH(maxlevel),D(maxlevel),F(maxlevel),
     +     Q1(maxlevel),WC(maxlevel),Q2(maxlevel)
 
C     Variables used for geographical filtering av observations
      REAL*8 x1,y1,x2,y2
      COMMON /COM_RECTANGLE/  x1,y1,x2,y2
 
C     Functions
      INTEGER lenstr
      CHARACTER*9 ctrim  ! length must be >= longest variable ctrim is used for
 
      one_bits = CHAR(255)
      WRITE(missing9,'(9A)') one_bits,one_bits,one_bits,one_bits,
     +     one_bits,one_bits,one_bits,one_bits,one_bits
 
C     Initialize all parameters to missing values
      call_sign = missing9
      II = rvind
      iii= rvind
      year = rvind
      month = rvind
      day = rvind
      hour = rvind
      minute = rvind
      latitude = rvind
      longitude = rvind
      height = rvind
      DO n=1,maxlevel
         HH(n) = rvind
         D(n) = rvind
         F(n) = rvind
         Q1(n) = rvind
         WC(n) = rvind
         Q2(n) = rvind
      END DO
 
C     Loop through all expanded descriptors
      n = 0 ! Numbering the pressure levels
      DO idx=1,ktdexl
         desc = ktdexp(idx)
         value = values(idx + (ksub-1)*kxelem)
 
C     Nothing to do if value is missing (note that the missing value
C     returned from libbufr might not be exactly equal to rvind)
         IF (ABS(value - rvind)/rvind.LE.0.001) THEN
            CYCLE
         END IF
 
         IF (desc.EQ.1001) THEN ! WMO block number
            II = value
         ELSE IF (desc.EQ.1002) THEN ! WMO station number
            iii = value
         ELSE IF (desc.EQ.1011.OR.   ! Ship or mobile land station identifier
     +           desc.EQ.1195) THEN  ! Mobil land station identifier
               cidx = int(value/1000)
               call_sign = cvals(cidx) ! CCITTIA5 data
               call_sign = ctrim(call_sign,9,missing9)
         ELSE IF (desc.EQ.2001) THEN ! Type of station
            ix = value
         ELSE IF (desc.EQ.4001) THEN ! Year
            year = value
         ELSE IF (desc.EQ.4002) THEN ! Month
            month = value
         ELSE IF (desc.EQ.4003) THEN ! Day
            day = value
         ELSE IF (desc.EQ.4004) THEN ! Hour
            hour = value
         ELSE IF (desc.EQ.4005) THEN ! Minute
            minute = value
C     Seen 5002 and 6002 used for each level in high resolution data
         ELSE IF (desc.EQ.5001 .AND. latitude.EQ.rvind) THEN ! Latitude (high accuracy)
            latitude = value
         ELSE IF (desc.EQ.5002 .AND. latitude.EQ.rvind) THEN ! Latitude (coarse accuracy)
            latitude = value
         ELSE IF (desc.EQ.6001 .AND. longitude.EQ.rvind) THEN ! Longitude (high accuracy)
            longitude = value
         ELSE IF (desc.EQ.6002 .AND. longitude.EQ.rvind) THEN ! Longitude (coarse accuracy)
            longitude = value
         ELSE IF (desc.EQ.7001) THEN  ! Height of station
            IF (height.EQ.rvind) THEN
               height = value
            END IF
         ELSE IF (desc.EQ.7007) THEN ! Height
            n = n + 1           ! new level
            IF (n.GT.maxlevel) THEN
               n = maxlevel
               WRITE(*,*) 'Too many levels! Skipping rest of message'
               GOTO 110
            END IF
            HH(n) = value
C     All following descriptors come after 7007 height
         ELSE IF (n.GT.0 .AND. n.LE.maxlevel) THEN
            IF (desc.EQ.11001) THEN ! Wind direction
               D(n) = value
            ELSE IF (desc.EQ.11002) THEN ! Wind speed
               F(n) = value
            ELSE IF (desc.EQ.11006) THEN ! W-component
               WC(n) = value
            ELSE IF (desc.EQ.33002) THEN ! Quality information, included 2 times per level
               IF (ktdexp(idx-1).EQ.11002) THEN
                  Q1(n) = value
               ELSE
                  Q2(n) = value
               END IF
            END IF
         END IF
      END DO
 110  CONTINUE
      numlevels = n
 
      IF (rectangle) THEN
         IF (longitude.EQ.rvind .OR. latitude.EQ.rvind
     +        .OR. longitude.LT.x1 .OR. longitude.GT.x2
     +        .OR. latitude.LT.y1 .OR. latitude.GT.y2) RETURN
      END IF
 
      IF (II.NE.rvind .AND. iii.NE.rvind) THEN
         WRITE(*,*)
         WRITE(*,'(A,I5.5)') 'wmonr=',NINT(II)*1000 + NINT(iii)
      ELSE IF (call_sign.NE.missing9) THEN
         WRITE(*,*)
         WRITE(*,'(A,A)') 'call_sign=',call_sign(1:lenstr(call_sign,1))
      ELSE
         IF (verbose .GT. 1) THEN
            WRITE(*,*)
            WRITE(*,*) 'Both wmonr and call sign are missing!!!'
         END IF
         RETURN
      END IF
 
      IF (year.NE.rvind.AND.month.NE.rvind.AND.day.NE.rvind
     +     .AND.hour.NE.rvind.AND.minute.NE.rvind) THEN
         WRITE(*,900),NINT(year),NINT(month),NINT(day),
     +        NINT(hour),NINT(minute)
 900     FORMAT('obstime=',I4,'-',I2.2,'-',I2.2,' ',I2.2,':',I2.2,':00')
      ELSE
         IF (verbose .GT. 1) THEN
            WRITE(*,*) 'obstime is missing!!!'
            RETURN
         END IF
      ENDIF
      IF (ix.NE.rvind) THEN
         IF (NINT(ix).EQ.0) THEN
            WRITE(*,'(A,A)') 'type=Automatic'
         ELSE IF (NINT(ix).EQ.1) THEN
            WRITE(*,'(A,A)') 'type=Manned'
         ELSE IF (NINT(ix).EQ.2) THEN
            WRITE(*,'(A,A)') 'type=Hybrid'
         END IF
      END IF
      IF (latitude.NE.rvind) THEN
         WRITE(*,'(A,F10.5)') 'lat=',latitude
      END IF
      IF (longitude.NE.rvind) THEN
         WRITE(*,'(A,F10.5)') 'lon=',longitude
      END IF
      IF (height.NE.rvind) THEN
         WRITE(*,'(A,I7)') 'height=',NINT(height)
      END IF
 
      DO n=1,numlevels
         WRITE(*,'(A,I12)'),'n=',n
         IF (HH(n).NE.rvind) THEN
            WRITE(*,'(A,F11.1)') 'HH=',HH(n) ! m
         END IF
         IF (D(n).NE.rvind) THEN
            WRITE(*,'(A,I11)') 'DD=',NINT(D(n))
         END IF
         IF (F(n).NE.rvind) THEN
            WRITE(*,'(A,F11.1)') 'FF=',F(n)
         END IF
         IF (Q1(n).NE.rvind) THEN
            WRITE(*,'(A,I11)') 'Q1=',NINT(Q1(n))
         END IF
         IF (WC(n).NE.rvind) THEN
            WRITE(*,'(A,I11)') 'WC=',NINT(WC(n))
         END IF
         IF (Q2(n).NE.rvind) THEN
            WRITE(*,'(A,I11)') 'Q2=',NINT(Q2(n))
         END IF
      END DO
 
      END SUBROUTINE print_radar_profiler_values
 
C     -----------------------------------------------------------------
 
      SUBROUTINE print_surface_values(ksub,kxelem,ktdexl,ktdexp,values,
     +     cvals,rectangle,metar,verbose)
C     Identify pressure, temperature etc and print parameter=value to screen
      IMPLICIT NONE
 
      INTEGER ksub              ! Input: number of subset currently processed
      INTEGER kxelem            ! Input: expected (max) number of expanded elements
      INTEGER ktdexl            ! Input: number of entries in list of expanded data descriptors
      INTEGER ktdexp(*)         ! Input: array containing expanded data descriptors
      REAL*8 values(*)          ! Input: expanded data values (one subset)
      CHARACTER*80 cvals(*)     ! Input: CCITTIA5 Bufr elements entries (one subset)
      LOGICAL rectangle         ! Input: TRUE if observations are wanted for a rectangle only
      LOGICAL metar             ! Input: TRUE if metar (data subcategory 5)
      INTEGER verbose           ! Input: verbose level
 
      REAL*8 rvind              ! missing value for real*8 data
      PARAMETER (rvind=1.7E38)
 
      CHARACTER*5 wigos_issuer,wigos_issueno,missing5
      CHARACTER*8 icao_id,missing8
      CHARACTER*9 call_sign,missing9
      CHARACTER*16 wigos_localid,missing16
      CHARACTER*20 name,missing20
      CHARACTER*32 long_name,missing32
C     Parameters defined in Kvalobs
      REAL*8 AA,BI,CH,CI,CL,CM,DD,DG,DG_010,DG_1,DG_X,DI,DW1,DW2,
     +     EE,ES,EV_1,EV_24,FF,FG,FG_010,FG_1,FG_X,FX,FX_1,FX_X,HL,
     +     HW,HW1,HW2,HWA,NH,NN,OT_1,OT_24,PH,PO,PP,PR,PW,PW1,PW2,PWA,
     +     QD,QE,QK,QL,QO,QS,QD_24,QE_24,QK_24,QL_24,QO_24,QS_24,
     +     RR_1,RR_3,RR_6,RR_12,RR_24,RS,SA,SG,SI,SS_24,
     +     TA,TAN_12,TAX_12,TAN,TAX,TD,TGN_12,TW,UU,VV,W1,W2,WW,XIS,ZI,
C     Other parameters
     +     year,month,day,hour,minute,a3,buoy_id5,buoy_id7,ds,
     +     height,hhh,hp,hour_p,II,iii,ix,latitude,longitude,
     +     minute_p,TbTbTb,vert_sign_first,vs,wmo_region_number,
     +     wmo_region_subarea,state_id,national_number,
     +     wigos_series
      REAL*8 vert_sign(4),CC(4),HS(4),NS(4)
      INTEGER idx,cidx
      INTEGER cloud_type_count  ! Will be increased by one for each 020012
                                ! (cloud type) encountered (0 initially).
                                ! Not used for metar
      INTEGER num_cloud_layers  ! Number of individual cloud layers, set
                                ! to value of 031001 (delayed descriptor
                                ! replication factor) if this is met immediately
                                ! after a 020012 descriptor (-1 initially).
                                ! For metar num_cloud_layers is increased
                                ! by one for each new 020011
      LOGICAL bad_cloud_data    ! Set to true if something serious wrong is
                                ! found in cloud data. No more cloud
                                ! data will then be attempted decoded.
      INTEGER cloud_layer       ! Numbers the individual cloud layers
      LOGICAL surface_data      ! Set to false if 007062 ('Depth below sea/water
                                ! surface') is encountered with a value different
                                ! from 0
      LOGICAL time_of_last_position ! Set to true if 008021 time significance is
                                    ! included with value 26
      CHARACTER one_bits
      REAL*8 value
      INTEGER desc,i,mm,hh,ind,ind2,ind3
      INTEGER degree2dir,NNtoWMO_N
 
C     Variables used for geographical filtering av observations
C     (--rectangle option set)
      REAL*8 x1,y1,x2,y2
      COMMON /COM_RECTANGLE/  x1,y1,x2,y2
 
C     Functions
      CHARACTER*32 ctrim ! length must be >= longest variable ctrim is used for
      INTEGER lenstr
 
      one_bits = CHAR(255)
      WRITE(missing5,'(5A)') one_bits,one_bits,one_bits,one_bits,
     +     one_bits
      WRITE(missing8,'(8A)') one_bits,one_bits,one_bits,one_bits,
     +     one_bits,one_bits,one_bits,one_bits
      missing9 = missing8 // one_bits
      missing16 = missing8 // missing8
      missing20 = missing9 // missing9 // one_bits // one_bits
      missing32 = missing16 // missing16
 
      cloud_type_count = 0
      bad_cloud_data = .FALSE.
      num_cloud_layers = -1
      surface_data = .TRUE.
      time_of_last_position = .FALSE.
 
C     Initialize all parameters to missing values
      hour_p = rvind
      minute_p = rvind
      icao_id = missing8
      call_sign = missing9
      wigos_issuer = missing5
      wigos_issueno = missing5
      wigos_localid = missing16
      name = missing20
      long_name = missing32
      AA = rvind
      BI = rvind
      CH = rvind
      CI = rvind
      CL = rvind
      CM = rvind
      DD = rvind
      DG = rvind
      DG_010 = rvind
      DG_1 = rvind
      DG_X = rvind
      DI = rvind
      DW1 = rvind
      DW2 = rvind
      EE = rvind
      ES = rvind
      EV_1 = rvind
      EV_24 = rvind
      FF = rvind
      FG = rvind
      FG_010 = rvind
      FG_1 = rvind
      FG_X = rvind
      FX = rvind
      FX_1 = rvind
      FX_X = rvind
      HL = rvind
      HW = rvind
      HW1 = rvind
      HW2 = rvind
      HWA = rvind
      NH = rvind
      NN = rvind
      PO = rvind
      OT_1 = rvind
      OT_24 = rvind
      PH = rvind
      PP = rvind
      PR = rvind
      PR = rvind
      PW = rvind
      PW1 = rvind
      PW2 = rvind
      PWA = rvind
      QD = rvind
      QE = rvind
      QK = rvind
      QL = rvind
      QO = rvind
      QS = rvind
      QD_24 = rvind
      QE_24 = rvind
      QK_24 = rvind
      QL_24 = rvind
      QO_24 = rvind
      QS_24 = rvind
      RR_1 = rvind
      RR_3 = rvind
      RR_6 = rvind
      RR_12 = rvind
      RR_24 = rvind
      RS = rvind
      SA = rvind
      SG = rvind
      SI = rvind
      SS_24 = rvind
      TA = rvind
      TAN_12 = rvind
      TAX_12 = rvind
      TAN = rvind
      TAX = rvind
      TD = rvind
      TGN_12 = rvind
      TW = rvind
      UU = rvind
      VV = rvind
      W1 = rvind
      W2 = rvind
      WW = rvind
      XIS = rvind
      ZI = rvind
      year = rvind
      month = rvind
      day = rvind
      hour = rvind
      minute = rvind
      latitude = rvind
      longitude = rvind
      height = rvind
      hp = rvind
      vert_sign_first = rvind
      II = rvind
      iii = rvind
      ix = rvind
      a3 = rvind
      hhh = rvind
      ds = rvind
      vs = rvind
      TbTbTb = rvind
      buoy_id5 = rvind
      buoy_id7 = rvind
      wmo_region_number = rvind
      wmo_region_subarea = rvind
      state_id = rvind
      national_number = rvind
      wigos_series = rvind
 
      DO i=1,4
         vert_sign(i) = rvind
         CC(i) = rvind
         HS(i) = rvind
         NS(i) = rvind
      END DO
 
C     Loop through all expanded descriptors
      DO idx=1,ktdexl
         desc = ktdexp(idx)
         value = values(idx + (ksub-1)*kxelem)
 
         IF (ABS(value - rvind)/rvind.LE.0.001) THEN
C     Missing value. Only a few descriptors require a reset of
C     corresponding parameter in this case. Note that the missing value
C     returned from libbufr might not be exactly equal to rvind
            IF (desc.EQ.4024) THEN ! Time period or displacement [hour]
               hour_p = rvind
            ELSE IF (desc.EQ.4025) THEN ! Time period or displacement [minute]
               minute_p = rvind
C     Delayed descriptor replication factor should never be missing
            ELSE IF (desc.EQ.31001) THEN
               IF (idx.GT.1 .AND. ktdexp(idx - 1).EQ.20012) THEN
                  WRITE(*,*) 'WARNING: delayed descriptor replication'
     +                 // ' factor after 020012 undefined!!!'
                  bad_cloud_data = .TRUE.
               ELSE
                  WRITE(*,*) 'WARNING: delayed descriptor replication'
     +                 // ' factor 31001 undefined!!!'
               END IF
C     Some counting needed for clouds even for missing values
            ELSE IF (desc.EQ.20012 .AND. .NOT.bad_cloud_data) THEN ! Cloud type
               cloud_type_count = cloud_type_count + 1
               IF (cloud_type_count.GT.3) THEN
                  cloud_layer = cloud_type_count - 3
               END IF
            END IF
            CYCLE
         END IF
 
C     Continue the loop for non-missing value. For most variables we
C     choose to not set the parameter if set before, because if a
C     descriptor unexpectedly occurs more than once it is likely that
C     the first occurrence is the 'standard' use of the descriptor,
C     while the later occurrence(s) might for example be due to data
C     required by regional or national reporting practices, added after
C     a standard WMO template
         IF (desc.EQ.4024) THEN ! Time period or displacement [hour]
            hour_p = value
         ELSE IF (desc.EQ.4025) THEN ! Time period or displacement [minute]
            minute_p = value
         ELSE IF (desc.EQ.8021) THEN ! Time significance
            IF (NINT(value).EQ.26) THEN
               time_of_last_position = .TRUE.
            ELSE
               time_of_last_position = .FALSE.
            END IF
         ELSE IF (desc.EQ.1001 .AND. II.EQ.rvind) THEN ! WMO block number
            IF (value.GE.0 .AND. value.LT.100) II = value
         ELSE IF (desc.EQ.1002 .AND. iii.EQ.rvind) THEN ! WMO station number
            IF (value.GE.0 .AND. value.LT.1000) iii = value
         ELSE IF (desc.EQ.1101 .AND. state_id.EQ.rvind) THEN ! WMO member state identifier
            IF (value.GE.0 .AND. value.LT.1000) state_id = value
         ELSE IF (desc.EQ.1102 .AND. national_number.EQ.rvind) THEN ! National station number
            IF (value.GE.0) national_number = value
         ELSE IF (desc.EQ.1015) THEN  ! Station or site name
            cidx = int(value/1000)
            name = cvals(cidx)  ! CCITTIA5 data
            name = ctrim(name,20,missing20)
         ELSE IF (desc.EQ.1019) THEN  ! Long station or site name
            cidx = int(value/1000)
            long_name = cvals(cidx) ! CCITTIA5 data
            long_name = ctrim(long_name,32,missing32)
         ELSE IF (desc.EQ.1125) THEN ! WIGOS identifier series
            wigos_series = value
         ELSE IF (desc.EQ.1126) THEN ! WIGOS issuer of identifier
            i = NINT(value)
            WRITE(wigos_issuer,'(I5)') i
            wigos_issuer = ADJUSTL(wigos_issuer)
         ELSE IF (desc.EQ.1127) THEN ! WIGOS issue number
            i = NINT(value)
            WRITE(wigos_issueno,'(I5)') i
            wigos_issueno = ADJUSTL(wigos_issueno)
         ELSE IF (desc.EQ.1128) THEN  ! WIGOS local identifier
            cidx = int(value/1000)
            wigos_localid = cvals(cidx) ! CCITTIA5 data
            wigos_localid = ctrim(wigos_localid,16,missing16)
         ELSE IF (desc.EQ.2001) THEN ! Type of station
            IF (ix.EQ.rvind) THEN
               ix = value
            END IF
         ELSE IF (desc.EQ.4001) THEN ! Year
            IF (year.EQ.rvind.AND..NOT.time_of_last_position) THEN
               year = value
            END IF
         ELSE IF (desc.EQ.4002) THEN ! Month
            IF (month.EQ.rvind.AND..NOT.time_of_last_position) THEN
               month = value
            END IF
         ELSE IF (desc.EQ.4003) THEN ! Day
            IF (day.EQ.rvind.AND..NOT.time_of_last_position) THEN
               day = value
            END IF
         ELSE IF (desc.EQ.4004) THEN ! Hour
            IF (hour.EQ.rvind.AND..NOT.time_of_last_position) THEN
               hour = value
            END IF
         ELSE IF (desc.EQ.4005) THEN ! Minute
            IF (minute.EQ.rvind.AND..NOT.time_of_last_position) THEN
               minute = value
            END IF
         ELSE IF (desc.EQ.5001.OR.  ! Latitude (high accuracy)
     +           desc.EQ.5002) THEN ! Latitude (coarse accuracy)
            IF (latitude.EQ.rvind) THEN
               latitude = value
            END IF
         ELSE IF (desc.EQ.6001.OR.  ! Longitude (high accuracy)
     +           desc.EQ.6002) THEN ! Longitude (coarse accuracy)
            IF (longitude.EQ.rvind) THEN
               longitude = value
            END IF
         ELSE IF (desc.EQ.7001.OR.  ! Height of station
     +           desc.EQ.7030) THEN ! Height of station ground above mean sea level
            IF (height.EQ.rvind) THEN
               height = value
            END IF
         ELSE IF (desc.EQ.7031) THEN ! Hp
            IF (hp.EQ.rvind) THEN
               hp = value
            END IF
         ELSE IF (desc.EQ.10004) THEN ! Pressure
            IF (PO.EQ.rvind) THEN
               PO = value
            END IF
         ELSE IF (desc.EQ.10051) THEN ! Pressure reduced to mean sea level
            IF (PR.EQ.rvind) THEN
               PR = value
            END IF
         ELSE IF (desc.EQ.10061) THEN ! 3-hour pressure change
            IF (PP.EQ.rvind) THEN
               PP = value
            END IF
         ELSE IF (desc.EQ.10063) THEN ! Characteristic of pressure tendency
            IF (AA.EQ.rvind) THEN
               AA = value
            END IF
         ELSE IF (desc.EQ.11011.OR.  ! Wind direction at 10 m
     +           desc.EQ.11001) THEN ! Wind direction
            IF (DD.EQ.rvind) THEN
               DD = value
            END IF
         ELSE IF (desc.EQ.11012.OR.  ! Wind speed at 10 m
     +           desc.EQ.11002) THEN ! Wind speed
            IF (FF.EQ.rvind) THEN
               FF = value
            END IF
         ELSE IF (desc.EQ.11043) THEN ! Maximum wind gust direction
C     DG is treated same way as FG
            IF (minute_p.NE.rvind .AND. hour.NE.rvind) THEN
               mm = NINT(minute_p)
               hh = NINT(hour)
               IF (mm.EQ.-10) THEN
                  IF (DG_010.EQ.rvind) DG_010 = value
               ELSE IF (mm.GE.-70 .AND. mm.LE.-50) THEN
                  IF (DG_1.EQ.rvind) DG_1 = value
               ELSE IF (mm.EQ.-360 .AND. MOD(hh,6).EQ.0) THEN
                  IF (DG.EQ.rvind) DG = value
               ELSE IF (mm.EQ.-180 .AND. MOD(hh,3).EQ.0
     +                 .AND. MOD(hh,6).NE.0) THEN
                  IF (DG.EQ.rvind) DG = value
               ELSE
C     Actually DG_X is not defined in Kvalobs (but FG_X is!)
                  IF (DG_X.EQ.rvind) DG_X = value
               END IF
            END IF
         ELSE IF (desc.EQ.11041) THEN ! Maximum wind gust speed
            IF (minute_p.NE.rvind .AND. hour.NE.rvind) THEN
               mm = NINT(minute_p)
               hh = NINT(hour)
               IF (mm.EQ.-10) THEN
                  IF (FG_010.EQ.rvind) FG_010 = value
               ELSE IF (mm.GE.-70 .AND. mm.LE.-50) THEN
                  IF (FG_1.EQ.rvind) FG_1 = value
C     For time periods > 1 hour, we choose to decode this as FG for
C     termins 0,6,12,18 if time period is 6 hours, and for termins
C     3,9,15,21 if time period is 3 hours. FG is defined as max wind
C     gust since last synoptic termin (0,6,12,18) and it is unlikely to
C     be reported for other termins than 0,3,6,9...
               ELSE IF (mm.EQ.-360 .AND. MOD(hh,6).EQ.0) THEN
                  IF (FG.EQ.rvind) FG = value
               ELSE IF (mm.EQ.-180 .AND. MOD(hh,3).EQ.0
     +                 .AND. MOD(hh,6).NE.0) THEN
                  IF (FG.EQ.rvind) FG = value
               ELSE
C     All other periods are put in FG_X (arbitrary period)
                  IF (FG_X.EQ.rvind) FG_X = value
               END IF
            END IF
         ELSE IF (desc.EQ.11042) THEN ! Maximum wind speed (10-min mean wind)
            IF (minute_p.NE.rvind .AND. hour.NE.rvind) THEN
C     FX is "Vindhastighet, maks. 10 minutt glidende middel siden
C     forrige hovedobservasjon, m/s". Assume this is reported for
C     termins 0,3,6,9... only
               mm = NINT(minute_p)
               hh = NINT(hour)
               IF ((mm.EQ.-360 .AND. MOD(hh,6).EQ.0)
     +              .OR. (mm.EQ.-180 .AND. MOD(hh,3).EQ.0
     +              .AND. MOD(hh,6).NE.0) .AND. FX.EQ.rvind) THEN
                  IF (FX.EQ.rvind) FX = value
               ELSE IF (mm.GE.-70 .AND. mm.LE.-50) THEN
                  IF (FX_1.EQ.rvind) FX_1 = value
               ELSE
C     All other periods are put in FX_X (arbitrary period)
                  IF (FX_X.EQ.rvind) FX_X = value
               END IF
            END IF
         ELSE IF (desc.EQ.12104.OR. ! Dry bulb temperature at 2m (data width 16 bits)
     +          desc.EQ.12004.OR.   ! Dry bulb temperature at 2m (12 bits)
     +          desc.EQ.12101.OR.   ! Temperature/dry bulb temperature (16 bits)
     +          desc.EQ.12001) THEN ! Temperature/dry bulb temperature (12 bits)
            IF (TA.EQ.rvind) THEN
               TA = value
            END IF
         ELSE IF (desc.EQ.12106.OR.  ! Dew-point temperature at 2m (16 bits)
     +           desc.EQ.12006.OR.   ! Dew-point temperature at 2m (12 bits)
     +           desc.EQ.12103.OR.   ! Dew-point temperature (16 bits)
     +           desc.EQ.12003) THEN ! Dew-point temperature (12 bits)
            IF (TD.EQ.rvind) THEN
               TD = value
            END IF
         ELSE IF (desc.EQ.12113.OR.  ! Ground minimum temperature at 2m (data width 16 bits)
     +           desc.EQ.12013) THEN ! Ground minimum temperature at 2m (12 bits)
            IF (TGN_12.EQ.rvind) THEN
               TGN_12 = value
            END IF
         ELSE IF (desc.EQ.12114.OR.  ! Maximum temperature at 2m, past 12 hours (16 bits)
     +           desc.EQ.12014) THEN ! Maximum temperature at 2m, past 12 hours (12 bits)
            IF (TAX_12.EQ.rvind) THEN
               TAX_12 = value
            END IF
         ELSE IF (desc.EQ.12111) THEN ! Maximum temperature at height and over period specified
            IF (TAX_12.EQ.rvind .AND. idx.GT.2
     +           .AND. ktdexp(idx-1).EQ.4024
     +           .AND. NINT(values(idx-1 + (ksub-1)*kxelem)).EQ.0
     +           .AND. ktdexp(idx-2).EQ.4024) THEN
               IF (NINT(values(idx-2 + (ksub-1)*kxelem)).EQ.-12) THEN
                  IF (TAX_12.EQ.rvind) TAX_12 = value
               ELSE IF (NINT(values(idx-2 + (ksub-1)*kxelem)).EQ.-1)THEN
                  IF (TAX.EQ.rvind) TAX = value
               END IF
            END IF
C     Do we also need to consider 12021 'Maximum temperature at 2m'?
         ELSE IF (desc.EQ.12115.OR.  ! Minimum temperature at 2m, past 12 hours (16 bits)
     +           desc.EQ.12015) THEN ! Minimum temperature at 2m, past 12 hours (12 bits)
            IF (TAN_12.EQ.rvind) THEN
               TAN_12 = value
            END IF
         ELSE IF (desc.EQ.12112) THEN ! Minimum temperature at height and over period specified
            IF (TAN_12.EQ.rvind .AND. idx.GT.2
     +           .AND. ktdexp(idx-1).EQ.4024
     +           .AND. values(idx-1 + (ksub-1)*kxelem).EQ.0
     +           .AND. ktdexp(idx-2).EQ.4024) THEN
               IF (NINT(values(idx-2 + (ksub-1)*kxelem)).EQ.-12) THEN
                  IF (TAN_12.EQ.rvind) TAN_12 = value
               ELSE IF (NINT(values(idx-2 + (ksub-1)*kxelem)).EQ.-1)THEN
                  IF (TAN.EQ.rvind) TAN = value
               END IF
            END IF
C     Do we also need to consider 12022 'Minimum temperature at 2m'?
         ELSE IF (desc.EQ.13003) THEN ! Relative humidity
            IF (UU.EQ.rvind) THEN
               UU = value
            END IF
         ELSE IF (desc.EQ.20001) THEN ! Horizontal visibility
            IF (VV.EQ.rvind) THEN
               VV = value
            END IF
         ELSE IF (desc.EQ.20003) THEN ! Present weather
            IF (WW.EQ.rvind) THEN
               WW = value
            END IF
         ELSE IF (desc.EQ.20004) THEN ! Past weather (1)
            IF (W1.EQ.rvind) THEN
               W1 = value
            END IF
         ELSE IF (desc.EQ.20005) THEN ! Past weather (2)
            IF (W2.EQ.rvind) THEN
               W2 = value
            END IF
         ELSE IF (desc.EQ.20010) THEN ! Cloud cover (total)
            IF (NN.EQ.rvind) THEN
               NN = value
            END IF
         ELSE IF (desc.EQ.31001) THEN
C     Delayed descriptor replication factor; this should be
C     number of cloud layers if previous descriptor is cloud
C     type, according to all WMO recommended templates
C     (but DNMI metar is an exception!)
            IF (ktdexp(idx - 1).EQ.20012) THEN
               IF (NINT(value).LE.4) THEN
                  num_cloud_layers = NINT(value)
               ELSE
                  bad_cloud_data = .TRUE.
               END IF
            END IF
         ELSE IF (desc.EQ.8002 .AND. .NOT.bad_cloud_data) THEN ! Vertical significance (surface observations)
            IF (cloud_type_count.EQ.0) THEN ! First occurrence
               IF (vert_sign_first.EQ.rvind) THEN
                  vert_sign_first = value
               END IF
            ELSE IF (cloud_type_count.LT.3) THEN
               bad_cloud_data = .TRUE. ! There should always be three 020012
                                       ! following first 008002
            ELSE IF (num_cloud_layers.GT.-1) THEN
               cloud_layer = cloud_type_count - 2
               IF (cloud_layer.LE.num_cloud_layers) THEN
                  vert_sign(cloud_layer) = value
               END IF
            ELSE                ! rdb-files always have 0 or 4 cloud layers
               cloud_layer = cloud_type_count - 2
               IF (cloud_layer.LT.5) THEN
                  vert_sign(cloud_layer) = value
               END IF
            END IF
         ELSE IF (desc.EQ.20011 .AND. .NOT.bad_cloud_data) THEN ! Cloud amount
            IF (metar) THEN
               IF (num_cloud_layers.GT.-1) THEN
                  num_cloud_layers = num_cloud_layers + 1
               ELSE
                  num_cloud_layers = 1
               END IF
               NS(num_cloud_layers) = value
            ELSE IF (cloud_type_count.EQ.0) THEN ! First occurrence
               IF (NH.EQ.rvind) THEN
                  NH = value
               END IF
            ELSE IF (cloud_type_count.LT.3) THEN
               bad_cloud_data = .TRUE. ! There should always be three 020012
                                       ! following first 008002
            ELSE IF (num_cloud_layers.GT.-1) THEN
               cloud_layer = cloud_type_count - 2
               IF (cloud_layer.LE.num_cloud_layers) THEN
                  NS(cloud_layer) = value
               END IF
            ELSE                ! rdb-files always have 0 or 4 cloud layers
               cloud_layer = cloud_type_count - 2
               IF (cloud_layer.LT.5) THEN
                  NS(cloud_layer) = value
               END IF
            END IF
         ELSE IF (desc.EQ.20012 .AND. .NOT.bad_cloud_data) THEN ! Cloud type
            IF (metar) THEN
               CC(num_cloud_layers) = value
            ELSE   
               cloud_type_count = cloud_type_count + 1
               IF (cloud_type_count.GT.3) THEN
                  cloud_layer = cloud_type_count - 3
                  IF (num_cloud_layers .GT.-1) THEN
                     IF (value < 10.0 ! Accept one digit values only
     +                    .AND. cloud_layer.LE.num_cloud_layers) THEN
                        CC(cloud_layer) = value
                     END IF
                  ELSE IF (cloud_layer.LT.5) THEN ! rdb-files always have 0 or 4 cloud layers
                     CC(cloud_layer) = value
                  END IF
               ELSE
                  IF (cloud_type_count.EQ.1) THEN
                     IF (CL.EQ.rvind) THEN
                        CL = value
                     END IF
                  ELSE IF (cloud_type_count.EQ.2) THEN
                     IF (CM.EQ.rvind) THEN
                        CM = value
                     END IF
                  ELSE IF (cloud_type_count.EQ.3) THEN
                     IF (CH.EQ.rvind) THEN
                        CH = value
                     END IF
                  END IF
               END IF
            END IF
         ELSE IF (desc.EQ.20013 .AND. .NOT.bad_cloud_data) THEN ! Height of base of cloud
            IF (metar) THEN
               HS(num_cloud_layers) = value
            ELSE IF (cloud_type_count.EQ.0) THEN ! First occurrence
               IF (HL.EQ.rvind) THEN
                  HL = value
               END IF
C     Note that 020013 in individual cloud layers comes
C     AFTER 020012 and therefore must be treated
C     differently than 008002 and 020011
            ELSE IF (cloud_type_count.LT.4) THEN
               bad_cloud_data = .TRUE. ! There should always be three 020012
                                       ! following first 008002
            ELSE IF (num_cloud_layers.GT.-1) THEN
               cloud_layer = cloud_type_count - 3
               IF (cloud_layer.LE.num_cloud_layers) THEN
                  HS(cloud_layer) = value
               END IF
            ELSE ! rdb-files always have 0 or 4 cloud layers
               cloud_layer = cloud_type_count - 3
               IF (cloud_layer.LT.5) THEN
                  HS(cloud_layer) = value
               END IF
            END IF
         ELSE IF (desc.EQ.13023) THEN ! Total precipitation past 24 hours
            IF (RR_24.EQ.rvind) THEN
               RR_24 = value
            END IF
         ELSE IF (desc.EQ.13022) THEN ! Total precipitation past 12 hours
            IF (RR_12.EQ.rvind) THEN
               RR_12 = value
            END IF
         ELSE IF (desc.EQ.13021) THEN ! Total precipitation past 6 hours
            IF (RR_6.EQ.rvind) THEN
               RR_6 = value
            END IF
         ELSE IF (desc.EQ.13020) THEN ! Total precipitation past 3 hours
            IF (RR_3.EQ.rvind) THEN
               RR_3 = value
            END IF
         ELSE IF (desc.EQ.13019) THEN ! Total precipitation past 1 hour
            IF (RR_1.EQ.rvind) THEN
               RR_1 = value
            END IF
         ELSE IF (desc.EQ.13011) THEN ! Total precipitation/total water equivalent
            IF (hour_p.NE.rvind) THEN
               hh = NINT(hour_p)
               IF (hh.EQ.-24) THEN
                  RR_24 = value
               ELSE IF (hh.EQ.-12) THEN
                  RR_12 = value
               ELSE IF (hh.EQ.-6) THEN
                  RR_6 = value
               ELSE IF (hh.EQ.-3) THEN
                  RR_3 = value
               ELSE IF (hh.EQ.-1) THEN
                  RR_1 = value
               END IF
            END IF
         ELSE IF (desc.EQ.13013) THEN ! Total snow depth
C     Don't check for SA.EQ.rvind, because SA might earlier have been set to 0 if
C     EE < 10, which probably means that 20062 has been wrongly encoded, not 13013
            SA = value
         ELSE IF (desc.EQ.20062) THEN ! State of the ground (with or without snow)
            IF (EE.EQ.rvind) THEN
               EE = value
            END IF
            IF (NINT(value).LE.10 .AND. SA.EQ.rvind) THEN
               SA = 0
            END IF
C     Equating 013012 with SS_24 is dubious generally, but this is how
C     SS_24 is encoded in kvalobs for Norwegian avalanche stations (and
C     we have no better kvalobs parameter for depth of fresh snow anyway)
         ELSE IF (desc.EQ.13012) THEN ! Depth of fresh snow
            IF (SS_24.EQ.rvind) THEN
               SS_24 = value
            END IF
         ELSE IF (desc.EQ.14031) THEN ! Total sunshine
            IF (hour_p.NE.rvind) THEN
               hh = NINT(hour_p)
               IF (hh.EQ.-1) THEN
                  OT_1 = value
               ELSE IF (hh.EQ.-24) THEN
                  OT_24 = value
               END IF
            END IF
         ELSE IF (desc.EQ.13033) THEN ! Evaporation/evapotranspiration
            IF (hour_p.NE.rvind) THEN
               hh = NINT(hour_p)
               IF (hh.EQ.-1) THEN
                  EV_1 = value
               ELSE IF (hh.EQ.-24) THEN
                  EV_24 = value
               END IF
            END IF
         ELSE IF (desc.EQ.14002) THEN ! Long-wave radiation
            IF (hour_p.NE.rvind) THEN
               hh = NINT(hour_p)
               IF (hh.EQ.-1) THEN
                  QL = value
               ELSE IF (hh.EQ.-24) THEN
                  QL_24 = value
               END IF
            END IF
         ELSE IF (desc.EQ.14004) THEN ! Short-wave radiation
            IF (hour_p.NE.rvind) THEN
               hh = NINT(hour_p)
               IF (hh.EQ.-1) THEN
                  QK = value
               ELSE IF (hh.EQ.-24) THEN
                  QK_24 = value
               END IF
            END IF
         ELSE IF (desc.EQ.14016) THEN ! Net radiation
            IF (hour_p.NE.rvind) THEN
               hh = NINT(hour_p)
               IF (hh.EQ.-1) THEN
                  QE = value
               ELSE IF (hh.EQ.-24) THEN
                  QE_24 = value
               END IF
            END IF
         ELSE IF (desc.EQ.14028) THEN ! Global solar radiation
            IF (hour_p.NE.rvind) THEN
               hh = NINT(hour_p)
               IF (hh.EQ.-1) THEN
                  QO = value
               ELSE IF (hh.EQ.-24) THEN
                  QO_24 = value
               END IF
            END IF
         ELSE IF (desc.EQ.14029) THEN ! Diffuse solar radiation
            IF (hour_p.NE.rvind) THEN
               hh = NINT(hour_p)
               IF (hh.EQ.-1) THEN
                  QD = value
               ELSE IF (hh.EQ.-24) THEN
                  QD_24 = value
               END IF
            END IF
         ELSE IF (desc.EQ.14030) THEN ! Direct solar radiation
            IF (hour_p.NE.rvind) THEN
               hh = NINT(hour_p)
               IF (hh.EQ.-1) THEN
                  QS = value
               ELSE IF (hh.EQ.-24) THEN
                  QS_24 = value
               END IF
            END IF
C     Special for high altitude stations
         ELSE IF (desc.EQ.7004) THEN ! Pressure (location class)
            IF (a3.EQ.rvind) THEN
               a3 = value
            END IF
         ELSE IF (desc.EQ.10009) THEN ! Geopotential height
            IF (hhh.EQ.rvind) THEN
               hhh = value
            END IF
C     Special for ship or marine stations
         ELSE IF (desc.EQ.1011) THEN  ! Ship or mobile land station identifier
            cidx = int(value/1000)
            IF (cidx.GT.0) THEN
               call_sign = cvals(cidx) ! CCITTIA5 data
               call_sign = ctrim(call_sign,9,missing9)
            END IF
         ELSE IF (desc.EQ.1012) THEN ! Direction of motion of moving observing platform
            IF (ds.EQ.rvind) THEN
               ds = value
            END IF
         ELSE IF (desc.EQ.1013) THEN ! Speed of motion of moving observing platform
            IF (vs.EQ.rvind) THEN
               vs = value
            END IF
         ELSE IF (desc.EQ.7062) THEN ! Depth below sea/water surface
C     Some buoy reports starts with depth 1.5 m, others starts with 0 m
C     then 1.5 m and always have same sea/water temperature for these 2
C     levels, so it seems like 0 m should be considered equivalent with 1.5 m
            IF (value.LT.1.6) THEN
               surface_data = .TRUE.
            ELSE
               surface_data = .FALSE.
            END IF
         ELSE IF (desc.EQ.22043.OR.  ! Sea/water temperature (15 bits)
     +           desc.EQ.22042.OR.   ! Sea/water temperature (12 bits)
     +           desc.EQ.22049) THEN ! Sea-surface temperature (15 bits)
            IF (TW.EQ.rvind .AND. surface_data)THEN
               TW = value
            END IF
         ELSE IF (desc.EQ.12102.OR.  ! Wet-bulb temperature (16 bits)
     +           desc.EQ.12005) THEN ! Wet-bulb temperature (12 bits)
            IF (TbTbTb.EQ.rvind) THEN
               TbTbTb = value
            END IF
         ELSE IF (desc.EQ.22011) THEN !  Period of waves (instrumentally measured)
            IF (PWA.EQ.rvind) THEN
               PWA = value
            END IF
         ELSE IF (desc.EQ.22012) THEN !  Period of wind waves (visually measured)
            IF (PW.EQ.rvind) THEN
               PW = value
            END IF
         ELSE IF (desc.EQ.22021) THEN ! Heigth of waves
            IF (HWA.EQ.rvind) THEN
               HWA = value
            END IF
         ELSE IF (desc.EQ.22022) THEN ! Heigth of wind waves
            IF (HW.EQ.rvind) THEN
               HW = value
            END IF
         ELSE IF (desc.EQ.22003) THEN ! Direction of swell waves
            IF (DW1.EQ.rvind) THEN
               DW1 = value
            ELSE
               DW2 = value
            END IF
         ELSE IF (desc.EQ.22013) THEN ! Period of swell waves
            IF (PW1.EQ.rvind) THEN
               PW1 = value
            ELSE
               PW2 = value
            END IF
         ELSE IF (desc.EQ.22023) THEN ! Height of swell waves
            IF (HW1.EQ.rvind) THEN
               HW1 = value
            ELSE
               HW2 = value
            END IF
         ELSE IF (desc.EQ.22061) THEN ! State of the sea
            IF (SG.EQ.rvind) THEN
               SG = value
            END IF
         ELSE IF (desc.EQ.20033) THEN ! Cause of ice accretion
            IF (XIS.EQ.rvind) THEN
               XIS = value
            END IF
         ELSE IF (desc.EQ.20031) THEN ! Ice deposit (thickness)
            IF (ES.EQ.rvind) THEN
               ES = value
            END IF
         ELSE IF (desc.EQ.20032) THEN ! Rate of ice accretion
            IF (RS.EQ.rvind) THEN
               RS = value
            END IF
         ELSE IF (desc.EQ.20034) THEN ! Sea ice concentration
            IF (CI.EQ.rvind) THEN
               CI = value
            END IF
         ELSE IF (desc.EQ.20037) THEN ! Ice development
            IF (SI.EQ.rvind) THEN
               SI = value
            END IF
         ELSE IF (desc.EQ.20035) THEN ! Amount and type of ice
            IF (BI.EQ.rvind) THEN
               BI = value
            END IF
         ELSE IF (desc.EQ.20038) THEN ! Bearing of ice edge
            IF (DI.EQ.rvind) THEN
               DI = value
            END IF
         ELSE IF (desc.EQ.20036) THEN ! Ice situation
            IF (ZI.EQ.rvind) THEN
               ZI = value
            END IF
         ELSE IF (desc.EQ.1005) THEN ! Buoy/platform identifier
            IF (buoy_id5.EQ.rvind) THEN
               buoy_id5 = value
            END IF
         ELSE IF (desc.EQ.1003) THEN ! WMO region number/geographical area
            IF (wmo_region_number.EQ.rvind) THEN
               wmo_region_number = value
            END IF
         ELSE IF (desc.EQ.1020) THEN ! WMO region sub-area
            IF (wmo_region_subarea.EQ.rvind) THEN
               wmo_region_subarea = value
            END IF
         ELSE IF (desc.EQ.1087) THEN ! WMO Marine observing platform extended identifier
            IF (buoy_id7.EQ.rvind) THEN
               buoy_id7 = value
            END IF
C     Special for metar
         ELSE IF (desc.EQ.1063) THEN  ! ICAO location indicator
            cidx = int(value/1000)
            icao_id = cvals(cidx) ! CCITTIA5 data
            icao_id = ctrim(icao_id,8,missing8)
         ELSE IF (desc.EQ.10052) THEN ! Altimeter setting (QNH)
            IF (PH.EQ.rvind) THEN
               PH = value
            END IF
         END IF
      END DO
 
      IF (rectangle) THEN
         IF (longitude.EQ.rvind .OR. latitude.EQ.rvind
     +        .OR. longitude.LT.x1 .OR. longitude.GT.x2
     +        .OR. latitude.LT.y1 .OR. latitude.GT.y2) RETURN
      END IF
 
      IF (II.NE.rvind .AND. iii.NE.rvind) THEN
         WRITE(*,*)
         WRITE(*,'(A,I5.5)') 'wmonr=',NINT(II)*1000 + NINT(iii)
      ELSE IF (wigos_series.NE.rvind .AND. wigos_issuer.NE.missing5
     +        .AND. wigos_issueno.NE.missing5
     +        .AND. wigos_localid.NE.missing16) THEN
         ind = index(wigos_issuer,' ') - 1
         IF (ind.EQ.-1) ind = 5
         ind2 = index(wigos_issueno,' ') - 1
         IF (ind2.EQ.-1) ind2 = 5
         ind3 = index(wigos_localid,' ') - 1
         IF (ind3.EQ.-1) ind3 = 16
         WRITE(*,*)
         WRITE(*,'(A,I1.1,A1,A,A1,A,A1,A)')
     +        'wigosid=',NINT(wigos_series),
     +        '-',wigos_issuer(1:ind),
     +        '-',wigos_issueno(1:ind2),
     +        '-',wigos_localid(1:ind3)
      ELSE IF (state_id.NE.rvind .AND. national_number.NE.rvind) THEN
         WRITE(*,*)
         WRITE(*,'(A,I3.3,A1,I10.10)') 'nationalnr=',NINT(state_id),
     +        '_',NINT(national_number)
      ELSE IF (call_sign.NE.missing9) THEN
         ind = index(call_sign,' ') - 1
         IF (ind.EQ.-1) ind = 9
C     Remove trailing NULL characters, which some centres erronously
C     insert
         DO WHILE (IACHAR(call_sign(ind:ind)).EQ.0)
            ind = ind - 1
         END DO
         WRITE(*,*)
         WRITE(*,'(A,A)') 'call_sign=',
     +        call_sign(1:ind)
      ELSE IF (buoy_id7.NE.rvind) THEN
C     New templates introduced in 2014 for data category 1 use 001087
C     WMO Marine observing platform extended identifier, 7 digits
         WRITE(*,*)
         WRITE(*,'(A,I7)') 'buoy_id=',NINT(buoy_id7)
      ELSE IF (buoy_id5.NE.rvind) THEN
         WRITE(*,*)
         IF (wmo_region_number.EQ.rvind
     +        .AND.wmo_region_subarea.EQ.rvind) THEN
C     Old drau files (wrongly) includes wmo_region_number and
C     wmo_region_subarea in 001005 Buoy/platform identifier. Should we
C     expand this to 7 digits by inserting '00'?
            WRITE(*,'(A,I5)') 'buoy_id=',NINT(buoy_id5)
         ELSE IF (wmo_region_number.EQ.rvind
     +        .AND.wmo_region_subarea.NE.rvind) THEN
C     Some BUFR BUOYS on GTS have 'missing' value for wmo_region_number,
C     but not for wmo_region_subarea
            WRITE(*,'(A,I6)') 'buoy_id=',
     +           NINT(wmo_region_subarea)*100000 + NINT(buoy_id5)
         ELSE IF (wmo_region_number.NE.rvind
     +        .AND.wmo_region_subarea.EQ.rvind) THEN
C     Not easy to know how to display this case, but then I have never
C     seen this in practice
            WRITE(*,'(A,I5)') 'buoy_id=',NINT(buoy_id5)
         ELSE IF (buoy_id5.GT.10000.AND.
     +           (NINT(buoy_id5) - MOD(NINT(buoy_id5),1000)).EQ.
     +           NINT(wmo_region_number)*10000
     +           + NINT(wmo_region_subarea)*1000) THEN
C     If first 2 digits of 5 digit buoy_id equals wmo_region_number and
C     wmo_region_subarea respectively, this is almost certainly an
C     encoding error and we choose to show last 3 digits of buoy_id5 only
           WRITE(*,'(A,I7)') 'buoy_id=',NINT(wmo_region_number)*1000000
     +           + NINT(wmo_region_subarea)*100000
     +           + MOD(NINT(buoy_id5),1000)
         ELSE
           WRITE(*,'(A,I7)') 'buoy_id=',NINT(wmo_region_number)*1000000
     +           + NINT(wmo_region_subarea)*100000 + NINT(buoy_id5)
         END IF
      ELSE
         IF (verbose .GT. 1) THEN
            WRITE(*,*)
            WRITE(*,*) 'Both wmonr, wigosid, nationalnr, call_sign',
     +           ' and buoy_id are missing!!!'
C     Example: ISRZ47 EGRR has no proper station identification (except
C     station name and position)
         END IF
         RETURN
      END IF
 
      IF (year.NE.rvind.AND.month.NE.rvind.AND.day.NE.rvind
     +     .AND.hour.NE.rvind.AND.minute.NE.rvind) THEN
         WRITE(*,900),NINT(year),NINT(month),NINT(day),
     +        NINT(hour),NINT(minute)
 900     FORMAT('obstime=',I4,'-',I2.2,'-',I2.2,' ',I2.2,':',I2.2,':00')
      ELSE
         IF (verbose .GT. 1) THEN
            WRITE(*,*) 'obstime is missing!!!'
            RETURN
         END IF
      ENDIF
      IF (icao_id.NE.missing8) THEN
         WRITE(*,'(A,A)') 'icao_id=',icao_id(1:lenstr(icao_id,1))
      END IF
      IF (name.NE.missing20) THEN
         WRITE(*,'(A,A)') 'name=',name(1:lenstr(name,1))
      END IF
      IF (long_name.NE.missing32) THEN
         WRITE(*,'(A,A)') 'name=',long_name(1:lenstr(long_name,1))
      END IF
      IF (ix.NE.rvind) THEN
         IF (NINT(ix).EQ.0) THEN
            WRITE(*,'(A,A)') 'type=Automatic'
         ELSE IF (NINT(ix).EQ.1) THEN
            WRITE(*,'(A,A)') 'type=Manned'
         ELSE IF (NINT(ix).EQ.2) THEN
            WRITE(*,'(A,A)') 'type=Hybrid'
         END IF
      END IF
      IF (longitude.NE.rvind) THEN
         WRITE(*,'(A,F10.5)') 'lon=',longitude
      END IF
      IF (latitude.NE.rvind) THEN
         WRITE(*,'(A,F10.5)') 'lat=',latitude
      END IF
      IF (height.NE.rvind) THEN ! 7030 has scale 1 but 7003 has scale 0 and is more common,
                                ! so display as integer
         WRITE(*,'(A,I7)') 'height=',NINT(height)
      END IF
      IF (hp.NE.rvind) THEN
         WRITE(*,'(A,F11.1)') 'hp=',hp
      END IF
      IF (vs.NE.rvind) THEN
         WRITE(*,'(A,F11.1)') 'vs=',vs
      END IF
      IF (ds.NE.rvind) THEN
         WRITE(*,'(A,I11)') 'ds=',NINT(ds)
      END IF
      IF (a3.NE.rvind) THEN     ! Standard isobaric surface for which the
                                ! geopotential is reported, no Kvalobs code exists
         WRITE(*,'(A,I11)') 'a3=',NINT(a3/100) ! hPa
      END IF
      IF (hhh.NE.rvind) THEN    ! Geopotential height, no Kvalobs code exists
         WRITE(*,'(A,F10.1)') 'hhh=',hhh
      END IF
      IF (DD.NE.rvind) THEN
         WRITE(*,'(A,I11)') 'DD=',NINT(DD)
      END IF
      IF (FF.NE.rvind) THEN
         WRITE(*,'(A,F11.1)') 'FF=',FF
      END IF
      IF (FX.NE.rvind) THEN
         WRITE(*,'(A,F11.1)') 'FX=',FX
      END IF
      IF (FX_1.NE.rvind) THEN
         WRITE(*,'(A,F9.1)') 'FX_1=',FX_1
      END IF
      IF (FX_X.NE.rvind) THEN
         WRITE(*,'(A,F9.1)') 'FX_X=',FX_X
      END IF
      IF (DG.NE.rvind) THEN
         WRITE(*,'(A,F11.1)') 'DG=',DG
      END IF
      IF (FG.NE.rvind) THEN
         WRITE(*,'(A,F11.1)') 'FG=',FG
      END IF
      IF (DG_010.NE.rvind) THEN
         WRITE(*,'(A,F7.1)') 'DG_010=',DG_010
      END IF
      IF (FG_010.NE.rvind) THEN
         WRITE(*,'(A,F7.1)') 'FG_010=',FG_010
      END IF
      IF (DG_1.NE.rvind) THEN
         WRITE(*,'(A,F9.1)') 'DG_1=',DG_1
      END IF
      IF (FG_1.NE.rvind) THEN
         WRITE(*,'(A,F9.1)') 'FG_1=',FG_1
      END IF
      IF (DG_X.NE.rvind) THEN
         WRITE(*,'(A,F9.1)') 'DG_X=',DG_X
      END IF
      IF (FG_X.NE.rvind) THEN
         WRITE(*,'(A,F9.1)') 'FG_X=',FG_X
      END IF
      IF (TA.NE.rvind) THEN
         WRITE(*,'(A,F11.1)') 'TA=',TA-273.15
      END IF
      IF (TD.NE.rvind) THEN
         WRITE(*,'(A,F11.1)') 'TD=',TD-273.15
      END IF
      IF (TAX_12.NE.rvind) THEN
         WRITE(*,'(A,F7.1)') 'TAX_12=',TAX_12-273.15
      END IF
      IF (TAN_12.NE.rvind) THEN
         WRITE(*,'(A,F7.1)') 'TAN_12=',TAN_12-273.15
      END IF
      IF (TAX.NE.rvind) THEN
         WRITE(*,'(A,F10.1)') 'TAX=',TAX-273.15
      END IF
      IF (TAN.NE.rvind) THEN
         WRITE(*,'(A,F10.1)') 'TAN=',TAN-273.15
      END IF
      IF (TGN_12.NE.rvind) THEN
         WRITE(*,'(A,F7.1)') 'TGN_12=',TGN_12-273.15
      END IF
      IF (TW.NE.rvind) THEN
         WRITE(*,'(A,F11.1)') 'TW=',TW-273.15
      END IF
      IF (TbTbTb.NE.rvind) THEN
         WRITE(*,'(A,F11.1)') 'Tb=',TbTbTb-273.15
      END IF
      IF (UU.NE.rvind) THEN
         WRITE(*,'(A,I11)') 'UU=',NINT(UU)
      END IF
      IF (PO.NE.rvind) THEN
         WRITE(*,'(A,F11.1)') 'PO=',PO/100 ! hPa
      END IF
      IF (PR.NE.rvind) THEN
         WRITE(*,'(A,F11.1)') 'PR=',PR/100 ! hPa
      END IF
      IF (PH.NE.rvind) THEN
         WRITE(*,'(A,F11.1)') 'PH=',PH/100 ! hPa
      END IF
      IF (AA.NE.rvind) THEN
         WRITE(*,'(A,I11)') 'AA=',NINT(AA)
      END IF
      IF (PP.NE.rvind) THEN
         WRITE(*,'(A,F11.1)') 'PP=',PP/100 ! hPa
      END IF
C     Use the BUFR some special values for precipitation, *not* the
C     Kvalobs special values. So 'trace' (less than 0.05 kg/m2), is
C     showed as -0.1 (not 0 as in Kvalobs)
      IF (RR_24.NE.rvind) THEN
         WRITE(*,'(A,F8.1)') 'RR_24=',RR_24
      END IF
      IF (RR_12.NE.rvind) THEN
         WRITE(*,'(A,F8.1)') 'RR_12=',RR_12
      END IF
      IF (RR_6.NE.rvind) THEN
         WRITE(*,'(A,F9.1)') 'RR_6=',RR_6
      END IF
      IF (RR_3.NE.rvind) THEN
         WRITE(*,'(A,F9.1)') 'RR_3=',RR_3
      END IF
      IF (RR_1.NE.rvind) THEN
         WRITE(*,'(A,F9.1)') 'RR_1=',RR_1
      END IF
      IF (WW.NE.rvind.AND.WW.LT.200) THEN ! 508-511 and w1w1 (in 333 9 group) ignored here
         IF (NINT(WW).LT.100) THEN
            WRITE(*,'(A,I11)') 'WW=',NINT(WW)
         ELSE
            WRITE(*,'(A,I9)') 'WAWA=',NINT(WW-100)
         END IF
      END IF
      IF (W1.NE.rvind) THEN
         IF (NINT(W1).LT.10) THEN
            WRITE(*,'(A,I11)') 'W1=',NINT(W1)
         ELSE
            WRITE(*,'(A,I10)') 'WA1=',NINT(W1-10)
         END IF
      END IF
      IF (W2.NE.rvind) THEN
         IF (NINT(W2).LT.10) THEN
            WRITE(*,'(A,I11)') 'W2=',NINT(W2)
         ELSE
            WRITE(*,'(A,I10)') 'WA2=',NINT(W2-10)
         END IF
      END IF
      IF (EE.NE.rvind) THEN
         WRITE(*,'(A,I11)') 'EE=',NINT(EE)
      END IF
C     Use the BUFR some special values for SA, *not* the Kvalobs special values
C     So 'trace' is showed as SA=-1, 'Snow cover not continuous' as SA=-2
C     Note that conversion from synop to BUFR normally will set SA=0 if E < 10
      IF (SA.NE.rvind) THEN
         WRITE(*,'(A,I11)') 'SA=',NINT(SA*100)
      END IF
      IF (SS_24.NE.rvind) THEN
         WRITE(*,'(A,I8)') 'SS_24=',NINT(SS_24*100)
      END IF
      IF (VV.NE.rvind) THEN
         WRITE(*,'(A,I11)') 'VV=',NINT(VV)
      END IF
      IF (NN.NE.rvind) THEN
         WRITE(*,'(A,I11)') 'NN=',NNtoWMO_N(NINT(NN))
      END IF
      IF (HL.NE.rvind) THEN
         WRITE(*,'(A,I11)') 'HL=',NINT(HL)
      END IF
      IF (NH.NE.rvind) THEN
         WRITE(*,'(A,I11)') 'NH=',NINT(NH)
      END IF
C     Convert 020012 Cloud type in BUFR into one digit CL (0513), CM
C     (0515) and CH (0509) in TAC
      IF (CL.NE.rvind) THEN
         IF (NINT(CL).GE.30.AND.NINT(CL).LT.40) THEN
            WRITE(*,'(A,I11)') 'CL=',NINT(CL) - 30
         END IF
      END IF
      IF (CM.NE.rvind) THEN
         IF (NINT(CM).GE.20.AND.NINT(CM).LT.30) THEN
            WRITE(*,'(A,I11)') 'CM=',NINT(CM) - 20
         END IF
      END IF
      IF (CH.NE.rvind) THEN
         IF (NINT(CH).GE.10.AND.NINT(CH).LT.20) THEN
            WRITE(*,'(A,I11)') 'CH=',NINT(CH) - 10
         END IF
      END IF
C     Cloud layer data
      DO i=1,num_cloud_layers
         IF (NS(i).NE.rvind) THEN
            WRITE(*,'(A,I1,A,I10)') 'NS',i,'=',NINT(NS(i))
         END IF
         IF (CC(i).NE.rvind) THEN
            WRITE(*,'(A,I1,A,I10)') 'CC',i,'=',NINT(CC(i))
         END IF
         IF (HS(i).NE.rvind) THEN
            WRITE(*,'(A,I1,A,I10)') 'HS',i,'=',NINT(HS(i))
         END IF
      END DO
      IF (SG.NE.rvind) THEN
         WRITE(*,'(A,I11)') 'SG=',NINT(SG)
      END IF
      IF (PWA.NE.rvind) THEN
         WRITE(*,'(A,I10)') 'PWA=',NINT(PWA)
      END IF
      IF (PW.NE.rvind) THEN
         WRITE(*,'(A,I11)') 'PW=',NINT(PW)
      END IF
      IF (HWA.NE.rvind) THEN
         WRITE(*,'(A,F10.1)') 'HWA=',HWA
      END IF
      IF (HW.NE.rvind) THEN
         WRITE(*,'(A,F11.1)') 'HW=',HW
      END IF
      IF (DW1.NE.rvind) THEN
         WRITE(*,'(A,I10)') 'DW1=',NINT(DW1)
      END IF
      IF (PW1.NE.rvind) THEN
         WRITE(*,'(A,I10)') 'PW1=',NINT(PW1)
      END IF
      IF (HW1.NE.rvind) THEN
         WRITE(*,'(A,F10.1)') 'HW1=',HW1
      END IF
      IF (DW2.NE.rvind) THEN
         WRITE(*,'(A,I10)') 'DW2=',NINT(DW2)
      END IF
      IF (PW2.NE.rvind) THEN
         WRITE(*,'(A,I10)') 'PW2=',NINT(PW2)
      END IF
      IF (HW2.NE.rvind) THEN
         WRITE(*,'(A,F10.1)') 'HW2=',HW2
      END IF
      IF (XIS.NE.rvind) THEN
         WRITE(*,'(A,F10.1)') 'XIS=',XIS
      END IF
      IF (ES.NE.rvind) THEN
         WRITE(*,'(A,F11.1)') 'ES=',ES/10
      END IF
      IF (RS.NE.rvind) THEN
         WRITE(*,'(A,I11)') 'RS=',NINT(RS)
      END IF
      IF (CI.NE.rvind) THEN
         WRITE(*,'(A,I11)') 'CI=',NINT(CI)
      END IF
      IF (SI.NE.rvind) THEN
         WRITE(*,'(A,I11)') 'SI=',NINT(SI)
      END IF
      IF (BI.NE.rvind) THEN
         WRITE(*,'(A,I11)') 'BI=',NINT(BI)
      END IF
      IF (DI.NE.rvind) THEN
         WRITE(*,'(A,I11)') 'DI=',degree2dir(DI)
      END IF
      IF (ZI.NE.rvind) THEN
         WRITE(*,'(A,I11)') 'ZI=',NINT(ZI)
      END IF
      IF (OT_1.NE.rvind) THEN
         WRITE(*,'(A,I9)') 'OT_1=',NINT(OT_1)
      END IF
      IF (OT_24.NE.rvind) THEN
         WRITE(*,'(A,I8)') 'OT_24=',NINT(OT_24)
      END IF
      IF (QE.NE.rvind) THEN
         WRITE(*,'(A,F11.2)') 'QE=',QE/3600 ! Wh/m2
      END IF
      IF (QO.NE.rvind) THEN
         WRITE(*,'(A,F11.2)') 'QO=',QO/3600
      END IF
      IF (QL.NE.rvind) THEN
         WRITE(*,'(A,F11.2)') 'QL=',QL/3600
      END IF
      IF (QK.NE.rvind) THEN
         WRITE(*,'(A,F11.2)') 'QK=',QK/3600
      END IF
      IF (QD.NE.rvind) THEN
         WRITE(*,'(A,F11.2)') 'QD=',QD/3600
      END IF
      IF (QS.NE.rvind) THEN
         WRITE(*,'(A,F11.2)') 'QS=',QS/3600
      END IF
      IF (QE_24.NE.rvind) THEN
         WRITE(*,'(A,F8.2)') 'QE_24=',QE_24/3600 ! Wh/m2
      END IF
      IF (QO_24.NE.rvind) THEN
         WRITE(*,'(A,F8.2)') 'QO_24=',QO_24/3600
      END IF
      IF (QL_24.NE.rvind) THEN
         WRITE(*,'(A,F8.2)') 'QL_24=',QL_24/3600
      END IF
      IF (QK_24.NE.rvind) THEN
         WRITE(*,'(A,F8.2)') 'QK_24=',QK_24/3600
      END IF
      IF (QD_24.NE.rvind) THEN
         WRITE(*,'(A,F8.2)') 'QD_24=',QD_24/3600
      END IF
      IF (QS_24.NE.rvind) THEN
         WRITE(*,'(A,F8.2)') 'QS_24=',QS_24/3600
      END IF
      IF (EV_1.NE.rvind) THEN
         WRITE(*,'(A,I9)') 'EV_1=',NINT(EV_1)
      END IF
      IF (EV_24.NE.rvind) THEN
         WRITE(*,'(A,I8)') 'EV_24=',NINT(EV_24)
      END IF
 
      END SUBROUTINE print_surface_values
 
C     -----------------------------------------------------------------
 
      SUBROUTINE print_oceanographic_values(ksub,kxelem,ktdexl,ktdexp,
     +     values,cvals,rectangle,verbose)
C     Identify pressure, temperature etc and print parameter=value to screen
      IMPLICIT NONE
 
      INTEGER ksub              ! Input: number of subset currently processed
      INTEGER kxelem            ! Input: expected (max) number of expanded elements
      INTEGER ktdexl            ! Input: number of entries in list of expanded data descriptors
      INTEGER ktdexp(*)         ! Input: array containing expanded data descriptors
      REAL*8 values(*)          ! Input: expanded data values (one subset)
      CHARACTER*80 cvals(*)     ! Input: CCITTIA5 Bufr elements entries (one subset)
      LOGICAL rectangle         ! Input: TRUE if observations are wanted for a rectangle only
      INTEGER verbose           ! Input: verbose level
 
      REAL*8 rvind              ! missing value for real*8 data
      PARAMETER (rvind=1.7E38)
 
C     Parameters defined in Kvalobs
      REAL*8 HW,PW,TW,
C     Other parameters
     +     year,month,day,hour,minute,
     +     buoy_id,latitude,longitude,sal,
     +     wmo_region_number,wmo_region_subarea
      INTEGER idx,cidx,desc,ind,maxlevel,n,numlevels
      PARAMETER(maxlevel=2000) ! Largest number seen was 499 in a bathy
      CHARACTER*9 call_sign,missing9
      CHARACTER one_bits
      REAL*8 value
      REAL*8 d(maxlevel),s(maxlevel),T(maxlevel),v(maxlevel),z(maxlevel)
      REAL*8 w(maxlevel)
 
C     Variables used for geographical filtering av observations
C     (--rectangle option set)
      REAL*8 x1,y1,x2,y2
      COMMON /COM_RECTANGLE/  x1,y1,x2,y2
 
C     Functions
      CHARACTER*9 ctrim ! length must be >= longest variable ctrim is used for
 
      one_bits = CHAR(255)
      WRITE(missing9,'(9A)') one_bits,one_bits,one_bits,one_bits,
     +     one_bits,one_bits,one_bits,one_bits,one_bits
 
C     Initialize all parameters to missing values
      call_sign = missing9
      HW = rvind
      PW = rvind
      TW = rvind
      year = rvind
      month = rvind
      day = rvind
      hour = rvind
      minute = rvind
      latitude = rvind
      longitude = rvind
      buoy_id = rvind
      sal = rvind
      wmo_region_number = rvind
      wmo_region_subarea = rvind
      DO n=1,maxlevel
         z(n) = rvind
         w(n) = rvind
         T(n) = rvind
         s(n) = rvind
         d(n) = rvind
         v(n) = rvind
      END DO
 
C     Loop through all expanded descriptors
      n = 0 ! Numbering the subsurface levels
      DO idx=1,ktdexl
         desc = ktdexp(idx)
         value = values(idx + (ksub-1)*kxelem)
 
         IF (ABS(value - rvind)/rvind.LE.0.001) THEN
C     Missing value, nothing to do
            CYCLE
         END IF
 
C     Continue the loop for non missing values
         IF (desc.EQ.4001) THEN ! Year
            IF (year.EQ.rvind) THEN
               year = value
           END IF
         ELSE IF (desc.EQ.4002) THEN ! Month
            IF (month.EQ.rvind) THEN
               month = value
            END IF
         ELSE IF (desc.EQ.4003) THEN ! Day
            IF (day.EQ.rvind) THEN
               day = value
            END IF
         ELSE IF (desc.EQ.4004) THEN ! Hour
            IF (hour.EQ.rvind) THEN
               hour = value
            END IF
         ELSE IF (desc.EQ.4005) THEN ! Minute
            IF (minute.EQ.rvind) THEN
               minute = value
            END IF
         ELSE IF (desc.EQ.5001.OR.  ! Latitude (high accuracy)
     +           desc.EQ.5002) THEN ! Latitude (coarse accuracy)
            IF (latitude.EQ.rvind) THEN
               latitude = value
            END IF
         ELSE IF (desc.EQ.6001.OR.  ! Longitude (high accuracy)
     +           desc.EQ.6002) THEN ! Longitude (coarse accuracy)
            IF (longitude.EQ.rvind) THEN
               longitude = value
            END IF
         ELSE IF (desc.EQ.31001) THEN
C     Delayed descriptor replication factor; this should be number of
C     subsurface levels
            IF (value.EQ.rvind) THEN
               WRITE(*,*) 'WARNING: delayed descriptor replication'
     +              // ' factor 31001 undefined!!!'
               RETURN
            END IF
         ELSE IF (desc.EQ.7062) THEN ! Depth below sea/water surface
            n = n + 1           ! new level
            IF (n.GT.maxlevel) THEN
               n = maxlevel
               WRITE(*,*) 'Too many levels! Skipping rest of message'
               GOTO 120
            END IF
            z(n) = value
         ELSE IF (desc.EQ.7065) THEN ! Water pressure
            n = n + 1           ! new level
            IF (n.GT.maxlevel) THEN
               n = maxlevel
               WRITE(*,*) 'Too many levels! Skipping rest of message'
               GOTO 120
            END IF
            w(n) = value
         ELSE IF (desc.EQ.22045.OR.  ! Sea/water temperature (19 bits)
     +           desc.EQ.22043.OR.   ! Sea/water temperature (15 bits)
     +           desc.EQ.22042) THEN ! Sea/water temperature (12 bits)
            IF (n.GT.0 .AND. n.LE.maxlevel) THEN
               t(n) = value
            ELSE IF (n.EQ.0 .AND. TW.EQ.rvind) THEN
               TW = value
            END IF
         ELSE IF (desc.EQ.22064.OR.  ! Salinity [part per thousand] (17 bits)
     +           desc.EQ.22062) THEN ! Salinity [part per thousand] (14 bits)
            IF (n.GT.0 .AND. n.LE.maxlevel) THEN
               s(n) = value
            ELSE IF (n.EQ.0 .AND. sal.EQ.rvind) THEN
               sal = value
            END IF
         ELSE IF (desc.EQ.22004) THEN ! Direction of current
               IF (n.GT.0 .AND. n.LE.maxlevel) THEN
                  d(n) = value
               ELSE IF (n.EQ.0 .AND. verbose.GT.1) THEN
                  WRITE(*,*) 'Find 22004 (dc) before first 7062 (zz)!'
               END IF
         ELSE IF (desc.EQ.22031) THEN ! Speed of current
               IF (n.GT.0 .AND. n.LE.maxlevel) THEN
                  v(n) = value
               ELSE IF (n.EQ.0 .AND. verbose.GT.1) THEN
                  WRITE(*,*) 'Find 22031 (vc) before first 7062 (zz)!'
               END IF
         ELSE IF (desc.EQ.22062) THEN ! Salinity [part per thousand]
            IF (n.GT.0 .AND. n.LE.maxlevel) THEN
               s(n) = value
            ELSE IF (n.EQ.0 .AND. sal.EQ.rvind) THEN
               sal = value
            END IF
         ELSE IF (desc.EQ.22011) THEN !  Period of waves (BUFR doesn't distinguish between PW and PWA)
            IF (PW.EQ.rvind) THEN
               PW = value
            END IF
         ELSE IF (desc.EQ.22021) THEN ! Heigth of waves (BUFR doesn't distinguish between HW and HWA)
            IF (HW.EQ.rvind) THEN
               HW = value
            END IF
         ELSE IF (desc.EQ.1005) THEN ! Buoy/platform identifier
            IF (buoy_id.EQ.rvind) THEN
               buoy_id = value
            END IF
         ELSE IF (desc.EQ.1003) THEN ! WMO region number/geographical area
            IF (wmo_region_number.EQ.rvind) THEN
               wmo_region_number = value
            END IF
         ELSE IF (desc.EQ.1020) THEN ! WMO region sub-area
            IF (wmo_region_subarea.EQ.rvind) THEN
               wmo_region_subarea = value
            END IF
         ELSE IF (desc.EQ.1011) THEN ! Ship or mobile land station identifier
            IF (value.NE.rvind) THEN
               cidx = int(value/1000)
               call_sign = cvals(cidx) ! CCITTIA5 data
               call_sign = ctrim(call_sign,9,missing9)
            END IF
         ELSE IF (desc.EQ.1087) THEN ! WMO marine observing platform extended identifier
            IF (buoy_id.EQ.rvind) THEN
               buoy_id = value
            END IF
         END IF
      END DO
 120  CONTINUE
      numlevels = n
 
      IF (rectangle) THEN
         IF (longitude.EQ.rvind .OR. latitude.EQ.rvind
     +        .OR. longitude.LT.x1 .OR. longitude.GT.x2
     +        .OR. latitude.LT.y1 .OR. latitude.GT.y2) RETURN
      END IF
 
      IF (buoy_id.NE.rvind.AND.wmo_region_number.NE.rvind
     +     .AND.wmo_region_subarea.NE.rvind) THEN
         WRITE(*,*)
         IF (buoy_id.LT.1000) THEN
            WRITE(*,'(A,I5)') 'buoy_id=',NINT(wmo_region_number)*10000
     +           + NINT(wmo_region_subarea)*1000 + NINT(buoy_id)
         ELSE
C     This is an error in encoding. We choose to show buoy_id only (and
C     in all cases I have seen of this error, first 2 digits of buoy_id
C     is wmo_region_number and wmo_region_subarea respectively).
            IF (buoy_id.LT.10000) THEN
               WRITE(*,'(A,I4)') 'buoy_id=',NINT(buoy_id)
            ELSE IF (buoy_id.LT.100000) THEN
               WRITE(*,'(A,I5)') 'buoy_id=',NINT(buoy_id)
            ELSE IF (buoy_id.LT.1000000) THEN
               WRITE(*,'(A,I6)') 'buoy_id=',NINT(buoy_id)
            ELSE
               WRITE(*,'(A,I7)') 'buoy_id=',NINT(buoy_id)
            END IF
         END IF
      ELSE IF (buoy_id.NE.rvind.AND.buoy_id.GT.1000) THEN
C     Old drau files (wrongly) includes wmo_region_number and
C     wmo_region_subarea in buoy_id
         WRITE(*,*)
         IF (buoy_id.LT.10000) THEN ! 001005
            WRITE(*,'(A,I5)') 'buoy_id=',NINT(buoy_id)
         ELSE                       ! 001087
            WRITE(*,'(A,I7)') 'buoy_id=',NINT(buoy_id)
         END IF
      ELSE IF (call_sign.NE.missing9) THEN
         ind = index(call_sign,' ') - 1
         IF (ind.EQ.-1) ind = 9
C     Remove trailing NULL characters, which some centres erronously
C     insert
         DO WHILE (IACHAR(call_sign(ind:ind)).EQ.0)
            ind = ind - 1
         END DO
         WRITE(*,*)
         WRITE(*,'(A,A)') 'call_sign=',
     +        call_sign(1:ind)
      ELSE
         IF (verbose .GT. 1) THEN
            WRITE(*,*)
            WRITE(*,*) 'Both buoy_id and call_sign are missing!!!'
         END IF
         RETURN
      END IF
 
      IF (year.NE.rvind.AND.month.NE.rvind.AND.day.NE.rvind
     +     .AND.hour.NE.rvind.AND.minute.NE.rvind) THEN
         WRITE(*,900),NINT(year),NINT(month),NINT(day),
     +        NINT(hour),NINT(minute)
 900     FORMAT('obstime=',I4,'-',I2.2,'-',I2.2,' ',I2.2,':',I2.2,':00')
      ELSE
         IF (verbose .GT. 1) THEN
            WRITE(*,*) 'obstime is missing!!!'
            RETURN
         END IF
      ENDIF
      IF (longitude.NE.rvind) THEN
         WRITE(*,'(A,F10.5)') 'lon=',longitude
      END IF
      IF (latitude.NE.rvind) THEN
         WRITE(*,'(A,F10.5)') 'lat=',latitude
      END IF
      IF (PW.NE.rvind) THEN
         WRITE(*,'(A,I11)') 'PW=',NINT(PW)
      END IF
      IF (HW.NE.rvind) THEN
         WRITE(*,'(A,F11.1)') 'HW=',HW
      END IF
      IF (TW.NE.rvind) THEN
         WRITE(*,'(A,F11.1)') 'TW=',TW-273.15
      END IF
      IF (sal.NE.rvind) THEN
         WRITE(*,'(A,F11.2)') 'ss=',sal
      END IF
 
      DO n=1,numlevels
C     Do not print level if empty (might happen with last levels in
C     compressed messages, or simply due to bad practice. Setting
C     delayed description replication factor = 1 when ought to be 0 is
C     not quite uncommon)
         IF (z(n).EQ.rvind .AND. t(n).EQ.rvind .AND. s(n).EQ.rvind
     +        .AND. d(n).EQ.rvind .AND. v(n).EQ.rvind
     +        .AND. w(n).EQ.rvind) THEN
            CYCLE
         END IF
         WRITE(*,'(A,I12)'),'n=',n
         IF (z(n).NE.rvind) THEN
            WRITE(*,'(A,I11)') 'zz=',NINT(z(n))
         END IF
         IF (w(n).NE.rvind) THEN
            WRITE(*,'(A,I11)') 'wp=',NINT(w(n))
         END IF
         IF (t(n).NE.rvind) THEN
            WRITE(*,'(A,F11.2)') 'tt=',t(n)-273.15
         END IF
         IF (s(n).NE.rvind) THEN
            WRITE(*,'(A,F11.2)') 'ss=',s(n)
         END IF
         IF (d(n).NE.rvind) THEN
            WRITE(*,'(A,I11)') 'dc=',NINT(d(n))
         END IF
         IF (v(n).NE.rvind) THEN
            WRITE(*,'(A,F11.1)') 'vc=',v(n)
         END IF
      END DO
 
      END SUBROUTINE print_oceanographic_values
 
C     -----------------------------------------------------------------
 
      SUBROUTINE print_amdar_values(ksub,kxelem,ktdexl,ktdexp,values,
     +     cvals,rectangle,verbose)
C     Identify pressure, temperature etc and print parameter=value to screen
      IMPLICIT NONE
 
      INTEGER ksub              ! Input: number of subset currently processed
      INTEGER kxelem            ! Input: expected (max) number of expanded elements
      INTEGER ktdexl            ! Input: number of entries in list of expanded data descriptors
      INTEGER ktdexp(*)         ! Input: array containing expanded data descriptors
      REAL*8 values(*)          ! Input: expanded data values (one subset)
      CHARACTER*80 cvals(*)     ! Input: CCITTIA5 Bufr elements entries (one subset)
      LOGICAL rectangle         ! Input: TRUE if observations are wanted for a rectangle only
      INTEGER verbose           ! Input: verbose level
 
      REAL*8 rvind              ! missing value for real*8 data
      PARAMETER (rvind=1.7E38)
 
      CHARACTER*8 aircraft,flight_number,missing8
C     Parameters defined in Kvalobs
      REAL*8 DD,FF,TT,PP,
C     Other parameters
     +     year,month,day,hour,minute,second,latitude,longitude,
     +     flight_level,phase,osn,mixing_ratio
      CHARACTER*3 cphase,missing3
      INTEGER idx,cidx,ind
      CHARACTER one_bits
      REAL*8 value
      INTEGER desc
 
C     Variables used for geographical filtering av observations
C     (--rectangle option set)
      REAL*8 x1,y1,x2,y2
      COMMON /COM_RECTANGLE/  x1,y1,x2,y2
 
C     Functions
      INTEGER lenstr
      CHARACTER*8 ctrim ! length must be >= longest variable ctrim is used for
      CHARACTER*3 phase_8004,phase_8009
 
      one_bits = CHAR(255)
      WRITE(missing3,'(3A)') one_bits,one_bits,one_bits
      WRITE(missing8,'(8A)') one_bits,one_bits,one_bits,one_bits,
     +     one_bits,one_bits,one_bits,one_bits
 
C     Initialize all parameters to missing values
      aircraft = missing8
      flight_number = missing8
      cphase = missing3
      osn = rvind
      DD = rvind
      FF = rvind
      TT = rvind
      PP = rvind
      year = rvind
      month = rvind
      day = rvind
      hour = rvind
      minute = rvind
      second = rvind
      latitude = rvind
      longitude = rvind
      flight_level = rvind
      phase = rvind
      mixing_ratio = rvind
 
C     Loop through all expanded descriptors
      DO idx=1,ktdexl
         desc = ktdexp(idx)
         value = values(idx + (ksub-1)*kxelem)
 
         IF (ABS(value - rvind)/rvind.LE.0.001) THEN
C     Missing value, nothing to do
            CYCLE
         END IF
 
C     Continue the loop for non missing values
         IF (desc.EQ.1008) THEN ! Aircraft registration number or other identification
            cidx = int(value/1000)
            aircraft = cvals(cidx) ! CCITTIA5 data
            aircraft = ctrim(aircraft,8,missing8)
         ELSE IF (desc.EQ.1006) THEN ! Aircraft flight number
            cidx = int(value/1000)
            flight_number = cvals(cidx) ! CCITTIA5 data
            flight_number = ctrim(flight_number,8,missing8)
         ELSE IF (desc.EQ.1023) THEN ! Observation sequence number
            IF (osn.EQ.rvind) osn = value
         ELSE IF (desc.EQ.4001) THEN ! Year
            IF (year.EQ.rvind) THEN
               year = value
            END IF
         ELSE IF (desc.EQ.4002) THEN ! Month
            IF (month.EQ.rvind) THEN
               month = value
            END IF
         ELSE IF (desc.EQ.4003) THEN ! Day
            IF (day.EQ.rvind) THEN
               day = value
            END IF
         ELSE IF (desc.EQ.4004) THEN ! Hour
            IF (hour.EQ.rvind) THEN
               hour = value
            END IF
         ELSE IF (desc.EQ.4005) THEN ! Minute
            IF (minute.EQ.rvind) THEN
               minute = value
            END IF
         ELSE IF (desc.EQ.4006) THEN ! Second
            IF (second.EQ.rvind) THEN
               second = value
            END IF
         ELSE IF (desc.EQ.5001.OR.  ! Latitude (high accuracy)
     +           desc.EQ.5002) THEN ! Latitude (coarse accuracy)
            IF (latitude.EQ.rvind) THEN
               latitude = value
            END IF
         ELSE IF (desc.EQ.6001.OR.  ! Longitude (high accuracy)
     +           desc.EQ.6002) THEN ! Longitude (coarse accuracy)
            IF (longitude.EQ.rvind) THEN
               longitude = value
            END IF
         ELSE IF (desc.EQ.7010.OR.   ! Flight level
     +           desc.EQ.7002.OR.    ! Height or altitude
     +           desc.EQ.10070) THEN ! Indicated aircraft altitude
            IF (flight_level.EQ.rvind) THEN
               flight_level = value
            END IF
         ELSE IF (desc.EQ.8009.OR.  ! Detailed phase of aircraft flight
     +           desc.EQ.8004) THEN ! Phase of aircraft flight
            IF (phase.EQ.rvind) THEN
               phase = value
               cphase = phase_8009(NINT(phase),missing3)
            END IF
         ELSE IF (desc.EQ.8004) THEN ! Phase of aircraft flight
            IF (phase.EQ.rvind) THEN
               phase = value
               cphase = phase_8004(NINT(phase),missing3)
            END IF
         ELSE IF (desc.EQ.12104.OR. ! Dry bulb temperature at 2m (data width 16 bits)
     +          desc.EQ.12004.OR.   ! Dry bulb temperature at 2m (12 bits)
     +          desc.EQ.12101.OR.   ! Temperature/dry bulb temperature (16 bits)
     +          desc.EQ.12001) THEN ! Temperature/dry bulb temperature (12 bits)
            IF (TT.EQ.rvind) THEN
               TT = value
            END IF
         ELSE IF (desc.EQ.11011.OR.  ! Wind direction at 10 m
     +           desc.EQ.11001) THEN ! Wind direction
            IF (DD.EQ.rvind) THEN
               DD = value
            END IF
         ELSE IF (desc.EQ.11012.OR.  ! Wind speed at 10 m
     +           desc.EQ.11002) THEN ! Wind speed
            IF (FF.EQ.rvind) THEN
               FF = value
            END IF
         ELSE IF (desc.EQ.7004) THEN ! Pressure
            IF (PP.EQ.rvind) THEN
               PP = value
            END IF
         ELSE IF (desc.EQ.13002) THEN ! Mixing ratio
            IF (mixing_ratio.EQ.rvind) THEN
               mixing_ratio = value
            END IF
         END IF
      END DO
 
      IF (rectangle) THEN
         IF (longitude.EQ.rvind .OR. latitude.EQ.rvind
     +        .OR. longitude.LT.x1 .OR. longitude.GT.x2
     +        .OR. latitude.LT.y1 .OR. latitude.GT.y2) RETURN
      END IF
 
      IF (aircraft.NE.missing8) THEN
         WRITE(*,*)
         WRITE(*,'(A,A)') 'aircraft=',aircraft(1:lenstr(aircraft,1))
      ELSE IF (flight_number.NE.missing8) THEN
         WRITE(*,*)
         WRITE(*,'(A,A)') 'aircraft=',
     +        flight_number(1:lenstr(flight_number,1))
      ELSE
         IF (verbose .GT. 1) THEN
            WRITE(*,*)
            WRITE(*,*) 'Aircraft (001008/001006) is missing!!!'
         END IF
         RETURN
      END IF
 
 901  FORMAT('obstime=',I4,'-',I2.2,'-',I2.2,' ',I2.2,':',I2.2,':',I2.2)
 902  FORMAT('obstime=',I4,'-',I2.2,'-',I2.2,' ',I2.2,':',I2.2,':00')
 
      IF (year.NE.rvind.AND.month.NE.rvind.AND.day.NE.rvind
     +     .AND.hour.NE.rvind.AND.minute.NE.rvind) THEN
         IF (second.NE.rvind) THEN
            WRITE(*,901),NINT(year),NINT(month),NINT(day),
     +           NINT(hour),NINT(minute),NINT(second)
         ELSE
            WRITE(*,902),NINT(year),NINT(month),NINT(day),
     +           NINT(hour),NINT(minute)
         END IF
      ELSE IF (verbose .GT. 1) THEN
         WRITE(*,*) 'obstime is missing!!!'
         RETURN
      END IF
      IF (longitude.NE.rvind) THEN
         WRITE(*,'(A,F15.5)') 'lon=',longitude
      END IF
      IF (latitude.NE.rvind) THEN
         WRITE(*,'(A,F15.5)') 'lat=',latitude
      END IF
      IF (osn.NE.rvind) THEN
         WRITE(*,'(A,I12)') 'seqnum=',NINT(osn)
      END IF
      IF (flight_level.NE.rvind) THEN
         WRITE(*,'(A,I6)') 'flight_level=',NINT(flight_level)
      END IF
      IF (phase.NE.rvind) THEN
         WRITE(*,'(A,A3)') 'phase_of_flight=',cphase
      END IF
      IF (DD.NE.rvind) THEN
         WRITE(*,'(A,I16)') 'DD=',NINT(DD)
      END IF
      IF (FF.NE.rvind) THEN
         WRITE(*,'(A,F16.1)') 'FF=',FF
      END IF
      IF (TT.NE.rvind) THEN
         WRITE(*,'(A,F16.1)') 'TT=',TT-273.15
      END IF
      IF (PP.NE.rvind) THEN
         WRITE(*,'(A,F16.1)') 'PP=',PP/100 ! hPa
      END IF
      IF (mixing_ratio.NE.rvind) THEN
         WRITE(*,'(A,F16.2)') 'mr=',mixing_ratio*1000 ! g/kg
      END IF
 
      END SUBROUTINE print_amdar_values
 
C     -----------------------------------------------------------------
 
C     Remove trailing blanks and nulls from string, returning missing if
C     nothing left
      CHARACTER*(*) FUNCTION ctrim(string,dim,missing)
      IMPLICIT NONE
      CHARACTER*(*) string,missing
      INTEGER dim,ind,ascii
 
      ind = dim
      ascii = IACHAR(string(ind:ind))
      DO WHILE (ind.GT.1 .AND. (ascii.EQ.32 .OR. ascii.EQ.0))
         ind = ind - 1
         ascii = IACHAR(string(ind:ind))
      END DO
      IF (ind.EQ.1) THEN
         ascii = IACHAR(string(1:1))
         IF (ascii.EQ.32 .OR. ascii.EQ.0) THEN
            ctrim = missing
         ELSE
            ctrim = string(1:1)
         END IF
      ELSE IF (ind.GT.1) THEN
         ctrim = string(1:ind)
      ELSE
         ctrim = missing
      END IF
 
      RETURN
      END FUNCTION ctrim
 
 
C     -----------------------------------------------------------------
 
      CHARACTER*3 FUNCTION phase_8004(phase,missing3)
      IMPLICIT NONE
      INTEGER phase
      CHARACTER*3 missing3,indicator(6)
 
      DATA indicator/'res','UNS','LVR','LVW','ASC','DES'/
C                      1     2     3     4     5     6
 
      IF (phase.LE.1 .OR. phase.GT.6) THEN
         phase_8004 = missing3
      ELSE
         phase_8004 = indicator(phase)
      END IF
 
      RETURN
      END FUNCTION phase_8004
 
C     -----------------------------------------------------------------
 
      CHARACTER*3 FUNCTION phase_8009(phase,missing3)
      IMPLICIT NONE
      INTEGER phase
      CHARACTER*3 missing3,indicator(15)
 
C                      0     1     2     3     4     5     6
      DATA indicator/'LVR','LVW','UNS','LVR','LVW','ASC','DES',
     +     4*'ASC',4*'DES'/
C            7-10    11-14
 
      IF (phase.LE.0 .OR. phase.GT.14) THEN
         phase_8009 = missing3
      ELSE
         phase_8009 = indicator(phase + 1)
      END IF
 
      RETURN
      END FUNCTION phase_8009
 
C     -----------------------------------------------------------------
 
C     Convert value of NN (in percent) into WMO code (table 2700)
      INTEGER FUNCTION NNtoWMO_N(NN)
      IMPLICIT NONE
      INTEGER NN,N
      IF (NN.EQ.0) THEN
         N = 0
      ELSE IF (NN.LE.15) THEN  ! 1/10 or less
         N = 1
      ELSE IF (NN.LE.30) THEN  ! 2/10 - 3/10
         N = 2
      ELSE IF (NN.LE.45) THEN  ! 4/10
         N = 3
      ELSE IF (NN.LE.55) THEN  ! 5/10
         N = 4
      ELSE IF (NN.LE.65) THEN  ! 6/10
         N = 5
      ELSE IF (NN.LE.80) THEN  ! 7/10 - 8/10
         N = 6
      ELSE IF (NN.LE.99) THEN  ! 9/10 or more, but not 10/10
         N = 7
      ELSE IF (NN.GT.100) THEN ! Sky obscured by fog or other meteorological phenomena
         N = 9                 ! NN will be 113 in WMO BUFR, 109 in surf files
      ELSE
         N = 8
      END IF
 
      NNtoWMO_N = N
      END FUNCTION NNtoWMO_N
 
C     -----------------------------------------------------------------
 
      INTEGER FUNCTION degree2dir(rd)
      IMPLICIT NONE
      REAL*8 rd
      INTEGER id
      IF (NINT(rd).EQ.0) THEN
         id = 0
      ELSE IF (rd.LT.0 .OR. rd.GT.360) THEN
         id = 9
      ELSE IF (rd.LT.22.5 .OR.rd.GE.337.5) THEN
         id = 8                 ! N
      ELSE IF (rd.LT.67.5) THEN
         id = 1                 ! NE
      ELSE IF (rd.LT.112.5) THEN
         id = 2                 ! E
      ELSE IF (rd.LT.157.5) THEN
         id = 3                 ! SE
      ELSE IF (rd.LT.202.5) THEN
         id = 4                 ! S
      ELSE IF (rd.LT.247.5) THEN
         id = 5                 ! SW
      ELSE IF (rd.LT.292.5) THEN
         id = 6                 ! W
      ELSE IF (rd.LT.337.5) THEN
         id = 7                 ! NW
      END IF
 
      degree2dir = id
      END FUNCTION degree2dir
 
C     -----------------------------------------------------------------
 
      SUBROUTINE vss_8001(vss,significance)
C     Returns vertical sounding significance as right justified string:
C     s means surface level
C     S       standard level
C     t       tropopause level
C     M       maximum wind level
C     T       significant level, temperature and/or relative humidity
C     W       significant level, wind
      implicit none
      integer vss,jj
      character*8 significance
 
      significance = '        '
      jj = 8
      IF (btest(vss,7-6)) THEN
         significance(jj:jj) = 'W' ! significant level, wind
         jj = jj-1
      END IF
      IF (btest(vss,7-5)) THEN
         significance(jj:jj) = 'T' ! significant level, temperature and/or relative humidity
         jj = jj-1
      END IF
      IF (btest(vss,7-4)) THEN
         significance(jj:jj) = 'M' ! maximum wind level
         jj = jj-1
      END IF
      IF (btest(vss,7-3)) THEN
         significance(jj:jj) = 't' ! tropopause level
         jj = jj-1
      END IF
      IF (btest(vss,7-2)) THEN
         significance(jj:jj) = 'S' ! standard level
         jj = jj-1
      END IF
      IF (btest(vss,7-1)) THEN
         significance(jj:jj) = 's' ! surface level
         jj = jj-1
      END IF
 
      END SUBROUTINE vss_8001
 
C     -----------------------------------------------------------------
 
      SUBROUTINE vss_8042(vss,significance)
C     Returns vertical sounding significance as right justified string:
C     s means surface level
C     S       standard level
C     t       tropopause level
C     M       maximum wind level
C     T       significant level temperature
C     H       significant level humidity
C     W       significant level wind
C     r       level determined by regional decision
C     These should be the most interesting levels in 008042 (but we might
C     consider including more later)
      implicit none
      integer vss,jj
      character*8 significance
 
      significance = '        '
      jj = 8
      IF (btest(vss,18-15)) THEN
         significance(jj:jj) = 'r' ! level determined by regional decision
         jj = jj-1
      END IF
      IF (btest(vss,18-7)) THEN
         significance(jj:jj) = 'W' ! significant level wind
         jj = jj-1
      END IF
      IF (btest(vss,18-6)) THEN
         significance(jj:jj) = 'H' ! significant level humidity
         jj = jj-1
      END IF
      IF (btest(vss,18-5)) THEN
         significance(jj:jj) = 'T' ! significant level temperature
         jj = jj-1
      END IF
      IF (btest(vss,18-4)) THEN
         significance(jj:jj) = 'M' ! maximum wind level
         jj = jj-1
      END IF
      IF (btest(vss,18-3)) THEN
         significance(jj:jj) = 't' ! tropopause level
         jj = jj-1
      END IF
      IF (btest(vss,18-2)) THEN
         significance(jj:jj) = 'S' ! standard level
         jj = jj-1
      END IF
      IF (btest(vss,18-1)) THEN
         significance(jj:jj) = 's' ! surface level
         jj = jj-1
      END IF
 
      END SUBROUTINE vss_8042
 
C     -----------------------------------------------------------------
 
      integer function lenstr(text,minlen)
c
c  NAME:
c     lenstr
c
c  PURPOSE:
c     Return actual length of text string, excl. trailing blanks.
c
c  SYNOPSIS:
c     integer function lenstr(text,minlen)
c     character*(*) text
c     integer       minlen
c
c  INPUT:
c     text   - text string
c     minlen - the minimum length returned (see NOTES below)
c
c  OUTPUT:
c     lenstr - the string length
c
c  NOTES:
c     Use minlen=1 if you use lenstr to print a text string without
c     trailing blanks. E.g. filenames declared with a large maximum
c     length which hardly ever is longer than one line, but always
c     is printed with trailing blanks on two ore more lines.
c     Example:  write(6,*) filename(1:lenstr(filename,1))
c     (filename(1:0) may abort the program if filename=' ')
c
c-----------------------------------------------------------------------
c  DNMI/FoU  15.03.1995  Anstein Foss
c-----------------------------------------------------------------------
c
      character*(*) text
      integer       k,l,lt,minlen
c
      lt=len(text)
      l=0
      do k=1,lt
        if(text(k:k).ne.' ') l=k
      end do
c
      if(l.lt.minlen) l=minlen
c
      lenstr=l
c
      return
      end
comfilter.f
C (C) Copyright 2010, met.no
C
C This program is free software; you can redistribute it and/or modify
C it under the terms of the GNU General Public License as published by
C the Free Software Foundation; either version 2 of the License, or
C (at your option) any later version.
C
C This program is distributed in the hope that it will be useful, but
C WITHOUT ANY WARRANTY; without even the implied warranty of
C MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
C General Public License for more details.
C
C You should have received a copy of the GNU General Public License
C along with this program; if not, write to the Free Software
C Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
C 02110-1301, USA.
 
C     Variables used for filtering av observations (--filter option set
C     in bufrread or bufrdump)
 
      INTEGER dim1_fid, dim2_fid, dim_fiv
      PARAMETER (dim1_fid=10, dim2_fid=5, dim_fiv=1000)
 
      INTEGER fid(1:dim1_fid,1:dim2_fid)
                                ! filter descriptors arrays. fid(i,j) is descriptor
                                ! j in filter criterium i
      CHARACTER*10 fidformat(1:dim1_fid,1:dim2_fid)
                                ! filter descriptor format (I2.2, A9 etc)
                                ! for fid(i,j)
      INTEGER nd_fid(1:dim1_fid)  ! number of descriptors for each filter criterium
                                ! (max value of j for fid(i,j))
      INTEGER nvl_fid(1:dim_fiv) ! nvl_fid(i) is number av lines with filter
                                ! values described by filter descriptor line i
      INTEGER nfidlines         ! number of filter descriptor lines
                                ! (max value of i for fid(i,j))
 
      INTEGER fivI(1:dim_fiv,1:dim2_fid) ! the filter values of integer type 
      CHARACTER*32 fivC(1:dim_fiv,1:dim2_fid) ! the filter values of character type
 
      INTEGER nfivlines         ! number of lines with filter values
 
      COMMON /COM_FILTER/ fid,nd_fid,nvl_fid,nfidlines,nfivlines,fivI
 
      COMMON /COM_FILTERC/ fidformat,fivC