SUBROUTINE OPENBF(LUNIT,IO,LUNDX)

C$$$  SUBPROGRAM DOCUMENTATION BLOCK
C
C SUBPROGRAM:    OPENBF
C   PRGMMR: WOOLLEN          ORG: NP20       DATE: 1994-01-06
C
C ABSTRACT: THIS SUBROUTINE NORMALLY (I.E. EXCEPT WHEN INPUT ARGUMENT
C   IO IS 'QUIET') IDENTIFIES A NEW LOGICAL UNIT TO THE BUFR ARCHIVE
C   LIBRARY SOFTWARE FOR INPUT OR OUTPUT OPERATIONS.  HOWEVER, THE
C   FIRST TIME IT IS CALLED, IT ALSO FIGURES OUT SOME IMPORTANT
C   INFORMATION ABOUT THE LOCAL MACHINE ON WHICH THE SOFTWARE IS BEING
C   RUN (VIA A CALL TO BUFR ARCHIVE LIBRARY SUBROUTINE WRDLEN), AND IT
C   ALSO INITIALIZES ARRAYS IN MANY BUFR ARCHIVE LIBRARY COMMON BLOCKS
C   (VIA A CALL TO BUFR ARCHIVE LIBRARY SUBROUTINE BFRINI). UP TO 32
C   LOGICAL UNITS CAN BE CONNECTED TO THE BUFR ARCHIVE LIBRARY SOFTWARE
C   AT ANY ONE TIME.
C
C   NOTE: IF IO IS PASSED IN AS 'QUIET', THEN OPENBF PERFORMS ONLY ONE
C   FUNCTION - IT SIMPLY SETS THE "DEGREE OF PRINTOUT" SWITCH IPRT (IN
C   COMMON BLOCK /QUIET/) TO THE VALUE OF INPUT ARGUMENT LUNDX,
C   OVERRIDING ITS PREVIOUS VALUE.  A DEFAULT IPRT VALUE OF 0 (I.E.
C   "LIMITED PRINTOUT") IS SET DURING THE FIRST CALL TO THIS ROUTINE,
C   BUT THIS OR ANY OTHER IPRT VALUE MAY BE SET AND RESET AS OFTEN AS
C   DESIRED VIA SUCCESSIVE CALLS TO OPENBF WITH IO = 'QUIET'.
C   IN ALL SUCH CASES, OPENBF SIMPLY (RE)SETS IPRT AND THEN RETURNS
C   WITHOUT ACTUALLY OPENING ANY FILES.  THE DEGREE OF PRINTOUT
C   INCREASES AS IPRT INCREASES FROM "-1" TO "0" TO "1" TO "2".
C
C PROGRAM HISTORY LOG:
C 1994-01-06  J. WOOLLEN -- ORIGINAL AUTHOR
C 1998-07-08  J. WOOLLEN -- REPLACED CALL TO CRAY LIBRARY ROUTINE
C                           "ABORT" WITH CALL TO NEW INTERNAL BUFRLIB
C                           ROUTINE "BORT"
C 1999-11-18  J. WOOLLEN -- THE NUMBER OF BUFR FILES WHICH CAN BE
C                           OPENED AT ONE TIME INCREASED FROM 10 TO 32
C                           (NECESSARY IN ORDER TO PROCESS MULTIPLE
C                           BUFR FILES UNDER THE MPI)
C 2003-11-04  J. ATOR    -- ADDED IO='NUL' OPTION IN ORDER TO PREVENT
C                           LATER WRITING TO BUFR FILE IN LUNIT (WAS IN
C                           DECODER VERSION); ADDED DOCUMENTATION
C 2003-11-04  S. BENDER  -- ADDED REMARKS/BUFRLIB ROUTINE
C                           INTERDEPENDENCIES
C 2003-11-04  D. KEYSER  -- UNIFIED/PORTABLE FOR WRF; ADDED HISTORY
C                           DOCUMENTATION; OUTPUTS MORE COMPLETE
C                           DIAGNOSTIC INFO WHEN ROUTINE TERMINATES
C                           ABNORMALLY, UNUSUAL THINGS HAPPEN OR FOR
C                           INFORMATIONAL PURPOSES
C 2004-08-18  J. ATOR    -- ADDED SAVE FOR IFIRST FLAG AND IO="NODX"
C                           OPTION 
C 2005-11-29  J. ATOR    -- ADDED COMMON /MSGFMT/ AND ICHKSTR CALL
C 2009-03-23  J. ATOR    -- ADDED IO='SEC3' OPTION; REMOVED CALL TO
C                           POSAPN; CLARIFIED COMMENTS; USE ERRWRT
C 2010-05-11  J. ATOR    -- ADDED COMMON /STCODE/
C 2012-06-18  J. ATOR    -- ADDED IO='INUL' OPTION
C 2012-09-15  J. WOOLLEN -- MODIFIED FOR C/I/O/BUFR INTERFACE;
C                           USE INQUIRE TO OBTAIN THE FILENAME;
C                           CALL C ROUTINES OPENRB, OPENWB, AND 
C                           OPENAB TO CONNECT BUFR FILES TO C;
C                           ADDED IO TYPE 'INX' TO ENABLE OPEN AND
C                           CLOSE FOR C FILE WITHOUT CLOSING FORTRAN
C                           FILE; ADD IO TYPE 'FIRST' TO SUPPORT CALLS   
C                           TO BFRINI AND WRDLEN PRIOR TO USER RESET
C                           OF BUFRLIB PARAMETERS FOUND IN NEW ROUTINES 
C                           SETBMISS AND SETBLOCK
C
C USAGE:    CALL OPENBF (LUNIT, IO, LUNDX)
C   INPUT ARGUMENT LIST:
C     LUNIT    - INTEGER: FORTRAN LOGICAL UNIT NUMBER FOR BUFR FILE
C                (UNLESS IO IS 'QUIET', THEN A DUMMY)
C     IO       - CHARACTER*(*): FLAG INDICATING HOW LUNIT IS TO BE
C                USED BY THE SOFTWARE:
C                    'IN' = input operations with table processing
C                   'INX' = input  operations w/o table processing
C                   'OUX' = output operations w/o table processing
C                   'OUT' = output operations with table processing
C                  'SEC3' = same as 'IN', except use Section 3 of input 
C                           messages for decoding rather than dictionary
C                           table information from LUNDX; in this case
C                           LUNDX is ignored, and user must provide 
C                           appropriate BUFR master tables within
C                           directory specified by a subsequent call
C                           to subroutine MTINFO
C                  'NODX' = same as 'OUT', except don't write dictionary
C                           (i.e. DX) table messages to LUNIT
C                   'APN' = same as 'NODX', except begin writing at end
C                           of file ("append")
C                   'APX' = same as 'APN', except backspace before
C                           appending
C                   'NUL' = same as 'OUT', except don't write any
C                           messages whatsoever to LUNIT (e.g. when
C                           subroutine WRITSA is to be used)
C                  'INUL' = same as 'IN', except don't read any
C                           messages whatsoever from LUNIT (e.g. when
C                           subroutine READERME is to be used)
C                 'QUIET' = LUNIT is ignored, this is an indicator
C                           that the value for IPRT in COMMON block
C                           /QUIET/ is being reset (see LUNDX)
C                 'FIRST' = calls bfrini and wrdlen as a prelude to user 
c                           resetting of bufrlib parameters such as
c                           missing value or output block type
C     LUNDX    - INTEGER: IF IO IS NOT 'QUIET':
C                            FORTRAN logical unit number containing 
C                            dictionary table information to be used in
C                            reading/writing from/to LUNIT (depending
C                            on the case); may be set equal to LUNIT if
C                            dictionary table information is already
C                            embedded in LUNIT
C                         IF IO IS 'QUIET':
C                            Indicator for degree of printout:
C                              -1 = NO printout except for ABORT
C                                   messages
C                               0 = LIMITED printout (default)
C                               1 = ALL warning messages are printed
C                                   out
C                               2 = ALL warning AND informational
C                                   messages are printed out
C                            (Note: this does not change until OPENBF
C                                   is again called with IO equal to
C                                   'QUIET')
C
C   INPUT FILES:
C     UNIT "LUNIT" - BUFR FILE
C
C REMARKS:
C    THIS ROUTINE CALLS:        BFRINI   BORT     DXINIT   ERRWRT
C                               POSAPX   READDX   STATUS   WRDLEN
C                               WRITDX   WTSTAT   OPENRB   OPENWB
C                               OPENAB
C    THIS ROUTINE IS CALLED BY: COPYBF   GETBMISS MESGBC   MESGBF
C                               RDMGSB   UFBINX   UFBMEM   UFBMEX
C                               UFBTAB   SETBMISS SETBLOCK
C                               Also called by application programs.
C
C ATTRIBUTES:
C   LANGUAGE: FORTRAN 77
C   MACHINE:  PORTABLE TO ALL PLATFORMS
C
C$$$

      INCLUDE 'bufrlib.prm'

      COMMON /MSGCWD/ NMSG(NFILES),NSUB(NFILES),MSUB(NFILES),
     .                INODE(NFILES),IDATE(NFILES)
      COMMON /STBFR / IOLUN(NFILES),IOMSG(NFILES)
      COMMON /NULBFR/ NULL(NFILES)
      COMMON /SC3BFR/ ISC3(NFILES),TAMNEM(NFILES)
      COMMON /LUSHR/  LUS(NFILES)
      COMMON /STCODE/ ISCODES(NFILES)
      COMMON /QUIET / IPRT

      CHARACTER*(*) IO
      CHARACTER*255 filename,fileacc   
      CHARACTER*128 BORT_STR,ERRSTR
      CHARACTER*28  CPRINT(0:3)
      CHARACTER*8   TAMNEM
      CHARACTER*1   BSTR(4)

      DATA IFIRST/0/
      DATA          CPRINT/
     . ' (only ABORTs)              ',
     . ' (limited - default)        ',
     . ' (all warnings)             ',
     . ' (all warning+informational)'/

      SAVE IFIRST

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

