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 | } |
---|