]> Pileus Git - ~andy/rsl/blob - src/dorade.c
Add blank gzip version for Win32
[~andy/rsl] / src / dorade.c
1 /*
2     NASA/TRMM, Code 910.1.
3     This is the TRMM Office Radar Software Library.
4     Copyright (C) 1999
5             John H. Merritt
6             Space Applications Corporation
7             Vienna, Virginia
8
9     This library is free software; you can redistribute it and/or
10     modify it under the terms of the GNU Library General Public
11     License as published by the Free Software Foundation; either
12     version 2 of the License, or (at your option) any later version.
13
14     This library is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17     Library General Public License for more details.
18
19     You should have received a copy of the GNU Library General Public
20     License along with this library; if not, write to the Free
21     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include "dorade.h"
28 #ifndef WIN32
29 #include <netinet/in.h>
30 #else
31 #include "win32compat.h"
32 #endif
33
34 int dorade_verbose = 0;
35
36 void dorade_verbose_on()
37 {
38   dorade_verbose = 1;
39 }
40 void dorade_verbose_off()
41 {
42   dorade_verbose = 0;
43 }
44
45 static int do_swap = 0;
46
47 /**********************************************************************/
48 /*                                                                    */
49 /*                      read_extra_bytes                              */
50 /*                                                                    */
51 /**********************************************************************/
52 int read_extra_bytes(int nbytes, FILE *in)
53 {
54   char *extra;
55   int nread;
56   /*
57    * Read and discard nbytes bytes.  The return value is the byte count
58    * returned by fread, unless there is an error, then it is 0.
59    */
60   extra = (char *) malloc(nbytes);
61   if (!extra) {
62     perror("\nError: read_extra_bytes");
63     fprintf(stderr,"Tried to allocate %d bytes\n", nbytes);
64     return 0;
65   }
66   nread = fread(extra, sizeof(char), nbytes, in);
67   free(extra);
68   return nread;
69 }
70
71 /**********************************************************************/
72 /*                                                                    */
73 /*                      dorade_read_comment_block                     */
74 /*                                                                    */
75 /**********************************************************************/
76 Comment_block *dorade_read_comment_block(FILE *in)
77 {
78   Comment_block *cb;
79   cb = (Comment_block *) calloc(1, sizeof(Comment_block));
80   if (cb == NULL) {
81         perror("dorade_read_comment_block");
82         return NULL;
83   }
84   if (fread(cb->code, sizeof(cb->code), 1, in) != 1) {
85         perror("dorade_read_comment_block: fread");
86         return NULL;
87   }
88   if (fread(&cb->len, sizeof(cb->len), 1, in) != 1) {
89         perror("dorade_read_comment_block: fread");
90         return NULL;
91   }
92
93   /* Check for big endian data on little endian platform.  The smallest value
94    * cb->len could have is 8 (length of cb->code + cb->len), so we put that in
95    * first byte of test value, and also test for negative, since sign bit could
96    * be set in a larger value.
97    */
98   if (cb->len > 0x08000000 || cb->len < 0) do_swap = 1;
99   if (do_swap) cb->len = ntohl(cb->len);
100
101   /* Length of cb->comment is cb->len-8 since cb->code and cb->len have
102    * already been read.
103    */
104   cb->comment = (char *) calloc(cb->len-8, sizeof(char));
105   if (cb->comment == NULL) {
106         perror("dorade_read_comment_block: cb->comment");
107         return cb;
108   }
109   if (fread(cb->comment, sizeof(char), cb->len-8, in) != cb->len){
110         perror("dorade_read_comment_block: fread");
111         return NULL;
112   }
113   return cb;
114 }
115
116 /**********************************************************************/
117 /*                                                                    */
118 /*                      dorade_read_volume_desc                       */
119 /*                                                                    */
120 /**********************************************************************/
121 Volume_desc    *dorade_read_volume_desc    (FILE *in)
122 {
123   Volume_desc *vd;
124
125   vd = (Volume_desc *) calloc(1, sizeof(Volume_desc));
126   if(!vd) {
127         perror("dorade_read_volume_desc");
128         return NULL;
129   }
130
131   if (fread(vd, sizeof(Volume_desc), 1, in) != 1) {
132         perror("dorade_read_volume_desc: fread");
133         return NULL;
134   }
135
136   /* Now, convert from Big Endian. */
137   if (do_swap) {
138       vd->len = ntohl(vd->len);
139       vd->version = ntohs(vd->version);
140       vd->volume_number = ntohs(vd->volume_number);
141       vd->max_bytes = ntohl(vd->max_bytes);
142       vd->year = ntohs(vd->year);
143       vd->month = ntohs(vd->month);
144       vd->day = ntohs(vd->day);
145       vd->hour = ntohs(vd->hour);
146       vd->minute = ntohs(vd->minute);
147       vd->second = ntohs(vd->second);
148       vd->gen_year = ntohs(vd->gen_year);
149       vd->gen_month = ntohs(vd->gen_month);
150       vd->gen_day = ntohs(vd->gen_day);
151       vd->nsensors = ntohs(vd->nsensors);
152   }
153   return vd;
154 }
155
156 extern int little_endian(void);
157 extern void swap_4_bytes(void *word);
158 extern void swap_2_bytes(void *word);
159
160
161 /* Sensor descriptor routines. */
162 /**********************************************************************/
163 /*                                                                    */
164 /*                      dorade_read_radar_desc                        */
165 /*                                                                    */
166 /**********************************************************************/
167 Radar_desc     *dorade_read_radar_desc     (FILE *in)
168 {
169   Radar_desc *rd;
170   int i;
171
172   rd = (Radar_desc *) calloc(1, sizeof(Radar_desc));
173   if(!rd) {
174         perror("dorade_read_radar_desc");
175         return NULL;
176   }
177
178   if (fread(rd, sizeof(Radar_desc), 1, in) != 1) {
179         perror("dorade_read_radar_desc: fread");
180         return NULL;
181   }
182   /* Now, convert from Big Endian. */
183   if (do_swap) {
184         swap_4_bytes(&rd->len);
185         swap_4_bytes(&rd->radar_constant); /* Yes, even the ieee floating values. */
186         swap_4_bytes(&rd->peak_power);
187         swap_4_bytes(&rd->noise_power);
188         swap_4_bytes(&rd->rcvr_gain);
189         swap_4_bytes(&rd->ant_gain);
190         swap_4_bytes(&rd->radar_system_gain);
191         swap_4_bytes(&rd->horizontal_beam_width);
192         swap_4_bytes(&rd->vertical_beam_width);
193         swap_2_bytes(&rd->radar_type);
194         swap_2_bytes(&rd->scan_mode);
195         swap_4_bytes(&rd->scan_rate);
196         swap_4_bytes(&rd->start_angle);
197         swap_4_bytes(&rd->stop_angle);
198         swap_2_bytes(&rd->nparam_desc);
199         swap_2_bytes(&rd->ndesc);
200         swap_2_bytes(&rd->compress_code);
201         swap_2_bytes(&rd->compress_algo);
202         swap_4_bytes(&rd->data_reduction_param1);
203         swap_4_bytes(&rd->data_reduction_param2);
204         swap_4_bytes(&rd->longitude);
205         swap_4_bytes(&rd->latitude);
206         swap_4_bytes(&rd->altitude);
207         swap_4_bytes(&rd->unambiguous_velocity);
208         swap_4_bytes(&rd->unambiguous_range);
209         swap_2_bytes(&rd->nfreq);
210         swap_2_bytes(&rd->npulse_periods);
211         for (i=0; i<5; i++) {
212           swap_4_bytes(&rd->freq[i]);
213           swap_4_bytes(&rd->period[i]);
214         }
215   }
216   /* If RADD block is longer than structure, read through extra bytes.
217    * This sometimes happens.
218    */
219   if (rd->len > sizeof(Radar_desc)) {
220       if (read_extra_bytes(rd->len - sizeof(Radar_desc), in) <= 0)
221           fprintf(stderr,"Called from %s, line: %d\n", __FILE__, __LINE__ - 1);
222   }
223   return rd;
224 }
225 /**********************************************************************/
226 /*                                                                    */
227 /*                      dorade_read_parameter_desc                    */
228 /*                                                                    */
229 /**********************************************************************/
230 Parameter_desc *dorade_read_parameter_desc (FILE *in)
231 {
232   Parameter_desc *pd;
233
234   pd = (Parameter_desc *) calloc(1, sizeof(Parameter_desc));
235   if(!pd) {
236         perror("dorade_read_parameter_desc");
237         return NULL;
238   }
239
240   if (fread(pd, sizeof(Parameter_desc), 1, in) != 1) {
241         perror("dorade_read_parameter_desc: fread");
242         return NULL;
243   }
244   /* Now, convert from Big Endian. */
245   if (do_swap) {
246         swap_4_bytes(&pd->len);
247         swap_2_bytes(&pd->ipp);
248         swap_2_bytes(&pd->xmit_freq);
249         swap_4_bytes(&pd->rcvr_bandwidth);
250         swap_2_bytes(&pd->pulse_width);
251         swap_2_bytes(&pd->polarization);
252         swap_2_bytes(&pd->nsamp_in_dwell_time);
253         swap_2_bytes(&pd->parameter_type);
254         swap_4_bytes(&pd->threshold_value);
255         swap_4_bytes(&pd->scale_factor);
256         swap_4_bytes(&pd->offset_factor);
257         swap_4_bytes(&pd->missing_data_flag);
258   }
259   /* If the descriptor block is longer than the structure, read past the extra bytes.
260    */
261   if (pd->len > sizeof(Parameter_desc)) {
262       if (read_extra_bytes(pd->len - sizeof(Parameter_desc), in) <= 0)
263           fprintf(stderr,"Called from %s, line: %d\n", __FILE__, __LINE__ - 1);
264   }
265   return pd;
266 }
267
268 /**********************************************************************/
269 /*                                                                    */
270 /*                      dorade_read_cell_range_vector                 */
271 /*                                                                    */
272 /**********************************************************************/
273 Cell_range_vector      *dorade_read_cell_range_vector     (FILE *in)
274 {
275   Cell_range_vector *cv;
276   char *buff;
277   int i;
278
279   cv = (Cell_range_vector *) calloc(1, sizeof(Cell_range_vector));
280   if(!cv) {
281         perror("dorade_read_cell_range_vector");
282         return NULL;
283   }
284
285   if (fread(&cv->code, sizeof(cv->code), 1, in) != 1 ||
286       fread(&cv->len, sizeof(cv->len), 1, in) != 1 ||
287       fread(&cv->ncells, sizeof(cv->ncells), 1, in) != 1) {
288         perror("dorade_read_cell_range_vector: fread");
289         return NULL;
290   }
291   if (do_swap) {
292         swap_4_bytes(&cv->len);
293         swap_4_bytes(&cv->ncells);
294   }
295   cv->range_cell = (float *)calloc(cv->ncells, sizeof(float));
296   if (!cv->range_cell) {
297         perror("dorade_read_cell_range_vector: cv->range_cell");
298         return cv;
299   }
300   if (fread(cv->range_cell, sizeof(float), cv->ncells, in) != cv->ncells) {
301         perror("dorade_read_cell_range_vector: fread");
302         return NULL;
303   }
304
305   if (do_swap) {
306         for (i=0; i<cv->ncells; i++)
307           swap_4_bytes(&cv->range_cell[i]);
308   }
309
310   /* Usually reading the range cells does not read to the end
311    * of the Cell_range_vector structure.  We may be reading
312    * a non seekable device!
313    */
314   i = cv->len            /* Remove a few bytes that precede. */
315         - sizeof(cv->code)
316         - sizeof(cv->len)
317         - sizeof(cv->ncells)
318         - cv->ncells*4;
319   buff = (char *)malloc(i);
320   if (!buff) return cv;
321   if (fread(buff, sizeof(char), i, in) != i) {
322         perror("dorade_read_cell_range_vector: fread");
323         return NULL;
324   }
325   free(buff);
326   return cv;
327 }
328
329 /**********************************************************************/
330 /*                                                                    */
331 /*                      dorade_read_correction_factor_desc            */
332 /*                                                                    */
333 /**********************************************************************/
334 Correction_factor_desc *dorade_read_correction_factor_desc(FILE *in)
335 {
336   Correction_factor_desc *cf;
337   char *remaining;
338   int is_cfac = 0;
339
340   cf = (Correction_factor_desc *) calloc(1, sizeof(Correction_factor_desc));
341   if(!cf) {
342         perror("dorade_read_correction_factor_desc");
343         return NULL;
344   }
345
346   /* Make sure we have Correction Factor Descriptor. */
347   while (!is_cfac) {
348       if (fread(cf->code, sizeof(cf->code), 1, in) != 1) {
349           perror("dorade_read_correction_factor_desc: fread");
350           return NULL;
351       }
352       if (strncmp(cf->code, "CFAC", 4) == 0)
353           is_cfac = 1;
354       else {
355           if (fread(&cf->len, sizeof(cf->len), 1, in) != 1) {
356               perror("dorade_read_correction_factor_desc: fread");
357               return NULL;
358           }
359           if (do_swap) swap_4_bytes(&cf->len);
360           remaining = (char *) malloc(cf->len-8);
361           if (!remaining) {
362               perror("\ndorade_read_correction_factor_desc");
363               fprintf(stderr,"cf->len = %d\n\n", cf->len);
364               return NULL;
365           }
366           if (fread(remaining, sizeof(char), cf->len-8, in) != 1) {
367               perror("dorade_read_correction_factor_desc: fread");
368               return NULL;
369           }
370           free(remaining);
371       }
372   }
373   if (fread(&cf->len, sizeof(Correction_factor_desc)-4, 1, in) != 1) {
374       perror("dorade_read_correction_factor_desc: fread");
375       return NULL;
376   }
377   /* Now, convert from Big Endian. */
378   if (do_swap) {
379         swap_4_bytes(&cf->len);
380         swap_4_bytes(&cf->azimuth);
381         swap_4_bytes(&cf->elevation);
382         swap_4_bytes(&cf->range);
383         swap_4_bytes(&cf->longitude);
384         swap_4_bytes(&cf->latitude);
385         swap_4_bytes(&cf->altitude);
386         swap_4_bytes(&cf->height);
387         swap_4_bytes(&cf->speed_east_west);
388         swap_4_bytes(&cf->speed_north_south);
389         swap_4_bytes(&cf->vertical_velocity);
390         swap_4_bytes(&cf->heading);
391         swap_4_bytes(&cf->roll);
392         swap_4_bytes(&cf->pitch);
393         swap_4_bytes(&cf->drift);
394         swap_4_bytes(&cf->rotation_angle);
395         swap_4_bytes(&cf->tilt_angle);
396   }
397   return cf;
398 }
399
400 /**********************************************************************/
401 /*                                                                    */
402 /*                      dorade_read_sensor                            */
403 /*                                                                    */
404 /**********************************************************************/
405 Sensor_desc            *dorade_read_sensor (FILE *in)
406
407          /* Read one 'Sensor #n' descriptor from FILE. */
408 {
409   Sensor_desc            *sd;
410   int i;
411
412   sd = (Sensor_desc *) calloc (1, sizeof(Sensor_desc));
413   if (!sd) {
414         perror("dorade_read_sensor");
415         return NULL;
416   }
417
418   sd->radar_desc = dorade_read_radar_desc(in);
419   sd->nparam = sd->radar_desc->nparam_desc;
420
421   sd->p_desc = (Parameter_desc **) calloc(sd->nparam, sizeof(Parameter_desc *));
422   if (!sd->p_desc) {
423         perror("dorade_read_sensor: sd->p_desc");
424         return sd;
425   }
426   for (i=0; i<sd->nparam; i++) {
427         sd->p_desc[i] = dorade_read_parameter_desc(in);
428   }
429
430   sd->cell_range_vector = dorade_read_cell_range_vector(in);
431   sd->correction_factor_desc = dorade_read_correction_factor_desc(in);
432   return sd;
433 }
434
435
436 /**********************************************************************/
437 /*                                                                    */
438 /*                      dorade_read_sweep_info                        */
439 /*                                                                    */
440 /**********************************************************************/
441 Sweep_info *dorade_read_sweep_info(FILE *in)
442 {
443   Sweep_info *si;
444
445   si = (Sweep_info *) calloc(1, sizeof(Sweep_info));
446   if(!si) {
447         perror("dorade_read_sweep_info");
448         return NULL;
449   }
450
451   if (fread(si, sizeof(Sweep_info), 1, in) != 1) {
452         perror("dorade_read_sweep_info: fread");
453         return NULL;
454   }
455   /* FIXME: ?? For now, VOLD is what we expect when there
456    *           are no more SWIB.  This is a data driven EOF.
457    *           Returning NULL should suffice.
458    */
459   if(strncmp(si->code, "SWIB", 4) != 0) {
460         /* Ignore the rest of the file. */
461         free(si);
462         return NULL;
463   }
464
465   /* Now, convert from Big Endian. */
466   if (do_swap) {
467         swap_4_bytes(&si->len);
468         swap_4_bytes(&si->sweep_num);
469         swap_4_bytes(&si->nrays);
470         swap_4_bytes(&si->start_angle);
471         swap_4_bytes(&si->stop_angle);
472         swap_4_bytes(&si->fixed_angle);
473         swap_4_bytes(&si->filter_flag);
474   }
475
476   return si;
477 }
478
479 /* Data Ray routines. */
480
481 /**********************************************************************/
482 /*                                                                    */
483 /*                      dorade_read_ray_info                          */
484 /*                                                                    */
485 /**********************************************************************/
486 Ray_info       *dorade_read_ray_info      (FILE *in)
487 {
488   Ray_info *ri;
489
490   ri = (Ray_info *) calloc(1, sizeof(Ray_info));
491   if(!ri) {
492         perror("dorade_read_ray_info");
493         return NULL;
494   }
495
496   if (fread(ri, sizeof(Ray_info), 1, in) != 1) {
497         perror("dorade_read_ray_info: fread");
498         return NULL;
499   }
500   /* Now, convert from Big Endian. */
501   if (do_swap) {
502         swap_4_bytes(&ri->len);
503         swap_4_bytes(&ri->sweep_num);
504         swap_4_bytes(&ri->jday);
505         swap_2_bytes(&ri->hour);
506         swap_2_bytes(&ri->minute);
507         swap_2_bytes(&ri->second);
508         swap_2_bytes(&ri->msec);
509         swap_4_bytes(&ri->azimuth);
510         swap_4_bytes(&ri->elevation);
511         swap_4_bytes(&ri->peak_power);
512         swap_4_bytes(&ri->scan_rate);
513         swap_4_bytes(&ri->status);
514   }
515
516   return ri;
517 }
518
519 /**********************************************************************/
520 /*                                                                    */
521 /*                      dorade_read_platform_info                     */
522 /*                                                                    */
523 /**********************************************************************/
524 Platform_info  *dorade_read_platform_info (FILE *in)
525 {
526   Platform_info *pi;
527   int len_first_two;
528
529   pi = (Platform_info *) calloc(1, sizeof(Platform_info));
530   if(!pi) {
531         perror("dorade_read_platform_info");
532         return NULL;
533   }
534
535   /* Read the id code to make sure we have "ASIB" for platform info.  If
536    * id is ASIB, then read data into the Platform_info structure.  If it is
537    * XSTF, read and discard remainder of block, which will have a different
538    * size than Platform_info.  XSTF is undocumented, but apparently it takes
539    * the place of ASIB when radar is grounded.
540    */
541
542   if (fread(pi->code, sizeof(pi->code), 1, in) != 1 ||
543       fread(&pi->len, sizeof(pi->len), 1, in) != 1) {
544       perror("dorade_read_platform_info: fread");
545       return NULL;
546   }
547   if (do_swap) swap_4_bytes(&pi->len);
548   len_first_two = sizeof(pi->code) + sizeof(pi->len);
549     
550   if (strncmp(pi->code, "ASIB", 4) == 0) {
551       if (fread(&pi->longitude, sizeof(Platform_info)-len_first_two, 1, in) != 1) {
552           perror("dorade_read_platform_info: fread");
553           return NULL;
554       }
555       /* Read past any extra bytes. */
556       if (pi->len > sizeof(Platform_info)) {
557           if (read_extra_bytes(pi->len - sizeof(Platform_info), in) <= 0)
558               fprintf(stderr,"Called from %s, line: %d\n",__FILE__,__LINE__-1);
559       }
560       /* Now, convert from Big Endian. */
561       if (do_swap) {
562           swap_4_bytes(&pi->longitude);
563           swap_4_bytes(&pi->latitude);
564           swap_4_bytes(&pi->altitude);
565           swap_4_bytes(&pi->height);
566           swap_4_bytes(&pi->ew_speed);
567           swap_4_bytes(&pi->ns_speed);
568           swap_4_bytes(&pi->v_speed);
569           swap_4_bytes(&pi->heading);
570           swap_4_bytes(&pi->roll);
571           swap_4_bytes(&pi->pitch);
572           swap_4_bytes(&pi->drift);
573           swap_4_bytes(&pi->rotation);
574           swap_4_bytes(&pi->tilt);
575           swap_4_bytes(&pi->ew_wind_speed);
576           swap_4_bytes(&pi->ns_wind_speed);
577           swap_4_bytes(&pi->v_wind_speed);
578           swap_4_bytes(&pi->heading_rate);
579           swap_4_bytes(&pi->pitch_rate);
580       }
581   } else if (strncmp(pi->code, "XSTF", 4) == 0) {
582       /* Read to end of XSTF block. */
583       if (read_extra_bytes(pi->len - len_first_two, in) <= 0)
584           fprintf(stderr,"Called from %s, line: %d\n", __FILE__, __LINE__ - 1);
585   } else {
586       fprintf(stderr,"Unexpected block id: \"%s\"."
587           "  Expected \"ASIB\" or \"XSTF\"\n", pi->code);
588   }
589
590   return pi;
591 }
592
593 /**********************************************************************/
594 /*                                                                    */
595 /*                      dorade_read_parameter_data                    */
596 /*                                                                    */
597 /**********************************************************************/
598
599 Parameter_data *dorade_read_parameter_data(FILE *in)
600 {
601   Parameter_data *pd;
602   int len;
603
604   pd = (Parameter_data *) calloc(1, sizeof(Parameter_data));
605   if(!pd) {
606         perror("dorade_read_parameter_data: pd");
607         return NULL;
608   }
609
610   if (fread(&pd->code, sizeof(pd->code), 1, in) != 1 ||
611       fread(&pd->len, sizeof(pd->len), 1, in) != 1 ||
612       fread(&pd->name, sizeof(pd->name), 1, in) != 1) {
613         perror("dorade_read_parameter_data: fread");
614         return NULL;
615   }
616   if (do_swap) swap_4_bytes(&pd->len);
617   /* Length is in parameter data block? or calculate if from pd->len. */
618
619   len = pd->len  /* Use pd->len for now. */
620         - sizeof(pd->code) /* Remove a few bytes from */
621         - sizeof(pd->len)  /* the count.              */
622         - sizeof(pd->name);
623   pd->data = (char *)calloc(len, sizeof(char));
624   if (!pd->data) {
625         perror("dorade_read_parameter_data: pd->data");
626         return pd;
627   }
628   if (fread(pd->data, sizeof(char), len, in) != len) {
629         perror("dorade_read_parameter_data: fread");
630         return NULL;
631   }
632   
633   /* FIXME: Big endian conversion in caller?  Is that the right place? */
634
635   return pd;
636 }
637 /**********************************************************************/
638 /*                                                                    */
639 /*                      dorade_read_sweep                             */
640 /*                                                                    */
641 /**********************************************************************/
642 Sweep_record *dorade_read_sweep(FILE *fp, Sensor_desc **sd)
643 {
644   Sweep_record   *sr;
645
646   Sweep_info     *si;
647   Ray_info       *ri;
648   Platform_info  *pi;
649   Parameter_data *pd;
650   Parameter_desc **parameter_desc;
651
652   int i, j, k,len;
653   int nparam;
654
655   sr = (Sweep_record *) calloc (1, sizeof(Sweep_record));
656   if (!sr) {
657         perror("dorade_read_sweep");
658         return NULL;
659   }
660
661   nparam         = sd[0]->nparam;
662   parameter_desc = sd[0]->p_desc;
663
664  /* Expect SWIB */
665   sr->s_info = si = dorade_read_sweep_info(fp);
666   if (!si) {
667         free(sr);
668         return NULL;  /* EOF or error. */
669   }
670   sr->nrays = si->nrays;
671   if (dorade_verbose) {
672         printf("=====< NEW SWIB >=====\n");
673         dorade_print_sweep_info(si);
674   }
675   sr->data_ray = (Data_ray **) calloc(si->nrays, sizeof(Data_ray *));
676   if (!sr->data_ray) {
677         free(sr);
678         return NULL;  /* EOF or error. */
679   }
680
681   for (i=0; i<si->nrays; i++) {
682         if (dorade_verbose) printf("---------- Ray %d ----------\n", i);
683         sr->data_ray[i] = (Data_ray *) calloc(1, sizeof(Data_ray));
684         if (!sr->data_ray[0]) {
685           free(sr);
686           return NULL;  /* EOF or error. */
687         }
688         ri = dorade_read_ray_info(fp);
689         if (dorade_verbose) {
690           dorade_print_ray_info(ri);
691         }
692         pi = dorade_read_platform_info(fp);
693         if (dorade_verbose) {
694           dorade_print_platform_info(pi);
695         }
696         sr->data_ray[i]->ray_info = ri;
697         sr->data_ray[i]->platform_info = pi;
698         sr->data_ray[i]->parameter_data = (Parameter_data **) calloc(nparam, sizeof(Parameter_data *));
699         sr->data_ray[i]->data_len  = (int *) calloc(nparam, sizeof(int));
700         sr->data_ray[i]->word_size = (int *) calloc(nparam, sizeof(int));
701         sr->data_ray[i]->nparam    = nparam;
702
703         for (j=0; j<nparam; j++) {
704           pd = dorade_read_parameter_data(fp);
705           /* Perform big endian conversion. */
706           len = pd->len  /* Use pd->len for now. */
707                 - sizeof(pd->code) /* Remove a few bytes from */
708                 - sizeof(pd->len)  /* the count.              */
709                 - sizeof(pd->name);
710           sr->data_ray[i]->parameter_data[j] = pd;
711           sr->data_ray[i]->data_len[j] = len;
712           if (parameter_desc[j]->parameter_type == 2)
713                 sr->data_ray[i]->word_size[j] = 2; /* 2 bytes per word */
714           else if (parameter_desc[j]->parameter_type == 3 ||
715                            parameter_desc[j]->parameter_type == 4)
716                 sr->data_ray[i]->word_size[j] = 4; /* 4 bytes per word */
717                 
718           if (do_swap) { /* Numbers were read big-endian. */
719                 if (sr->data_ray[i]->word_size[j] == 2)
720                   for (k=0; k<len; k+=2)
721                         swap_2_bytes(&pd->data[k]);
722                 else if (sr->data_ray[i]->word_size[j] == 4)
723                   for (k=0; k<len; k+=4)
724                         swap_4_bytes(&pd->data[k]);
725           }
726         }
727   }
728   return sr;
729 }
730
731
732 /* MEMORY MANAGEMENT ROUTINES */
733
734 /**********************************************************************/
735 /*                                                                    */
736 /*                      dorade_free_data_ray                          */
737 /*                                                                    */
738 /**********************************************************************/
739 void dorade_free_data_ray(Data_ray *r)
740 {
741   int i;
742   if (r == NULL) return;
743
744   free(r->ray_info);
745   free(r->platform_info);
746   if (r->parameter_data) {
747         for (i=0; i<r->nparam; i++)
748           free(r->parameter_data[i]);
749         free(r->parameter_data);
750   }
751   free(r);
752 }
753
754 /**********************************************************************/
755 /*                                                                    */
756 /*                      dorade_free_sweep                             */
757 /*                                                                    */
758 /**********************************************************************/
759 void dorade_free_sweep(Sweep_record *s)
760 {
761   int i;
762   if (s == NULL) return;
763   
764   if (s->data_ray) {
765         for (i=0; i<s->nrays; i++)
766           dorade_free_data_ray(s->data_ray[i]);
767         free(s->data_ray);
768   }
769   if (s->s_info) free(s->s_info);
770   free(s);
771 }