/*$$$ SUBPROGRAM DOCUMENTATION BLOCK C C SUBPROGRAM: CRBMG C PRGMMR: ATOR ORG: NP12 DATE: 2005-11-29 C C ABSTRACT: THIS ROUTINE READS THE NEXT BUFR MESSAGE FROM THE SYSTEM C FILE MOST RECENTLY OPENED FOR READING/INPUT VIA BUFR ARCHIVE LIBRARY C ROUTINE COBFL. ANY BUFR EDITION 0 OR EDITION 1 MESSAGES THAT ARE C READ ARE AUTOMATICALLY CONVERTED TO BUFR EDITION 2. C C PROGRAM HISTORY LOG: C 2005-11-29 J. ATOR -- ORIGINAL AUTHOR C C USAGE: CALL CRBMG( BMG, MXMB, NMB, IRET ) C INPUT ARGUMENT LIST: C MXMB - INTEGER: DIMENSIONED SIZE (IN BYTES) OF BMG; USED C BY THE ROUTINE TO ENSURE THAT IT DOES NOT OVERFLOW C THE BMG ARRAY C C OUTPUT ARGUMENT LIST: C BMG - CHARACTER*1: ARRAY CONTAINING BUFR MESSAGE C NMB - INTEGER: SIZE (IN BYTES) OF BUFR MESSAGE IN BMG C IRET - INTEGER: RETURN CODE: C 0 = normal return C 1 = overflow of BMG array C 2 = "7777" indicator not found in expected location C -1 = end-of-file encountered while reading C -2 = I/O error encountered while reading C C REMARKS: C THIS ROUTINE CALLS: BORT GETS1LOC ICHKSTR IPKM C IUPBS01 IUPM RBYTES C THIS ROUTINE IS CALLED BY: None C Normally called only by application C programs. C C ATTRIBUTES: C LANGUAGE: C C MACHINE: PORTABLE TO ALL PLATFORMS C C$$$*/ #include "bufrlib.h" void crbmg( char *bmg, f77int *mxmb, f77int *nmb, f77int *iret ) { f77int i1 = 1, i2 = 2, i3 = 3, i4 = 4, i24 = 24; f77int wkint[2]; f77int iben, isbyt, iwid; char errstr[129]; unsigned short i, nsecs; unsigned int lsec; /* ** Make sure that a file is open for reading. */ if ( pbf[0] == NULL ) { sprintf( errstr, "BUFRLIB: CRBMG - NO FILE IS OPEN FOR READING" ); bort( errstr, ( f77int ) strlen( errstr ) ); } /* ** Initialize the first 4 characters of the output array to blanks. */ if ( *mxmb < 4 ) { *iret = 1; return; } strncpy( bmg, " ", 4); /* ** Look for the start of the next BUFR message. */ while ( ichkstr( "BUFR", bmg, &i4, 4, 4 ) != 0 ) { memmove( bmg, &bmg[1], 3 ); if ( ( *iret = rbytes( bmg, mxmb, 3, 1 ) ) != 0 ) return; } /* ** Read the next 4 bytes and determine the BUFR edition number that was used ** to encode the message. */ if ( ( *iret = rbytes( bmg, mxmb, 4, 4 ) ) != 0 ) return; memcpy( wkint, bmg, 8 ); iben = iupbs01( wkint, "BEN", 3 ); if ( iben >= 2 ) { /* ** Get the length of the BUFR message. */ *nmb = iupbs01( wkint, "LENM", 4 ); /* ** Read the remainder of the BUFR message. */ if ( ( *iret = rbytes( bmg, mxmb, 8, *nmb-8 ) ) != 0 ) return; } else { /* ** Read the remainder of the BUFR message and then convert it to BUFR ** edition 2. The message length isn't encoded in Section 0, so we need ** to compute it by unpacking and summing the lengths of the individual ** sections. */ lsec = 4; /* length of Section 0 */ /* ** Get the length of Section 1 and add it to the total. */ gets1loc( "LEN1", &iben, &isbyt, &iwid, &wkint[0], 4 ); *nmb = lsec + iupm( &bmg[lsec+isbyt-1], &iwid, 3 ); /* ** Read up through the end of Section 1. */ if ( ( *iret = rbytes( bmg, mxmb, 8, *nmb-8 ) ) != 0 ) return; /* ** Is there a Section 2? */ gets1loc( "ISC2", &iben, &isbyt, &iwid, &wkint[0], 4 ); nsecs = iupm( &bmg[lsec+isbyt-1], &iwid, 1 ) + 2; /* ** Read up through the end of Section 4. */ for ( i = 1; i <= nsecs; i++ ) { if ( ( *iret = rbytes( bmg, mxmb, *nmb, 3 ) ) != 0 ) return; lsec = iupm( &bmg[*nmb], &i24, 3 ); if ( ( *iret = rbytes( bmg, mxmb, *nmb+3, lsec-3 ) ) != 0 ) return; *nmb += lsec; } /* ** Read Section 5. */ if ( ( *iret = rbytes( bmg, mxmb, *nmb, 4 ) ) != 0 ) return; *nmb += 4; /* ** Expand Section 0 from 4 bytes to 8 bytes, then encode the message length ** and new edition number (i.e. 2) into the new (expanded) Section 0. */ if ( *nmb + 4 > *mxmb ) { *iret = 1; return; } memmove( &bmg[8], &bmg[4], *nmb-4 ); *nmb += 4; ipkm( &bmg[4], &i3, nmb, 3 ); ipkm( &bmg[7], &i1, &i2, 1 ); } /* ** Check that the "7777" is in the expected location. */ *iret = ( ( ichkstr( "7777", &bmg[*nmb-4], &i4, 4, 4 ) == 0 ) ? 0 : 2 ); return; }