updated top-level README and version_decl for V4.5 (#1847)
[WRF.git] / var / external / bufr / crbmg.c
blob4633a501b29d6ea793cb83e0d04816835acc97c9
1 /*$$$ SUBPROGRAM DOCUMENTATION BLOCK
3 C SUBPROGRAM: CRBMG
4 C PRGMMR: ATOR ORG: NP12 DATE: 2005-11-29
6 C ABSTRACT: THIS ROUTINE READS THE NEXT BUFR MESSAGE FROM THE SYSTEM
7 C FILE MOST RECENTLY OPENED FOR READING/INPUT VIA BUFR ARCHIVE LIBRARY
8 C ROUTINE COBFL. ANY BUFR EDITION 0 OR EDITION 1 MESSAGES THAT ARE
9 C READ ARE AUTOMATICALLY CONVERTED TO BUFR EDITION 2.
11 C PROGRAM HISTORY LOG:
12 C 2005-11-29 J. ATOR -- ORIGINAL AUTHOR
14 C USAGE: CALL CRBMG( BMG, MXMB, NMB, IRET )
15 C INPUT ARGUMENT LIST:
16 C MXMB - INTEGER: DIMENSIONED SIZE (IN BYTES) OF BMG; USED
17 C BY THE ROUTINE TO ENSURE THAT IT DOES NOT OVERFLOW
18 C THE BMG ARRAY
20 C OUTPUT ARGUMENT LIST:
21 C BMG - CHARACTER*1: ARRAY CONTAINING BUFR MESSAGE
22 C NMB - INTEGER: SIZE (IN BYTES) OF BUFR MESSAGE IN BMG
23 C IRET - INTEGER: RETURN CODE:
24 C 0 = normal return
25 C 1 = overflow of BMG array
26 C 2 = "7777" indicator not found in expected location
27 C -1 = end-of-file encountered while reading
28 C -2 = I/O error encountered while reading
30 C REMARKS:
31 C THIS ROUTINE CALLS: BORT GETS1LOC ICHKSTR IPKM
32 C IUPBS01 IUPM RBYTES
33 C THIS ROUTINE IS CALLED BY: None
34 C Normally called only by application
35 C programs.
37 C ATTRIBUTES:
38 C LANGUAGE: C
39 C MACHINE: PORTABLE TO ALL PLATFORMS
41 C$$$*/
43 #include "bufrlib.h"
45 void crbmg( char *bmg, f77int *mxmb, f77int *nmb, f77int *iret )
47 f77int i1 = 1, i2 = 2, i3 = 3, i4 = 4, i24 = 24;
48 f77int wkint[2];
49 f77int iben, isbyt, iwid;
51 char errstr[129];
53 unsigned short i, nsecs;
54 unsigned int lsec;
56 ** Make sure that a file is open for reading.
58 if ( pbf[0] == NULL ) {
59 sprintf( errstr, "BUFRLIB: CRBMG - NO FILE IS OPEN FOR READING" );
60 bort( errstr, ( f77int ) strlen( errstr ) );
63 ** Initialize the first 4 characters of the output array to blanks.
65 if ( *mxmb < 4 ) {
66 *iret = 1;
67 return;
69 strncpy( bmg, " ", 4);
71 ** Look for the start of the next BUFR message.
73 while ( ichkstr( "BUFR", bmg, &i4, 4, 4 ) != 0 ) {
74 memmove( bmg, &bmg[1], 3 );
75 if ( ( *iret = rbytes( bmg, mxmb, 3, 1 ) ) != 0 ) return;
78 ** Read the next 4 bytes and determine the BUFR edition number that was used
79 ** to encode the message.
81 if ( ( *iret = rbytes( bmg, mxmb, 4, 4 ) ) != 0 ) return;
82 memcpy( wkint, bmg, 8 );
83 iben = iupbs01( wkint, "BEN", 3 );
85 if ( iben >= 2 ) {
87 ** Get the length of the BUFR message.
89 *nmb = iupbs01( wkint, "LENM", 4 );
91 ** Read the remainder of the BUFR message.
93 if ( ( *iret = rbytes( bmg, mxmb, 8, *nmb-8 ) ) != 0 ) return;
95 else {
97 ** Read the remainder of the BUFR message and then convert it to BUFR
98 ** edition 2. The message length isn't encoded in Section 0, so we need
99 ** to compute it by unpacking and summing the lengths of the individual
100 ** sections.
102 lsec = 4; /* length of Section 0 */
104 ** Get the length of Section 1 and add it to the total.
106 gets1loc( "LEN1", &iben, &isbyt, &iwid, &wkint[0], 4 );
107 *nmb = lsec + iupm( &bmg[lsec+isbyt-1], &iwid, 3 );
109 ** Read up through the end of Section 1.
111 if ( ( *iret = rbytes( bmg, mxmb, 8, *nmb-8 ) ) != 0 ) return;
113 ** Is there a Section 2?
115 gets1loc( "ISC2", &iben, &isbyt, &iwid, &wkint[0], 4 );
116 nsecs = iupm( &bmg[lsec+isbyt-1], &iwid, 1 ) + 2;
118 ** Read up through the end of Section 4.
120 for ( i = 1; i <= nsecs; i++ ) {
121 if ( ( *iret = rbytes( bmg, mxmb, *nmb, 3 ) ) != 0 ) return;
122 lsec = iupm( &bmg[*nmb], &i24, 3 );
123 if ( ( *iret = rbytes( bmg, mxmb, *nmb+3, lsec-3 ) ) != 0 ) return;
124 *nmb += lsec;
127 ** Read Section 5.
129 if ( ( *iret = rbytes( bmg, mxmb, *nmb, 4 ) ) != 0 ) return;
130 *nmb += 4;
132 ** Expand Section 0 from 4 bytes to 8 bytes, then encode the message length
133 ** and new edition number (i.e. 2) into the new (expanded) Section 0.
135 if ( *nmb + 4 > *mxmb ) {
136 *iret = 1;
137 return;
139 memmove( &bmg[8], &bmg[4], *nmb-4 );
140 *nmb += 4;
141 ipkm( &bmg[4], &i3, nmb, 3 );
142 ipkm( &bmg[7], &i1, &i2, 1 );
145 ** Check that the "7777" is in the expected location.
147 *iret = ( ( ichkstr( "7777", &bmg[*nmb-4], &i4, 4, 4 ) == 0 ) ? 0 : 2 );
149 return;