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