[2759] | 1 | #include <stdio.h> |
---|
| 2 | #include <stdlib.h> |
---|
| 3 | #include "gribfuncs.h" |
---|
| 4 | /* |
---|
| 5 | ************************************************************************** |
---|
| 6 | * A. FUNCTION: prt_badmsg |
---|
| 7 | * Print out as much information as possible from the GRIB message |
---|
| 8 | * currently in GRIB_HDR structure. This may be an erroneous or |
---|
| 9 | * a partial message. |
---|
| 10 | * |
---|
| 11 | * INTERFACE: |
---|
| 12 | * int prt_badmsg (gh, errmsg) |
---|
| 13 | * |
---|
| 14 | * ARGUMENTS (I=input, O=output, I&O=input and output): |
---|
| 15 | * (I) GRIB_HDR *gh; |
---|
| 16 | * pointer to Grib header structure. |
---|
| 17 | * (O) char *errmsg; |
---|
| 18 | * Empty array, Returned filled if error is found; |
---|
| 19 | * |
---|
| 20 | * RETURN CODE: |
---|
| 21 | * 0> decoded message without any errors; |
---|
| 22 | * 1> error, errmsg buffer filled; |
---|
| 23 | *********************************************************************** |
---|
| 24 | */ |
---|
| 25 | #if PROTOTYPE_NEEDED |
---|
| 26 | int prt_badmsg (GRIB_HDR *gh, char *errmsg) |
---|
| 27 | #else |
---|
| 28 | int prt_badmsg (gh, errmsg) |
---|
| 29 | GRIB_HDR *gh; /*input= Grib Header struct */ |
---|
| 30 | char *errmsg; /* output= empty unless Error happens */ |
---|
| 31 | #endif |
---|
| 32 | { |
---|
| 33 | PDS_INPUT pds; /* local PDS struct */ |
---|
| 34 | grid_desc_sec gds; /* local GDS struct */ |
---|
| 35 | BDS_HEAD_INPUT bds_head; /* local BDS header struct */ |
---|
| 36 | BMS_INPUT bms; /* local bitmap section struct */ |
---|
| 37 | float *grib_data; /* local ptr to float data */ |
---|
| 38 | PDS_INPUT *Tpds = NULL; /* Null until valid PDS found*/ |
---|
| 39 | grid_desc_sec *Tgds = NULL; /* Null until valid GDS found*/ |
---|
| 40 | BDS_HEAD_INPUT *Tbds= NULL; /* Null until valid BDS found*/ |
---|
| 41 | BMS_INPUT *Tbms = NULL; /* Null until valid BMS found*/ |
---|
| 42 | char *func="prt_badmsg"; /* Function name */ |
---|
| 43 | char *curr_ptr; /* pts to beginning of GRIB message */ |
---|
| 44 | unsigned long lMessageSize; /* message length */ |
---|
| 45 | unsigned long edition; /* GRIB edition number */ |
---|
| 46 | int bms_flag = 0; /* set if Bms present*/ |
---|
| 47 | int gds_flag = 0; /* set if Gds present */ |
---|
| 48 | int nReturn = 1; /* status, default is bad */ |
---|
| 49 | unsigned long skip; |
---|
| 50 | |
---|
| 51 | /* |
---|
| 52 | * |
---|
| 53 | * A.1 CLEAR out local structures |
---|
| 54 | */ |
---|
| 55 | fprintf(stdout,"\nEntering %s: getting info from GRIB Header\n", func); |
---|
| 56 | memset ((void *)&pds, '\0', sizeof(PDS_INPUT)); |
---|
| 57 | memset ((void *)&gds, '\0', sizeof(grid_desc_sec)); |
---|
| 58 | memset ((void *)&bds_head, '\0', sizeof(BDS_HEAD_INPUT)); |
---|
| 59 | memset ((void *)&bms, '\0', sizeof(BMS_INPUT)); |
---|
| 60 | grib_data = (float *)NULL; |
---|
| 61 | |
---|
| 62 | /* |
---|
| 63 | * |
---|
| 64 | * A.2 IF (incoming pointer is not at 'GRIB') |
---|
| 65 | * RETURN 1 !errmsg filled |
---|
| 66 | * ENDIF |
---|
| 67 | */ |
---|
| 68 | curr_ptr = (char *)gh->entire_msg; |
---|
| 69 | if(strncmp(curr_ptr,"GRIB",4) != 0) { |
---|
| 70 | sprintf(errmsg,"%s: no 'GRIB' at beg. of this msg. Cannot continue.\n", |
---|
| 71 | func); |
---|
| 72 | goto BYE; |
---|
| 73 | } |
---|
| 74 | fprintf(stdout,"See 'GRIB'\n"); |
---|
| 75 | |
---|
| 76 | /* |
---|
| 77 | * |
---|
| 78 | * A.3 FUNCTION gbyte !get total message length from IDS |
---|
| 79 | */ |
---|
| 80 | skip=32; |
---|
| 81 | gbyte(curr_ptr,&lMessageSize,&skip,24); |
---|
| 82 | if (lMessageSize <= 8) { |
---|
| 83 | sprintf(errmsg,"Message length too short (%ld), cannot continue\n", |
---|
| 84 | lMessageSize); |
---|
| 85 | goto BYE; |
---|
| 86 | } |
---|
| 87 | fprintf(stdout,"Message Length = %ld\n", lMessageSize); |
---|
| 88 | |
---|
| 89 | /* |
---|
| 90 | * |
---|
| 91 | * A.4 PRINT warning message if Message length > Buffer size |
---|
| 92 | */ |
---|
| 93 | if (lMessageSize > gh->abs_size) |
---|
| 94 | fprintf(stdout, |
---|
| 95 | "*** Messagelen (%ld) > buffersize (%ld), MAY BE CORRUPTED ***\n", |
---|
| 96 | lMessageSize, gh->abs_size); |
---|
| 97 | |
---|
| 98 | /* |
---|
| 99 | * |
---|
| 100 | * A.5 EXTRACT the GRIB edition out of Section 0 |
---|
| 101 | */ |
---|
| 102 | gbyte (curr_ptr,&edition, &skip,8); |
---|
| 103 | fprintf(stdout,"Edition = %ld\n", edition); |
---|
| 104 | |
---|
| 105 | /* |
---|
| 106 | * |
---|
| 107 | * A.6 MOVE pointer to the Product Definition section |
---|
| 108 | */ |
---|
| 109 | curr_ptr = curr_ptr + 8; |
---|
| 110 | fprintf(stdout,"Expect PDS to start at offset %ld\n", |
---|
| 111 | (long)curr_ptr - (long)gh->entire_msg); |
---|
| 112 | |
---|
| 113 | /* |
---|
| 114 | * |
---|
| 115 | * A.7 FUNCTION gribgetpds !decode the PDS |
---|
| 116 | * RETURN error code if fails !errmsg filled |
---|
| 117 | * SAVE pointer to PDS block for printing later |
---|
| 118 | */ |
---|
| 119 | if( nReturn= gribgetpds(curr_ptr, &pds, errmsg)) { |
---|
| 120 | fprintf(stdout,"%s: %s;\n", func, errmsg); |
---|
| 121 | goto BYE; |
---|
| 122 | } |
---|
| 123 | fprintf(stdout,"got PDS\n"); |
---|
| 124 | Tpds = &pds; |
---|
| 125 | |
---|
| 126 | /* |
---|
| 127 | * |
---|
| 128 | * A.8 PRINT warning if PDS length < 28 bytes |
---|
| 129 | */ |
---|
| 130 | if (pds.uslength < 28) |
---|
| 131 | fprintf(stdout,"*** PDS (%ld) < 28 bytes, MAY BE CORRUPTED ***\n", |
---|
| 132 | pds.uslength); |
---|
| 133 | |
---|
| 134 | /* |
---|
| 135 | * |
---|
| 136 | * A.9 MOVE pointer to the end of PDS |
---|
| 137 | */ |
---|
| 138 | curr_ptr += pds.uslength; |
---|
| 139 | if ((long)curr_ptr > (long)gh->entire_msg + (gh->abs_size -1L)) { |
---|
| 140 | fprintf(stdout,"PDS size is much too big, cannot step past it\n"); |
---|
| 141 | goto BYE; |
---|
| 142 | } |
---|
| 143 | fprintf(stdout,"Expect next section to start at offset %ld\n", |
---|
| 144 | (long)curr_ptr - (long)gh->entire_msg); |
---|
| 145 | |
---|
| 146 | /* |
---|
| 147 | * |
---|
| 148 | * A.10 IF (GDS is present) |
---|
| 149 | */ |
---|
| 150 | if ((gds_flag = pds.usGds_bms_id >> 7 & 1)) |
---|
| 151 | { |
---|
| 152 | /* |
---|
| 153 | * A.10.1 FUNCTION gribgetgds !Exit on error |
---|
| 154 | * SAVE pointer to GDS block for printing later |
---|
| 155 | */ |
---|
| 156 | if ((nReturn=gribgetgds(curr_ptr, &gds, errmsg)) != 0) goto BYE; |
---|
| 157 | fprintf(stdout,"got GDS\n"); |
---|
| 158 | Tgds = &gds; |
---|
| 159 | |
---|
| 160 | /* |
---|
| 161 | * A.10.2 SET ulGrid_size based on Projection type |
---|
| 162 | */ |
---|
| 163 | switch(gds.head.usData_type) |
---|
| 164 | { |
---|
| 165 | case LATLON_PRJ: /* Lat/Lon Grid */ |
---|
| 166 | case GAUSS_PRJ: /* Gaussian Latitude/Longitude grid */ |
---|
| 167 | case ROT_LATLON_PRJ: /* Rotated Lat/Lon */ |
---|
| 168 | case ROT_GAUSS_PRJ: /* Rotated Gaussian */ |
---|
| 169 | case STR_LATLON_PRJ: /* Stretched Lat/Lon */ |
---|
| 170 | case STR_GAUSS_PRJ : /* Stretched Gaussian */ |
---|
| 171 | case STR_ROT_LATLON_PRJ : /* Stretched and Rotated Lat/Lon */ |
---|
| 172 | case STR_ROT_GAUSS_PRJ : /* Stretched and Rotated Gaussian */ |
---|
| 173 | bds_head.ulGrid_size = gds.llg.usNi * gds.llg.usNj; break; |
---|
| 174 | |
---|
| 175 | case MERC_PRJ: /* Mercator Grid */ |
---|
| 176 | bds_head.ulGrid_size = gds.merc.cols * gds.merc.rows; break; |
---|
| 177 | |
---|
| 178 | case LAMB_PRJ: /* Lambert Conformal */ |
---|
| 179 | case ALBERS_PRJ: /* Albers equal-area */ |
---|
| 180 | case OBLIQ_LAMB_PRJ: /* Oblique Lambert Conformal */ |
---|
| 181 | bds_head.ulGrid_size = gds.lam.iNx * gds.lam.iNy; break; |
---|
| 182 | |
---|
| 183 | case POLAR_PRJ: /* Polar Stereographic */ |
---|
| 184 | bds_head.ulGrid_size = gds.pol.usNx * gds.pol.usNy; break; |
---|
| 185 | |
---|
| 186 | default: |
---|
| 187 | fprintf(stdout,"%s: unsupported usData_type=%d\n", |
---|
| 188 | func, gds.head.usData_type); |
---|
| 189 | sprintf(errmsg,"%s: unsupported usData_type=%d\n", |
---|
| 190 | func, gds.head.usData_type); |
---|
| 191 | nReturn= (1); goto BYE; |
---|
| 192 | } |
---|
| 193 | |
---|
| 194 | /* |
---|
| 195 | * A.10.3 PRINT warning if GDS length < 32 bytes |
---|
| 196 | */ |
---|
| 197 | if (gds.head.uslength < 32) |
---|
| 198 | fprintf(stdout,"*** GDS (%d bytes) < 32 bytes, MAY BE CORRUPTED ***\n", |
---|
| 199 | gds.head.uslength); |
---|
| 200 | |
---|
| 201 | /* |
---|
| 202 | * A.10.4 MOVE the cursor to the next section (either BMS/BDS) |
---|
| 203 | */ |
---|
| 204 | curr_ptr += gds.head.uslength; |
---|
| 205 | if ((long)curr_ptr > (long)gh->entire_msg + (gh->abs_size -1L)) { |
---|
| 206 | fprintf(stdout,"GDS size is much too big, cannot step past it\n"); |
---|
| 207 | goto BYE; |
---|
| 208 | } |
---|
| 209 | /* |
---|
| 210 | * A.10 ENDIF (GDS is present) |
---|
| 211 | */ |
---|
| 212 | } /* gds present */ |
---|
| 213 | else fprintf(stdout,"Flag shows NO Grid Defn Sect included\n"); |
---|
| 214 | |
---|
| 215 | |
---|
| 216 | fprintf(stdout,"Expect next section to start at offset %ld\n", |
---|
| 217 | (long)curr_ptr - (long)gh->entire_msg); |
---|
| 218 | bms_flag = pds.usGds_bms_id >> 6 & 1; |
---|
| 219 | /* |
---|
| 220 | * |
---|
| 221 | * A.11 IF (bitmap Section is present) |
---|
| 222 | */ |
---|
| 223 | if(bms_flag) /* bit map section present */ |
---|
| 224 | { |
---|
| 225 | /* |
---|
| 226 | * A.11.1 FUNCTION gribgetbms !decode BMS |
---|
| 227 | * RETURN error code if fails !errmsg filled |
---|
| 228 | * SAVE pointer to BMS block for printing later |
---|
| 229 | */ |
---|
| 230 | if( nReturn= |
---|
| 231 | gribgetbms(curr_ptr,&bms,gds_flag, bds_head.ulGrid_size,errmsg)) |
---|
| 232 | { |
---|
| 233 | fprintf(stdout,"%s: error=%d in grib get BMS;\n",func,nReturn); |
---|
| 234 | goto BYE; |
---|
| 235 | } |
---|
| 236 | fprintf(stdout,"got BMS\n"); |
---|
| 237 | Tbms = &bms; |
---|
| 238 | |
---|
| 239 | /* |
---|
| 240 | * A.11.2 PRINT warning if BMS length < 7 bytes |
---|
| 241 | */ |
---|
| 242 | if (bms.uslength < 7) |
---|
| 243 | fprintf(stdout,"*** BMS (%d bytes) < 7 bytes, MAY BE CORRUPTED ***\n", |
---|
| 244 | bms.uslength); |
---|
| 245 | |
---|
| 246 | /* |
---|
| 247 | * A.11.3 MOVE the cursor to beginning of Binary Data Section |
---|
| 248 | */ |
---|
| 249 | curr_ptr += bms.uslength; |
---|
| 250 | if ((long)curr_ptr > (long)gh->entire_msg + (gh->abs_size -1L)) { |
---|
| 251 | fprintf(stdout,"BMS size is much too big, cannot step past it\n"); |
---|
| 252 | goto BYE; |
---|
| 253 | } |
---|
| 254 | /* |
---|
| 255 | * A.11 ENDIF !bms present |
---|
| 256 | */ |
---|
| 257 | } /* Bms present */ |
---|
| 258 | else fprintf(stdout,"Flag shows NO Bit Map Section included\n"); |
---|
| 259 | |
---|
| 260 | |
---|
| 261 | fprintf(stdout,"Expect BDS to start at offset %ld\n", |
---|
| 262 | (long)curr_ptr - (long)gh->entire_msg); |
---|
| 263 | /* |
---|
| 264 | * |
---|
| 265 | * A.12 FUNCTION gribgetbds() |
---|
| 266 | * RETURN error code if failed !errmsg filled |
---|
| 267 | * SAVE pointer to BDS for printing later |
---|
| 268 | */ |
---|
| 269 | if(nReturn=gribgetbds(curr_ptr, pds.sDec_sc_fctr, &bms, &gds, &grib_data, |
---|
| 270 | &bds_head, errmsg)) |
---|
| 271 | { fprintf(stdout,"%s: error=%d in grib get BDS;\n",func,nReturn); |
---|
| 272 | goto BYE; |
---|
| 273 | } |
---|
| 274 | fprintf(stdout,"got BDS\n"); |
---|
| 275 | Tbds= &bds_head; |
---|
| 276 | |
---|
| 277 | /* |
---|
| 278 | * A.13 PRINT warning if BDS < 11 bytes |
---|
| 279 | */ |
---|
| 280 | if (bds_head.length < 11) |
---|
| 281 | fprintf(stdout,"*** BDS (%d bytes) < 11 bytes, MAY BE CORRUPTED ***\n", |
---|
| 282 | bds_head.length); |
---|
| 283 | |
---|
| 284 | /* |
---|
| 285 | * A.14 BUMP pointer to next section !return on failure |
---|
| 286 | */ |
---|
| 287 | curr_ptr += bds_head.length; |
---|
| 288 | if ((long)curr_ptr > (long)gh->entire_msg + (gh->abs_size -1L)) { |
---|
| 289 | fprintf(stdout,"BDS size is much too big, cannot step past it\n"); |
---|
| 290 | goto BYE; |
---|
| 291 | } |
---|
| 292 | |
---|
| 293 | /* |
---|
| 294 | * A.15 CHECK for '7777' string |
---|
| 295 | * SET return code to 0 if found string |
---|
| 296 | */ |
---|
| 297 | fprintf(stdout,"Expect 7777 to start at offset %ld\n", |
---|
| 298 | (long)curr_ptr - (long)gh->entire_msg); |
---|
| 299 | if (strncmp (curr_ptr, "7777", 4)) |
---|
| 300 | fprintf(stdout,"'7777' is NOT at expected location\n"); |
---|
| 301 | else { |
---|
| 302 | fprintf(stdout,"see '7777' at offset %ld\n", |
---|
| 303 | (long)curr_ptr - (long)gh->entire_msg); |
---|
| 304 | nReturn = 0; |
---|
| 305 | } |
---|
| 306 | |
---|
| 307 | |
---|
| 308 | BYE: |
---|
| 309 | /* |
---|
| 310 | * |
---|
| 311 | * A.16 FUNCTION prt_inp_struct !print as many sections as possible |
---|
| 312 | */ |
---|
| 313 | fprintf(stdout,"\nNow will print all avail sections=\n"); |
---|
| 314 | prt_inp_struct (Tpds, Tgds, Tbms, Tbds, &grib_data); |
---|
| 315 | |
---|
| 316 | /* |
---|
| 317 | * |
---|
| 318 | * A.17 FREE data array |
---|
| 319 | */ |
---|
| 320 | if (grib_data != NULL) free (grib_data); |
---|
| 321 | |
---|
| 322 | /* |
---|
| 323 | * |
---|
| 324 | * A.18 RETURN with exit status |
---|
| 325 | */ |
---|
| 326 | fprintf(stdout,"Exiting %s\n", func); |
---|
| 327 | return (nReturn); |
---|
| 328 | } |
---|