C     If this is the first call to this subroutine, initialize
C     IPRT in /QUIET/ as 0 (limited printout - except for abort
C     messages)

      IF(IFIRST.EQ.0) IPRT = 0

      IF(IO.EQ.'QUIET') THEN
c  .... override previous IPRT value (printout indicator)
         IF(LUNDX.LT.-1)  LUNDX = -1
         IF(LUNDX.GT. 2)  LUNDX =  2
         IF(LUNDX.GE.0) THEN
      CALL ERRWRT('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
      WRITE ( UNIT=ERRSTR, FMT='(A,I3,A,A,I3,A)' )
     . 'BUFRLIB: OPENBF - DEGREE OF MESSAGE PRINT INDICATOR '//
     . 'CHNGED FROM',IPRT,CPRINT(IPRT+1),' TO',LUNDX,CPRINT(LUNDX+1)
      CALL ERRWRT(ERRSTR)
      CALL ERRWRT('++++++++++++++BUFR ARCHIVE LIBRARY+++++++++++++++++')
      CALL ERRWRT(' ')
         ENDIF
         IPRT = LUNDX
      ENDIF

      IF(IFIRST.EQ.0) THEN

C        If this is the first call to this subroutine, then call WRDLEN
C        to figure out some important information about the local
C        machine and call BFRINI to initialize some global variables.

C        NOTE: WRDLEN must be called prior to calling BFRINI!  

         CALL WRDLEN
         CALL BFRINI
         IFIRST = 1
      ENDIF

      IF(IO.EQ.'FIRST') GOTO 100
      IF(IO.EQ.'QUIET') GOTO 100

C  SEE IF A FILE CAN BE OPENED
C  ---------------------------

      CALL STATUS(LUNIT,LUN,IL,IM)
      IF(LUN.EQ.0) GOTO 900
      IF(IL .NE.0) GOTO 901
      NULL(LUN) = 0
      ISC3(LUN) = 0
      ISCODES(LUN) = 0
      LUS(LUN) = 0

C  USE INQUIRE TO OBTAIN THE FILENAME ASSOCIATED WITH UNIT LUNIT
C  -------------------------------------------------------------

      IF (IO.NE.'NUL' .AND. IO.NE.'INUL') THEN
         inquire(lunit,access=fileacc)
         if(fileacc=='UNDEFINED') open(lunit)
         inquire(lunit,name=filename)
         filename=trim(filename)//char(0)
      ENDIF

C  SET INITIAL OPEN DEFAULTS (CLEAR OUT A MSG CONTROL WORD PARTITION)
C  ------------------------------------------------------------------

      NMSG (LUN) = 0
      NSUB (LUN) = 0
      MSUB (LUN) = 0
      INODE(LUN) = 0
      IDATE(LUN) = 0

C  DECIDE HOW TO OPEN THE FILE AND SETUP THE DICTIONARY
C  ----------------------------------------------------

      IF(IO.EQ.'IN') THEN
         call openrb(lun,filename)
         CALL WTSTAT(LUNIT,LUN,-1,0)
         CALL READDX(LUNIT,LUN,LUNDX)
      ELSE IF(IO.EQ.'INUL') THEN
         CALL WTSTAT(LUNIT,LUN,-1,0)
         IF(LUNIT.NE.LUNDX) CALL READDX(LUNIT,LUN,LUNDX)
         NULL(LUN) = 1
      ELSE IF(IO.EQ.'NUL') THEN
         CALL WTSTAT(LUNIT,LUN, 1,0)
         IF(LUNIT.NE.LUNDX) CALL READDX(LUNIT,LUN,LUNDX)
         NULL(LUN) = 1
      ELSE IF(IO.EQ.'INX') THEN
         call openrb(lun,filename)
         CALL WTSTAT(LUNIT,LUN,-1,0)
         NULL(LUN) = 1
      ELSE IF(IO.EQ.'OUX') THEN
         call openwb(lun,filename)
         CALL WTSTAT(LUNIT,LUN, 1,0)
      ELSE IF(IO.EQ.'SEC3') THEN
         call openrb(lun,filename)
         CALL WTSTAT(LUNIT,LUN,-1,0)
         ISC3(LUN) = 1
      ELSE IF(IO.EQ.'OUT') THEN
         call openwb(lun,filename)
         CALL WTSTAT(LUNIT,LUN, 1,0)
         CALL WRITDX(LUNIT,LUN,LUNDX)
      ELSE IF(IO.EQ.'NODX') THEN
         call openwb(lun,filename)
         CALL WTSTAT(LUNIT,LUN, 1,0)
         CALL READDX(LUNIT,LUN,LUNDX)
      ELSE IF(IO.EQ.'APN' .OR. IO.EQ.'APX') THEN
         call openab(lun,filename)
         CALL WTSTAT(LUNIT,LUN, 1,0)
         IF(LUNIT.NE.LUNDX) CALL READDX(LUNIT,LUN,LUNDX)
         CALL POSAPX(LUNIT)
      ELSE
         GOTO 904
      ENDIF

      GOTO 100

C     FILE OPENED FOR INPUT IS EMPTY - LET READMG OR READERME GIVE
C     THE BAD NEWS LATER

200   REWIND LUNIT
      IF(IPRT.GE.0) THEN
      CALL ERRWRT('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
      WRITE ( UNIT=ERRSTR, FMT='(A,I3,A)' )
     .  'BUFRLIB: OPENBF - INPUT BUFR FILE IN UNIT ', LUNIT,
     .  ' IS EMPTY'
      CALL ERRWRT(ERRSTR)
      CALL ERRWRT('+++++++++++++++++++++WARNING+++++++++++++++++++++++')
      CALL ERRWRT(' ')
      ENDIF
      CALL WTSTAT(LUNIT,LUN,-1,0)

C  INITIALIZE THE DICTIONARY TABLE PARTITION
C  -----------------------------------------

      CALL DXINIT(LUN,0)

C  EXITS
C  -----

100   RETURN
900   WRITE(BORT_STR,'("BUFRLIB: OPENBF - THERE ARE ALREADY",I3,'//
     . '" BUFR FILES OPENED, CANNOT OPEN FILE CONNECTED TO UNIT",I4)')
     . NFILES,LUNIT
      CALL BORT(BORT_STR)
901   WRITE(BORT_STR,'("BUFRLIB: OPENBF - THE FILE CONNECTED TO UNIT"'//
     . ',I5," IS ALREADY OPEN")') LUNIT
      CALL BORT(BORT_STR)
904   CALL BORT('BUFRLIB: OPENBF - SECOND (INPUT) ARGUMENT MUST BE'//
     . ' "IN", "OUT", "NODX", "NUL", "APN", "APX", "SEC3"'//
     . ' OR "QUIET"')
      END