1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 /*
9  * $Header: /src/master/dx/src/exec/dxmods/genimp_io.c,v 1.10 2006/01/04 22:00:51 davidt Exp $
10  */
11 
12 #include <dxconfig.h>
13 
14 
15 /*
16  * There are four variables fields(f), series(s), grid(g) and structure(d).
17  * I am representing them from slow to fastest changing variable index.
18  *
19  * 1.  f, s, g, d :- vector
20  * 2.  f, s, d, g :- vector-record ?
21  * 3.  f, d, s, g
22  * 4.  f, d, g, s
23  * 5.  f, g, s, d
24  * 6.  f, g, d, s
25  * 7.  s, f, g, d :- record-vector
26  * 8.  s, f, d, g :- record
27  * 9.  s, g, f, d :- field
28  *10.  g, f, s, d
29  *11.  g, s, f, d
30  *12.  g, f, d, s
31  */
32 
33 #include <string.h>
34 #include "genimp.h"
35 
36 static int  FgetAsciiData(FILE *, void **, int);
37 static int  FgetBinaryData(FILE *, void **, int);
38 static int  RgetAsciiData(FILE *, void **, int);
39 static int  RgetBinaryData(FILE *, void **, int);
40 static int  VgetAsciiData(FILE *, void **, int);
41 static int  VgetBinaryData(FILE *, void **, int);
42 static int  RVgetAsciiData(FILE *, void **, int);
43 static int  RVgetBinaryData(FILE *, void **, int);
44 
45 static Error convert_string(char *s, Type t, void *data, int index, int *nl);
46 static Error read_ascii(FILE *fp, Type t, void *data, int index);
47 static Error skip_header(FILE *fp,struct header *);
48 static Error skip_bdata(FILE *fp, int toskip);
49 static Error skip_ascii(FILE *fp, int num);
50 static Error doread(void *p, int size, int cnt, FILE* fp);
51 static Error skip_numchar( FILE *, int, char **);
52 static void add_parse_message(char *op, int s, int f, int item, int comp);
53 static void *reorderData(void *data, int f);
54 static Pointer locations2float(Pointer from, Type from_type, int cnt);
55 static Error _dxf_getline(char **, FILE *);
56 static Error extract_fromline(char str[MAX_DSTR],int which);
57 
58 #if !defined(DXD_STANDARD_IEEE)
59 static void _dxfdenormalize(void **);
60 #endif
61 
62 static int (* FgetData[])(FILE *, void **, int) = {
63   FgetAsciiData,
64   FgetBinaryData};
65 static int (* RgetData[])(FILE *, void **, int) = {
66   RgetAsciiData,
67   RgetBinaryData};
68 static int (* VgetData[])(FILE *, void **, int) = {
69   VgetAsciiData,
70   VgetBinaryData};
71 static int (* RVgetData[])(FILE *, void **, int) = {
72   RVgetAsciiData,
73   RVgetBinaryData};
74 
75 /*
76  * DXRead the data file as specified by the general import file.
77  * The data for series s and field f is placed in the buffer pointed
78  * to by XF[s*_dxd_gi_numflds + f].  After reading in the raw data from the
79  * file, we must
80  *	1) Change column majority data to row majority.
81  *	2) DXSwap byte order if they differ and it was binary data.
82  *	3) Denormalize floating point data for the PVS.
83  * So what is a returned in each XF[i] buffer is the data for each field
84  * of each requested series, in the correct majority and byte order.
85  *
86  * See genimp.c:import_Group for a discussion of XF.
87  */
_dxf_gi_read_file(void ** XF,FILE ** fp)88 int _dxf_gi_read_file(void **XF,FILE **fp)
89 {
90   int size,s,nitems,i,f;
91 
92   /*
93    * DXRead the raw data into the XF[i].
94    */
95   if(!(_dxf_gi_importDatafile(XF,fp)))
96     goto error;
97 
98   /*size = _dxfnumGridPoints();*/
99 
100   /*
101    * Change the majority if the input data is in column majority order.
102    */
103   if ( _dxd_gi_majority == COL ) {
104     for (s=i=0 ; i<_dxd_gi_series ; i++, s+=_dxd_gi_numflds) {
105 	for (f=0 ; f<_dxd_gi_numflds ; f++) {
106 	    size = _dxfnumGridPoints(f);
107 	    if (XF[s+f]) {
108                 XF[s+f] = reorderData(XF[s+f],f);
109 		if (!XF[s+f])
110             		goto error;
111 	    }
112 	}
113     }
114   }
115 
116   /*
117    * Change the byte order if necessary.
118    */
119   if ((_dxd_gi_format == BINARY) &&
120       (_dxfLocalByteOrder() != _dxd_gi_byteorder)) {
121 	for (f=0 ; f<_dxd_gi_numflds ; f++) {
122 	    if (_dxd_gi_whichflds[f]  == ON) {
123 	        size = _dxfnumGridPoints(f);
124 	        nitems = size * _dxd_gi_var[f]->datadim;
125 	        for (s=i=0 ; i<_dxd_gi_series ; i++, s+=_dxd_gi_numflds)
126 		    if ((_dxd_gi_whichser[i] == ON)  &&
127 	            	!_dxfByteSwap(XF[s+f], XF[s+f],
128 				nitems, _dxd_gi_var[f]->datatype))
129 			goto error;
130 	    }
131 	}
132   }
133 
134 #if !defined(DXD_STANDARD_IEEE)
135   /*
136    * Denormalize the IEEE floating point numbers.
137    */
138    _dxfdenormalize(XF);
139 #endif /* !normal ieee */
140 
141   /*
142    * If user has used the 'locations' keyword and the locations are
143    * not type float, then convert them to floats.
144    * Note that if we convert, then we free the old array.
145    */
146     if ((_dxd_gi_positions == FIELD_PRODUCT) &&
147 	(_dxd_gi_var[_dxd_gi_loc_index]->datatype != TYPE_FLOAT)) {
148 	int nfloats=0;
149 	Type ltype;
150         size = _dxfnumGridPoints(_dxd_gi_loc_index);
151 	nfloats = _dxd_gi_var[_dxd_gi_loc_index]->datadim * size;
152 	ltype = _dxd_gi_var[_dxd_gi_loc_index]->datatype;
153 	for (s=0 ; s<_dxd_gi_series ; s++) {
154 	    if (_dxd_gi_whichser[s] == ON) {
155 		Pointer new_XF;
156 	        i = s*_dxd_gi_numflds + _dxd_gi_loc_index;
157 		new_XF = locations2float( XF[i], ltype, nfloats);
158 		if (!new_XF) goto error;
159 		DXFree(XF[i]);
160 		XF[i] = new_XF;
161        	    }
162 	}
163 	_dxd_gi_var[_dxd_gi_loc_index]->datatype = TYPE_FLOAT;
164 	_dxd_gi_var[_dxd_gi_loc_index]->databytes = DXTypeSize(TYPE_FLOAT);
165    }
166 
167    return OK;
168 
169 error:
170   return ERROR;
171 }
172 
173 /*
174     FN:  open the data file
175 */
176 Error
_dxf_gi_OpenFile(char * name,FILE ** fp,int infofile)177 _dxf_gi_OpenFile(char *name, FILE **fp, int infofile)
178 {
179   int i;
180   char *outname, *f;
181   static char infopath[256];	/* Save the path when opening the info file */
182 
183 
184   /* try to open the filename as given, and save the name
185    *  for error messages later.
186    */
187   outname = NULL;
188   if (!infofile && (strlen(infopath) > 0)) {
189       if (!(*fp = _dxfopen_dxfile(name,infopath,&outname,".general")))
190 	 goto error;
191   }
192   else{
193       if (!(*fp = _dxfopen_dxfile(name,NULL,&outname,".general")))
194 	 goto error;
195       /*
196        * Save the path to the info file so that we can use it to open the
197        * the data file if necessary.
198        */
199       if (infofile) {
200 	if (strchr(outname,'/'))  {
201 	    strcpy(infopath,outname);
202 	    for (i=strlen(outname)-1 ; i>=0 ; i--) {
203 		if (infopath[i] == '/') {
204 		    infopath[i+1] = '\0';
205 		    break;
206 		}
207 	    }
208 	} else
209 	    infopath[0] = '\0';
210       }
211    }
212    DXFree(outname);
213    return OK;
214 
215 error:
216   if (outname) DXFree(outname);
217   infopath[0] = '\0';
218   if (infofile)
219 	f = "general import file";
220   else
221 	f = "data file";
222   DXSetError(ERROR_BAD_PARAMETER, "#10903", f, name);
223   return ERROR;
224 }
225 
226 
227 /*
228    FN: According to the interleaving technique it calls different getdata
229        routines.
230    RT: Returns OK if succesful otherwise an ERROR.
231 */
232 
_dxf_gi_importDatafile(void ** data,FILE ** fp)233 int _dxf_gi_importDatafile(void **data,FILE **fp)
234 {
235   int size, gd=ERROR;
236 
237   /*size = _dxfnumGridPoints();*/
238   size = _dxfnumGridPoints(-1);
239 
240   if(!*fp && !_dxf_gi_OpenFile(_dxd_gi_filename, fp, 0)) /* 0 = data file */
241     goto error;
242 
243   if ((_dxd_gi_header.type != SKIP_NOTHING)&& !skip_header(*fp,&_dxd_gi_header))
244       goto error;
245 
246   switch (_dxd_gi_interleaving) {
247       case IT_RECORD_VECTOR:
248        	if(!(gd = (* RVgetData[_dxd_gi_format])(*fp, data, size)))
249 	    goto error;
250 	break;
251       case IT_FIELD:
252         if(!(gd = (* FgetData[_dxd_gi_format])(*fp, data, size)))
253 	    goto error;
254 	break;
255       case IT_RECORD:
256         if (!(gd = (* RgetData[_dxd_gi_format])(*fp, data, size)))
257 	    goto error;
258 	break;
259       case IT_VECTOR:
260      	if (!(gd = (* VgetData[_dxd_gi_format])(*fp, data, size)))
261 	    goto error;
262 	break;
263       default:
264 	DXErrorGoto(ERROR_INTERNAL,"Unexpected interleave");
265   }
266 
267   return(gd);
268 
269  error:
270   return ERROR;
271 }
272 
273 /*
274   FN: Field interleaving ascii data read routine.
275 */
276 
FgetAsciiData(FILE * fp,void ** data,int size)277 static int FgetAsciiData(FILE *fp, void **data, int size)
278 {
279   int cnt, f, k, comp, d, dim, width;
280   int step, s,nl=0,maxseries,sersize=0;
281   char *str, r[MAX_DSTR], *op;
282   Type t;
283 
284   size = _dxfnumGridPoints(0);
285 
286   /* what is the max series input */
287   for (s=_dxd_gi_series-1; s>=0; s--)
288      if (_dxd_gi_whichser[s] == ON) break;
289   maxseries = s+1;
290   /* how many numbers per series */
291   for (f=0; f<_dxd_gi_numflds; f++){
292      if (_dxd_gi_var[f]->datatype==TYPE_STRING) dim=1;
293      else dim = _dxd_gi_var[f]->datadim;
294      sersize += dim;
295   }
296   sersize = size * sersize;
297 
298   if ( _dxd_gi_asciiformat == FREE )
299     {
300       for (s=step= 0; s<maxseries; s++, step += _dxd_gi_numflds)
301 	{
302 	  for (cnt = 0; cnt < size; cnt++)
303 	    {
304 	      for (f = 0; f < _dxd_gi_numflds; f++)
305 		{
306 		  t = _dxd_gi_var[f]->datatype;
307 		  dim = _dxd_gi_var[f]->datadim;
308 		  if (_dxd_gi_whichflds[f] == ON && _dxd_gi_whichser[s] == ON)
309 		    {
310 		      for (comp = 0; comp < dim; comp++)
311 			{
312 			  d = (cnt*dim) + comp;
313 			  if (!read_ascii(fp,t,data[step+f],d)) {
314 			    op = "Reading";
315 			    goto parse_error;
316 			  }
317 			  if (t==TYPE_STRING) comp=dim;
318 			}
319 		    }
320 		  else
321 		    {
322 		      for (comp = 0; comp < dim; comp++)
323 			{
324 			  if (!skip_ascii(fp,1)) {
325 			    op = "Skipping";
326 			    goto parse_error;
327 			  }
328 			  if (t==TYPE_STRING) comp=dim;
329 			}
330 		    }
331 		}
332 	    }
333            if ((_dxd_gi_series-1) != s && !skip_header(fp,&_dxd_gi_serseparat)){
334                DXAddMessage("error reading series separator %d",s+1);
335                goto error;
336            }
337 	}
338     }
339   else if ( _dxd_gi_asciiformat == FIX )
340     {
341       op = "Reading";
342       str = (char *)DXAllocate(MAX_DSTR);
343       for (s=comp=f=step=0; s < maxseries; s++, step += _dxd_gi_numflds)
344 	{
345 	  for (cnt=0; cnt < size; cnt++)
346 	    {
347 	      if (!_dxf_getline(&str, fp))
348 		{
349 		  DXSetError(ERROR_MISSING_DATA,"#10898","data file");
350 	          f=0;
351 		  goto parse_error;
352 		}
353 	      if (_dxd_gi_whichser[s] == ON)
354 		{
355 	      k = 0;
356 	      for (f=0; f < _dxd_gi_numflds; f++)
357 		{
358 		  k += _dxd_gi_var[f]->leading;
359 	  	  t = _dxd_gi_var[f]->datatype;
360     	  	  dim = _dxd_gi_var[f]->datadim;
361 	  	  width = _dxd_gi_var[f]->width;
362 		  if (_dxd_gi_whichflds[f] == ON)
363 		    {
364 		      for (comp = 0; comp < dim; comp++)
365 			{
366 			  d = (cnt*dim) + comp;
367 			  strncpy(r, &str[k], width);
368 			  r[width] = (char)NULL;
369 			  if (!convert_string(r,t,data[step+f],d,&nl))
370 				goto parse_error;
371 			  k += width;
372 			  if (t==TYPE_STRING) comp=dim;
373 			}
374 		    }
375 		  else
376 		    {
377 		      if (t==TYPE_STRING) dim=1;
378 		      k += dim*width;
379 		    }
380 		}
381 		}
382 	    }
383            if ((_dxd_gi_series-1) != s && !skip_header(fp,&_dxd_gi_serseparat)){
384                DXAddMessage("error reading series separator %d",s+1);
385                goto error;
386            }
387 	}
388         DXFree(str);
389     }
390   else
391     {
392       DXSetError(ERROR_INTERNAL,"Unknown ascii format");
393       goto error;
394     }
395   return OK;
396 
397 parse_error:
398   add_parse_message(op, s,f,cnt,comp);
399 
400 error:
401   return ERROR;
402 }
403 
404 /*
405   FN : Field interleaving binary data read routine.
406 */
407 
FgetBinaryData(FILE * fp,void ** data,int size)408 static int FgetBinaryData(FILE *fp, void **data, int size)
409 {
410   int i, j, k, len, step, d, s, type_size;
411   char *p=NULL, *op,*tp;
412   int maxseries;
413 
414   size = _dxfnumGridPoints(0);		/* all fields same size */
415 
416   for( len=j=0; j<_dxd_gi_numflds; j++)
417       len += _dxd_gi_var[j]->databytes * _dxd_gi_var[j]->datadim;
418 
419   if (!(p = (char *)DXAllocate(len)) )
420       goto error;
421 
422   /* what is the max series input */
423   for (s=_dxd_gi_series-1; s>=0; s--)
424      if (_dxd_gi_whichser[s] == ON) break;
425   maxseries = s+1;
426 
427   for (s=step = 0; s < maxseries; s++, step += _dxd_gi_numflds)
428     {
429       for(i=0; i<size; i++)
430 	{
431 	  if (_dxd_gi_whichser[s] == OFF)  {
432               if (!skip_bdata(fp, len*size)) {
433 		  op = "skip";
434 		  goto parse_error;
435 	      }
436 	      continue;
437 	  } else {
438               if (!doread(p, 1, len, fp)) {
439 		  op = "read";
440 		  goto parse_error;
441 	      }
442 	  }
443           tp = p;
444 	  for(j=0; j<_dxd_gi_numflds; j++)
445 	    {
446 	      type_size = _dxd_gi_var[j]->databytes;
447 	      if (_dxd_gi_whichflds[j] == ON)
448 		{
449 		  for(k=0; k<_dxd_gi_var[j]->datadim; k++)
450 		    {
451 		      d = (i*_dxd_gi_var[j]->datadim) + k;
452 		      switch( _dxd_gi_var[j]->datatype )
453 			{
454 			case TYPE_UBYTE:
455 			  DREF(ubyte,data[step+j],d) = DREF(ubyte,tp,0);
456 			  break;
457  			case TYPE_BYTE:
458 			  DREF(byte,data[step+j],d) = DREF(byte,tp,0);
459 			  break;
460 			case TYPE_SHORT:
461 			  DREF(short,data[step+j],d) = DREF(short,tp,0);
462 			  break;
463 			case TYPE_USHORT:
464 			  DREF(unsigned short,data[step+j],d) = DREF(unsigned                                  short,tp,0);
465      			  break;
466 			case TYPE_INT:
467 			  DREF(int,data[step+j],d) = DREF(int,tp,0);
468 			  break;
469  			case TYPE_UINT:
470 			  DREF(unsigned int,data[step+j],d) = DREF(unsigned                                   int,tp,0);
471 			  break;
472 			case TYPE_FLOAT:
473 			  DREF(float,data[step+j],d) = DREF(float,tp,0);
474 			  break;
475 			case TYPE_DOUBLE:
476 			  DREF(double,data[step+j],d) = DREF(double,tp,0);
477 			  break;
478 			default:
479 			  DXSetError(ERROR_INTERNAL,
480 				   "Unknown data type to read data file");
481 			  goto error;
482 			}
483 		      tp += type_size;
484 		    }
485 		}
486 	      else
487 		{	/* Skip the data for this field */
488 		    tp += _dxd_gi_var[j]->datadim * type_size;
489 		}
490 	    }
491 	}
492        if ((_dxd_gi_series-1) != s && !skip_header(fp,&_dxd_gi_serseparat)){
493           DXAddMessage("error reading series header %d",s+1);
494           goto error;
495        }
496     }
497 
498   DXFree((Pointer) p );
499   return OK;
500 
501 parse_error:
502   if (_dxd_gi_series > 1)
503     DXAddMessage("\nTrying to %s item %d from all fields of series %d",op,s+1);
504   else
505     DXAddMessage("\nTrying to %s item %d from all fields",op);
506 
507  error:
508   if (p) DXFree((Pointer)p);
509   return ERROR;
510 }
511 
512 /*
513   FN: Record interleaving ascii format read.
514 */
515 
RgetAsciiData(FILE * fp,void ** data,int size)516 static int RgetAsciiData(FILE *fp, void **data, int size)
517 {
518   int cnt=0, f, comp, d, dim, ll=0, kk, elements,leading,width;
519   int step, s, nl=0,maxseries;
520   char *str, r[MAX_DSTR], *op;
521   Type t;
522   struct header rec_sep;
523 
524   /* what is the max series input */
525   for (s=_dxd_gi_series-1; s>=0; s--)
526      if (_dxd_gi_whichser[s] == ON) break;
527   maxseries = s+1;
528 
529   if ( _dxd_gi_asciiformat == FREE )
530     {
531       for (s=step = 0; s < maxseries; s++, step += _dxd_gi_numflds)
532 	{
533 	  for (f = 0; f < _dxd_gi_numflds; f++)
534 	    {
535 	      size = _dxfnumGridPoints(f);
536 	      dim = _dxd_gi_var[f]->datadim;
537 	      t = _dxd_gi_var[f]->datatype;
538 	      if (_dxd_gi_whichflds[f] == ON && _dxd_gi_whichser[s] == ON)
539 		{
540 		  for (comp = 0; comp < dim; comp++)
541 		    {
542 		      d = comp;
543 		      for (cnt = 0; cnt < size; cnt++)
544 			{
545 			  if (!read_ascii(fp,t,data[step+f],d))  {
546 		            op = "Reading";
547 			    goto parse_error;
548 			  }
549 			  d += dim;
550 			}
551 	                if (t == TYPE_STRING) dim=1;
552                       /* skip according to record separator */
553                       rec_sep = _dxd_gi_var[f]->rec_separat[comp];
554                       if (!skip_header(fp,&rec_sep)){
555                          op = "record separator";
556                          goto parse_error;
557                       }
558 		    }
559 		}
560 	      else
561 		{
562 		  for (comp = 0; comp < dim; comp++)
563 		    {
564 		      if (!skip_ascii(fp,size)) 	/* read one record */
565 			 goto error;
566                       rec_sep = _dxd_gi_var[f]->rec_separat[comp];
567                       if (!skip_header(fp,&rec_sep)){
568                          op = "record separator";
569                          goto parse_error;
570                       }
571 	              if (t == TYPE_STRING) dim=1;
572 		    }
573 		}
574 	    }
575            if ((_dxd_gi_series-1) != s && !skip_header(fp,&_dxd_gi_serseparat)){
576                DXAddMessage("error reading series separator %d",s+1);
577                goto error;
578            }
579         }
580     }
581   else if ( _dxd_gi_asciiformat == FIX )
582     {
583       op = "Reading";
584       str = (char *)DXAllocate(MAX_DSTR);
585       for (s=step= 0; s < maxseries; s++, step += _dxd_gi_numflds)
586 	{
587 	  for (f = 0; f < _dxd_gi_numflds; f++)
588 	    {
589 	      size = _dxfnumGridPoints(f);
590 	      t = _dxd_gi_var[f]->datatype;
591     	      dim = _dxd_gi_var[f]->datadim;
592 	      elements = _dxd_gi_var[f]->elements;
593 	      leading = _dxd_gi_var[f]->leading;
594 	      width = _dxd_gi_var[f]->width;
595 	      for (comp = 0; comp < dim; comp++)
596 		{
597 		  d = comp;
598 		  for (cnt=0; cnt<size; cnt+=elements)
599 		    {
600 		      if (!(skip_numchar(fp, leading, &str)))
601 			goto parse_error;
602 		      kk = 0;
603 		      for( ll=0; ll<elements; ll++)
604 			{
605 			  if (cnt+ll < size)
606 			    {
607 			      strncpy(r, &str[kk], width);
608 			      r[width] = (char)NULL;
609 			      if (_dxd_gi_whichflds[f] == ON &&
610 				  _dxd_gi_whichser[s] == ON)
611 				{
612 				  if (!convert_string(r,t,data[step+f],d,&nl))
613 				    goto parse_error;
614  				  if (nl==1){
615 	                            if (!(skip_numchar(fp, leading, &str)))
616                                       goto parse_error;
617 				    kk=0;
618 				    nl=0;
619 				    ll--;
620  				  }
621 				  else{
622 				     kk+=width;
623 				     d+=dim;
624 				  }
625 				}
626 			      else
627 			        {
628 			         if (r[0] == '\n'){
629 				   ll--;
630 				   kk=0;
631 				   if (!skip_numchar(fp,leading,&str))
632 				      goto parse_error;
633 			         }
634 			         else{
635 				   d+=dim;
636 			           kk+=width;
637 				 }
638 				}
639 			    }
640 			}
641 		    }
642 	            if (t == TYPE_STRING) dim=1;
643                     rec_sep = _dxd_gi_var[f]->rec_separat[comp];
644                     if (!skip_header(fp,&rec_sep)){
645                        op = " record separator";
646                        goto parse_error;
647                     }
648 		}
649 	    }
650           if ((_dxd_gi_series-1) != s && !skip_header(fp,&_dxd_gi_serseparat)){
651             DXAddMessage("error reading series separator %d",s+1);
652             goto error;
653           }
654         }
655         DXFree(str);
656     }
657   return OK;
658 
659 parse_error:
660   add_parse_message(op,s,f,cnt+ll,comp);
661  error:
662   return ERROR;
663 }
664 
665 /*
666   FN: Record interleaving binary read.
667 */
RgetBinaryData(FILE * fp,void ** data,int size)668 static int RgetBinaryData(FILE *fp, void **data, int size)
669 {
670   int i, j, k, maxlen, len, step, d, incd, s;
671   char *p=NULL, *op;
672   struct header rec_sep;
673   int maxseries;
674 
675   for(maxlen=j=0; j<_dxd_gi_numflds; j++) {
676 	  len = size * _dxd_gi_var[j]->datadim * _dxd_gi_var[j]->databytes;
677 	  maxlen =  (len > maxlen ? len : maxlen);
678   }
679   if (!(p = (char *)DXAllocate(maxlen)))
680       goto error;
681 
682   /* what is the max series input */
683   for (s=_dxd_gi_series-1; s>=0; s--)
684      if (_dxd_gi_whichser[s] == ON) break;
685   maxseries = s+1;
686 
687   for (s=step=0; s < maxseries; s++, step += _dxd_gi_numflds)
688     {
689       for(j=0; j<_dxd_gi_numflds; j++) {
690 	  size = _dxfnumGridPoints(j);
691           incd = _dxd_gi_var[j]->datadim;
692           for(k=0; k<_dxd_gi_var[j]->datadim; k++) {
693 	     d = k;
694  	     len = size * _dxd_gi_var[j]->databytes;
695              if (_dxd_gi_whichser[s]==OFF || _dxd_gi_whichflds[j]==OFF){
696                   if(!(skip_bdata(fp, len))) {
697                      op = "skip";
698                      goto parse_error;
699                   }
700              }
701              else {
702                   if (!doread(p, 1, len, fp)) {
703                       op = "read";
704                       goto parse_error;
705                   }
706 		  switch( _dxd_gi_var[j]->datatype ) {
707 		    case TYPE_UBYTE:
708 		      for(i=0; i<size; i++) {
709 			  DREF(ubyte,data[step+j],d) = DREF(ubyte,p, i);
710 			  d += incd;
711 		      }
712       		      break;
713 		    case TYPE_BYTE:
714 		      for(i=0; i<size; i++) {
715 			  DREF(byte,data[step+j],d) = DREF(byte,p, i);
716 			  d += incd;
717 		      }
718 		      break;
719 		    case TYPE_SHORT:
720 		      for(i=0; i<size; i++) {
721 			  DREF(short,data[step+j],d) = DREF(short,p,i);
722 			  d += incd;
723 		      }
724  		      break;
725 		    case TYPE_USHORT:
726 		      for(i=0; i<size; i++) {
727 	                  DREF(unsigned short,data[step+j],d) = DREF(unsigned                                  short,p,i);
728 			  d += incd;
729 		      }
730 		      break;
731 		    case TYPE_INT:
732 		      for(i=0; i<size; i++) {
733 			  DREF(int,data[step+j],d) = DREF(int,p,i);
734 			  d += incd;
735 		      }
736 		      break;
737 		    case TYPE_UINT:
738 		      for(i=0; i<size; i++) {
739 			  DREF(unsigned int,data[step+j],d) = DREF(unsigned                                   int,p,i);
740 			  d += incd;
741 		      }
742 		      break;
743 		    case TYPE_FLOAT:
744 		      for(i=0; i<size; i++) {
745 			  DREF(float,data[step+j],d) = DREF(float,p,i);
746 			  d += incd;
747 		      }
748 		      break;
749 		    case TYPE_DOUBLE:
750 		      for(i=0; i<size; i++) {
751 			  DREF(double,data[step+j],d)=DREF(double,p,i);
752 			  d += incd;
753 		      }
754 		      break;
755 		    default:
756 		      DXSetError(ERROR_INTERNAL,
757 			       "Unknown data type to read data file");
758 		      goto error;
759 		    }
760                  }
761                  rec_sep = _dxd_gi_var[j]->rec_separat[k];
762                  if (!skip_header(fp,&rec_sep)){
763                     op = " record separator";
764                     goto parse_error;
765                  }
766            }
767 	}
768       if ((_dxd_gi_series-1) != s && !skip_header(fp,&_dxd_gi_serseparat)){
769           DXAddMessage("error reading series separator %d",s+1);
770           goto error;
771       }
772     }
773 
774   DXFree((Pointer) p );
775   return OK;
776 
777 parse_error:
778   if (_dxd_gi_series > 1)
779     DXAddMessage("\nTrying to %s field '%s' of series %d",op,_dxd_gi_var[j]->name,s+1);
780   else
781     DXAddMessage("\nTrying to %s field '%s'",op,_dxd_gi_var[j]->name);
782 error:
783   if (p) DXFree((Pointer)p);
784   return ERROR;
785 }
786 
787 /*
788   FN: Vector interleaving ascii file format read.
789 */
790 
VgetAsciiData(FILE * fp,void ** data,int size)791 static int VgetAsciiData(FILE *fp, void **data, int size)
792 {
793   int s, f, l=0, ll, kk, dim, elements, leading, width;
794   int step, dim_mul_size,nl=0;
795   char *str, r[MAX_DSTR], *op;
796   Type t;
797   struct header rec_sep;
798   int offset = 1, d;
799 
800   if ( _dxd_gi_asciiformat == FREE )
801     {
802       for (f = 0; f < _dxd_gi_numflds; f++)
803 	{
804 	  size = _dxfnumGridPoints(f);
805 	  t = _dxd_gi_var[f]->datatype;
806     	  dim = _dxd_gi_var[f]->datadim;
807 	  offset = 1;
808 	  if (t == TYPE_STRING) {
809 	     offset = dim;
810 	     dim = 1;
811 	  }
812 	  for (s = 0; s < _dxd_gi_series; s++)
813 	    {
814 	      if (_dxd_gi_whichflds[f] == ON && _dxd_gi_whichser[s] == ON)
815 		{
816 		  step = s*_dxd_gi_numflds;
817 		  for (l = 0, d = 0; l < dim*size; l++) {
818 		    if (!read_ascii(fp,t,data[step+f],d)) {
819       			op = "Reading";
820 		        goto parse_error;
821 		    }
822 		    d += offset;
823 		  }
824 		}
825 	      else
826 		{
827 		   if (!skip_ascii(fp,size*dim)) {
828       		      op = "Skipping";
829 		      goto parse_error;
830 		   }
831 		}
832                if ((_dxd_gi_series-1) != s && !skip_header(fp,&_dxd_gi_serseparat)){
833                   DXAddMessage("error reading series separator %d",s+1);
834                   goto error;
835                }
836 	    }
837                     rec_sep = _dxd_gi_var[f]->rec_separat[0];
838                     if (!skip_header(fp,&rec_sep)){
839                        op = " record separator";
840                        goto parse_error;
841                     }
842 	}
843     }
844   else if ( _dxd_gi_asciiformat == FIX )
845     {
846       op = "Reading";
847       str = (char *)DXAllocate(MAX_DSTR);
848       for (f = 0; f < _dxd_gi_numflds; f++)
849 	{
850 	  size = _dxfnumGridPoints(f);
851 	  t = _dxd_gi_var[f]->datatype;
852     	  dim = _dxd_gi_var[f]->datadim;
853 	  elements = _dxd_gi_var[f]->elements;
854 	  leading = _dxd_gi_var[f]->leading;
855 	  width = _dxd_gi_var[f]->width;
856 	  offset = 1;
857 	  if (t == TYPE_STRING) {
858 	     offset = dim;
859 	     dim=1;
860 	  }
861 	  dim_mul_size = dim*size;
862 	  for (s = 0; s < _dxd_gi_series; s++)
863 	    {
864 	      step = s*_dxd_gi_numflds;
865 	      for (l = 0, d = 0; l < dim_mul_size; l+=elements)
866 		{
867 		  if (!(skip_numchar(fp, leading, &str)))
868 		    goto parse_error;
869 		  kk = 0;
870 		  for( ll=0; ll<elements; ll++)
871 		    {
872 		      if ( l+ll < dim_mul_size )
873 			{
874 			  if (_dxd_gi_whichflds[f] == ON && _dxd_gi_whichser[s] == ON)
875 			    {
876 			      strncpy(r, &str[kk], width);
877 			      r[width] = (char)NULL;
878 			      if (!convert_string(r,t,data[step+f],d,&nl))
879 				goto parse_error;
880 			      if (nl==1){
881 				nl=0;
882 				kk=0;
883 				ll--;
884                                 if (!(skip_numchar(fp, leading, &str)))
885                                   goto parse_error;
886 			      }
887 			      else{
888 				d += offset;
889 				kk+=width;
890 			      }
891 			    }
892 			  else
893 			    {
894 			      if (r[0] == '\n'){
895 				 ll--;
896 				 kk=0;
897 				 if (!skip_numchar(fp,leading,&str))
898 				    goto parse_error;
899 			      }
900 			      else{
901 				 d += offset;
902 			         kk += width;
903 			      }
904 			    }
905 			}
906 		    }
907 		}
908                 if ((_dxd_gi_series-1) != s && !skip_header(fp,&_dxd_gi_serseparat)){
909                   DXAddMessage("error reading series separator %d",s+1);
910                   goto error;
911                 }
912 	    }
913                     rec_sep = _dxd_gi_var[f]->rec_separat[0];
914                     if (!skip_header(fp,&rec_sep)){
915                        op = " record separator";
916                        goto parse_error;
917                     }
918 	}
919         DXFree(str);
920     }
921   return OK;
922 
923 parse_error:
924   add_parse_message(op,s,f,l/dim,l%dim);
925  error:
926   return ERROR;
927 }
928 
929 /*
930   FN: Vector binary file format read.
931 */
932 
VgetBinaryData(FILE * fp,void ** data,int size)933 static int VgetBinaryData(FILE *fp, void **data, int size)
934 {
935   int j, s, len, step;
936   char	*op;
937   struct header rec_sep;
938 
939   for(j=0; j<_dxd_gi_numflds; j++)
940     {
941       size = _dxfnumGridPoints(j);
942       for (s = 0; s < _dxd_gi_series; s++)
943 	{
944 	  step = s*_dxd_gi_numflds;
945 	  len = _dxd_gi_var[j]->databytes * _dxd_gi_var[j]->datadim * size;
946 	  if (_dxd_gi_whichser[s] == OFF || _dxd_gi_whichflds[j] == OFF)
947 	    {
948 	      if(!(skip_bdata(fp, len))) {
949  	        op = "read";
950 		goto error;
951   	      }
952 	    }
953 	  else if(!doread(data[step+j], 1, len, fp)) {
954  	    op = "read";
955 	    goto error;
956 	  }
957           if ((_dxd_gi_series-1) != s && !skip_header(fp,&_dxd_gi_serseparat)){
958              op = "read series header";
959              goto error;
960           }
961 	}
962                     rec_sep = _dxd_gi_var[j]->rec_separat[0];
963                     if (!skip_header(fp,&rec_sep)){
964                        op = " record separator";
965                        goto error;
966                     }
967     }
968   return OK;
969 
970 error:
971   if (_dxd_gi_series > 1)
972     DXAddMessage("\nTrying to %s field '%s' of series %d",op,_dxd_gi_var[j]->name,s+1);
973   else
974     DXAddMessage("\nTrying to %s field '%s'",op,_dxd_gi_var[j]->name);
975   return ERROR;
976 }
977 
978 /*
979   FN: Record Vector ascii file format read.
980 */
981 
RVgetAsciiData(FILE * fp,void ** data,int size)982 static int RVgetAsciiData(FILE *fp, void **data, int size)
983 {
984   int f, cnt=0, ll=0, kk, dim,elements,leading,width;
985   int step=0, s=0, dim_mul_size,nl=0,maxseries;
986   char *str, r[MAX_DSTR], *op;
987   Type t;
988   struct header rec_sep;
989   int d, offset = 1;
990 
991   /* what is the max series input */
992   for (s=_dxd_gi_series-1; s>=0; s--)
993      if (_dxd_gi_whichser[s] == ON) break;
994   maxseries = s+1;
995 
996   if ( _dxd_gi_asciiformat == FREE )
997     {
998       for (s = step = 0; s < maxseries; s++, step += _dxd_gi_numflds)
999 	{
1000 	  for (f = 0; f < _dxd_gi_numflds; f++)
1001 	    {
1002 	      size = _dxfnumGridPoints(f);
1003 	      dim = _dxd_gi_var[f]->datadim;
1004 	      t = _dxd_gi_var[f]->datatype;
1005 	      offset = 1;
1006 	      if (t == TYPE_STRING) {
1007 		 offset = dim;
1008 		 dim=1;
1009 	      }
1010 	      if (_dxd_gi_whichflds[f] == ON && _dxd_gi_whichser[s] == ON)
1011 		{
1012 		  for (cnt = 0, d = 0; cnt < dim*size; cnt++)
1013 		    {
1014 		      if (!read_ascii(fp,t,data[step+f],d)) {
1015 			op = "Reading";
1016 			goto parse_error;
1017 		      }
1018 		      d += offset;
1019 		    }
1020 		}
1021 	      else
1022 		{
1023 		  if (!skip_ascii(fp,dim*size)) {
1024 		    op = "Skipping";
1025 		    goto parse_error;
1026 		  }
1027 		}
1028                 rec_sep = _dxd_gi_var[f]->rec_separat[0];
1029                 if (!skip_header(fp,&rec_sep)){
1030                    DXAddMessage("error reading record separator");
1031                    goto error;
1032                 }
1033 	    }
1034           if ((_dxd_gi_series-1) != s && !skip_header(fp,&_dxd_gi_serseparat)){
1035              DXAddMessage("error reading series separator %d",s+1);
1036              goto error;
1037           }
1038 	}
1039     }
1040   else if ( _dxd_gi_asciiformat == FIX )
1041     {
1042       op = "Reading";
1043       str = (char *)DXAllocate(MAX_DSTR);
1044       for (s=step = 0; s < maxseries; s++, step += _dxd_gi_numflds)
1045 	{
1046 	  for (f = 0; f < _dxd_gi_numflds; f++)
1047 	    {
1048 	      size = _dxfnumGridPoints(f);
1049 	      dim = _dxd_gi_var[f]->datadim;
1050 	      t = _dxd_gi_var[f]->datatype;
1051 	      elements = _dxd_gi_var[f]->elements;
1052 	      leading = _dxd_gi_var[f]->leading;
1053 	      width = _dxd_gi_var[f]->width;
1054 	      offset = 1;
1055 	      if (t == TYPE_STRING) {
1056 		 offset = dim;
1057 		 dim=1;
1058 	      }
1059 	      dim_mul_size = dim*size;
1060 	      for (cnt = 0, d = 0; cnt < dim_mul_size; cnt+=elements)
1061 		{
1062 		  if (!(skip_numchar(fp, leading, &str)))
1063 		    goto parse_error;
1064 		  kk = 0;
1065 		  for( ll=0; ll<elements; ll++)
1066 		    {
1067 		      if ( cnt+ll < dim_mul_size )
1068 			{
1069 			  strncpy(r, &str[kk], width);
1070 			  r[width] = (char)NULL;
1071 			  if (_dxd_gi_whichflds[f] == ON && _dxd_gi_whichser[s]==ON)
1072 			    {
1073 			      if (!convert_string(r,t,data[step+f],d,&nl))
1074 				goto parse_error;
1075 			      if (nl==1){
1076 			        ll--;
1077 				nl=0;
1078 				kk=0;
1079                                 if (!(skip_numchar(fp, leading, &str)))
1080                                   goto parse_error;
1081 			      }
1082 			      else{
1083 				 d += offset;
1084 			         kk+=width;
1085 			      }
1086 			    }
1087 			  else
1088 			    {
1089 			      if (r[0] == '\n'){
1090 				 ll--;
1091 				 kk=0;
1092 				 if (!skip_numchar(fp,leading,&str))
1093 				    goto parse_error;
1094 			      }
1095 			      else{
1096 				 d += offset;
1097 			         kk+=width;
1098 			      }
1099 			    }
1100 			}
1101 		    }
1102 		}
1103                 rec_sep = _dxd_gi_var[f]->rec_separat[0];
1104                 if (!skip_header(fp,&rec_sep)){
1105                    DXAddMessage("error reading record separator");
1106                    goto error;
1107                 }
1108 	    }
1109            if ((_dxd_gi_series-1) != s && !skip_header(fp,&_dxd_gi_serseparat)){
1110                DXAddMessage("error reading series separator %d",s+1);
1111                goto error;
1112            }
1113 	}
1114         DXFree(str);
1115     }
1116   return OK;
1117 
1118 parse_error:
1119   add_parse_message(op, s,f,(cnt+ll)/dim,(cnt+ll)%dim);
1120 error:
1121   return ERROR;
1122 }
1123 
1124 /*
1125   FN: Record Vector binary file format read.
1126 */
1127 
RVgetBinaryData(FILE * fp,void ** data,int size)1128 static int RVgetBinaryData(FILE *fp, void **data, int size)
1129 {
1130   int j, len, step, s;
1131   char *op;
1132   struct header rec_sep;
1133   int maxseries;
1134 
1135   /* what is the max series input */
1136   for (s=_dxd_gi_series-1; s>=0; s--)
1137      if (_dxd_gi_whichser[s] == ON) break;
1138   maxseries = s+1;
1139 
1140   for (s=step= 0; s<maxseries; s++, step += _dxd_gi_numflds)
1141     {
1142       for(j=0; j<_dxd_gi_numflds; j++)
1143 	{
1144 	  size = _dxfnumGridPoints(j);
1145 	  len = _dxd_gi_var[j]->databytes * _dxd_gi_var[j]->datadim * size;
1146 	  if (_dxd_gi_whichser[s] == OFF || _dxd_gi_whichflds[j] == OFF)
1147 	    {
1148 	      if(!(skip_bdata(fp, len))) {
1149 		op = "skip";
1150 		goto error;
1151 	      }
1152 	    }
1153 	  else if(!doread(data[step+j], 1, len, fp)) {
1154  	    op = "read";
1155 	    goto error;
1156 	  }
1157           rec_sep = _dxd_gi_var[j]->rec_separat[0];
1158           if (!skip_header(fp,&rec_sep)){
1159              op = " read record separator";
1160              goto error;
1161           }
1162 	}
1163       if ((_dxd_gi_series-1) != s && !skip_header(fp,&_dxd_gi_serseparat)){
1164          op = "read series separator";
1165          goto error;
1166       }
1167     }
1168   return OK;
1169 
1170  error:
1171   if (_dxd_gi_series > 1)
1172     DXAddMessage("\nTrying to %s field '%s' of series %d",op,_dxd_gi_var[j]->name,s+1);
1173   else
1174     DXAddMessage("\nTrying to %s field '%s'",op,_dxd_gi_var[j]->name);
1175   return ERROR;
1176 }
1177 
1178 /*
1179  * DXRead a value of type 't' from stream fp and put it in the index'th
1180  * array position relative to data for the given type.
1181  *
1182  */
1183 static Error
read_ascii(FILE * fp,Type t,void * data,int index)1184 read_ascii(FILE *fp, Type t, void *data, int index)
1185 {
1186     int r, i;
1187     char string[80];
1188 
1189     switch (t) {
1190     case TYPE_BYTE:
1191 	r = fscanf(fp,"%d",&i);
1192 	if (i<DXD_MIN_BYTE || i>DXD_MAX_BYTE) {
1193 	    DXSetError(ERROR_DATA_INVALID,"#10905",i,"byte");
1194 	    goto error;
1195 	}
1196 	DREF(byte,data,index) = (byte)i;
1197 	break;
1198     case TYPE_UBYTE:
1199 	r = fscanf(fp,"%d",&i);
1200 	if (i<0 || i>DXD_MAX_UBYTE) {
1201 	    DXSetError(ERROR_DATA_INVALID,"#10905",i,"ubyte");
1202 	    goto error;
1203 	}
1204 	DREF(ubyte,data,index) = (ubyte)i;
1205 	break;
1206     case TYPE_SHORT:
1207 	r = fscanf(fp,"%d",&i);
1208 	if (i<DXD_MIN_SHORT || i>DXD_MAX_SHORT) {
1209 	    DXSetError(ERROR_DATA_INVALID,"#10905",i,"short");
1210 	    goto error;
1211 	}
1212 	DREF(short,data,index) = (short)i;
1213 	break;
1214     case TYPE_USHORT:
1215 	r = fscanf(fp,"%d",&i);
1216 	if (i<0 || i>DXD_MAX_USHORT) {
1217 	    DXSetError(ERROR_DATA_INVALID,"#10905",i,"ushort");
1218 	    goto error;
1219 	}
1220 	DREF(unsigned short,data,index) = (unsigned short)i;
1221 	break;
1222     case TYPE_INT:
1223 	r = fscanf(fp,"%d",&DREF(int,data,index));
1224 	break;
1225     case TYPE_UINT:
1226   	r = fscanf(fp,"%u",&DREF(unsigned int,data,index));
1227 	break;
1228     case TYPE_FLOAT:
1229 	r = fscanf(fp,"%f",&DREF(float,data,index));
1230 	break;
1231     case TYPE_DOUBLE:
1232 	r = fscanf(fp,"%lf",&DREF(double,data,index));
1233 	break;
1234     case TYPE_STRING:
1235 	r = fscanf(fp,"%s",&DREF(char,data,index));
1236 	break;
1237     default:
1238 	DXErrorGoto(ERROR_INTERNAL,
1239 		"Type not implemented for ascii files");
1240     }
1241 
1242     if (r == 0){
1243 		fscanf(fp,"%70s",string);
1244 		DXSetError(ERROR_DATA_INVALID, "#10906",string);
1245         goto error;
1246     }
1247 
1248     if (r == EOF){
1249 	DXSetError(ERROR_MISSING_DATA, "#10898",_dxd_gi_filename);
1250         goto error;
1251     }
1252 
1253     return OK;
1254 error:
1255     return ERROR;
1256 
1257 }
1258 
1259 /* skip n numbers */
1260 static Error
skip_ascii(FILE * fp,int num)1261 skip_ascii(FILE *fp, int num)
1262 {
1263    int c,prev,curr,found;
1264 
1265    c = getc(fp);
1266    if (c == ' ' || c == '\n' || c == '\t'){
1267       prev = 0;
1268       found = 0;
1269    }
1270    else {
1271       prev = 1;
1272       found = 1;
1273    }
1274    while (1) {
1275       c = getc(fp);
1276       if (c == ' ' || c == '\n' || c == '\t') curr = 0;
1277       else curr = 1;
1278       if (prev != curr) found++;
1279       if (found == 2*num) break;
1280       prev=curr;
1281    }
1282    /* put back last whitespace */
1283    ungetc(c,fp);
1284    return OK;
1285 }
1286 
1287 /*
1288  * Convert the string of characters to a numeric value of type 't'
1289  * and put it in the index'th array position relative to data for the
1290  * given type.
1291  */
1292 static Error
convert_string(char * s,Type t,void * data,int index,int * nl)1293 convert_string(char *s, Type t, void *data, int index,int *nl)
1294 {
1295     int i;
1296     float f;
1297     double d;
1298 	char format[5];
1299 
1300     /* if newline return nl=1 */
1301     if (s[0]=='\n') {*nl=1; return OK;}
1302 
1303     switch (t) {
1304     case TYPE_BYTE:
1305         if (sscanf(s,"%d",&i) <= 0) {
1306                 DXSetError(ERROR_DATA_INVALID,"#10907","byte",s);
1307                 goto error;
1308         }
1309         if (i<DXD_MIN_BYTE || i>DXD_MAX_BYTE) {
1310             DXSetError(ERROR_DATA_INVALID,"#10905",i,"byte");
1311             goto error;
1312         }
1313         DREF(byte,data,index) = (byte)i;
1314         break;
1315     case TYPE_UBYTE:
1316 	if (sscanf(s,"%d",&i) <= 0) {
1317 		DXSetError(ERROR_DATA_INVALID,"#10907","ubyte",s);
1318 		goto error;
1319 	}
1320 	if (i<0 || i>DXD_MAX_UBYTE) {
1321 	    DXSetError(ERROR_DATA_INVALID,"#10905",i,"ubyte");
1322 	    goto error;
1323 	}
1324 	DREF(ubyte,data,index) = (ubyte)i;
1325 	break;
1326     case TYPE_SHORT:
1327         if (sscanf(s,"%d",&i) <= 0) {
1328                 DXSetError(ERROR_DATA_INVALID,"#10907","short",s);
1329                 goto error;
1330         }
1331         if (i<DXD_MIN_SHORT || i>DXD_MAX_SHORT) {
1332             DXSetError(ERROR_DATA_INVALID,"#10905",i,"short");
1333             goto error;
1334         }
1335         DREF(short,data,index) = (short)i;
1336         break;
1337     case TYPE_USHORT:
1338 	if (sscanf(s,"%d",&i) <= 0) {
1339 		DXSetError(ERROR_DATA_INVALID,"#10907","ushort",s);
1340 		goto error;
1341 	}
1342 	if (i<0 || i>DXD_MAX_USHORT) {
1343 	    DXSetError(ERROR_DATA_INVALID,"#10905",i,"ushort");
1344 	    goto error;
1345 	}
1346 	DREF(unsigned short,data,index) = (unsigned short)i;
1347 	break;
1348     case TYPE_INT:
1349 	if (sscanf(s,"%d",&i) <= 0) {
1350 		DXSetError(ERROR_DATA_INVALID,"#10907","int",s);
1351 		goto error;
1352 	}
1353 	DREF(int,data,index) = i;
1354 	break;
1355     case TYPE_UINT:
1356 	if (sscanf(s,"%u",&i) <= 0) {
1357 		DXSetError(ERROR_DATA_INVALID,"#10907","uint",s);
1358 		goto error;
1359 	}
1360 	DREF(unsigned int,data,index) = i;
1361 	break;
1362     case TYPE_FLOAT:
1363 	if (sscanf(s,"%f",&f) <= 0) {
1364 		DXSetError(ERROR_DATA_INVALID,"#10907","float",s);
1365 		goto error;
1366 	}
1367 	DREF(float,data,index) = f;
1368 	break;
1369     case TYPE_DOUBLE:
1370 	if (sscanf(s,"%lf",&d) <= 0) {
1371 		DXSetError(ERROR_DATA_INVALID,"#10907","double",s);
1372 		goto error;
1373 	}
1374 	DREF(double,data,index) = d;
1375 	break;
1376     case TYPE_STRING:
1377 	i = strlen(s)+1;
1378 	if (s[i-2] == '\n')
1379 	   s[i-2] = (char)NULL;
1380 	i = strlen(s) + 1;
1381 	sprintf(format,"%%%dc",i);
1382 	if (sscanf(s,format,&DREF(char,data,index)) <=0){
1383 		DXSetError(ERROR_DATA_INVALID,"#10907","string",s);
1384 		goto error;
1385 	}
1386 	break;
1387     default:
1388 	DXErrorGoto(ERROR_INTERNAL, "Unexpected type for ascii files");
1389     }
1390 
1391     return OK;
1392 error:
1393     return ERROR;
1394 
1395 }
1396 
1397 /*
1398  * Skip the header, which can be denoted by either a number of lines
1399  * or bytes, or a marker string.
1400  * Returns OK/ERROR, and sets error code on ERROR.
1401  */
1402 static Error
skip_header(FILE * fp,struct header * head)1403 skip_header(FILE *fp, struct header *head)
1404 {
1405   int i, c;
1406   char s[MAX_DSTR];
1407 
1408 
1409     switch (head->type) {
1410     case SKIP_MARKER:
1411         for (i=0;;) {
1412         c = getc(fp);
1413         if (c == EOF)  {
1414             DXSetError(ERROR_DATA_INVALID,"#10898",
1415 		"before encountering header marker");
1416             goto error;
1417         } else if ((char)c == head->marker[i])  {
1418             if (head->marker[++i] == '\0')
1419                 break;
1420         } else
1421             i=0;
1422         }
1423         break;
1424     case SKIP_LINES:
1425         for (i=0; i<head->size; )  {
1426         if (!fgets(s, MAX_DSTR, fp)){
1427             DXSetError(ERROR_MISSING_DATA,"#10910","lines");
1428             goto error;
1429         }
1430         if (s[strlen(s)-1] == '\n')
1431             i++;
1432         }
1433         break;
1434     case SKIP_BYTES:
1435         if (fseek(fp, head->size, 1) != 0){
1436           DXSetError(ERROR_MISSING_DATA,"#10910","byte");
1437           goto error;
1438         }
1439         break;
1440     case SKIP_NOTHING:
1441         break;
1442     default:
1443         DXSetError(ERROR_INTERNAL,"#10910","all");
1444         goto error;
1445     }
1446 
1447     return OK;
1448 
1449  error:
1450   return ERROR;
1451 }
1452 
1453 /*
1454  * Skip some bytes in a file.
1455  * Returns OK/ERROR, and sets error code on ERROR.
1456  */
1457 static Error
skip_bdata(FILE * fp,int toskip)1458 skip_bdata(FILE *fp, int toskip)
1459 {
1460 
1461   if (_dxd_gi_format == BINARY && toskip != 0) {
1462       if (fseek(fp, toskip, 1) != 0) {
1463           DXSetError(ERROR_MISSING_DATA,"#10911",
1464 			ftell(fp) + toskip);
1465 	  goto error;
1466 	}
1467     }
1468 
1469   return OK;
1470 
1471  error:
1472   return ERROR;
1473 }
1474 /*
1475  * Do fread()s until we are sure we either have all the data or
1476  * we hit an end of file.
1477  */
1478 static Error
doread(void * p,int size,int cnt,FILE * fp)1479 doread(void *p, int size, int cnt, FILE* fp)
1480 {
1481     int left,n;
1482 
1483     for (left=cnt*size; left>0 ; ) {
1484 	  n = fread((char*)p, 1, left, fp);
1485 	  if (n == 0) {
1486 	      DXSetError(ERROR_MISSING_DATA,"#10898","data file");
1487 	      goto error;
1488 	  }
1489 	  left -= n;
1490 	  p = (char*)p + n;
1491     }
1492 
1493     return OK;
1494 
1495 error:
1496     return ERROR;
1497 }
1498 
1499 /*
1500  * Skip number of characters in a file from the point defined by fp.
1501  * Returns OK/ERROR and sets error code on ERROR.
1502  */
1503 static Error
skip_numchar(FILE * fp,int num_char,char ** ret_str)1504 skip_numchar(FILE *fp, int num_char, char **ret_str)
1505 {
1506   int i, c;
1507 
1508   for (i=0; i<num_char; i++)
1509     {
1510       c = getc(fp);
1511       if (c == EOF)
1512 	{
1513 	  DXSetError(ERROR_DATA_INVALID,"#10898",
1514 	   "skipping beginning of line characters");
1515           goto error;
1516         }
1517       else if (c == '\n')
1518 	{
1519 	  DXSetError(ERROR_DATA_INVALID,"#10899",
1520 		"skipping beginning of line characters");
1521           goto error;
1522  	}
1523     }
1524   /* if (!fgets(ret_str, MAX_DSTR, fp)) */
1525   if (!_dxf_getline(ret_str,fp))
1526      goto error;
1527   return OK;
1528 
1529  error:
1530   return ERROR;
1531 }
1532 
1533 /* getline allocating space as you go
1534  */
1535 static
_dxf_getline(char ** ret_str,FILE * fp)1536 Error _dxf_getline(char **ret_str,FILE *fp)
1537 {
1538    char str[MAX_DSTR];
1539    int n=0;
1540    char *line = *ret_str;
1541 
1542    /* get newline allocating space if ness */
1543    if ((fgets(str,MAX_DSTR,fp))==NULL){
1544      DXSetError(ERROR_DATA_INVALID,"#10898",_dxd_gi_filename);
1545      return ERROR;
1546    }
1547    strcpy(line,str);
1548    while ((int)strlen(str)>MAX_DSTR-2){
1549       if ((fgets(str,MAX_DSTR,fp))==NULL){
1550         DXSetError(ERROR_DATA_INVALID,"#10898","data file");
1551         return ERROR;
1552       }
1553       n++;
1554       line = (char *)DXReAllocate(line,(unsigned int)strlen(str)+n*MAX_DSTR);
1555       strcat(line,str);
1556    }
1557    *ret_str = line;
1558    return OK;
1559 }
1560 
1561 /* search for header info (keeping track of lines and bytes read)
1562  * and when found place into data
1563  */
1564 Error
_dxf_gi_extract(struct place_state * dataps,int * read_header)1565 _dxf_gi_extract(struct place_state *dataps,int *read_header)
1566 {
1567    int i,k;
1568    int num_sets=0,sets_read=0;
1569    char str[MAX_DSTR], *pmark;
1570    int read[MAX_POS_DIMS*3];
1571 
1572    /* open the data file if not already open */
1573    if(!dataps->fp && !_dxf_gi_OpenFile(_dxd_gi_filename, &dataps->fp, 0))
1574       return ERROR;
1575 
1576    /* how many offset are there? */
1577    for (i=0; _dxd_gi_fromfile[i]; i++){
1578       if (_dxd_gi_fromfile[i]->begin.type==SKIP_NOTHING){
1579 	 sets_read++;
1580 	 read[i]=1;
1581       }
1582       else
1583          read[i]=0;
1584    }
1585    num_sets=i;
1586 
1587    /* read one line at a time searching for any header */
1588    while (fgets(str, MAX_DSTR, dataps->fp) != NULL){
1589       /* are any header lines and if so are the the current line */
1590       for (i=0; i<num_sets; i++){
1591          if (_dxd_gi_fromfile[i]->begin.type==SKIP_LINES &&
1592 	    dataps->lines == _dxd_gi_fromfile[i]->begin.size){
1593 	    if (!extract_fromline(str,i))
1594 	       goto error;
1595 	    sets_read++;
1596 	    read[i]=1;
1597 	 }
1598 	 else if (_dxd_gi_fromfile[i]->begin.type==SKIP_BYTES &&
1599 		 dataps->bytes <= _dxd_gi_fromfile[i]->begin.size &&
1600 		 (dataps->bytes+strlen(str))>_dxd_gi_fromfile[i]->begin.size){
1601 		 k = _dxd_gi_fromfile[i]->begin.size - dataps->bytes;
1602 	    if (!extract_fromline(&str[k],i))
1603 	       goto error;
1604 	    sets_read++;
1605 	    read[i]=1;
1606 	 }
1607 	 else if (_dxd_gi_fromfile[i]->begin.type==SKIP_MARKER &&
1608 		 (pmark = strstr(str,_dxd_gi_fromfile[i]->begin.marker))!=NULL){
1609 	    if (read[i] == 1){	/* already hit this marker once */
1610 	      DXWarning("the marker \"%s\" is defined more than one place in this file, check your results",_dxd_gi_fromfile[i]->begin.marker);
1611 	      continue;
1612 	    }
1613 	    for( k=0; k<strlen(_dxd_gi_fromfile[i]->begin.marker);k++)
1614 	       pmark++;
1615 	    if (!extract_fromline(pmark,i))
1616 	       goto error;
1617 	    sets_read++;
1618 	    read[i]=1;
1619 	 }
1620       }
1621       dataps->lines++;
1622       dataps->bytes += strlen(str);
1623       /* search for header marker if exists and if found return flag */
1624       if (_dxd_gi_header.type==SKIP_MARKER &&
1625 	  strstr(str,_dxd_gi_header.marker)){
1626 	 if (sets_read == num_sets &&
1627 	      _dxd_gi_header.marker[strlen(_dxd_gi_header.marker-1)]=='\n')
1628 	    _dxd_gi_header.type = SKIP_NOTHING;
1629 	 else
1630 	    *read_header=1;
1631       }
1632       if (sets_read == num_sets) break;
1633    }
1634 
1635    /* all offsets were found? */
1636    if (sets_read < num_sets){
1637       for (i=0; i<num_sets; i++){
1638 	 if (read[i]==0){
1639 	    DXSetError(ERROR_DATA_INVALID,"offset for field %d not found",i);
1640 	    goto error;
1641 	 }
1642       }
1643    }
1644 
1645    return OK;
1646 
1647 error:
1648    return ERROR;
1649 }
1650 
1651 /* read data from a line */
1652 static Error
extract_fromline(char str[MAX_DSTR],int which)1653 extract_fromline(char str[MAX_DSTR],int which)
1654 {
1655    int i,j,k,index,width,nl=0;
1656    Type t;
1657    char r[MAX_DSTR];
1658 
1659    i = which;
1660          t = _dxd_gi_fromfile[i]->type;
1661          j=0;
1662          k=0;
1663 	 index=0;
1664          while (_dxd_gi_fromfile[i]->skip[j] >= 0){
1665             k += _dxd_gi_fromfile[i]->skip[j];
1666             width = _dxd_gi_fromfile[i]->width[j];
1667             strncpy(r, &str[k], width);
1668             r[width] = (char)NULL;
1669 	    if (!convert_string(r,t,_dxd_gi_fromfile[i]->data,index,&nl))
1670 	       goto error;
1671 	    if (nl){
1672 	       DXSetError(ERROR_DATA_INVALID,"error reading values");
1673 	       goto error;
1674 	    }
1675             index++;
1676 	    j++;
1677 	    k += width;
1678          }
1679 	 if (j==0){	/* not skip info read all values on this line */
1680 	    index=0;
1681 	    for (k=0; k<strlen(str); ){
1682 	       while(str[k]==' ' || str[k]=='\t')	/* skip whitespace */
1683 	          k++;
1684 	       if (k>=strlen(str)) break;
1685 	       if (isdigit(str[k]) || str[k]=='-' || str[k]=='.'){
1686 	          strcpy(r,&str[k]);
1687 	          if (!convert_string(r,t,_dxd_gi_fromfile[i]->data,index,&nl))
1688 	             goto error;
1689 	          if (nl){
1690 	             DXSetError(ERROR_DATA_INVALID,"error reading values");
1691 	             goto error;
1692 	          }
1693 	          _dxd_gi_fromfile[i]->skip[index] = 0;  /*set skip to indicate number*/
1694 	          index++;
1695 	          while(str[k]!=' ' && str[k]!='\t') /* skip number */
1696 	             k++;
1697 	       }
1698 	       else
1699 		  break;
1700 	    }
1701 	    _dxd_gi_fromfile[i]->skip[index]=-1;
1702 	 }
1703    return OK;
1704 
1705 error:
1706    return ERROR;
1707 }
1708 
1709 
1710 /*
1711  * DXAdd a message to the current error message indicating the give
1712  * series number (s), field name (from f), item number in field (item)
1713  * and the component of the given item (comp).
1714  */
1715 static void
add_parse_message(char * op,int s,int f,int item,int comp)1716 add_parse_message(char *op, int s, int f, int item, int comp)
1717 {
1718 
1719   item++;		/* Change to a base 1 */
1720 
1721   if (_dxd_gi_series > 1) {
1722       s++;
1723       if (_dxd_gi_var[f]->datadim > 1)
1724           DXAddMessage("\n%s Series %d, Field '%s', Datum %d, Component %d",
1725 				op, s,_dxd_gi_var[f]->name,item,comp+1);
1726       else
1727           DXAddMessage("\n%s Series %d, Field '%s', Datum %d",
1728 				op, s,_dxd_gi_var[f]->name,item);
1729   } else {
1730      if (_dxd_gi_var[f]->datadim > 1)
1731           DXAddMessage("\n%s Field '%s', Datum %d, Component %d",
1732 			op, _dxd_gi_var[f]->name,item,comp+1);
1733      else
1734           DXAddMessage("\n%s Field '%s', Datum %d",op,_dxd_gi_var[f]->name,item);
1735   }
1736 }
1737 
1738 /*
1739    FN: reorder data arg1 from row majority to column majority.
1740    EF: arg1 pointer points to a set of reordered data and original space has
1741        been freed. NULL on error and sets error code.
1742    Note: handle only 2, 3 and 4 dimensional data.
1743 */
1744 
1745 static void*
reorderData(void * data,int f)1746 reorderData(void *data, int f)
1747 /*reorderData(void *data, int ndatum, int rank, Type type) */
1748 {
1749   void *d1 = NULL;
1750   int  xskip, k, x, y, z, v, offset, data_size;
1751   int dim0,dim1,dim2,dim3,adjust,rank,ndatum;
1752   Type type;
1753 
1754   ndatum = _dxfnumGridPoints(f);
1755   type = _dxd_gi_var[f]->datatype;
1756   rank = _dxd_gi_var[f]->datadim;
1757   if (_dxd_gi_var[f]->datadep==DEP_CONNECTIONS) adjust=1;
1758   else adjust=0;
1759 
1760   if ( _dxd_gi_numdims == 1 )
1761       return data;
1762 
1763   data_size = DXTypeSize(type) * rank;
1764   dim0 = _dxd_gi_dimsize[0]-adjust;
1765   dim1 = _dxd_gi_dimsize[1]-adjust;
1766 
1767   if (!(d1 = (void *)DXAllocate(ndatum * data_size)))
1768       goto error;
1769 
1770   k = 0;
1771 
1772   if (_dxd_gi_numdims == 2)
1773     {
1774       xskip = dim1 * data_size;
1775       for (y = 0; y < dim1; y++)
1776         {
1777           offset = y * data_size;
1778           for (x = 0; x < dim0; x++)
1779             {
1780               memcpy((char*)d1 + offset, (char*)data + k, data_size);
1781               k += data_size;
1782               offset += xskip;
1783             }
1784         }
1785     }
1786   else if (_dxd_gi_numdims == 3)
1787     {
1788       dim2 = _dxd_gi_dimsize[2] - adjust;
1789       for (z = 0; z < dim2; z++)
1790 	{
1791 	  for (y = 0; y < dim1; y++)
1792 	    {
1793 	      for (x = 0; x < dim0; x++)
1794 		{
1795 		  offset = (x*dim1*dim2)+(y*dim2)+z;
1796 		  offset *= data_size;
1797 	          memcpy((char*)d1 + offset, (char*)data + k, data_size);
1798 	          k += data_size;
1799 		}
1800 	    }
1801 	}
1802     }
1803   else if (_dxd_gi_numdims == 4)
1804     {
1805       dim2 = _dxd_gi_dimsize[2] - adjust;
1806       dim3 = _dxd_gi_dimsize[3] - adjust;
1807       for (v = 0; v < dim3; v++)
1808 	{
1809 	  for (z = 0; z < dim2; z++)
1810 	    {
1811 	      for (y = 0; y < dim1; y++)
1812 		{
1813 		  for (x = 0; x < dim0; x++)
1814 		    {
1815 		      offset = (x*dim1*dim2*dim3) +
1816 			(y*dim2*dim3) + (z*dim3) + v;
1817 		      offset *= data_size;
1818 	              memcpy((char*)d1 + offset, (char*)data + k, data_size);
1819 	              k += data_size;
1820 		    }
1821 		}
1822 	    }
1823 	}
1824     }
1825   else
1826     {
1827       DXSetError(ERROR_NOT_IMPLEMENTED,"#10913",_dxd_gi_numdims);
1828       goto error;
1829     }
1830 
1831   DXFree((Pointer) data );
1832   return d1;
1833 
1834  error:
1835   if (d1) DXFree((Pointer)d1);
1836 
1837   return NULL;
1838 }
1839 
1840 /*
1841  * Denormalize any floating point numbers in XF.
1842  */
1843 #if !defined(DXD_STANDARD_IEEE)
1844 static void
_dxfdenormalize(void ** XF)1845 _dxfdenormalize(void **XF)
1846 {
1847   int size, f, s, i, badfp, denorm, nitems;
1848 
1849   for (f=0 ; f<_dxd_gi_numflds ; f++) {
1850   size = _dxfnumGridPoints(f);
1851 	if (_dxd_gi_whichflds[f] == ON) {
1852  	    nitems = size * _dxd_gi_var[f]->datadim;
1853 	    badfp = denorm = 0;
1854 	    switch  (_dxd_gi_var[f]->datatype) {
1855 		case TYPE_DOUBLE:
1856 		    for (s=i=0 ; i<_dxd_gi_series ; i++, s+=_dxd_gi_numflds)
1857 			if (_dxd_gi_whichser[i] == ON)
1858 			    _dxfdouble_denorm(XF[s+f],nitems,&denorm,&badfp);
1859 		    break;
1860 		case TYPE_FLOAT:
1861 		    for (s=i=0 ; i<_dxd_gi_series ; i++, s+=_dxd_gi_numflds)
1862 			if (_dxd_gi_whichser[i] == ON)
1863 			    _dxffloat_denorm(XF[s+f],nitems,&denorm,&badfp);
1864 		    break;
1865 	    }
1866 	    if (denorm && badfp)
1867 		DXWarning("Denormalized and NaN/Infinite floating point numbers in field '%s'",
1868 			_dxd_gi_var[f]->name);
1869 	    else if (denorm)
1870 		DXWarning("Denormalized floating point numbers in field '%s'",
1871 			_dxd_gi_var[f]->name);
1872 	    else if (badfp)
1873 		DXWarning("NaN/Infinite floating point numbers in field '%s'",
1874 			_dxd_gi_var[f]->name);
1875 
1876 	}
1877   }
1878 }
1879 #endif /* !normal ieee */
1880 
1881 /*
1882  * Convert cnt items of type from_type in the given array to floats.
1883  * Return a pointer to the converted array.
1884  * We do an DXAllocateLocal here, because we know that the array data
1885  * will eventually be copied into an Array with DXAddArrayData.
1886  */
1887 static Pointer
locations2float(Pointer from,Type from_type,int cnt)1888 locations2float(Pointer from, Type from_type, int cnt)
1889 {
1890     int i;
1891     float *f;
1892 
1893     f = (float*)DXAllocateLocal(cnt * sizeof(float));
1894     if (!f) {
1895 	f = (float *)DXAllocate(cnt * sizeof(float));
1896 	if (!f)
1897 	    goto error;
1898     }
1899 
1900     switch (from_type) {
1901 	case TYPE_UBYTE:
1902 	    for (i=0 ; i<cnt ; i++) f[i] = (float)DREF(ubyte,from,i);
1903 	    break;
1904 	case TYPE_BYTE:
1905 	    for (i=0 ; i<cnt ; i++) f[i] = (float)DREF(byte,from,i);
1906 	    break;
1907 	case TYPE_SHORT:
1908 	    for (i=0 ; i<cnt ; i++) f[i] = (float)DREF(short,from,i);
1909 	    break;
1910 	case TYPE_USHORT:
1911 	    for (i=0 ; i<cnt ; i++) f[i] = (float)DREF(ushort,from,i);
1912 	    break;
1913 	case TYPE_INT:
1914 	    for (i=0 ; i<cnt ; i++) f[i] = (float)DREF(int,from,i);
1915 	    break;
1916 	case TYPE_UINT:
1917 	    for (i=0 ; i<cnt ; i++) f[i] = (float)DREF(uint,from,i);
1918 	    break;
1919 	case TYPE_DOUBLE:	/* FIXME: may need to check value on PVS */
1920 	    for (i=0 ; i<cnt ; i++) f[i] = (float)DREF(double,from,i);
1921 	    break;
1922 	default:
1923 	    DXErrorGoto(ERROR_UNEXPECTED,"Can't copy locations for given type");
1924     }
1925     return (Pointer)f;
1926 error:
1927     if (f) DXFree((Pointer)f);
1928     return NULL;
1929 }
1930 
1931