1 /******************************************************************************
2 *
3 *  NSSDC/CDF              Toolbox of routines for CDF Toolkit (Miscellaneous).
4 *
5 *  Version 1.6b, 3-Mar-97, Hughes STX.
6 *
7 *  Modification history:
8 *
9 *   V1.0  25-Jan-94, J Love     Original version.
10 *   V1.0a  6-Feb-94, J Love     DEC Alpha/OpenVMS port.
11 *   V1.1  10-Mar-94, J Love     Modified `ParseOptionList' to make the
12 *                               enclosing parentheses optional (on any
13 *                               operating system).
14 *   V1.2  13-Dec-94, J Love     CDF V2.5.
15 *   V1.2a 13-Jan-95, J Love     Changed `IsCDF' to allow all possible
16 *                               extensions on Macintosh machines also.
17 *   V1.2b 20-Jan-95, J Love     IRIX 6.x (64-bit).
18 *   V1.2c  3-Mar-95, J Love     Moved `EncodeKeyDefinitions', etc. to
19 *                               `windoz.c'.
20 *   V1.3  21-Mar-95, J Love     POSIX.
21 *   V1.3a 18-Apr-95, J Love     More POSIX.
22 *   V1.4  22-May-95, J Love     `ASSIGNx', `EQx', etc. moved here (and some
23 *                               calling sequences changed).
24 *   V1.5  14-Sep-95, J Love     Added routines used by CDFexport.  Hyper
25 *                               groups.
26 *   V1.5a 19-Sep-95, J Love     Macintosh event handling.
27 *   V1.6   9-Sep-96, J Love     CDF V2.6.
28 *   V1.6a 21-Feb-97, J Love	Removed RICE.
29 *   V1.6b  3-Mar-97, J Love	Windows NT for MS Visual C/C++ on an IBM PC.
30 *   V1.6c 18-Dec-98, M Liu      Add the missing cases for ALPHAVMSi in
31 *                               WhichEncoding and EncodingToken.
32 *   V1.7  05-May-04, M Liu      Changed function AllocateBuffers when the
33 *                               record count is 1 or more.
34 *   V1.8  11-Jul-05, M Liu      Added MingW port for PC.
35 *   V1.9  13-Oct-06, M Liu      Changed to allow upper and lower case CDF
36 *                               name to be used on win32.
37 *   V2.0  21-Oct-08, M Liu      Modified RemoveTrailingBlanks to end process
38 *                               when the first non-blank is found.
39 *   V3.3  10-Jan-09, M Liu      Validate a file before it is used.
40 *
41 ******************************************************************************/
42 
43 #include "cdftools.h"
44 
45 /******************************************************************************
46 * Macros.
47 ******************************************************************************/
48 
49 #if defined(dos)
50 #define MAXnBYTESperALLOCATION  50000L  /* Remember 64Kb limit. */
51 #else
52 #if defined(mac)
53 #define MAXnBYTESperALLOCATION  50000L
54 #else
55 #define MAXnBYTESperALLOCATION  500000L
56 #endif
57 #endif
58 
59 /******************************************************************************
60 * Local function prototypes.
61 ******************************************************************************/
62 
63 static Logical EqStringsIgLTws PROTOARGs((char *string1, char *string2));
64 static Logical DecodeInt32 PROTOARGs((char *, Int32 *));
65 static Logical DecodeInt32u PROTOARGs((char *, uInt32 *));
66 static char *strnchr PROTOARGs((char *string, int chr, int n));
67 static QOP *ParseSlashStyle PROTOARGs((
68   int argc, char *argv[], char *validQuals[], int optRequired[]
69 ));
70 static QOP *ParseHyphenStyle PROTOARGs((
71   int argc, char *argv[], char *validQuals[], int optRequired[]
72 ));
73 static void FreeArgvT PROTOARGs((int lastArgN, char *argvT[]));
74 static QOP *BuildQOP PROTOARGs((
75   int Nparms, char *parms[], char *validQuals[], int *qualEntered,
76   char *qualOpt[]
77 ));
78 static Logical AttemptAllocations PROTOARGs((
79   long nScalarValues, int nScalars, long nHyperValues, int nHypers,
80   Byte **handles[], size_t nValueBytes[]
81 ));
82 
83 /******************************************************************************
84 * EncodeRecordJustify.
85 ******************************************************************************/
86 
EncodeRecordJustify(string,recN,minWidth)87 void EncodeRecordJustify (string, recN, minWidth)
88 char *string;
89 long recN;
90 int minWidth;   /* If zero, no minimum width.  If positive, right justified.
91 		   If negative, left justified. */
92 {
93   sprintf (string, "%ld", recN + 1);
94   Justify (string, minWidth);
95   return;
96 }
97 
98 /******************************************************************************
99 * EncodeIndicesJustify.
100 ******************************************************************************/
101 
EncodeIndicesJustify(string,numDims,indices,minWidth)102 void EncodeIndicesJustify (string, numDims, indices, minWidth)
103 char *string;
104 long numDims;
105 long indices[];
106 int minWidth;   /* If zero, no minimum width.  If positive, right justified.
107 		   If negative, left justified. */
108 {
109   int n;
110   strcpyX (string, "[", 0);
111   for (n = 0; n < numDims; n++) {
112      if (n > 0) strcatX (string, ",", 0);
113      sprintf (EofS(string), "%ld", indices[n] + 1);
114   }
115   strcatX (string, "]", 0);
116   Justify (string, minWidth);
117   return;
118 }
119 
120 /******************************************************************************
121 * EncodeRecordIndicesJustify.
122 ******************************************************************************/
123 
EncodeRecordIndicesJustify(string,recN,numDims,indices,minWidth)124 void EncodeRecordIndicesJustify (string, recN, numDims, indices, minWidth)
125 char *string;
126 long recN;
127 long numDims;
128 long indices[];
129 int minWidth;   /* If zero, no minimum width.  If positive, right justified.
130 		   If negative, left justified. */
131 {
132   EncodeRecordJustify (string, recN, 0);
133   EncodeIndicesJustify (EofS(string), numDims, indices, 0);
134   Justify (string, minWidth);
135   return;
136 }
137 
138 /******************************************************************************
139 * Justify.
140 ******************************************************************************/
141 
Justify(string,minWidth)142 void Justify (string, minWidth)
143 char *string;
144 int minWidth;   /* If zero, no minimum width.  If positive, right justified.
145 		   If negative, left justified. */
146 {
147   if (minWidth < 0) {
148     int pad = -minWidth - strlen(string);
149     if (pad > 0) CatNcharacters (string, pad, (int) ' ');
150   }
151   else {
152     if (minWidth > 0) {
153       int i, stringL = strlen(string);
154       int shift = minWidth - stringL;
155       if (shift > 0) {
156 	memmove (&(string[shift]), string, stringL + 1);
157 	for (i = 0; i < shift; i++) string[i] = ' ';
158       }
159     }
160   }
161   return;
162 }
163 
164 /******************************************************************************
165 * CatString.
166 ******************************************************************************/
167 
CatToString(string,cat,length,justify,more)168 void CatToString (string, cat, length, justify, more)
169 char *string;
170 char *cat;
171 int length;
172 int justify;
173 char *more;
174 {
175   int catL = (int) strlen (cat);
176   int moreL = (int) strlen (more);
177   if (catL > length)
178     if (moreL >= length)
179       CatNcharacters (string, length, '*');
180     else {
181       strcatX (string, cat, strlen(string) + (length - moreL));
182       strcatX (string, more, 0);
183     }
184   else
185     switch (justify) {
186       case LEFT_JUSTIFY:
187 	strcatX (string, cat, 0);
188 	CatNcharacters (string, length - catL, ' ');
189 	break;
190       case CENTER_JUSTIFY: {
191 	int after = (length - catL) / 2;
192 	int before = (length - catL) - after;
193 	CatNcharacters (string, before, ' ');
194 	strcatX (string, cat, 0);
195 	CatNcharacters (string, after, ' ');
196 	break;
197       }
198       case RIGHT_JUSTIFY:
199 	CatNcharacters (string, length - catL, ' ');
200 	strcatX (string, cat, 0);
201 	break;
202     }
203   return;
204 }
205 
206 /******************************************************************************
207 * RemoveLeadingBlanks.
208 ******************************************************************************/
209 
RemoveLeadingBlanks(string)210 void RemoveLeadingBlanks (string)
211 char *string;
212 {
213   while (string[0] == ' ') memmove (string, &string[1], strlen(string));
214   return;
215 }
216 
217 /******************************************************************************
218 * RemoveTrailingBlanks.
219 ******************************************************************************/
220 
RemoveTrailingBlanks(string)221 void RemoveTrailingBlanks (string)
222 char *string;
223 {
224   int i;
225   for (i = strlen(string) - 1; i >= 0; i--) {
226      if (string[i] != ' ') return;
227      string[i] = NUL;
228   }
229   return;
230 }
231 
232 /******************************************************************************
233 * RemoveWhiteSpace.
234 ******************************************************************************/
235 
RemoveWhiteSpace(string)236 void RemoveWhiteSpace (string)
237 char *string;
238 {
239   char *c = string;
240   while (*c != NUL) {
241     if (Spacing(*c))
242       memmove (c, c + 1, strlen(c+1) + 1);
243     else
244       c++;
245   }
246   return;
247 }
248 
249 /******************************************************************************
250 * CopyToField.
251 *    Copies a string to a field and blank pads to the end of the field.
252 ******************************************************************************/
253 
CopyToField(string,field,length)254 void CopyToField (string, field, length)
255 char *string;
256 char *field;
257 int length;
258 {
259   strcpyX (field, string, length);
260   BlankPadRight (field, length - strlen(string));
261   return;
262 }
263 
264 /******************************************************************************
265 * CopyFromField.
266 *    Copies from a field to a string and removes trailing blanks.  It is
267 * assumed that the string is large enough.
268 ******************************************************************************/
269 
CopyFromField(field,length,string)270 void CopyFromField (field, length, string)
271 char *field;
272 int length;
273 char *string;
274 {
275   strcpyX (string, field, length);
276   RemoveTrailingBlanks (string);
277   return;
278 }
279 
280 /******************************************************************************
281 * SystemClock.
282 ******************************************************************************/
283 
SystemClock()284 double SystemClock () {
285   return ((double) time(NULL));
286 }
287 
288 /******************************************************************************
289 * ParsePath.
290 ******************************************************************************/
291 
ParsePath(path,dir,name)292 void ParsePath (path, dir, name)
293 char *path;
294 char dir[DU_MAX_DIR_LEN+1];
295 char name[DU_MAX_NAME_LEN+1];
296 {
297   char *cp;
298   size_t len;
299   char dirT[DU_MAX_DIR_LEN+1];
300   char nameT[DU_MAX_NAME_LEN+1];
301 #if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \
302     defined(posixSHELL)
303   if (IsDir(path)) {
304     strcpyX (dirT, path, DU_MAX_DIR_LEN);
305     nameT[0] = NUL;
306   }
307   else {
308     cp = strrchr (path, '/');
309     if (cp == NULL) {
310       dirT[0] = NUL;
311       strcpyX (nameT, path, DU_MAX_NAME_LEN);
312     }
313     else {
314       len = cp - path;                          /* No trailing '/'. */
315       strcpyX (dirT, path, MINIMUM(len,DU_MAX_DIR_LEN));
316       strcpyX (nameT, cp + 1, DU_MAX_NAME_LEN);
317     }
318   }
319 #endif
320 #if defined(dos) || defined(win32) || defined(__CYGWIN__) || \
321     defined(__MINGW32__)
322   if (IsDir(path)) {
323     strcpyX (dirT, path, DU_MAX_DIR_LEN);
324     nameT[0] = NUL;
325   }
326   else {
327     char *cp1 = strrchr (path, ':');
328     char *cp2 = strrchr (path, '\\');
329     cp = (cp1 > cp2 ? cp1 : cp2);
330     if (cp == NULL) {
331       dirT[0] = NUL;
332       strcpyX (nameT, path, DU_MAX_NAME_LEN);
333     }
334     else {
335       if (cp1 == NULL) {
336 	len = (size_t) (cp2 - path);            /* No trailing '\'. */
337 	strcpyX (dirT, path, MINIMUM(len,DU_MAX_DIR_LEN));
338       }
339       else {
340 	if (cp2 == NULL) {
341 	  len = (size_t) (cp1 - path + 1);      /* Trailing ':'. */
342 	  strcpyX (dirT, path, MINIMUM(len,DU_MAX_DIR_LEN));
343 	}
344 	else {
345 	  if (cp1 + 1 == cp2)
346 	    len = (size_t) (cp2 - path + 1);    /* Trailing ':'. */
347 	  else
348 	    len = (size_t) (cp2 - path);        /* No trailing ':'. */
349 	  strcpyX (dirT, path, MINIMUM(len,DU_MAX_DIR_LEN));
350 	}
351       }
352       strcpyX (nameT, cp + 1, DU_MAX_NAME_LEN);
353     }
354   }
355 #endif
356 #if defined(vms)
357   char *cp1 = strrchr (path, ':');
358   char *cp2 = strrchr (path, ']');
359   cp = (cp1 > cp2 ? cp1 : cp2);
360   if (cp == NULL) {
361     dirT[0] = NUL;
362     strcpyX (nameT, path, DU_MAX_NAME_LEN);
363   }
364   else {
365     len = cp - path + 1;                        /* Trailing ':' or ']' */
366     strcpyX (dirT, path, MINIMUM(len,DU_MAX_DIR_LEN));
367     strcpyX (nameT, cp + 1, DU_MAX_NAME_LEN);
368   }
369 #endif
370 #if defined(mac)
371   if (IsDir(path)) {
372     strcpyX (dirT, path, DU_MAX_DIR_LEN);
373     nameT[0] = NUL;
374   }
375   else {
376     cp = strrchr (path, ':');
377     if (cp == NULL) {
378       dirT[0] = NUL;
379       strcpyX (nameT, path, DU_MAX_NAME_LEN);
380     }
381     else {
382       len = cp - path + 1;                      /* Trailing ':'. */
383       strcpyX (dirT, path, MINIMUM(len,DU_MAX_DIR_LEN));
384       strcpyX (nameT, cp + 1, DU_MAX_NAME_LEN);
385     }
386   }
387 #endif
388   if (dir != NULL) strcpyX (dir, dirT, DU_MAX_DIR_LEN);
389   if (name != NULL) strcpyX (name, nameT, DU_MAX_NAME_LEN);
390   return;
391 }
392 
393 /******************************************************************************
394 * IsDir (directory).
395 * `stat' on MS-DOS systems will indicate a directory if the pathname
396 * contains a wildcard character.
397 ******************************************************************************/
398 
IsDir(path)399 Logical IsDir (path)
400 char *path;
401 {
402   char pathX[DU_MAX_PATH_LEN+1];
403   size_t len;
404 #if (!defined(unix) && !defined(posixSHELL)) || defined(__CYGWIN__) || \
405     defined(__MINGW32__)
406   int lastChar;
407 #endif
408 #if defined(unix) || defined(dos) || defined(posixSHELL) || defined(win32)
409   struct stat st;
410 #endif
411   ExpandPath (path, pathX);
412   len = strlen (pathX);
413   if (len == 0) return FALSE;
414 #if (!defined(unix) && !defined(posixSHELL)) || defined(__CYGWIN__) || \
415      defined(__MINGW32__)
416   lastChar = len - 1;
417 #endif
418 #if defined(unix) || defined(dos) || defined(posixSHELL) || defined(win32)
419   /****************************************************************************
420   * UNIX/POSIXshell, DOS, and Windows.
421   ****************************************************************************/
422 #if defined(dos) || defined(win32) || defined(__CYGWIN__) || \
423     defined(__MINGW32__)
424   /****************************************************************************
425   * DOS/Windows: Check for wildcard character in the pathname.
426   ****************************************************************************/
427   if (strchr(pathX,'*') != NULL) return FALSE;
428   if (strchr(pathX,'?') != NULL) return FALSE;
429   /****************************************************************************
430   * DOS/Windows: Strip trailing backslash (if present).
431   ****************************************************************************/
432   if (pathX[lastChar] == '\\') {
433     pathX[lastChar] = NUL;         /* Strip trailing '\' */
434     len--;
435   }
436   /****************************************************************************
437   * DOS/Windows: Check for disk drive specification.
438   ****************************************************************************/
439   if (len == 2)
440     if (Alphabetic(pathX[0]) && pathX[1] == ':') return TRUE;
441 #endif
442 #if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \
443     defined(posixSHELL)
444   /****************************************************************************
445   * UNIX: Check for wildcard character in the pathname.
446   ****************************************************************************/
447   if (strchr(pathX,'*') != NULL) return FALSE;
448   if (strchr(pathX,'?') != NULL) return FALSE;
449 #endif
450   /****************************************************************************
451   * Call `stat' to determine type of file.
452   ****************************************************************************/
453   if (stat(pathX, &st) == 0) {
454 #if defined(SALFORDC)           /* Salford's `stat' is broken. */
455     return (st.st_size == 0);
456 #else
457 #if defined(S_ISDIR)
458     return S_ISDIR(st.st_mode);
459 #else
460     return (st.st_mode & S_IFDIR);
461 #endif
462 #endif
463   }
464   else
465     return FALSE;
466 #endif
467 #if defined(vms)
468   /****************************************************************************
469   * VMS.
470   ****************************************************************************/
471   /****************************************************************************
472   * Check for wildcard character in the pathname.
473   ****************************************************************************/
474   if (strchr(pathX,'*') != NULL) return FALSE;
475   if (strchr(pathX,'%') != NULL) return FALSE;
476   /****************************************************************************
477   * Check for possible logical name defined to be a full file specification
478   * (not just a directory).
479   ****************************************************************************/
480   if (IsReg(pathX))
481     return FALSE;
482   else
483     /**************************************************************************
484     * If not, check if the path ends with a ':' (logical name) or ']'
485     * (directory).
486     **************************************************************************/
487     if (pathX[lastChar] == ':' || pathX[lastChar] == ']')
488       return TRUE;
489     else
490       return FALSE;
491 #endif
492 #if defined(mac)
493   /****************************************************************************
494   * MAC: Check to see if specification ends with a `:' (and assume it to be a
495   * directory without actually checking).  If specification doesn't end with
496   * a `:', check if it is a directory anyway.
497   ****************************************************************************/
498   if (pathX[lastChar] == ':')
499     return TRUE;
500   else {
501     return MacDirSpecified (pathX, NULL, NULL);
502   }
503 #endif
504 }
505 
506 /******************************************************************************
507 * IsWild (Wildcard specification in name).
508 ******************************************************************************/
509 
IsWild(path)510 Logical IsWild (path)
511 char *path;
512 {
513   char dir[DU_MAX_DIR_LEN+1];
514   char name[DU_MAX_NAME_LEN+1];
515   ParsePath (path, dir, name);
516   if (strchr(name,'*') != NULL) return TRUE;
517 #if defined(vms)
518   if (strchr(name,'%') != NULL) return TRUE;
519 #else
520   if (strchr(name,'?') != NULL) return TRUE;
521 #endif
522   return FALSE;
523 }
524 
525 /******************************************************************************
526 * IsCDF.
527 *    Determines if the specified pathname is that of a CDF.  Because of
528 * inconsistent behavior of CD-ROM drivers on various UNIX/POSIXshell machines
529 * and the Macintosh, the following extensions are tried: `.cdf', `.CDF',
530 * `.cdf;1', and `.CDF;1'.
531 ******************************************************************************/
532 
IsCDF(pathname)533 Logical IsCDF (pathname)
534 char *pathname;
535 {
536   char pathnameX[DU_MAX_PATH_LEN+1];
537   ExpandPath (pathname, pathnameX);
538   if (IsReg(pathnameX)) return TRUE;
539   strcatX (pathnameX, ".cdf", DU_MAX_PATH_LEN);
540   if (IsReg(pathnameX)) return TRUE;
541 #if defined(unix) || defined(mac) || defined(posixSHELL)
542   ExpandPath (pathname, pathnameX);
543   strcatX (pathnameX, ".cdf;1", DU_MAX_PATH_LEN);
544   if (IsReg(pathnameX)) return TRUE;
545   ExpandPath (pathname, pathnameX);
546   strcatX (pathnameX, ".CDF", DU_MAX_PATH_LEN);
547   if (IsReg(pathnameX)) return TRUE;
548   ExpandPath (pathname, pathnameX);
549   strcatX (pathnameX, ".CDF;1", DU_MAX_PATH_LEN);
550   if (IsReg(pathnameX)) return TRUE;
551 #endif
552   return FALSE;
553 }
554 
555 /******************************************************************************
556 * Qop.
557 ******************************************************************************/
558 
Qop(argc,argv,validQuals,optRequired)559 QOP *Qop (argc, argv, validQuals, optRequired)
560 int argc;
561 char *argv[];
562 char *validQuals[];
563 int optRequired[];
564 {
565   /****************************************************************************
566   * Check to see if a style definition has been specified.  (A slash or hyphen
567   * as the first command line argument.)
568   ****************************************************************************/
569   if (argc > 1) {
570     if (!strcmp(argv[1],"/")) return ParseSlashStyle (argc - 1, &argv[1],
571 						      validQuals, optRequired);
572     if (!strcmp(argv[1],"-")) return ParseHyphenStyle (argc - 1, &argv[1],
573 						       validQuals,optRequired);
574   }
575   /****************************************************************************
576   * No style definition, parse according to default for operating system
577   * being used.
578   ****************************************************************************/
579 #if defined(vms)
580   return ParseSlashStyle (argc, argv, validQuals, optRequired);
581 #else
582   return ParseHyphenStyle (argc, argv, validQuals, optRequired);
583 #endif
584 }
585 
586 /******************************************************************************
587 * ParseSlashStyle.
588 * Assume qualifiers begin with a slash (/).
589 ******************************************************************************/
590 
ParseSlashStyle(argc,argv,validQuals,optRequired)591 static QOP *ParseSlashStyle (argc, argv, validQuals, optRequired)
592 int argc;
593 char *argv[];
594 char *validQuals[];
595 int optRequired[];
596 {
597   QOP *qop;                     /* Pointer to QOP structure. */
598   int argN,                     /* Argument number. */
599       qualNv,                   /* Qualifier number (from list of valid
600 				   qualifiers). */
601       qualNe,                   /* Qualifier number (from list of qualifiers
602 				   entered). */
603       Nparms = 0,               /* Number of parameters entered. */
604       Nquals = 0,               /* Number of qualifiers entered. */
605       matchQualNv,              /* Matching qualifier number (from list of
606 				   valid qualifiers). */
607       qualEntered[QOP_MAX_QUALs];
608 				/* TRUE if the corresponding qualifier was
609 				   entered. */
610   char *parms[QOP_MAX_PARMs],   /* Pointers to the parameters entered. */
611        *qualOpt[QOP_MAX_QUALs], /* Pointers to the options of the qualifiers
612 				   entered (indexed to correspond to the list
613 				   of valid qualifiers). */
614        *argvT[QOP_MAX_ARGVs],   /* Pointers to temporary `argv' strings. */
615        *quals[QOP_MAX_QUALs],   /* Pointers to the qualifiers entered (in the
616 				   order they were entered). */
617        *opts[QOP_MAX_QUALs],    /* Pointers to the options entered (in the
618 				   order they were entered). */
619        *ptr;                    /* Pointer into character string. */
620   enum modes { UNKNOWN_,
621 	       START_OF_PARM_,
622 	       FIND_PARM_END_,
623 	       START_OF_QUAL_,
624 	       FIND_QUAL_END_,
625 	       START_OF_OPT_,
626 	       FIND_OPT_END_ } mode;  /* The current mode when scanning the
627 					 list of command line arguments. */
628   /****************************************************************************
629   * Determine parameters and qualifiers/options.
630   ****************************************************************************/
631   for (argN = 1; argN < argc; argN++) {
632      char nChars = strlen (argv[argN]);
633      argvT[argN] = (char *) cdf_AllocateMemory (nChars + 1, FatalError);
634      strcpyX (argvT[argN], argv[argN], nChars);
635      mode = UNKNOWN_;
636      for (ptr = argvT[argN]; *ptr != NUL;) {
637 	switch (mode) {
638 	  case UNKNOWN_:
639 	    if (*ptr == '/') {
640 	      mode = START_OF_QUAL_;
641 	      ptr++;
642 	    }
643 	    else
644 	      mode = START_OF_PARM_;
645 	    break;
646 	  case START_OF_PARM_:
647 	    Nparms++;
648 	    if (Nparms <= QOP_MAX_PARMs)
649 	      parms[Nparms-1] = ptr;
650 	    else {
651 	      DisplayError ("Too many parameters.");
652 	      FreeArgvT (argN, argvT);
653 	      return NULL;
654 	    }
655 	    mode = FIND_PARM_END_;
656 	    ptr++;
657 	    break;
658 	  case FIND_PARM_END_:
659 	    if (*ptr == '/')
660 	      if (*(ptr+1) == '/')
661 		memmove (ptr, ptr+1, strlen(ptr+1) + 1);
662 	      else {
663 		*ptr = NUL;
664 		mode = START_OF_QUAL_;
665 	      }
666 	    ptr++;
667 	    break;
668 	  case START_OF_QUAL_:
669 	    if (*ptr == '/')
670 	      mode = START_OF_PARM_;
671 	    else {
672 	      Nquals++;
673 	      if (Nquals <= QOP_MAX_QUALs)
674 		quals[Nquals-1] = ptr;
675 	      else {
676 		DisplayError ("Too many qualifiers.");
677 		FreeArgvT (argN, argvT);
678 		return NULL;
679 	      }
680 	      mode = FIND_QUAL_END_;
681 	      ptr++;
682 	    }
683 	    break;
684 	  case FIND_QUAL_END_:
685 	    switch (*ptr) {
686 	      case '/':
687 		*ptr = NUL;
688 		opts[Nquals-1] = NULL;
689 		mode = START_OF_QUAL_;
690 		break;
691 	      case '=':
692 		*ptr = NUL;
693 		mode = START_OF_OPT_;
694 		break;
695 	    }
696 	    ptr++;
697 	    break;
698 	  case START_OF_OPT_:
699 	    if (*ptr == '/')
700 	      if (*(ptr+1) == '/') {
701 		opts[Nquals-1] = ptr + 1;
702 		ptr += 2;
703 		mode = FIND_OPT_END_;
704 	      }
705 	      else {
706 		char tempS[MAX_MESSAGE_TEXT_LEN+1];
707 		sprintf (tempS, "Missing option for qualifier `/%s'.",
708 				 quals[Nquals-1]);
709 		DisplayError (tempS);
710 		FreeArgvT (argN, argvT);
711 		return NULL;
712 	      }
713 	    else {
714 	      opts[Nquals-1] = ptr;
715 	      mode = FIND_OPT_END_;
716 	      ptr++;
717 	    }
718 	    break;
719 	  case FIND_OPT_END_:
720 	    if (*ptr == '/')
721 	      if (*(ptr+1) == '/')
722 		memmove (ptr, ptr+1, strlen(ptr+1) + 1);
723 	      else {
724 		*ptr = NUL;
725 		mode = START_OF_QUAL_;
726 	      }
727 	    ptr++;
728 	    break;
729 	}
730      }
731      switch (mode) {
732        case UNKNOWN_:
733 	 /* Logic error. */
734 	 break;
735        case START_OF_PARM_:
736 	 /* Logic error. */
737 	 break;
738        case START_OF_QUAL_:
739 	 DisplayError ("Missing qualifier body (/).");
740 	 FreeArgvT (argN, argvT);
741 	 return NULL;
742        case FIND_QUAL_END_:
743 	 /* Qualifier already NUL-terminated */
744 	 opts[Nquals-1] = NULL;
745 	 break;
746        case FIND_PARM_END_:
747 	 /* Parameter already NUL-terminated */
748 	 break;
749        case START_OF_OPT_: {
750 	 char tempS[MAX_MESSAGE_TEXT_LEN+1];
751 	 sprintf (tempS,"Missing option for qualifier `/%s'.",quals[Nquals-1]);
752 	 DisplayError (tempS);
753 	 FreeArgvT (argN, argvT);
754 	 return NULL;
755        }
756        case FIND_OPT_END_:
757 	 /* Option already NUL-terminated */
758 	 break;
759      }
760   }
761   /****************************************************************************
762   * Set up to scan command line arguments (while checking number of valid
763   * qualifiers).
764   ****************************************************************************/
765   for (qualNv = 0; validQuals[qualNv] != NULL; qualNv++) {
766      if (qualNv < QOP_MAX_QUALs) {
767        qualEntered[qualNv] = FALSE;
768        qualOpt[qualNv] = NULL;
769      }
770      else {
771        WriteOut (stdout, "Too many valid qualifiers.\n");
772        FreeArgvT (argc - 1, argvT);
773        return NULL;
774      }
775   }
776   /****************************************************************************
777   * Determine which qualifiers/options were entered.
778   ****************************************************************************/
779   for (qualNe = 0; qualNe < Nquals; qualNe++) {
780      matchQualNv = FindUniqueMatch (quals[qualNe], validQuals);
781      switch (matchQualNv) {
782        case NOMATCH: {
783 	 char tempS[MAX_MESSAGE_TEXT_LEN+1];
784 	 sprintf (tempS, "Unknown qualifier (/%s).", quals[qualNe]);
785 	 DisplayError (tempS);
786 	 FreeArgvT (argc - 1, argvT);
787 	 return NULL;
788        }
789        case MATCHES: {
790 	 char tempS[MAX_MESSAGE_TEXT_LEN+1];
791 	 sprintf (tempS, "Ambiguous qualifier (/%s).", quals[qualNe]);
792 	 DisplayError (tempS);
793 	 FreeArgvT (argc - 1, argvT);
794 	 return NULL;
795        }
796        default: {
797 	 if (optRequired[matchQualNv] && opts[qualNe] == NULL) {
798 	   char tempS[MAX_MESSAGE_TEXT_LEN+1];
799 	   sprintf (tempS, "Option missing for qualifier `/%s'.",
800 		    validQuals[matchQualNv]);
801 	   DisplayError (tempS);
802 	   FreeArgvT (argc - 1, argvT);
803 	   return NULL;
804          }
805 	 if (!optRequired[matchQualNv] && opts[qualNe] != NULL) {
806 	   char tempS[MAX_MESSAGE_TEXT_LEN+1];
807 	   sprintf (tempS, "Extraneous option for qualifier `/%s'.",
808 		    validQuals[matchQualNv]);
809 	   DisplayError (tempS);
810 	   FreeArgvT (argc - 1, argvT);
811 	   return NULL;
812 	 }
813 	 if (qualEntered[matchQualNv]) {
814 	   char tempS[MAX_MESSAGE_TEXT_LEN+1];
815 	   sprintf (tempS, "Redundant qualifier (/%s).",
816 		    validQuals[matchQualNv]);
817 	   DisplayError (tempS);
818 	   FreeArgvT (argc - 1, argvT);
819 	   return NULL;
820 	 }
821 	 qualEntered[matchQualNv] = TRUE;
822 	 qualOpt[matchQualNv] = opts[qualNe];
823 	 break;
824        }
825      }
826   }
827   /****************************************************************************
828   * Build QOP structure.
829   ****************************************************************************/
830   qop = BuildQOP (Nparms, parms, validQuals, qualEntered, qualOpt);
831   /****************************************************************************
832   * Free memory used and return QOP structure.
833   ****************************************************************************/
834   FreeArgvT (argc - 1, argvT);
835   return qop;
836 }
837 
838 /******************************************************************************
839 * ParseHyphenStyle.
840 * Assume qualifiers begin with a hyphen (-).
841 ******************************************************************************/
842 
ParseHyphenStyle(argc,argv,validQuals,optRequired)843 static QOP *ParseHyphenStyle (argc, argv, validQuals, optRequired)
844 int argc;
845 char *argv[];
846 char *validQuals[];
847 int optRequired[];
848 {
849   QOP *qop;                     /* Pointer to a QOP structure. */
850   int argN,                     /* Command line argument number. */
851       qualNv,                   /* Qualifier number from `valids' list. */
852       Nparms = 0,               /* Number of parameters entered. */
853       matchQualNv,              /* Matching qualifier number (from list of
854 				   valid qualifiers). */
855       qualEntered[QOP_MAX_QUALs];
856 				/* TRUE if the corresponding qualifier was
857 				   entered. */
858   char *parms[QOP_MAX_PARMs],   /* Pointers to the parameters entered. */
859        *qualOpt[QOP_MAX_QUALs]; /* Pointers to the options of the qualifiers
860 				   entered (indexed to correspond to the list
861 				   of valid qualifiers). */
862   /****************************************************************************
863   * Set up to scan command line arguments (while checking number of valid
864   * qualifiers).
865   ****************************************************************************/
866   for (qualNv = 0; validQuals[qualNv] != NULL; qualNv++) {
867      if (qualNv < QOP_MAX_QUALs) {
868        qualEntered[qualNv] = FALSE;
869        qualOpt[qualNv] = NULL;
870      }
871      else {
872        DisplayError ("Too many valid qualifiers.");
873        return NULL;
874      }
875   }
876   /****************************************************************************
877   * Determine which qualifiers were entered (the rest being parameters).
878   ****************************************************************************/
879   for (argN = 1; argN < argc; argN++) {
880      if (argv[argN][0] == '-' && argv[argN][1] != '-') {
881        matchQualNv = FindUniqueMatch (&argv[argN][1], validQuals);
882        switch (matchQualNv) {
883 	 case NOMATCH: {
884 	   char tempS[MAX_MESSAGE_TEXT_LEN+1];
885 	   sprintf (tempS, "Unknown qualifier (-%s).", &argv[argN][1]);
886 	   DisplayError (tempS);
887 	   return NULL;
888 	 }
889 	 case MATCHES: {
890 	   char tempS[MAX_MESSAGE_TEXT_LEN+1];
891 	   sprintf (tempS, "Ambiguous qualifier (-%s).", &argv[argN][1]);
892 	   DisplayError (tempS);
893 	   return NULL;
894 	 }
895 	 default: {
896 	   if (qualEntered[matchQualNv]) {
897 	     char tempS[MAX_MESSAGE_TEXT_LEN+1];
898 	     sprintf (tempS, "Redundant qualifier (-%s).",
899 		      validQuals[matchQualNv]);
900 	     DisplayError (tempS);
901 	     return NULL;
902 	   }
903 	   else
904 	     qualEntered[matchQualNv] = TRUE;
905 	   if (optRequired[matchQualNv]) {
906 	     if (argN+1 < argc) {
907 	       qualOpt[matchQualNv] = argv[argN+1];
908 	       argN++;
909 	     }
910 	     else {
911 	       char tempS[MAX_MESSAGE_TEXT_LEN+1];
912 	       sprintf (tempS, "Option missing for qualifier `-%s'.",
913 			validQuals[matchQualNv]);
914 	       DisplayError (tempS);
915 	       return NULL;
916 	     }
917 	   }
918 	 }
919        }
920      }
921      else {
922        Nparms++;
923        if (Nparms <= QOP_MAX_PARMs)
924 	 parms[Nparms-1] = BOO(strncmp(argv[argN],"--",2),
925 			       argv[argN],argv[argN] + 1);
926        else {
927 	 DisplayError ("Too many parameters.");
928 	 return NULL;
929        }
930      }
931   }
932   /****************************************************************************
933   * Build QOP structure.
934   ****************************************************************************/
935   qop = BuildQOP (Nparms, parms, validQuals, qualEntered, qualOpt);
936   /****************************************************************************
937   * Return QOP structure.
938   ****************************************************************************/
939   return qop;
940 }
941 
942 /******************************************************************************
943 * BuildQOP.
944 ******************************************************************************/
945 
BuildQOP(Nparms,parms,validQuals,qualEntered,qualOpt)946 static QOP *BuildQOP (Nparms, parms, validQuals, qualEntered, qualOpt)
947 int Nparms;
948 char *parms[];
949 char *validQuals[];
950 int *qualEntered;
951 char *qualOpt[];
952 {
953   QOP *qop;             /* Pointer to a QOP structure. */
954   int parmN,            /* Parameter number. */
955       qualNv,           /* Qualifier number (in list of valid qualifiers. */
956       strCount = 0;     /* Number of characters in the strings to be contained
957 			   in the QOP structure. */
958   char *strOffset;      /* Offset into the QOP structure of a string
959 			   (parameter/option). */
960   for (parmN = 0; parmN < Nparms; parmN++)
961      strCount += strlen(parms[parmN]) + 1;
962   for (qualNv = 0; validQuals[qualNv] != NULL; qualNv++)
963      if (qualEntered[qualNv])
964        if (qualOpt[qualNv] != NULL) strCount += strlen(qualOpt[qualNv]) + 1;
965   qop = (QOP *) cdf_AllocateMemory (sizeof(QOP) + strCount,
966 				FatalError);
967   strOffset = (char *) qop + sizeof(QOP);
968   qop->Nparms = Nparms;
969   for (parmN = 0; parmN < Nparms; parmN++) {
970      qop->parms[parmN] = strOffset;
971      strOffset += strlen(parms[parmN]) + 1;
972      strcpyX (qop->parms[parmN], parms[parmN], 0);
973   }
974   for (qualNv = 0; validQuals[qualNv] != NULL; qualNv++) {
975      qop->qualEntered[qualNv] = qualEntered[qualNv];
976      if (qualEntered[qualNv]) {
977        if (qualOpt[qualNv] != NULL) {
978 	 qop->qualOpt[qualNv] = strOffset;
979 	 strOffset += strlen(qualOpt[qualNv]) + 1;
980 	 strcpyX (qop->qualOpt[qualNv], qualOpt[qualNv], 0);
981        }
982        else
983 	 qop->qualOpt[qualNv] = NULL;
984      }
985   }
986   return qop;
987 }
988 
989 /******************************************************************************
990 * FreeArgvT.
991 ******************************************************************************/
992 
FreeArgvT(lastArgN,argvT)993 static void FreeArgvT (lastArgN, argvT)
994 int lastArgN;
995 char *argvT[];
996 {
997   int argN;
998   for (argN = 1; argN <= lastArgN; argN++) cdf_FreeMemory (argvT[argN],
999 						       FatalError);
1000   return;
1001 }
1002 
1003 /******************************************************************************
1004 * ASSIGNx.
1005 ******************************************************************************/
1006 
ASSIGNx(dst,src,dataType,numElems)1007 void ASSIGNx (dst, src, dataType, numElems)
1008 void *dst;
1009 void *src;
1010 long dataType;
1011 long numElems;
1012 {
1013   memmove (dst, src, (size_t) (CDFelemSize(dataType) * numElems));
1014   return;
1015 }
1016 
1017 /******************************************************************************
1018 * EQx.
1019 ******************************************************************************/
1020 
EQx(a,b,dataType,numElems)1021 Logical EQx (a, b, dataType, numElems)
1022 void *a;
1023 void *b;
1024 long dataType;
1025 long numElems;
1026 {
1027   if (dataType != CDF_EPOCH16)
1028     return BOO(memcmp(a,b,(size_t)(CDFelemSize(dataType)*numElems)),FALSE,TRUE);
1029   else {
1030     double epoch16_a[2], epoch16_b[2];
1031     epoch16_a[0] = *((double *) a);
1032     epoch16_a[1] = *(((double *) a)+1);
1033     epoch16_b[0] = *((double *) b);
1034     epoch16_b[1] = *(((double *) b)+1);
1035     if (epoch16_a[0] == epoch16_b[0] && epoch16_a[1] == epoch16_b[1])
1036       return TRUE;
1037     return FALSE;
1038   }
1039 }
1040 
1041 /******************************************************************************
1042 * NEx.
1043 ******************************************************************************/
1044 
NEx(a,b,dataType,numElems)1045 Logical NEx (a, b, dataType, numElems)
1046 void *a;
1047 void *b;
1048 long dataType;
1049 long numElems;
1050 {
1051   if (dataType != CDF_EPOCH16)
1052     return BOO(memcmp(a,b,(size_t)(CDFelemSize(dataType)*numElems)),TRUE,FALSE);
1053   else {
1054     double epoch16_a[2], epoch16_b[2];
1055     epoch16_a[0] = *((double *) a);
1056     epoch16_a[1] = *(((double *) a)+1);
1057     epoch16_b[0] = *((double *) b);
1058     epoch16_b[1] = *(((double *) b)+1);
1059     if (epoch16_a[0] == epoch16_b[0] && epoch16_a[1] == epoch16_b[1])
1060       return FALSE;
1061     return TRUE;
1062   }
1063 }
1064 
1065 /******************************************************************************
1066 * LEx.
1067 ******************************************************************************/
1068 
LEx(a,b,dataType,numElems)1069 Logical LEx (a, b, dataType, numElems)
1070 void *a;
1071 void *b;
1072 long dataType;
1073 long numElems;
1074 {
1075 switch (dataType) {
1076   case CDF_BYTE:
1077   case CDF_INT1:
1078     return (*((sChar *) a) <= *((sChar *) b));
1079   case CDF_UINT1:
1080     return (*((uChar *) a) <= *((uChar *) b));
1081   case CDF_INT2:
1082     return (*((Int16 *) a) <= *((Int16 *) b));
1083   case CDF_UINT2:
1084     return (*((uInt16 *) a) <= *((uInt16 *) b));
1085   case CDF_INT4:
1086     return (*((Int32 *) a) <= *((Int32 *) b));
1087   case CDF_UINT4:
1088     return (*((uInt32 *) a) <= *((uInt32 *) b));
1089   case CDF_REAL4:
1090   case CDF_FLOAT:
1091     return (*((float *) a) <= *((float *) b));
1092   case CDF_REAL8:
1093   case CDF_DOUBLE:
1094   case CDF_EPOCH:
1095     return (*((double *) a) <= *((double *) b));
1096   case CDF_EPOCH16: {
1097     double epoch16_a[2], epoch16_b[2];
1098     epoch16_a[0] = *((double *) a);
1099     epoch16_a[1] = *(((double *) a)+1);
1100     epoch16_b[0] = *((double *) b);
1101     epoch16_b[1] = *(((double *) b)+1);
1102     if (epoch16_a[0] > epoch16_b[0]) return FALSE;
1103     if (epoch16_a[0] == epoch16_b[0] && epoch16_a[1] > epoch16_b[1])
1104       return FALSE;
1105     return TRUE;
1106   }
1107   case CDF_CHAR:
1108   case CDF_UCHAR:
1109     return BOO(memcmp(a,b,(size_t)numElems) <= 0,TRUE,FALSE);
1110 }
1111 return FALSE;
1112 }
1113 
1114 /******************************************************************************
1115 * LTx.
1116 ******************************************************************************/
1117 
LTx(a,b,dataType,numElems)1118 Logical LTx (a, b, dataType, numElems)
1119 void *a;
1120 void *b;
1121 long dataType;
1122 long numElems;
1123 {
1124 switch (dataType) {
1125   case CDF_BYTE:
1126   case CDF_INT1:
1127     return (*((sChar *) a) < *((sChar *) b));
1128   case CDF_UINT1:
1129     return (*((uChar *) a) < *((uChar *) b));
1130   case CDF_INT2:
1131     return (*((Int16 *) a) < *((Int16 *) b));
1132   case CDF_UINT2:
1133     return (*((uInt16 *) a) < *((uInt16 *) b));
1134   case CDF_INT4:
1135     return (*((Int32 *) a) < *((Int32 *) b));
1136   case CDF_UINT4:
1137     return (*((uInt32 *) a) < *((uInt32 *) b));
1138   case CDF_REAL4:
1139   case CDF_FLOAT:
1140     return (*((float *) a) < *((float *) b));
1141   case CDF_REAL8:
1142   case CDF_DOUBLE:
1143   case CDF_EPOCH:
1144     return (*((double *) a) < *((double *) b));
1145   case CDF_EPOCH16: {
1146     double epoch16_a[2], epoch16_b[2];
1147     epoch16_a[0] = *((double *) a);
1148     epoch16_a[1] = *(((double *) a)+1);
1149     epoch16_b[0] = *((double *) b);
1150     epoch16_b[1] = *(((double *) b)+1);
1151     if (epoch16_a[0] > epoch16_b[0]) return FALSE;
1152     if (epoch16_a[0] == epoch16_b[0] && epoch16_a[1] >= epoch16_b[1])
1153       return FALSE;
1154     return TRUE;
1155   }
1156   case CDF_CHAR:
1157   case CDF_UCHAR:
1158     return BOO(memcmp(a,b,(size_t)numElems) < 0,TRUE,FALSE);
1159 }
1160 return FALSE;
1161 }
1162 
1163 /******************************************************************************
1164 * GEx.
1165 ******************************************************************************/
1166 
GEx(a,b,dataType,numElems)1167 Logical GEx (a, b, dataType, numElems)
1168 void *a;
1169 void *b;
1170 long dataType;
1171 long numElems;
1172 {
1173 switch (dataType) {
1174   case CDF_BYTE:
1175   case CDF_INT1:
1176     return (*((sChar *) a) >= *((sChar *) b));
1177   case CDF_UINT1:
1178     return (*((uChar *) a) >= *((uChar *) b));
1179   case CDF_INT2:
1180     return (*((Int16 *) a) >= *((Int16 *) b));
1181   case CDF_UINT2:
1182     return (*((uInt16 *) a) >= *((uInt16 *) b));
1183   case CDF_INT4:
1184     return (*((Int32 *) a) >= *((Int32 *) b));
1185   case CDF_UINT4:
1186     return (*((uInt32 *) a) >= *((uInt32 *) b));
1187   case CDF_REAL4:
1188   case CDF_FLOAT:
1189     return (*((float *) a) >= *((float *) b));
1190   case CDF_REAL8:
1191   case CDF_DOUBLE:
1192   case CDF_EPOCH:
1193     return (*((double *) a) >= *((double *) b));
1194   case CDF_EPOCH16: {
1195     double epoch16_a[2], epoch16_b[2];
1196     epoch16_a[0] = *((double *) a);
1197     epoch16_a[1] = *(((double *) a)+1);
1198     epoch16_b[0] = *((double *) b);
1199     epoch16_b[1] = *(((double *) b)+1);
1200     if (epoch16_a[0] < epoch16_b[0]) return FALSE;
1201     if (epoch16_a[0] == epoch16_b[0] && epoch16_a[1] < epoch16_b[1])
1202       return FALSE;
1203     return TRUE;
1204   }
1205   case CDF_CHAR:
1206   case CDF_UCHAR:
1207     return BOO(memcmp(a,b,(size_t)numElems) >= 0,TRUE,FALSE);
1208 }
1209 return FALSE;
1210 }
1211 
1212 /******************************************************************************
1213 * GTx.
1214 ******************************************************************************/
1215 
GTx(a,b,dataType,numElems)1216 Logical GTx (a, b, dataType, numElems)
1217 void *a;
1218 void *b;
1219 long dataType;
1220 long numElems;
1221 {
1222 switch (dataType) {
1223   case CDF_BYTE:
1224   case CDF_INT1:
1225     return (*((sChar *) a) > *((sChar *) b));
1226   case CDF_UINT1:
1227     return (*((uChar *) a) > *((uChar *) b));
1228   case CDF_INT2:
1229     return (*((Int16 *) a) > *((Int16 *) b));
1230   case CDF_UINT2:
1231     return (*((uInt16 *) a) > *((uInt16 *) b));
1232   case CDF_INT4:
1233     return (*((Int32 *) a) > *((Int32 *) b));
1234   case CDF_UINT4:
1235     return (*((uInt32 *) a) > *((uInt32 *) b));
1236   case CDF_REAL4:
1237   case CDF_FLOAT:
1238     return (*((float *) a) > *((float *) b));
1239   case CDF_REAL8:
1240   case CDF_DOUBLE:
1241   case CDF_EPOCH:
1242     return (*((double *) a) > *((double *) b));
1243   case CDF_EPOCH16: {
1244     double epoch16_a[2], epoch16_b[2];
1245     epoch16_a[0] = *((double *) a);
1246     epoch16_a[1] = *(((double *) a)+1);
1247     epoch16_b[0] = *((double *) b);
1248     epoch16_b[1] = *(((double *) b)+1);
1249     if (epoch16_a[0] < epoch16_b[0]) return FALSE;
1250     if (epoch16_a[0] == epoch16_b[0] && epoch16_a[1] <= epoch16_b[1])
1251       return FALSE;
1252     return TRUE;
1253   }
1254   case CDF_CHAR:
1255   case CDF_UCHAR:
1256     return BOO(memcmp(a,b,(size_t)numElems) > 0,TRUE,FALSE);
1257 }
1258 return FALSE;
1259 }
1260 
1261 /******************************************************************************
1262 * IncrRecordIndicesFirstLast.
1263 * Rolls over to `first' indices if at `last' indices (and increments record).
1264 ******************************************************************************/
1265 
IncrRecordIndicesFirstLast(rowMajor,recordN,numDims,first,last,indices)1266 void IncrRecordIndicesFirstLast (rowMajor, recordN, numDims, first, last,
1267 				 indices)
1268 Logical rowMajor;
1269 long *recordN;
1270 long numDims;
1271 long first[];
1272 long last[];
1273 long indices[];
1274 {
1275   if (numDims > 0) {
1276     int firstDim = BOO(rowMajor,(int)(numDims - 1),0);
1277     int lastDim = BOO(rowMajor,0,(int)(numDims - 1));
1278     int dimIncr = BOO(rowMajor,-1,1);
1279     int doneDim = lastDim + dimIncr, dimN;
1280     for (dimN = firstDim; dimN != doneDim; dimN += dimIncr) {
1281        if (indices[dimN] == last[dimN]) {
1282          indices[dimN] = first[dimN];
1283          if (dimN == lastDim) (*recordN)++;
1284        }
1285        else {
1286          indices[dimN]++;
1287          break;
1288        }
1289     }
1290   }
1291   else
1292     (*recordN)++;
1293   return;
1294 }
1295 
1296 /******************************************************************************
1297 * IncrIndicesFirstLastRow.
1298 * Rolls over to `first' indices if at `last' indices.
1299 ******************************************************************************/
1300 
IncrIndicesFirstLastRow(numDims,first,last,indices)1301 void IncrIndicesFirstLastRow (numDims, first, last, indices)
1302 long numDims;
1303 long first[];
1304 long last[];
1305 long indices[];
1306 {
1307   int dimN;
1308   for (dimN = (int) (numDims - 1); dimN >= 0; dimN--) {
1309      if (indices[dimN] == last[dimN])
1310        indices[dimN] = first[dimN];
1311      else {
1312        indices[dimN]++;
1313        break;
1314      }
1315   }
1316   return;
1317 }
1318 
1319 /******************************************************************************
1320 * IncrIndicesFirstLastCol.
1321 * Rolls over to `first' indices if at `last' indices.
1322 ******************************************************************************/
1323 
IncrIndicesFirstLastCol(numDims,first,last,indices)1324 void IncrIndicesFirstLastCol (numDims, first, last, indices)
1325 long numDims;
1326 long first[];
1327 long last[];
1328 long indices[];
1329 {
1330   int dimN;
1331   for (dimN = 0; dimN < numDims; dimN++) {
1332      if (indices[dimN] == last[dimN])
1333        indices[dimN] = first[dimN];
1334      else {
1335        indices[dimN]++;
1336        break;
1337      }
1338   }
1339   return;
1340 }
1341 
1342 /******************************************************************************
1343 * AllocateBuffers.
1344 ******************************************************************************/
1345 
AllocateBuffers(nRecords,numDims,dimSizes,groups,nScalarBuffers,nHyperBuffers,handles,nValueBytes,rowMajor,minNofHypers,fatalFnc)1346 Logical AllocateBuffers (nRecords, numDims, dimSizes, groups, nScalarBuffers,
1347 			 nHyperBuffers, handles, nValueBytes, rowMajor,
1348 			 minNofHypers, fatalFnc)
1349 long nRecords;
1350 long numDims;
1351 long dimSizes[];
1352 struct GroupStruct *groups;
1353 int nScalarBuffers;
1354 int nHyperBuffers;
1355 Byte **handles[];
1356 size_t nValueBytes[];
1357 Logical rowMajor;
1358 int minNofHypers;
1359 void (*fatalFnc) PROTOARGs((char *msg));
1360 {
1361   int lsDimN;           /* Least significant dimension number. */
1362   int msDimN;           /* Most significant dimension number. */
1363   int dimStep;          /* How to increment dimension number from most
1364 			   significant to least significant. */
1365   int dimN, dN;
1366   long nValuesPerRec, nValuesPerDim[CDF_MAX_DIMS], count, nHypersSoFar;
1367   /****************************************************************************
1368   * Setup for majority.
1369   ****************************************************************************/
1370   lsDimN = BOO(rowMajor,(int)(numDims-1),0);
1371   msDimN = BOO(rowMajor,0,(int)(numDims-1));
1372   dimStep = BOO(rowMajor,1,-1);
1373   /****************************************************************************
1374   * Calculate number of values per record/dimension.
1375   ****************************************************************************/
1376   if (numDims > 0) {
1377     nValuesPerDim[lsDimN] = 1;
1378     for (dimN = lsDimN - dimStep; dimN != msDimN - dimStep; dimN -= dimStep) {
1379        nValuesPerDim[dimN] = dimSizes[dimN+dimStep] *
1380 			     nValuesPerDim[dimN+dimStep];
1381     }
1382     nValuesPerRec = dimSizes[msDimN] * nValuesPerDim[msDimN];
1383   }
1384   else
1385     nValuesPerRec = 1;
1386   /****************************************************************************
1387   * Check if full records can be allocated.
1388   ****************************************************************************/
1389   count = nRecords;
1390   while (count >= 1 ) {
1391      long nRecGroups = nRecords/count + BOO(nRecords % count == 0,0,1);
1392      if (nRecGroups >= minNofHypers || count == 1) {
1393        if (AttemptAllocations(count,nScalarBuffers,count*nValuesPerRec,
1394 			      nHyperBuffers,handles,nValueBytes)) {
1395 	 groups->nRecGroups = nRecGroups;
1396 	 groups->firstRecCount = count;
1397 	 groups->lastRecCount = BOO(nRecords % count == 0,
1398 				    count,nRecords % count);
1399 	 groups->recGroupN = 1;
1400 	 for (dimN = msDimN; dimN != lsDimN + dimStep; dimN += dimStep) {
1401 	    groups->nDimGroups[dimN] = 1;
1402 	    groups->firstDimCount[dimN] = dimSizes[dimN];
1403 	    groups->lastDimCount[dimN] = dimSizes[dimN];
1404 	    groups->dimGroupN[dimN] = 1;
1405 	 }
1406 	 return TRUE;
1407        }
1408      }
1409      if (count == 1) break;
1410      count = (count + BOO(count % 2 == 0,0,1)) / 2;
1411   }
1412   groups->nRecGroups = nRecords;
1413   groups->firstRecCount = 1;
1414   groups->lastRecCount = 1;
1415   groups->recGroupN = 1;
1416   nHypersSoFar = nRecords;
1417   /****************************************************************************
1418   * Check how much of each dimension can be allocated.
1419   ****************************************************************************/
1420   for (dimN = msDimN; dimN != lsDimN + dimStep; dimN += dimStep) {
1421      count = dimSizes[dimN];
1422      while (count > 1) {
1423 	long nDimGroups = (dimSizes[dimN] / count) +
1424 			  BOO(dimSizes[dimN] % count == 0,0,1);
1425 	if (nHypersSoFar * nDimGroups >= minNofHypers) {
1426 	  if (AttemptAllocations(1L,nScalarBuffers,count*nValuesPerDim[dimN],
1427 				 nHyperBuffers,handles,nValueBytes)) {
1428 	    groups->nDimGroups[dimN] = nDimGroups;
1429 	    groups->firstDimCount[dimN] = count;
1430 	    groups->lastDimCount[dimN] = BOO(dimSizes[dimN] % count == 0,
1431 					     count,dimSizes[dimN] % count);
1432 	    groups->dimGroupN[dimN] = 1;
1433 	    for (dN = dimN + dimStep; dN != lsDimN + dimStep; dN += dimStep) {
1434 	       groups->nDimGroups[dN] = 1;
1435 	       groups->firstDimCount[dN] = dimSizes[dN];
1436 	       groups->lastDimCount[dN] = dimSizes[dN];
1437 	       groups->dimGroupN[dN] = 1;
1438 	    }
1439 	    return TRUE;
1440 	  }
1441 	}
1442 	count = (count + 1) / 2;
1443      }
1444      groups->nDimGroups[dimN] = dimSizes[dimN];
1445      groups->firstDimCount[dimN] = 1;
1446      groups->lastDimCount[dimN] = 1;
1447      groups->dimGroupN[dimN] = 1;
1448      nHypersSoFar *= dimSizes[dimN];
1449   }
1450   if (AttemptAllocations(1L,nScalarBuffers,1L,nHyperBuffers,
1451 			 handles,nValueBytes)) return TRUE;
1452   /****************************************************************************
1453   * Not all of the buffers can be allocated even at only one value per buffer.
1454   ****************************************************************************/
1455   if (fatalFnc != NULL) (*fatalFnc)("Unable to allocate memory buffers.");
1456   return FALSE;
1457 }
1458 
1459 /******************************************************************************
1460 * AttemptAllocations.
1461 ******************************************************************************/
1462 
AttemptAllocations(nScalarValues,nScalarBuffers,nHyperValues,nHyperBuffers,handles,nValueBytes)1463 static Logical AttemptAllocations (nScalarValues, nScalarBuffers, nHyperValues,
1464 				   nHyperBuffers, handles, nValueBytes)
1465 long nScalarValues;
1466 int nScalarBuffers;
1467 long nHyperValues;
1468 int nHyperBuffers;
1469 Byte **handles[];
1470 size_t nValueBytes[];
1471 {
1472   int bN, bNt; uLong maxBytes = 1, nBytes;
1473 #if defined(mac) || defined(dos)
1474   void *ptr;
1475 #endif
1476   /****************************************************************************
1477   * First allocate scalar buffers.
1478   ****************************************************************************/
1479   for (bN = 0; bN < nScalarBuffers; bN++) {
1480      nBytes = nScalarValues * nValueBytes[bN];
1481      if (nBytes > MAXnBYTESperALLOCATION)
1482        *handles[bN] = NULL;
1483      else
1484        *handles[bN] = cdf_AllocateMemory ((size_t) nBytes, NULL);
1485      if (*handles[bN] == NULL) {
1486        for (bNt = bN - 1; bNt >= 0; bNt--) cdf_FreeMemory (*handles[bNt],
1487 						       NULL);
1488        return FALSE;
1489      }
1490      maxBytes = MAXIMUM(maxBytes,nBytes);
1491   }
1492   /****************************************************************************
1493   * Then allocate hyper buffers.
1494   ****************************************************************************/
1495   for (bN = nScalarBuffers; bN < nScalarBuffers + nHyperBuffers; bN++) {
1496      nBytes = nHyperValues * nValueBytes[bN];
1497      if (nBytes > MAXnBYTESperALLOCATION)
1498        *handles[bN] = NULL;
1499      else
1500        *handles[bN] = cdf_AllocateMemory ((size_t) nBytes, NULL);
1501      if (*handles[bN] == NULL) {
1502        for (bNt = bN - 1; bNt >= 0; bNt--) cdf_FreeMemory (*handles[bNt],
1503 						       NULL);
1504        return FALSE;
1505      }
1506      maxBytes = MAXIMUM(maxBytes,nBytes);
1507   }
1508   /****************************************************************************
1509   * Allocate and then free a buffer twice the size of the largest buffer
1510   * allocated.  This will save some space on the heap for other uses.
1511   ****************************************************************************/
1512 #if defined(mac) || defined(dos)
1513   ptr = cdf_AllocateMemory ((size_t) (2 * maxBytes), NULL);
1514   if (ptr == NULL) {
1515     for (bNt = nScalarBuffers + nHyperBuffers - 1; bNt >= 0; bNt--) {
1516        cdf_FreeMemory (*handles[bNt], NULL);
1517     }
1518     return FALSE;
1519   }
1520   cdf_FreeMemory (ptr, NULL);
1521 #endif
1522   /****************************************************************************
1523   * All allocations succeeded, return TRUE.
1524   ****************************************************************************/
1525   return TRUE;
1526 }
1527 
1528 /******************************************************************************
1529 * HyperFullRecord.
1530 ******************************************************************************/
1531 
HyperFullRecord(groups,numDims)1532 Logical HyperFullRecord (groups, numDims)
1533 struct GroupStruct *groups;
1534 long numDims;
1535 {
1536   int dimN;
1537   for (dimN = 0; dimN < numDims; dimN++) {
1538      if (groups->nDimGroups[dimN] > 1) return FALSE;
1539   }
1540   return TRUE;
1541 }
1542 
1543 /******************************************************************************
1544 * HypersPerRecord.
1545 ******************************************************************************/
1546 
HypersPerRecord(groups,numDims)1547 long HypersPerRecord (groups, numDims)
1548 struct GroupStruct *groups;
1549 long numDims;
1550 {
1551   int dimN; long nHypers = 1;
1552   for (dimN = 0; dimN < numDims; dimN++) {
1553      nHypers *= groups->nDimGroups[dimN];
1554   }
1555   return nHypers;
1556 }
1557 
1558 /******************************************************************************
1559 * HyperStartRecord.
1560 ******************************************************************************/
1561 
HyperStartOfRecord(hyper,numDims)1562 Logical HyperStartOfRecord (hyper, numDims)
1563 struct HyperStruct *hyper;
1564 long numDims;
1565 {
1566   int dimN;
1567   for (dimN = 0; dimN < numDims; dimN++) {
1568      if (hyper->dimIndices[dimN] > 0) return FALSE;
1569   }
1570   return TRUE;
1571 }
1572 
1573 /******************************************************************************
1574 * InitHyperParms.
1575 ******************************************************************************/
1576 
InitHyperParms(hyper,groups,numDims,nHypers,nValues)1577 void InitHyperParms (hyper, groups, numDims, nHypers, nValues)
1578 struct HyperStruct *hyper;
1579 struct GroupStruct *groups;
1580 long numDims;
1581 long *nHypers;
1582 long *nValues;
1583 {
1584   int dimN;
1585   *nHypers = groups->nRecGroups;
1586   for (dimN = 0; dimN < numDims; dimN++) *nHypers *= groups->nDimGroups[dimN];
1587   hyper->recNumber = 0;
1588   hyper->recCount = groups->firstRecCount;
1589   hyper->recInterval = 1;
1590   for (dimN = 0; dimN < numDims; dimN++) {
1591      hyper->dimIndices[dimN] = 0;
1592      hyper->dimCounts[dimN] = groups->firstDimCount[dimN];
1593      hyper->dimIntervals[dimN] = 1;
1594   }
1595   *nValues = hyper->recCount;
1596   for (dimN = 0; dimN < numDims; dimN++) *nValues *= hyper->dimCounts[dimN];
1597   return;
1598 }
1599 
1600 /******************************************************************************
1601 * IncrHyperParms.
1602 ******************************************************************************/
1603 
IncrHyperParms(hyper,groups,numDims,rowMajor,nValues)1604 void IncrHyperParms (hyper, groups, numDims, rowMajor, nValues)
1605 struct HyperStruct *hyper;
1606 struct GroupStruct *groups;
1607 long numDims;
1608 Logical rowMajor;
1609 long *nValues;
1610 {
1611   int lsDimN;           /* Least significant dimension number. */
1612   int msDimN;           /* Most significant dimension number. */
1613   int dimStep;          /* How to increment dimension number from most
1614 			   significant to least significant. */
1615   int dimN;
1616   /****************************************************************************
1617   * Setup for majority.
1618   ****************************************************************************/
1619   lsDimN = BOO(rowMajor,(int)(numDims-1),0);
1620   msDimN = BOO(rowMajor,0,(int)(numDims-1));
1621   dimStep = BOO(rowMajor,1,-1);
1622   /****************************************************************************
1623   * Increment indices.
1624   ****************************************************************************/
1625   for (dimN = lsDimN; dimN != msDimN - dimStep; dimN -= dimStep) {
1626      if (groups->dimGroupN[dimN] < groups->nDimGroups[dimN]) {
1627        groups->dimGroupN[dimN]++;
1628        if (groups->dimGroupN[dimN] < groups->nDimGroups[dimN]) {
1629 	 hyper->dimIndices[dimN] += groups->firstDimCount[dimN];
1630 	 hyper->dimCounts[dimN] = groups->firstDimCount[dimN];
1631        }
1632        else {
1633 	 hyper->dimIndices[dimN] += groups->firstDimCount[dimN];
1634 	 hyper->dimCounts[dimN] = groups->lastDimCount[dimN];
1635        }
1636        *nValues = hyper->recCount;
1637        for (dimN = 0; dimN < numDims; dimN++) {
1638 	  *nValues *= hyper->dimCounts[dimN];
1639        }
1640        return;
1641      }
1642      else {
1643        groups->dimGroupN[dimN] = 1;
1644        hyper->dimIndices[dimN] = 0;
1645        hyper->dimCounts[dimN] = groups->firstDimCount[dimN];
1646      }
1647   }
1648   /****************************************************************************
1649   * Increment record.
1650   ****************************************************************************/
1651   groups->recGroupN++;
1652   hyper->recNumber += groups->firstRecCount;
1653   hyper->recCount = BOO(groups->recGroupN < groups->nRecGroups,
1654 			groups->firstRecCount,groups->lastRecCount);
1655   *nValues = hyper->recCount;
1656   for (dimN = 0; dimN < numDims; dimN++) *nValues *= hyper->dimCounts[dimN];
1657   return;
1658 }
1659 
1660 /******************************************************************************
1661 * WriteOutPct.
1662 ******************************************************************************/
1663 
WriteOutPct(pct)1664 void WriteOutPct (pct)
1665 int pct;
1666 {
1667   char text[8+1];
1668   strcpyX (text, "\b\b\b\b", 8);
1669   if (pct < 10) strcatX (text, ".", 8);
1670   if (pct < 100) strcatX (text, ".", 8);
1671   sprintf (EofS(text), "%d", pct);
1672   strcatX (text, "%", 8);
1673   WriteOut (stdout, text);
1674   return;
1675 }
1676 
1677 /******************************************************************************
1678 * SwitchMajority.
1679 ******************************************************************************/
1680 
SwitchMajority(buffer,rowMajor,numDims,dimSizes,recCount,nValueBytes)1681 Logical SwitchMajority (buffer, rowMajor, numDims, dimSizes, recCount,
1682 			nValueBytes)
1683 Byte *buffer;
1684 Logical rowMajor;
1685 long numDims;
1686 long dimSizes[];
1687 long recCount;
1688 size_t nValueBytes;
1689 {
1690   int dimN; long nRecordBytes, recX; Byte *offset; void *tBuffer;
1691   /****************************************************************************
1692   * If less than two dimensions no switching needs to be done.
1693   ****************************************************************************/
1694   if (numDims < 2) return TRUE;
1695   /****************************************************************************
1696   * Calculate number of bytes per record.
1697   ****************************************************************************/
1698   nRecordBytes = nValueBytes;
1699   for (dimN = 0; dimN < numDims; dimN++) nRecordBytes *= dimSizes[dimN];
1700   /****************************************************************************
1701   * Attempt to allocate a temporary buffer for one record.
1702   ****************************************************************************/
1703 #if defined(dos)
1704   if (TOObigIBMpc(nRecordBytes))
1705     tBuffer = NULL;
1706   else
1707 #endif
1708     tBuffer = cdf_AllocateMemory ((size_t) nRecordBytes, NULL);
1709   if (tBuffer == NULL) return FALSE;
1710   /****************************************************************************
1711   * Switch majority.
1712   ****************************************************************************/
1713   for (recX = 0, offset = buffer; recX < recCount;
1714        recX++, offset += (size_t) nRecordBytes) {
1715     if (rowMajor)
1716       ROWtoCOL (offset, tBuffer, numDims, dimSizes, (long) nValueBytes);
1717     else
1718       COLtoROW (offset, tBuffer, numDims, dimSizes, (long) nValueBytes);
1719     memmove (offset, tBuffer, (size_t) nRecordBytes);
1720   }
1721   /****************************************************************************
1722   * Free temporary buffer and return success.
1723   ****************************************************************************/
1724   cdf_FreeMemory (tBuffer, FatalError);
1725   return TRUE;
1726 }
1727 
1728 /******************************************************************************
1729 * CompressedCDF.
1730 ******************************************************************************/
1731 
CompressedCDF(CDFpath)1732 Logical CompressedCDF (CDFpath)
1733 char *CDFpath;
1734 {
1735   CDFstatus status; long cType, cParms[CDF_MAX_PARMS];
1736   OFF_T cFileSize, uFileSize;
1737   status = CDFlib (GET_, CDF_INFO_, CDFpath, &cType, cParms,
1738                                     &cFileSize, &uFileSize,
1739                    NULL_);
1740   if (StatusBAD(status)) return FALSE;
1741   return ((Logical) (cType != NO_COMPRESSION));
1742 }
1743 
1744 /******************************************************************************
1745 * SameCompressions.
1746 ******************************************************************************/
1747 
SameCompressions(cType1,cParms1,cType2,cParms2)1748 Logical SameCompressions (cType1, cParms1, cType2, cParms2)
1749 long cType1;
1750 long cParms1[CDF_MAX_PARMS];
1751 long cType2;
1752 long cParms2[CDF_MAX_PARMS];
1753 {
1754   int parmN, pCount;
1755   /****************************************************************************
1756   * Compare compression types.
1757   ****************************************************************************/
1758   if (cType1 != cType2) return FALSE;
1759   /****************************************************************************
1760   * If same types, compare compression parameters (if any).
1761   ****************************************************************************/
1762   pCount = CompressionParmsCount(cType1);
1763   for (parmN = 0; parmN < pCount; parmN++) {
1764      if (cParms1[parmN] != cParms2[parmN]) return FALSE;
1765   }
1766   /****************************************************************************
1767   * Compressions must be the same.
1768   ****************************************************************************/
1769   return TRUE;
1770 }
1771 
1772 /******************************************************************************
1773 * SameSparsenesses.
1774 ******************************************************************************/
1775 
SameSparsenesses(sRecordsType1,sArraysType1,sArraysParms1,sRecordsType2,sArraysType2,sArraysParms2)1776 Logical SameSparsenesses (sRecordsType1, sArraysType1, sArraysParms1,
1777 			  sRecordsType2, sArraysType2, sArraysParms2)
1778 long sRecordsType1;
1779 long sArraysType1;
1780 long sArraysParms1[CDF_MAX_PARMS];
1781 long sRecordsType2;
1782 long sArraysType2;
1783 long sArraysParms2[CDF_MAX_PARMS];
1784 {
1785   int parmN, pCount;
1786   /****************************************************************************
1787   * Compare sparse records.
1788   ****************************************************************************/
1789   if (sRecordsType1 != sRecordsType2) return FALSE;
1790   /****************************************************************************
1791   * Compare sparse array types.
1792   ****************************************************************************/
1793   if (sArraysType1 != sArraysType2) return FALSE;
1794   /****************************************************************************
1795   * If same types, compare sparse array parameters (if any).
1796   ****************************************************************************/
1797   pCount = SparsenessParmsCount(sArraysType1);
1798   for (parmN = 0; parmN < pCount; parmN++) {
1799      if (sArraysParms1[parmN] != sArraysParms2[parmN]) return FALSE;
1800   }
1801   /****************************************************************************
1802   * Sparsenesses must be the same.
1803   ****************************************************************************/
1804   return TRUE;
1805 }
1806 
1807 /******************************************************************************
1808 * WhichFormat.
1809 ******************************************************************************/
1810 
WhichFormat(token)1811 long WhichFormat (token)
1812 char *token;
1813 {
1814   if (strncmpIgCase(token,"SINGLE",6) != 0) return SINGLE_FILE;
1815   if (strncmpIgCase(token,"MULTI",5) != 0) return MULTI_FILE;
1816   return -1;
1817 }
1818 
1819 /******************************************************************************
1820 * WhichMajority.
1821 ******************************************************************************/
1822 
WhichMajority(token)1823 long WhichMajority (token)
1824 char *token;
1825 {
1826   if (strncmpIgCase(token,"ROW",3) != 0) return ROW_MAJOR;
1827   if ((strncmpIgCase(token,"COL",3) != 0) ||
1828       (strncmpIgCase(token,"COLUMN",6) != 0)) return COLUMN_MAJOR;
1829   return -1;
1830 }
1831 
1832 /******************************************************************************
1833 * WhichRecSparseness.
1834 ******************************************************************************/
1835 
WhichRecSparseness(token)1836 long WhichRecSparseness (token)
1837 char *token;
1838 {
1839   if (strncmpIgCase(token,"None",4) != 0) return NO_SPARSERECORDS;
1840   if (strncmpIgCase(token,"sRecords.PAD",12) != 0) return PAD_SPARSERECORDS;
1841   if (strncmpIgCase(token,"sRecords.PREV",13) != 0) return PREV_SPARSERECORDS;
1842   return -1;
1843 }
1844 
1845 /******************************************************************************
1846 * WhichCompression
1847 ******************************************************************************/
1848 
WhichCompression(token,compression,cParms)1849 long WhichCompression (token, compression, cParms)
1850 char *token;
1851 long *compression;
1852 long cParms[CDF_MAX_PARMS];
1853 {
1854   *compression = -1;
1855   cParms[0] = 0;
1856   if (strncmpIgCase(token,"No",2) != 0) *compression = NO_COMPRESSION;
1857   else if (strncmpIgCase(token,"RLE",3) != 0) *compression = RLE_COMPRESSION;
1858   else if (strncmpIgCase(token,"HUFF",4) != 0)  *compression = HUFF_COMPRESSION;
1859   else if (strncmpIgCase(token,"AHUFF",5) != 0) *compression = AHUFF_COMPRESSION;
1860   else if (strncmpIgCase(token,"GZIP",4) != 0) {
1861 #if defined(__osf__)
1862     int clevel;
1863     if (sscanf(token,"GZIP.%d",&clevel) == 1)
1864 #else
1865     long clevel;
1866     if (sscanf(token,"GZIP.%1d",&clevel) == 1)
1867 #endif
1868         if (INCLUSIVE(1,clevel,9)) {
1869 	  *compression =  GZIP_COMPRESSION;
1870 	  cParms[0] = (long) clevel;
1871 	}
1872   }
1873 /*  if (strncmpIgCase(token,"ZLIB",4)) *compression = ZLIB_COMPRESSION; */
1874   return (long) *compression;
1875 }
1876 
1877 /******************************************************************************
1878 * WhichEncoding.  `MIPSEL' (DECstation) and `MIPSEB' (SGi) are valid synonyms
1879 *                 in order to remain compatible with previous releases of CDF.
1880 ******************************************************************************/
1881 
WhichEncoding(token)1882 long WhichEncoding (token)
1883 char *token;
1884 {
1885   if (strncmpIgCase(token,"HOST",4) != 0) return HOST_ENCODING;
1886   if (strncmpIgCase(token,"NETWORK",6) != 0) return NETWORK_ENCODING;
1887   if (strncmpIgCase(token,"IBMPC",5) != 0) return IBMPC_ENCODING;
1888   if ((strncmpIgCase(token,"PPC",3) != 0) ||
1889       (strncmpIgCase(token,"MAC",3) != 0)) return PPC_ENCODING;
1890   if (strncmpIgCase(token,"SUN",3) != 0) return SUN_ENCODING;
1891   if (strncmpIgCase(token,"VAX",3) != 0) return VAX_ENCODING;
1892   if ((strncmpIgCase(token,"SGi",3) != 0) ||
1893       (strncmpIgCase(token,"MIPSEB",6) != 0)) return SGi_ENCODING;
1894   if ((strncmpIgCase(token,"DECSTATION",10) != 0) ||
1895       (strncmpIgCase(token,"MIPSEL",6) != 0)) return DECSTATION_ENCODING;
1896   if (strncmpIgCase(token,"IBMRS",5) != 0) return IBMRS_ENCODING;
1897   if (strncmpIgCase(token,"HP",2) != 0) return HP_ENCODING;
1898   if (strncmpIgCase(token,"NeXT",4) != 0) return NeXT_ENCODING;
1899   if (strncmpIgCase(token,"ALPHAOSF1",9) != 0) return ALPHAOSF1_ENCODING;
1900   if (strncmpIgCase(token,"ALPHAVMSd",9) != 0) return ALPHAVMSd_ENCODING;
1901   if (strncmpIgCase(token,"ALPHAVMSg",9) != 0) return ALPHAVMSg_ENCODING;
1902   if (strncmpIgCase(token,"ALPHAVMSi",9) != 0) return ALPHAVMSi_ENCODING;
1903   return -1;
1904 }
1905 
1906 /******************************************************************************
1907 * WhichDataType.
1908 ******************************************************************************/
1909 
WhichDataType(token)1910 long WhichDataType (token)
1911 char *token;
1912 {
1913   if (strncmpIgCase(token,"BYTE",4) != 0) return CDF_BYTE;
1914   if (strncmpIgCase(token,"INT1",4) != 0) return CDF_INT1;
1915   if (strncmpIgCase(token,"UINT1",5) != 0) return CDF_UINT1;
1916   if (strncmpIgCase(token,"INT2",4) != 0) return CDF_INT2;
1917   if (strncmpIgCase(token,"UINT2",5) != 0) return CDF_UINT2;
1918   if (strncmpIgCase(token,"INT4",4) != 0) return CDF_INT4;
1919   if (strncmpIgCase(token,"UINT4",5) != 0) return CDF_UINT4;
1920   if (strncmpIgCase(token,"REAL4",5) != 0) return CDF_REAL4;
1921   if (strncmpIgCase(token,"FLOAT",5) != 0) return CDF_FLOAT;
1922   if (strncmpIgCase(token,"REAL8",5) != 0) return CDF_REAL8;
1923   if (strncmpIgCase(token,"DOUBLE",6) != 0) return CDF_DOUBLE;
1924   if (strncmpIgCase(token,"CHAR",4) != 0) return CDF_CHAR;
1925   if (strncmpIgCase(token,"UCHAR",5) != 0) return CDF_UCHAR;
1926   if (strncmpIgCase(token,"EPOCH",5) != 0) return CDF_EPOCH;
1927   if (strncmpIgCase(token,"EPOCH16",7) != 0) return CDF_EPOCH16;
1928   if (strncmpIgCase(token,"CDF_BYTE",8) != 0) return CDF_BYTE;
1929   if (strncmpIgCase(token,"CDF_INT1",8) != 0) return CDF_INT1;
1930   if (strncmpIgCase(token,"CDF_UINT1",9) != 0) return CDF_UINT1;
1931   if (strncmpIgCase(token,"CDF_INT2",8) != 0) return CDF_INT2;
1932   if (strncmpIgCase(token,"CDF_UINT2",9) != 0) return CDF_UINT2;
1933   if (strncmpIgCase(token,"CDF_INT4",8) != 0) return CDF_INT4;
1934   if (strncmpIgCase(token,"CDF_UINT4",9) != 0) return CDF_UINT4;
1935   if (strncmpIgCase(token,"CDF_REAL4",9) != 0) return CDF_REAL4;
1936   if (strncmpIgCase(token,"CDF_FLOAT",9) != 0) return CDF_FLOAT;
1937   if (strncmpIgCase(token,"CDF_REAL8",9) != 0) return CDF_REAL8;
1938   if (strncmpIgCase(token,"CDF_DOUBLE",10) != 0) return CDF_DOUBLE;
1939   if (strncmpIgCase(token,"CDF_CHAR",8) != 0) return CDF_CHAR;
1940   if (strncmpIgCase(token,"CDF_UCHAR",9) != 0) return CDF_UCHAR;
1941   if (strncmpIgCase(token,"CDF_EPOCH",9) != 0) return CDF_EPOCH;
1942   if (strncmpIgCase(token,"CDF_EPOCH16",11) != 0) return CDF_EPOCH16;
1943   return -1;
1944 }
1945 
1946 /******************************************************************************
1947 * WhichChecksum.
1948 ******************************************************************************/
1949 
WhichChecksum(token)1950 long WhichChecksum (token)
1951 char *token;
1952 {
1953   if ((strncmpIgCase(token,"NO",2) != 0) ||
1954       (strncmpIgCase(token,"NONE",4) != 0)) return NO_CHECKSUM;
1955   if (strncmpIgCase(token,"MD5",3) != 0) return MD5_CHECKSUM;
1956   if (strncmpIgCase(token,"OTHER",5) != 0) return OTHER_CHECKSUM;
1957   return -1;
1958 }
1959 
1960 /******************************************************************************
1961 * EncodingToken.
1962 *   Returns address of character string for encoding.
1963 ******************************************************************************/
1964 
EncodingToken(encoding)1965 char *EncodingToken (encoding)
1966 long encoding;
1967 {
1968   switch (encoding) {
1969     case NETWORK_ENCODING: return "NETWORK";
1970     case VAX_ENCODING: return "VAX";
1971     case SUN_ENCODING: return "SUN";
1972     case DECSTATION_ENCODING: return "DECSTATION";
1973     case SGi_ENCODING: return "SGi";
1974     case IBMRS_ENCODING: return "IBMRS";
1975     case IBMPC_ENCODING: return "IBMPC";
1976     case HP_ENCODING: return "HP";
1977     case NeXT_ENCODING: return "NeXT";
1978     case ALPHAOSF1_ENCODING: return "ALPHAOSF1";
1979     case ALPHAVMSd_ENCODING: return "ALPHAVMSd";
1980     case ALPHAVMSg_ENCODING: return "ALPHAVMSg";
1981     case ALPHAVMSi_ENCODING: return "ALPHAVMSi";
1982     case PPC_ENCODING: return "PPC";
1983     default: return "?";
1984   }
1985 }
1986 
1987 /******************************************************************************
1988 * MajorityToken.
1989 *   Returns address of character string for majority.
1990 ******************************************************************************/
1991 
MajorityToken(majority)1992 char *MajorityToken (majority)
1993 long majority;
1994 {
1995   switch (majority) {
1996     case ROW_MAJOR: return "ROW";
1997     case COLUMN_MAJOR: return "COLUMN";
1998     default: return "?";
1999   }
2000 }
2001 
2002 /******************************************************************************
2003 * FormatToken.
2004 *   Returns address of character string for format.
2005 ******************************************************************************/
2006 
FormatToken(format)2007 char *FormatToken (format)
2008 long format;
2009 {
2010   switch (format) {
2011     case SINGLE_FILE: return "SINGLE";
2012     case MULTI_FILE: return "MULTI";
2013     default: return "?";
2014   }
2015 }
2016 
2017 /******************************************************************************
2018 * ChecksumToken.
2019 *   Returns address of character string for checksum.
2020 ******************************************************************************/
2021 
ChecksumToken(checksum)2022 char *ChecksumToken (checksum)
2023 long checksum;
2024 {
2025   switch (checksum) {
2026     case NO_CHECKSUM: return "None";
2027     case MD5_CHECKSUM: return "MD5";
2028     case OTHER_CHECKSUM: return "Other";
2029     default: return "?";
2030   }
2031 }
2032 
2033 /******************************************************************************
2034 * ScopeToken.
2035 *   Returns address of character string for scope.
2036 ******************************************************************************/
2037 
ScopeToken(scope)2038 char *ScopeToken (scope)
2039 long scope;
2040 {
2041   switch (scope) {
2042     case GLOBAL_SCOPE: return "GLOBAL";
2043     case VARIABLE_SCOPE: return "VARIABLE";
2044     default: return "?";
2045   }
2046 }
2047 
2048 /******************************************************************************
2049 * VarianceToken.
2050 *   Returns address of character string for variance.
2051 ******************************************************************************/
2052 
VarianceToken(variance)2053 char *VarianceToken (variance)
2054 long variance;
2055 {
2056   switch (variance) {
2057     case VARY: return "VARY";
2058     case NOVARY: return "NOVARY";
2059     default: return "?";
2060   }
2061 }
2062 
2063 /******************************************************************************
2064 * TFvarianceToken.
2065 *   Returns address of character string for variance (T/F).
2066 ******************************************************************************/
2067 
TFvarianceToken(variance)2068 char *TFvarianceToken (variance)
2069 long variance;
2070 {
2071   switch (variance) {
2072     case VARY: return "T";
2073     case NOVARY: return "F";
2074     default: return "?";
2075   }
2076 }
2077 
2078 /******************************************************************************
2079 * DataTypeToken.
2080 *   Returns address of character string for data type.
2081 ******************************************************************************/
2082 
DataTypeToken(dataType)2083 char *DataTypeToken (dataType)
2084 long dataType;
2085 {
2086   switch (dataType) {
2087     case CDF_BYTE: return "BYTE";
2088     case CDF_INT1: return "INT1";
2089     case CDF_INT2: return "INT2";
2090     case CDF_INT4: return "INT4";
2091     case CDF_UINT1: return "UINT1";
2092     case CDF_UINT2: return "UINT2";
2093     case CDF_UINT4: return "UINT4";
2094     case CDF_REAL4: return "REAL4";
2095     case CDF_REAL8: return "REAL8";
2096     case CDF_FLOAT: return "FLOAT";
2097     case CDF_DOUBLE: return "DOUBLE";
2098     case CDF_EPOCH: return "EPOCH";
2099     case CDF_EPOCH16: return "EPOCH16";
2100     case CDF_CHAR: return "CHAR";
2101     case CDF_UCHAR: return "UCHAR";
2102     default: return "?";
2103   }
2104 }
2105 
2106 /******************************************************************************
2107 * CompressionToken.
2108 *   Returns address of character string for compression type/parameters.
2109 ******************************************************************************/
2110 
CompressionToken(cType,cParms)2111 char *CompressionToken (cType, cParms)
2112 long cType;
2113 long cParms[CDF_MAX_PARMS];
2114 {
2115   switch (cType) {
2116     case NO_COMPRESSION:
2117       return "None";
2118     case RLE_COMPRESSION:
2119       switch (cParms[0]) {
2120 	case RLE_OF_ZEROs: return "RLE.0";
2121 	default: return "RLE.?";
2122       }
2123     case HUFF_COMPRESSION:
2124       switch (cParms[0]) {
2125 	case OPTIMAL_ENCODING_TREES: return "HUFF.0";
2126 	default: return "HUFF.?";
2127       }
2128     case AHUFF_COMPRESSION:
2129       switch (cParms[0]) {
2130 	case OPTIMAL_ENCODING_TREES: return "AHUFF.0";
2131 	default: return "AHUFF.?";
2132       }
2133     case GZIP_COMPRESSION: {
2134       static char token[MAX_GZIP_TOKEN_LEN+1];
2135       sprintf (token, "GZIP.%d", (int) cParms[0]);
2136       return token;
2137     }
2138 /*
2139     case ZLIB_COMPRESSION:
2140       switch (cParms[0]) {
2141         case RLE_OF_ZEROs: return "ZLIB.0";
2142         default: return "ZLIB.?";
2143       }
2144 */
2145     default: return "?";
2146   }
2147 }
2148 
2149 /******************************************************************************
2150 * SparsenessToken.
2151 *   Returns address of character string for sparseness types/parameters.
2152 * Both record and array sparseness is encoded in the same string.
2153 ******************************************************************************/
2154 
SparsenessToken(sRecordsType,sArraysType,sArraysParms)2155 char *SparsenessToken (sRecordsType, sArraysType, sArraysParms)
2156 long sRecordsType;
2157 long sArraysType;
2158 long sArraysParms[CDF_MAX_PARMS];
2159 {
2160   if (sArraysParms[0] == 0) { };    /* Quiets some compilers. */
2161   switch (sRecordsType) {
2162     case NO_SPARSERECORDS:
2163       switch (sArraysType) {
2164 	case NO_SPARSEARRAYS:
2165 	  return "None";
2166 	default:
2167 	  return "?";
2168       }
2169     case PAD_SPARSERECORDS:
2170       switch (sArraysType) {
2171 	case NO_SPARSEARRAYS:
2172 	  return "sRecords.PAD";
2173 	default:
2174 	  return "?";
2175       }
2176     case PREV_SPARSERECORDS:
2177       switch (sArraysType) {
2178 	case NO_SPARSEARRAYS:
2179 	  return "sRecords.PREV";
2180 	default:
2181 	  return "?";
2182       }
2183     default:
2184       return "?";
2185   }
2186 }
2187 
2188 /******************************************************************************
2189 * PickDelimiter.
2190 *    Exclamation mark (`!') isn't used because it starts a comment in a
2191 * skeleton table.  Period (`.') isn't used because it ends a list of
2192 * attribute entries (in a skeleton table).  Left bracket (`[') isn't used
2193 * because it starts a set of NRV indices (in a skeleton table).
2194 ******************************************************************************/
2195 
PickDelimiter(string,N)2196 char PickDelimiter (string, N)
2197 char *string;
2198 size_t N;
2199 {
2200   static char choices[] = "\"'`^~:-,;|+=@#$%&*()/?<>{}]\\";
2201   int i;
2202   for (i = 0; choices[i] != NUL; i++) {
2203      if (strnchr(string,choices[i],N) == NULL) return choices[i];
2204   }
2205   return NUL;   /* Very bad, use character stuffing if this is a problem. */
2206 }
2207 
2208 /******************************************************************************
2209 * strnchr.
2210 ******************************************************************************/
2211 
strnchr(string,chr,n)2212 static char *strnchr (string, chr, n)
2213 char *string;
2214 int chr;
2215 int n;
2216 {
2217   int i;
2218   for (i = 0; i < n; i++) if (string[i] == chr) return &string[i];
2219   return NULL;
2220 }
2221 
2222 /******************************************************************************
2223 * sleep.  Only for Microsoft C.
2224 ******************************************************************************/
2225 
2226 #if defined(MICROSOFTC)
sleep(seconds)2227 void sleep (seconds)
2228 uInt seconds;
2229 {
2230 time_t start_time;
2231 time_t current_time;
2232 
2233 time (&start_time);
2234 time (&current_time);
2235 
2236 while (current_time - start_time < seconds) time (&current_time);
2237 
2238 return;
2239 }
2240 #endif
2241 
2242 /******************************************************************************
2243 * strstrIgCase.
2244 ******************************************************************************/
2245 
strstrIgCase(string,substring)2246 char *strstrIgCase (string, substring)
2247 char *string;
2248 char *substring;
2249 {
2250   int stringL = strlen(string);
2251   int substringL = strlen(substring);
2252   int i, j;
2253   if (stringL == 0 || substringL == 0) return NULL;
2254   if (stringL < substringL) return NULL;
2255   for (i = 0; i < stringL; i++) {
2256      for (j = 0; j < substringL; j++) {
2257 	if (MakeLower(substring[j]) != MakeLower(string[i+j])) break;
2258      }
2259      if (j == substringL) return &string[i];
2260   }
2261   return NULL;
2262 }
2263 
2264 /******************************************************************************
2265 * strcmpIgCase.
2266 * It returns  1 if compared strings are identical with the same length
2267 *             0 if compared (sub)strings are not same
2268 ******************************************************************************/
2269 
strcmpIgCase(string1,string2)2270 int strcmpIgCase (string1, string2)
2271 char *string1;
2272 char *string2;
2273 {
2274   int string1L = strlen(string1);
2275   int string2L = strlen(string2);
2276   int i;
2277   if (string1L != string2L) return 0;
2278   for (i = 0; i < string1L; i++) {
2279      if (MakeLower(string1[i]) != MakeLower(string2[i]))
2280        return 0;
2281   }
2282   return 1;
2283 }
2284 
2285 /******************************************************************************
2286 * strncmpIgCase... Assuming count is the length from one of passed strings.
2287 *                  It compares characters upto the passed count.
2288 * It returns  1 if compared strings are identical with same length
2289 *             0 if compared (sub)strings are not same
2290 ******************************************************************************/
2291 
strncmpIgCase(string1,string2,count)2292 int strncmpIgCase (string1, string2, count)
2293 char *string1;
2294 char *string2;
2295 size_t count;
2296 {
2297   int string1L = (int) strlen(string1);
2298   int string2L = (int) strlen(string2);
2299   int maxL, i;
2300   maxL = MAXIMUM(string1L,string2L);
2301   maxL = MINIMUM(maxL,(int)count);
2302   for (i = 0; i < maxL; i++) {
2303      if (i == string1L || i == string2L) break;
2304      if (MakeLower(string1[i]) != MakeLower(string2[i])) {
2305        return 0;
2306      }
2307   }
2308   if (string1L == string2L) return 1;
2309   else return 0;
2310 }
2311 
2312 /******************************************************************************
2313 * strncmpIgCasePattern.
2314 * It returns  0 if compared strings are the same for the specified length
2315 *             <>0 if compared (sub)strings do not have the same pattern
2316 ******************************************************************************/
2317 
strncmpIgCasePattern(string1,string2,count)2318 int strncmpIgCasePattern (string1, string2, count)
2319 char *string1;
2320 char *string2;
2321 size_t count;
2322 {
2323   int string1L = (int) strlen(string1);
2324   int string2L = (int) strlen(string2);
2325   int maxL, i;
2326   maxL = MAXIMUM(string1L,string2L);
2327   maxL = MINIMUM(maxL,(int)count);
2328   for (i = 0; i < maxL; i++) {
2329     if (MakeLower(string1[i]) != MakeLower(string2[i])) {
2330       return ((int) (string1[i] - string2[i]));
2331     }
2332   }
2333   return 0;
2334 }
2335 
2336 /******************************************************************************
2337 * strchrIgCase.
2338 ******************************************************************************/
2339 
strchrIgCase(str,chr)2340 char *strchrIgCase (str, chr)
2341 char *str;
2342 int chr;
2343 {
2344   int strL = strlen(str);
2345   int i;
2346   if (strL == 0) return NULL;
2347   for (i = 0; i < strL; i++) {
2348      if (MakeLower(chr) == MakeLower(str[i])) return &str[i];
2349   }
2350   return NULL;
2351 }
2352 
2353 /******************************************************************************
2354 * WriteEntryValue.
2355 ******************************************************************************/
2356 
WriteEntryValue(fp,dataType,numElements,value,ccc,MaXcc)2357 void WriteEntryValue (fp, dataType, numElements, value, ccc, MaXcc)
2358 FILE *fp;
2359 long dataType;
2360 long numElements;
2361 void *value;
2362 int ccc;                /* Current Cursor Column (at start). */
2363 int MaXcc;              /* Maximum Cursor Column at which to output. */
2364 {
2365   if (STRINGdataType(dataType))
2366     WriteStringValue (fp, numElements, value, ccc, MaXcc);
2367   else {
2368     int i, elemN, n, cccBase = ccc;
2369     char evalue[80+1];
2370     Logical newLine = TRUE;
2371     for (elemN = 0; elemN < numElements; elemN++) {
2372        n = EncodeValue (dataType, (Byte *) value + elemN*CDFelemSize(dataType),
2373 			evalue, EPOCH0_STYLE);
2374        if (ccc + (newLine ? 0 : 1) + n +
2375 	   (elemN != numElements - 1 ? 1 : 0) > MaXcc) {
2376 	 WriteOut (fp, "\n");
2377 	 for (i = 0; i < cccBase; i++) WriteOut (fp, " ");
2378 	 ccc = cccBase;
2379 	 newLine = TRUE;
2380        }
2381        if (!newLine) ccc += WriteOut (fp, " ");
2382        ccc += WriteOut (fp, evalue);
2383        if (elemN != numElements - 1) ccc += WriteOut (fp, ",");
2384        newLine = FALSE;
2385     }
2386   }
2387   return;
2388 }
2389 
2390 /******************************************************************************
2391 * WriteStringValue.
2392 *    Note that control characters may exist in the string being written (even
2393 * a NUL character).  Control characters are to be replaced with `.'.  For this
2394 * reason `memmove' is used to move around strings/substrings.
2395 ******************************************************************************/
2396 
WriteStringValue(fp,numChars,value,ccc,MaXcc)2397 void WriteStringValue (fp, numChars, value, ccc, MaXcc)
2398 FILE *fp;
2399 long numChars;
2400 void *value;
2401 int ccc;                /* Current Cursor Column (at start). */
2402 int MaXcc;              /* Maximum Cursor Column at which to output. */
2403 {
2404   int cccBase = ccc, i;
2405   char *string = (char *) value;
2406   char delim;
2407   size_t textL = MaXcc + 1;             /* MaXcc + 1. */
2408   char *text = (char *) cdf_AllocateMemory ((size_t) (textL + 1),
2409 					FatalError);
2410 
2411   if (ccc + 1 + numChars + 1 - 1 <= MaXcc) {
2412     delim = PickDelimiter (string, (size_t) numChars);
2413     text[0] = delim;
2414     memmove (&text[1], string, (size_t) numChars);
2415     text[(int)numChars+1] = delim;
2416     text[(int)numChars+2] = NUL;
2417     for (i = 1; i <= numChars; i++) {
2418        if (!Printable(text[i])) text[i] = '.';
2419     }
2420     WriteOut (fp, text);
2421   }
2422   else {
2423     int sss = MaXcc - ccc - 4 + 1;      /* 4 for starting `"' and ending `" -'
2424 					   (assuming `"' is the delimeter). */
2425     char *substring = (char *) cdf_AllocateMemory ((size_t) (sss + 1),
2426 					       FatalError);
2427     int x = 0, len;
2428     while (x + sss < numChars) {
2429       if (string[x+sss] == ' ') /* First character next line will be a blank.*/
2430 	len = sss;
2431       else {
2432 	if (string[x+sss-1] == ' ') /* Last character on line is a blank. */
2433 	  len = sss;
2434 	else {                 /* Look for a blank at which to break line. */
2435 	  for (i = x + sss - 2; i > x; i--) if (string[i] == ' ') break;
2436 	  if (i > x)
2437 	    len = i - x + 1;
2438 	  else
2439 	    len = sss;
2440 	}
2441       }
2442       memmove (substring, &string[x], len);
2443       substring[len] = NUL;
2444       for (i = 0; i < len; i++) {
2445 	 if (!Printable(substring[i])) substring[i] = '.';
2446       }
2447       delim = PickDelimiter (substring, strlen(substring));
2448       sprintf (text, "%c%s%c -", delim, substring, delim);
2449       WriteOut (fp, text);
2450       WriteOut (fp, "\n");
2451       for (i = 0; i < cccBase; i++) WriteOut (fp, " ");
2452       x += len;
2453     }
2454     len = (size_t) (numChars - x);
2455     memmove (substring, &string[x], len);
2456     substring[len] = NUL;
2457     for (i = 0; i < len; i++) {
2458        if (!Printable(substring[i])) substring[i] = '.';
2459     }
2460     delim = PickDelimiter (substring, strlen(substring));
2461     sprintf (text, "%c%s%c", delim, substring, delim);
2462     WriteOut (fp, text);
2463     cdf_FreeMemory (substring, FatalError);
2464   }
2465   cdf_FreeMemory (text, FatalError);
2466   return;
2467 }
2468 
2469 /******************************************************************************
2470 * ConvertDataType.
2471 ******************************************************************************/
2472 
ConvertDataType(fromDataType,fromNumElems,fromPtr,toDataType,toNumElems,toPtr)2473 void ConvertDataType (fromDataType, fromNumElems, fromPtr, toDataType,
2474 		      toNumElems, toPtr)
2475 long fromDataType;
2476 long fromNumElems;              /* Only used if character data type. */
2477 void *fromPtr;
2478 long toDataType;
2479 long toNumElems;                /* Only used if character data type. */
2480 void *toPtr;
2481 {
2482   switch (fromDataType) {
2483     /**************************************************************************
2484     * 1-byte signed integer to...
2485     **************************************************************************/
2486     case CDF_BYTE:
2487     case CDF_INT1:
2488       switch (toDataType) {
2489 	case CDF_BYTE:
2490 	case CDF_INT1:
2491 	  *((sChar *) toPtr) = (sChar) *((sChar *) fromPtr);
2492 	  break;
2493 	case CDF_UINT1:
2494 	  *((uChar *) toPtr) = (uChar) *((sChar *) fromPtr);
2495 	  break;
2496 	case CDF_INT2:
2497 	  *((Int16 *) toPtr) = (Int16) *((sChar *) fromPtr);
2498 	  break;
2499 	case CDF_UINT2:
2500 	  *((uInt16 *) toPtr) = (uInt16) *((sChar *) fromPtr);
2501 	  break;
2502 	case CDF_INT4:
2503 	  *((Int32 *) toPtr) = (Int32) *((sChar *) fromPtr);
2504 	  break;
2505 	case CDF_UINT4:
2506 	  *((uInt32 *) toPtr) = (uInt32) *((sChar *) fromPtr);
2507 	  break;
2508 	case CDF_FLOAT:
2509 	case CDF_REAL4:
2510 	  *((float *) toPtr) = (float) *((sChar *) fromPtr);
2511 	  break;
2512 	case CDF_EPOCH:
2513 	case CDF_DOUBLE:
2514 	case CDF_REAL8:
2515 	  *((double *) toPtr) = (double) *((sChar *) fromPtr);
2516 	  break;
2517         case CDF_EPOCH16:
2518           *((double *) toPtr) = (double) *((sChar *) fromPtr);
2519 	  *(((double *) toPtr) + 1) = (double) *(((sChar *) fromPtr) + 1);
2520           break;
2521 	case CDF_CHAR:
2522 	case CDF_UCHAR: {
2523 	  int i, len;
2524 	  char tmp[MAX_nonSTRING_VALUE_LEN+1];
2525 	  sprintf (tmp, "%d", *((sChar *) fromPtr));
2526 	  for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
2527 	     *((char *) toPtr + i) = (i < len ? tmp[i] : ' ');
2528 	  }
2529 	  break;
2530 	}
2531       }
2532       break;
2533     /**************************************************************************
2534     * 1-byte unsigned integer to...
2535     **************************************************************************/
2536     case CDF_UINT1:
2537       switch (toDataType) {
2538 	case CDF_BYTE:
2539 	case CDF_INT1:
2540 	  *((sChar *) toPtr) = (sChar) *((uChar *) fromPtr);
2541 	  break;
2542 	case CDF_UINT1:
2543 	  *((uChar *) toPtr) = (uChar) *((uChar *) fromPtr);
2544 	  break;
2545 	case CDF_INT2:
2546 	  *((Int16 *) toPtr) = (Int16) *((uChar *) fromPtr);
2547 	  break;
2548 	case CDF_UINT2:
2549 	  *((uInt16 *) toPtr) = (uInt16) *((uChar *) fromPtr);
2550 	  break;
2551 	case CDF_INT4:
2552 	  *((Int32 *) toPtr) = (Int32) *((uChar *) fromPtr);
2553 	  break;
2554 	case CDF_UINT4:
2555 	  *((uInt32 *) toPtr) = (uInt32) *((uChar *) fromPtr);
2556 	  break;
2557 	case CDF_FLOAT:
2558 	case CDF_REAL4:
2559 	  *((float *) toPtr) = (float) *((uChar *) fromPtr);
2560 	  break;
2561 	case CDF_EPOCH:
2562 	case CDF_DOUBLE:
2563 	case CDF_REAL8:
2564 	  *((double *) toPtr) = (double) *((uChar *) fromPtr);
2565 	  break;
2566         case CDF_EPOCH16:
2567           *((double *) toPtr) = (double) *((uChar *) fromPtr);
2568 	  *(((double *) toPtr) + 1) = (double) *(((uChar *) fromPtr) + 1);
2569           break;
2570 	case CDF_CHAR:
2571 	case CDF_UCHAR: {
2572 	  int i, len;
2573 	  char tmp[MAX_nonSTRING_VALUE_LEN+1];
2574 	  sprintf (tmp, "%u", *((uChar *) fromPtr));
2575 	  for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
2576 	     *((char *) toPtr + i) = (i < len ? tmp[i] : ' ');
2577 	  }
2578 	  break;
2579 	}
2580       }
2581       break;
2582     /**************************************************************************
2583     * 2-byte signed integer to...
2584     **************************************************************************/
2585     case CDF_INT2:
2586       switch (toDataType) {
2587 	case CDF_BYTE:
2588 	case CDF_INT1:
2589 	  *((sChar *) toPtr) = (sChar) *((Int16 *) fromPtr);
2590 	  break;
2591 	case CDF_UINT1:
2592 	  *((uChar *) toPtr) = (uChar) *((Int16 *) fromPtr);
2593 	  break;
2594 	case CDF_INT2:
2595 	  *((Int16 *) toPtr) = (Int16) *((Int16 *) fromPtr);
2596 	  break;
2597 	case CDF_UINT2:
2598 	  *((uInt16 *) toPtr) = (uInt16) *((Int16 *) fromPtr);
2599 	  break;
2600 	case CDF_INT4:
2601 	  *((Int32 *) toPtr) = (Int32) *((Int16 *) fromPtr);
2602 	  break;
2603 	case CDF_UINT4:
2604 	  *((uInt32 *) toPtr) = (uInt32) *((Int16 *) fromPtr);
2605 	  break;
2606 	case CDF_FLOAT:
2607 	case CDF_REAL4:
2608 	  *((float *) toPtr) = (float) *((Int16 *) fromPtr);
2609 	  break;
2610 	case CDF_EPOCH:
2611 	case CDF_DOUBLE:
2612 	case CDF_REAL8:
2613 	  *((double *) toPtr) = (double) *((Int16 *) fromPtr);
2614 	  break;
2615         case CDF_EPOCH16:
2616           *((double *) toPtr) = (double) *((Int16 *) fromPtr);
2617 	  *(((double *) toPtr) + 1) = (double) *(((Int16 *) fromPtr) + 1);
2618           break;
2619 	case CDF_CHAR:
2620 	case CDF_UCHAR: {
2621 	  int i, len;
2622 	  char tmp[MAX_nonSTRING_VALUE_LEN+1];
2623 	  sprintf (tmp, "%d", (int) *((Int16 *) fromPtr));
2624 	  for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
2625 	     *((char *) toPtr + i) = (i < len ? tmp[i] : ' ');
2626 	  }
2627 	  break;
2628 	}
2629       }
2630       break;
2631     /**************************************************************************
2632     * 2-byte unsigned integer to...
2633     **************************************************************************/
2634     case CDF_UINT2:
2635       switch (toDataType) {
2636 	case CDF_BYTE:
2637 	case CDF_INT1:
2638 	  *((sChar *) toPtr) = (sChar) *((uInt16 *) fromPtr);
2639 	  break;
2640 	case CDF_UINT1:
2641 	  *((uChar *) toPtr) = (uChar) *((uInt16 *) fromPtr);
2642 	  break;
2643 	case CDF_INT2:
2644 	  *((Int16 *) toPtr) = (Int16) *((uInt16 *) fromPtr);
2645 	  break;
2646 	case CDF_UINT2:
2647 	  *((uInt16 *) toPtr) = (uInt16) *((uInt16 *) fromPtr);
2648 	  break;
2649 	case CDF_INT4:
2650 	  *((Int32 *) toPtr) = (Int32) *((uInt16 *) fromPtr);
2651 	  break;
2652 	case CDF_UINT4:
2653 	  *((uInt32 *) toPtr) = (uInt32) *((uInt16 *) fromPtr);
2654 	  break;
2655 	case CDF_FLOAT:
2656 	case CDF_REAL4:
2657 	  *((float *) toPtr) = (float) *((uInt16 *) fromPtr);
2658 	  break;
2659 	case CDF_EPOCH:
2660 	case CDF_DOUBLE:
2661 	case CDF_REAL8:
2662 	  *((double *) toPtr) = (double) *((uInt16 *) fromPtr);
2663 	  break;
2664         case CDF_EPOCH16:
2665           *((double *) toPtr) = (double) *((uInt16 *) fromPtr);
2666 	  *(((double *) toPtr) + 1) = (double) *(((uInt16 *) fromPtr) + 1);
2667           break;
2668 	case CDF_CHAR:
2669 	case CDF_UCHAR: {
2670 	  int i, len;
2671 	  char tmp[MAX_nonSTRING_VALUE_LEN+1];
2672 	  sprintf (tmp, "%u", (int) *((uInt16 *) fromPtr));
2673 	  for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
2674 	     *((char *) toPtr + i) = (i < len ? tmp[i] : ' ');
2675 	  }
2676 	  break;
2677 	}
2678       }
2679       break;
2680     /**************************************************************************
2681     * 4-byte signed integer to...
2682     **************************************************************************/
2683     case CDF_INT4:
2684       switch (toDataType) {
2685 	case CDF_BYTE:
2686 	case CDF_INT1:
2687 	  *((sChar *) toPtr) = (sChar) *((Int32 *) fromPtr);
2688 	  break;
2689 	case CDF_UINT1:
2690 	  *((uChar *) toPtr) = (uChar) *((Int32 *) fromPtr);
2691 	  break;
2692 	case CDF_INT2:
2693 	  *((Int16 *) toPtr) = (Int16) *((Int32 *) fromPtr);
2694 	  break;
2695 	case CDF_UINT2:
2696 	  *((uInt16 *) toPtr) = (uInt16) *((Int32 *) fromPtr);
2697 	  break;
2698 	case CDF_INT4:
2699 	  *((Int32 *) toPtr) = (Int32) *((Int32 *) fromPtr);
2700 	  break;
2701 	case CDF_UINT4:
2702 	  *((uInt32 *) toPtr) = (uInt32) *((Int32 *) fromPtr);
2703 	  break;
2704 	case CDF_FLOAT:
2705 	case CDF_REAL4:
2706 	  *((float *) toPtr) = (float) *((Int32 *) fromPtr);
2707 	  break;
2708 	case CDF_EPOCH:
2709 	case CDF_DOUBLE:
2710 	case CDF_REAL8:
2711 	  *((double *) toPtr) = (double) *((Int32 *) fromPtr);
2712 	  break;
2713         case CDF_EPOCH16:
2714           *((double *) toPtr) = (double) *((Int32 *) fromPtr);
2715 	  *(((double *) toPtr) + 1) = (double) *(((Int32 *) fromPtr) + 1);
2716           break;
2717 	case CDF_CHAR:
2718 	case CDF_UCHAR: {
2719 	  int i, len;
2720 	  char tmp[MAX_nonSTRING_VALUE_LEN+1];
2721 	  sprintf (tmp, "%ld", (long) *((Int32 *) fromPtr));
2722 	  for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
2723 	     *((char *) toPtr + i) = (i < len ? tmp[i] : ' ');
2724 	  }
2725 	  break;
2726 	}
2727       }
2728       break;
2729     /**************************************************************************
2730     * 4-byte unsigned integer to...
2731     **************************************************************************/
2732     case CDF_UINT4:
2733       switch (toDataType) {
2734 	case CDF_BYTE:
2735 	case CDF_INT1:
2736 	  *((sChar *) toPtr) = (sChar) *((uInt32 *) fromPtr);
2737 	  break;
2738 	case CDF_UINT1:
2739 	  *((uChar *) toPtr) = (uChar) *((uInt32 *) fromPtr);
2740 	  break;
2741 	case CDF_INT2:
2742 	  *((Int16 *) toPtr) = (Int16) *((uInt32 *) fromPtr);
2743 	  break;
2744 	case CDF_UINT2:
2745 	  *((uInt16 *) toPtr) = (uInt16) *((uInt32 *) fromPtr);
2746 	  break;
2747 	case CDF_INT4:
2748 	  *((Int32 *) toPtr) = (Int32) *((uInt32 *) fromPtr);
2749 	  break;
2750 	case CDF_UINT4:
2751 	  *((uInt32 *) toPtr) = (uInt32) *((uInt32 *) fromPtr);
2752 	  break;
2753 	case CDF_FLOAT:
2754 	case CDF_REAL4:
2755 	  *((float *) toPtr) = (float) *((uInt32 *) fromPtr);
2756 	  break;
2757 	case CDF_EPOCH:
2758 	case CDF_DOUBLE:
2759 	case CDF_REAL8:
2760 	  *((double *) toPtr) = (double) *((uInt32 *) fromPtr);
2761 	  break;
2762         case CDF_EPOCH16:
2763           *((double *) toPtr) = (double) *((uInt32 *) fromPtr);
2764 	  *(((double *) toPtr) + 1) = (double) *(((uInt32 *) fromPtr) + 1);
2765           break;
2766 	case CDF_CHAR:
2767 	case CDF_UCHAR: {
2768 	  int i, len;
2769 	  char tmp[MAX_nonSTRING_VALUE_LEN+1];
2770 	  sprintf (tmp, "%lu", (uLong) *((uInt32 *) fromPtr));
2771 	  for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
2772 	     *((char *) toPtr + i) = (i < len ? tmp[i] : ' ');
2773 	  }
2774 	  break;
2775 	}
2776       }
2777       break;
2778     /**************************************************************************
2779     * 4-byte floating-point to...
2780     **************************************************************************/
2781     case CDF_FLOAT:
2782     case CDF_REAL4:
2783       switch (toDataType) {
2784 	case CDF_BYTE:
2785 	case CDF_INT1:
2786 	  *((sChar *) toPtr) = (sChar) *((float *) fromPtr);
2787 	  break;
2788 	case CDF_UINT1:
2789 	  *((uChar *) toPtr) = (uChar) *((float *) fromPtr);
2790 	  break;
2791 	case CDF_INT2:
2792 	  *((Int16 *) toPtr) = (Int16) *((float *) fromPtr);
2793 	  break;
2794 	case CDF_UINT2:
2795 	  *((uInt16 *) toPtr) = (uInt16) *((float *) fromPtr);
2796 	  break;
2797 	case CDF_INT4:
2798 	  *((Int32 *) toPtr) = (Int32) *((float *) fromPtr);
2799 	  break;
2800 	case CDF_UINT4:
2801 	  *((uInt32 *) toPtr) = (uInt32) *((float *) fromPtr);
2802 	  break;
2803 	case CDF_FLOAT:
2804 	case CDF_REAL4:
2805 	  *((float *) toPtr) = (float) *((float *) fromPtr);
2806 	  break;
2807 	case CDF_EPOCH:
2808 	case CDF_DOUBLE:
2809 	case CDF_REAL8:
2810 	  *((double *) toPtr) = (double) *((float *) fromPtr);
2811 	  break;
2812         case CDF_EPOCH16:
2813           *((double *) toPtr) = (double) *((float *) fromPtr);
2814 	  *(((double *) toPtr) + 1) = (double) *(((float *) fromPtr) + 1);
2815           break;
2816 	case CDF_CHAR:
2817 	case CDF_UCHAR: {
2818 	  int i, len;
2819 	  char tmp[MAX_nonSTRING_VALUE_LEN+1];
2820 	  sprintf (tmp, "%f", *((float *) fromPtr));
2821 	  for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
2822 	     *((char *) toPtr + i) = (i < len ? tmp[i] : ' ');
2823 	  }
2824 	  break;
2825 	}
2826       }
2827       break;
2828     /**************************************************************************
2829     * 8-byte floating-point to...
2830     **************************************************************************/
2831     case CDF_EPOCH:
2832     case CDF_DOUBLE:
2833     case CDF_REAL8:
2834       switch (toDataType) {
2835 	case CDF_BYTE:
2836 	case CDF_INT1:
2837 	  *((sChar *) toPtr) = (sChar) *((double *) fromPtr);
2838 	  break;
2839 	case CDF_UINT1:
2840 	  *((uChar *) toPtr) = (uChar) *((double *) fromPtr);
2841 	  break;
2842 	case CDF_INT2:
2843 	  *((Int16 *) toPtr) = (Int16) *((double *) fromPtr);
2844 	  break;
2845 	case CDF_UINT2:
2846 	  *((uInt16 *) toPtr) = (uInt16) *((double *) fromPtr);
2847 	  break;
2848 	case CDF_INT4:
2849 	  *((Int32 *) toPtr) = (Int32) *((double *) fromPtr);
2850 	  break;
2851 	case CDF_UINT4:
2852 	  *((uInt32 *) toPtr) = (uInt32) *((double *) fromPtr);
2853 	  break;
2854 	case CDF_FLOAT:
2855 	case CDF_REAL4:
2856 	  *((float *) toPtr) = (float) *((double *) fromPtr);
2857 	  break;
2858 	case CDF_EPOCH:
2859 	case CDF_DOUBLE:
2860 	case CDF_REAL8:
2861 	  *((double *) toPtr) = (double) *((double *) fromPtr);
2862 	  break;
2863 	case CDF_CHAR:
2864 	case CDF_UCHAR: {
2865 	  int i, len;
2866 	  char tmp[MAX_nonSTRING_VALUE_LEN+1];
2867 	  sprintf (tmp, "%f", *((double *) fromPtr));
2868 	  for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
2869 	     *((char *) toPtr + i) = (i < len ? tmp[i] : ' ');
2870 	  }
2871 	  break;
2872 	}
2873       }
2874       break;
2875     /**************************************************************************
2876     * 16-byte floating-point to...
2877     **************************************************************************/
2878     case CDF_EPOCH16:
2879       switch (toDataType) {
2880         case CDF_BYTE:
2881         case CDF_INT1:
2882           *((sChar *) toPtr) = (sChar) *((double *) fromPtr);
2883 	  *(((sChar *) toPtr) + 1) = (sChar) *(((double *) fromPtr) + 1);
2884           break;
2885         case CDF_UINT1:
2886           *((uChar *) toPtr) = (uChar) *((double *) fromPtr);
2887 	  *(((uChar *) toPtr) + 1) = (uChar) *(((double *) fromPtr) + 1);
2888           break;
2889         case CDF_INT2:
2890           *((Int16 *) toPtr) = (Int16) *((double *) fromPtr);
2891 	  *(((Int16 *) toPtr) + 1) = (Int16) *(((double *) fromPtr) + 1);
2892           break;
2893         case CDF_UINT2:
2894           *((uInt16 *) toPtr) = (uInt16) *((double *) fromPtr);
2895 	  *(((uInt16 *) toPtr) + 1) = (uInt16) *(((double *) fromPtr) + 1);
2896           break;
2897         case CDF_INT4:
2898           *((Int32 *) toPtr) = (Int32) *((double *) fromPtr);
2899 	  *(((Int32 *) toPtr) + 1) = (Int32) *(((double *) fromPtr) + 1);
2900           break;
2901         case CDF_UINT4:
2902           *((uInt32 *) toPtr) = (uInt32) *((double *) fromPtr);
2903 	  *(((uInt32 *) toPtr) + 1) = (uInt32) *(((double *) fromPtr) + 1);
2904           break;
2905         case CDF_FLOAT:
2906         case CDF_REAL4:
2907           *((float *) toPtr) = (float) *((double *) fromPtr);
2908 	  *(((float *) toPtr) + 1) = (float) *(((double *) fromPtr) + 1);
2909           break;
2910         case CDF_EPOCH:
2911         case CDF_DOUBLE:
2912         case CDF_REAL8:
2913           *((double *) toPtr) = (double) *((double *) fromPtr);
2914 	  *(((double *) toPtr) + 1) = (double) *(((double *) fromPtr) + 1);
2915           break;
2916         case CDF_EPOCH16:
2917           *((double *) toPtr) = (double) *((double *) fromPtr);
2918           *(((double *) toPtr) + 1) = (double) *(((double *) fromPtr) + 1);
2919           break;
2920         case CDF_CHAR:
2921         case CDF_UCHAR: {
2922           int i, j, len;
2923           char tmp[MAX_nonSTRING_VALUE_LEN+1];
2924           sprintf (tmp, "%f", *((double *) fromPtr));
2925           for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
2926              *((char *) toPtr + i) = (i < len ? tmp[i] : ' ');
2927           }
2928           sprintf (tmp, "%f", *(((double *) fromPtr) + 1));
2929 	  j = i;
2930           for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
2931              *((char *) toPtr + j) = (i < len ? tmp[i] : ' ');
2932           }
2933           break;
2934         }
2935       }
2936       break;
2937     /**************************************************************************
2938     * character (string) to...
2939     **************************************************************************/
2940     case CDF_CHAR:
2941     case CDF_UCHAR: {
2942       size_t nBytes = (size_t) (fromNumElems + 1);
2943       char *str = (char *) cdf_AllocateMemory (nBytes, FatalError);
2944       memmove (str, fromPtr, (size_t) fromNumElems);
2945       str[(int)fromNumElems] = NUL;
2946       switch (toDataType) {
2947 	case CDF_BYTE:
2948 	case CDF_INT1: {
2949 	  int tmp;
2950 	  if (sscanf(str,"%d",&tmp) < 1)
2951 	    *((sChar *) toPtr) = 0;
2952 	  else
2953 	    *((sChar *) toPtr) = (sChar) tmp;
2954 	  break;
2955 	}
2956 	case CDF_UINT1: {
2957 	  uInt tmp;
2958 	  if (sscanf(str,"%u",&tmp) < 1)
2959 	    *((uChar *) toPtr) = 0;
2960 	  else
2961 	    *((uChar *) toPtr) = (uChar) tmp;
2962 	  break;
2963 	}
2964 	case CDF_INT2: {
2965 	  int tmp;
2966 	  if (sscanf(str,"%d",&tmp) < 1)
2967 	    *((Int16 *) toPtr) = 0;
2968 	  else
2969 	    *((Int16 *) toPtr) = (Int16) tmp;
2970 	  break;
2971 	}
2972 	case CDF_UINT2: {
2973 	  uInt tmp;
2974 	  if (sscanf(str,"%u",&tmp) < 1)
2975 	    *((uInt16 *) toPtr) = 0;
2976 	  else
2977 	    *((uInt16 *) toPtr) = (uInt16) tmp;
2978 	  break;
2979 	}
2980 	case CDF_INT4: {
2981 	  long tmp;
2982 	  if (sscanf(str,"%ld",&tmp) < 1)
2983 	    *((Int32 *) toPtr) = 0;
2984 	  else
2985 	    *((Int32 *) toPtr) = (Int32) tmp;
2986 	  break;
2987 	}
2988 	case CDF_UINT4: {
2989 	  uLong tmp;
2990 	  if (sscanf(str,"%lu",&tmp) < 1)
2991 	    *((uInt32 *) toPtr) = 0;
2992 	  else
2993 	    *((uInt32 *) toPtr) = (uInt32) tmp;
2994 	  break;
2995 	}
2996 	case CDF_FLOAT:
2997 	case CDF_REAL4: {
2998 	  float tmp;
2999 	  if (sscanf(str,"%g",&tmp) < 1)
3000 	    *((float *) toPtr) = (float) 0.0;
3001 	  else
3002 	    *((float *) toPtr) = tmp;
3003 	  break;
3004 	}
3005 	case CDF_EPOCH:
3006 	case CDF_DOUBLE:
3007 	case CDF_REAL8: {
3008 	  double tmp;
3009 	  if (sscanf(str,"%lg",&tmp) < 1)
3010 	    *((double *) toPtr) = 0.0;
3011 	  else
3012 	    *((double *) toPtr) = tmp;
3013 	  break;
3014 	}
3015         case CDF_EPOCH16: {
3016           double tmp1, tmp2;
3017           if (sscanf(str,"%lg %lg",&tmp1, &tmp2) < 2) {
3018             *((double *) toPtr) = 0.0;
3019 	    *(((double *) toPtr) + 1) = 0.0;
3020           } else {
3021             *((double *) toPtr) = tmp1;
3022 	    *(((double *) toPtr) + 1) = tmp2;
3023 	  }
3024           break;
3025         }
3026 	case CDF_CHAR:
3027 	case CDF_UCHAR: {
3028 	  int i;
3029 	  for (i = 0; i < toNumElems; i++) {
3030 	     *((char *) toPtr + i) = (i < fromNumElems ? str[i] : ' ');
3031 	  }
3032 	  break;
3033 	}
3034       }
3035       cdf_FreeMemory (str, FatalError);
3036       break;
3037     }
3038   }
3039   return;
3040 }
3041 
3042 /******************************************************************************
3043 * DecodeValues.
3044 *     Memory for the values is allocated here but is NOT freed (unless an
3045 * error occurred.)
3046 ******************************************************************************/
3047 
DecodeValues(string,dataType,numElems,values,style)3048 Logical DecodeValues (string, dataType, numElems, values, style)
3049 char *string;
3050 long dataType;
3051 long *numElems;
3052 void **values;
3053 int style;              /* EPOCH style. */
3054 {
3055 if (STRINGdataType(dataType)) {
3056   /****************************************************************************
3057   * Delimited character string.
3058   ****************************************************************************/
3059   char delim;
3060   char *firstDelim, *secondDelim;
3061   char *ptr = string;
3062   while (*ptr != NUL && Spacing(*ptr)) ptr++;    /* Skip to delimiter. */
3063   if (*ptr == NUL) return FALSE;                    /* Null-string. */
3064   delim = *ptr;
3065   firstDelim = ptr;
3066   secondDelim = strchr (ptr + 1, delim);
3067   if (secondDelim == NULL) return FALSE;
3068   *numElems = secondDelim - firstDelim - 1;
3069   *values = cdf_AllocateMemory ((size_t) (*numElems + 1), FatalError);
3070   memmove (*values, firstDelim + 1, (size_t) *numElems);
3071   ((char *) *values)[(int)(*numElems)] = NUL;
3072 }
3073 else {
3074   /****************************************************************************
3075   * Comma separated values.
3076   ****************************************************************************/
3077   int i, Ncommas; char *ptr;
3078   for (Ncommas = 0, i = 0; string[i] != NUL; i++)       /* Count commas. */
3079      if (string[i] == ',') Ncommas++;
3080   *numElems = Ncommas + 1;
3081   *values = cdf_AllocateMemory ((size_t) (*numElems * CDFelemSize(dataType)),
3082 			    FatalError);
3083   for (ptr = string, i = 0; i < *numElems; i++) {
3084      switch (dataType) {
3085        case CDF_BYTE:
3086        case CDF_INT1: {
3087 	 int temp;
3088 	 if (sscanf(ptr,"%d",&temp) != 1) {
3089 	   cdf_FreeMemory (*values, FatalError);
3090 	   return FALSE;
3091 	 }
3092 	 if (temp < -128 || temp > 127) {
3093 	   cdf_FreeMemory (*values, FatalError);
3094 	   return FALSE;
3095 	 }
3096 	 *((sChar *) *values + i) = (sChar) temp;
3097 	 break;
3098        }
3099        case CDF_UINT1: {
3100 	 int temp;
3101 	 if (sscanf(ptr,"%d",&temp) != 1) {
3102 	   cdf_FreeMemory (*values, FatalError);
3103 	   return FALSE;
3104 	 }
3105 	 if (temp < 0 || temp > 255) {
3106 	   cdf_FreeMemory (*values, FatalError);
3107 	   return FALSE;
3108 	 }
3109 	 *((uChar *) *values + i) = (uChar) temp;
3110 	 break;
3111        }
3112        case CDF_INT2: {
3113 	 if (sscanf(ptr,"%hd",(Int16 *) *values + i) != 1) {
3114 	   cdf_FreeMemory (*values, FatalError);
3115 	   return FALSE;
3116 	 }
3117 	 break;
3118        }
3119        case CDF_UINT2: {
3120 	 long temp;
3121 	 if (sscanf(ptr,"%ld",&temp) != 1) {
3122 	   cdf_FreeMemory (*values, FatalError);
3123 	   return FALSE;
3124 	 }
3125 	 if (temp < 0 || temp > 65535L) {
3126 	   cdf_FreeMemory (*values, FatalError);
3127 	   return FALSE;
3128 	 }
3129 	 *((uInt16 *) *values + i) = (uInt16) temp;
3130 	 break;
3131        }
3132        case CDF_INT4:
3133 	 if (!DecodeInt32(ptr,(Int32 *) *values + i)) {
3134 	   cdf_FreeMemory (*values, FatalError);
3135 	   return FALSE;
3136 	 }
3137 	 break;
3138        case CDF_UINT4:
3139 	 if (!DecodeInt32u(ptr,(uInt32 *) *values + i)) {
3140 	   cdf_FreeMemory (*values, FatalError);
3141 	   return FALSE;
3142 	 }
3143 	 break;
3144        case CDF_REAL4:
3145        case CDF_FLOAT:
3146 	 if (sscanf(ptr,"%f",(float *) *values + i) != 1) {
3147 	   cdf_FreeMemory (*values, FatalError);
3148 	   return FALSE;
3149 	 }
3150 	 break;
3151        case CDF_REAL8:
3152        case CDF_DOUBLE:
3153 	 if (sscanf(ptr,"%lf",(double *) *values + i) != 1) {
3154 	   cdf_FreeMemory (*values, FatalError);
3155 	   return FALSE;
3156 	 }
3157 	 break;
3158        case CDF_EPOCH: {
3159 	 double value;
3160 	 switch (style) {
3161 	   case EPOCH0_STYLE:
3162 	     value = parseEPOCH (ptr);
3163 	     break;
3164 	   case EPOCH1_STYLE:
3165 	     value = parseEPOCH1 (ptr);
3166 	     break;
3167 	   case EPOCH2_STYLE:
3168 	     value = parseEPOCH2 (ptr);
3169 	     break;
3170 	   case EPOCH3_STYLE:
3171 	     value = parseEPOCH3 (ptr);
3172 	     break;
3173 	   case EPOCHf_STYLE:
3174 	     cdf_FreeMemory (*values, FatalError);
3175 	     return DecodeValues(string,CDF_DOUBLE,numElems,values,style);
3176 	   case EPOCHx_STYLE:
3177 	     value = parseEPOCH (ptr);  /* Assume EPOCH0_STYLE instead. */
3178 	     break;
3179 	 }
3180 	 if (value == ILLEGAL_EPOCH_VALUE) {
3181 	   cdf_FreeMemory (*values, FatalError);
3182 	   return FALSE;
3183 	 }
3184 	 else
3185 	   *((double *) *values + i) = value;
3186 	 break;
3187        }
3188        case CDF_EPOCH16: {
3189          double value[2], dummy;
3190          switch (style) {
3191            case EPOCH0_STYLE:
3192              dummy = parseEPOCH16 (ptr, value);
3193              break;
3194            case EPOCH1_STYLE:
3195              dummy = parseEPOCH16_1 (ptr, value);
3196              break;
3197            case EPOCH2_STYLE:
3198              dummy = parseEPOCH16_2 (ptr, value);
3199              break;
3200            case EPOCH3_STYLE:
3201              dummy = parseEPOCH16_3 (ptr, value);
3202              break;
3203            case EPOCHf_STYLE:
3204              cdf_FreeMemory (*values, FatalError);
3205              return DecodeValues(string,CDF_DOUBLE,numElems,values,style);
3206            case EPOCHx_STYLE:	/* Assume EPOCH0_STYLE instead. */
3207              dummy = parseEPOCH16 (ptr, value);
3208              break;
3209          }
3210          if (dummy == ILLEGAL_EPOCH_VALUE ||
3211 	     value[0] == ILLEGAL_EPOCH_VALUE ||
3212 	     value[1] == ILLEGAL_EPOCH_VALUE) {
3213            cdf_FreeMemory (*values, FatalError);
3214            return FALSE;
3215          }
3216          else {
3217 	   int j = 2 * i;
3218            *((double *) *values + j) = value[0];
3219 	   *(((double *) *values + j) + 1) = value[1];
3220 	 }
3221          break;
3222        }
3223      }
3224      ptr = strchr (ptr, ',') + 1;      /* Garbage last time, doesn't matter. */
3225   }
3226 }
3227 return TRUE;
3228 }
3229 
3230 /******************************************************************************
3231 * DecodeInt32.
3232 *    This routine is necessary because DEC Alphas running OpenVMS do not
3233 * decode "-2147483648" properly.
3234 ******************************************************************************/
3235 
DecodeInt32(text,binary)3236 static Logical DecodeInt32 (text, binary)
3237 char *text;
3238 Int32 *binary;
3239 {
3240   if (EqStringsIgLTws(text,"-2147483648"))
3241 #if defined(dos)
3242     *binary = (Int32) -2147483648L;
3243 #else
3244     *binary = (Int32) 0x80000000;
3245 #endif
3246   else
3247     if (sscanf(text,Int32FORMAT,binary) != 1) return FALSE;
3248   return TRUE;
3249 }
3250 
3251 /******************************************************************************
3252 * DecodeInt32u.
3253 *    This routine is necessary because VAX/VMS systems do not properly decode
3254 * unsigned values.
3255 ******************************************************************************/
3256 
DecodeInt32u(text,binary)3257 static Logical DecodeInt32u (text, binary)
3258 char *text;
3259 uInt32 *binary;
3260 {
3261    char *start = text;
3262    char *end, temp[MAX_ENCODED_INT4_LEN+1];
3263    int len; uLong tempB;
3264    while (*start != NUL && Spacing(*start)) start++;
3265    if (*start == NUL) return FALSE;
3266    end = start;
3267    while (*end != NUL && Decimal(*end)) end++;
3268    len = (int) (end - start);
3269    if (len > MAX_ENCODED_INT4_LEN) return FALSE;
3270    strcpyX (temp, start, MINIMUM(len,MAX_ENCODED_INT4_LEN));
3271    if (len < MAX_ENCODED_INT4_LEN) {
3272      if (sscanf(temp,"%ld",&tempB) != 1) return FALSE;
3273    }
3274    else {
3275      if (strcmp(temp,"4294967295") > 0) return FALSE;
3276      if (sscanf(&temp[1],"%ld",&tempB) != 1) return FALSE;
3277 #if defined(dos)
3278      tempB += (1000000000UL * (temp[0] - '0'));
3279 #else
3280      tempB += ((uLong) 1000000000 * (temp[0] - '0'));
3281 #endif
3282    }
3283    *binary = (uInt32) tempB;
3284    return TRUE;
3285 }
3286 
3287 /******************************************************************************
3288 * EqStringsIgLTws.
3289 *     Compares two strings ignoring leading and trailing white space.
3290 ******************************************************************************/
3291 
EqStringsIgLTws(string1,string2)3292 static Logical EqStringsIgLTws (string1, string2)
3293 char *string1;
3294 char *string2;
3295 {
3296   char *tString1, *tString2, *ptr;
3297   size_t nChars;
3298   Logical returnValue;
3299   /****************************************************************************
3300   * Strip leading and trailing white space from 1st string.
3301   ****************************************************************************/
3302   ptr = string1;
3303   while (*ptr != NUL && Spacing(*ptr)) ptr++;
3304   nChars = strlen (ptr);
3305   tString1 = (char *) cdf_AllocateMemory (nChars + 1, FatalError);
3306   strcpyX (tString1, ptr, 0);
3307   ptr = tString1 + nChars;
3308   while (ptr != tString1 && Spacing(*(ptr-1))) ptr--;
3309   *ptr = NUL;
3310   /****************************************************************************
3311   * Strip leading and trailing white space from 2nd string.
3312   ****************************************************************************/
3313   ptr = string2;
3314   while (*ptr != NUL && Spacing(*ptr)) ptr++;
3315   nChars = strlen (ptr);
3316   tString2 = (char *) cdf_AllocateMemory (nChars + 1, FatalError);
3317   strcpyX (tString2, ptr, 0);
3318   ptr = tString2 + nChars;
3319   while (ptr != tString2 && Spacing(*(ptr-1))) ptr--;
3320   *ptr = NUL;
3321   /****************************************************************************
3322   * Free temporary strings and return result of comparison.
3323   ****************************************************************************/
3324   returnValue = (!strcmp(tString1,tString2) ? TRUE : FALSE);
3325   cdf_FreeMemory (tString1, FatalError);
3326   cdf_FreeMemory (tString2, FatalError);
3327   return returnValue;
3328 }
3329 
3330 /******************************************************************************
3331 * LongWidth.
3332 ******************************************************************************/
3333 
LongWidth(value)3334 int LongWidth (value)
3335 long value;
3336 {
3337   if (value < -999999999L) return 11;
3338   if (value < -99999999L) return 10;
3339   if (value < -9999999L) return 9;
3340   if (value < -999999L) return 8;
3341   if (value < -99999L) return 7;
3342   if (value < -9999L) return 6;
3343   if (value < -999L) return 5;
3344   if (value < -99L) return 4;
3345   if (value < -9L) return 3;
3346   if (value < 0L) return 2;
3347   if (value < 10L) return 1;
3348   if (value < 100L) return 2;
3349   if (value < 1000L) return 3;
3350   if (value < 10000L) return 4;
3351   if (value < 100000L) return 5;
3352   if (value < 1000000L) return 6;
3353   if (value < 10000000L) return 7;
3354   if (value < 100000000L) return 8;
3355   if (value < 1000000000L) return 9;
3356   return 10;
3357 }
3358 
3359 /******************************************************************************
3360 * Long64Width.
3361 ******************************************************************************/
3362 
Long64Width(value)3363 int Long64Width (value)
3364 OFF_T value;
3365 {
3366 #if !defined(win32) && !defined(__osf__)
3367   if (value < (OFF_T) -999999999999999999LL) return 20;
3368   if (value < (OFF_T) -99999999999999999LL) return 19;
3369   if (value < (OFF_T) -9999999999999999LL) return 18;
3370   if (value < (OFF_T) -999999999999999LL) return 17;
3371   if (value < (OFF_T) -99999999999999LL) return 16;
3372   if (value < (OFF_T) -9999999999999LL) return 15;
3373   if (value < (OFF_T) -999999999999LL) return 14;
3374   if (value < (OFF_T) -99999999999LL) return 13;
3375   if (value < (OFF_T) -9999999999LL) return 12;
3376   if (value < (OFF_T) -999999999LL) return 11;
3377   if (value < (OFF_T) -99999999LL) return 10;
3378   if (value < (OFF_T) -9999999LL) return 9;
3379   if (value < (OFF_T) -999999LL) return 8;
3380   if (value < (OFF_T) -99999LL) return 7;
3381   if (value < (OFF_T) -9999LL) return 6;
3382   if (value < (OFF_T) -999LL) return 5;
3383   if (value < (OFF_T) -99LL) return 4;
3384   if (value < (OFF_T) -9LL) return 3;
3385   if (value < (OFF_T) 0LL) return 2;
3386   if (value < (OFF_T) 10LL) return 1;
3387   if (value < (OFF_T) 100LL) return 2;
3388   if (value < (OFF_T) 1000LL) return 3;
3389   if (value < (OFF_T) 10000LL) return 4;
3390   if (value < (OFF_T) 100000LL) return 5;
3391   if (value < (OFF_T) 1000000LL) return 6;
3392   if (value < (OFF_T) 10000000LL) return 7;
3393   if (value < (OFF_T) 100000000LL) return 8;
3394   if (value < (OFF_T) 1000000000LL) return 9;
3395   if (value < (OFF_T) 10000000000LL) return 10;
3396   if (value < (OFF_T) 100000000000LL) return 11;
3397   if (value < (OFF_T) 1000000000000LL) return 12;
3398   if (value < (OFF_T) 10000000000000LL) return 13;
3399   if (value < (OFF_T) 100000000000000LL) return 14;
3400   if (value < (OFF_T) 1000000000000000LL) return 15;
3401   if (value < (OFF_T) 10000000000000000LL) return 16;
3402   if (value < (OFF_T) 100000000000000000LL) return 17;
3403   if (value < (OFF_T) 1000000000000000000LL) return 18;
3404 #else
3405   if (value < (OFF_T) -999999999999999999L) return 20;
3406   if (value < (OFF_T) -99999999999999999L) return 19;
3407   if (value < (OFF_T) -9999999999999999L) return 18;
3408   if (value < (OFF_T) -999999999999999L) return 17;
3409   if (value < (OFF_T) -99999999999999L) return 16;
3410   if (value < (OFF_T) -9999999999999L) return 15;
3411   if (value < (OFF_T) -999999999999L) return 14;
3412   if (value < (OFF_T) -99999999999L) return 13;
3413   if (value < (OFF_T) -9999999999L) return 12;
3414   if (value < (OFF_T) -999999999L) return 11;
3415   if (value < (OFF_T) -99999999L) return 10;
3416   if (value < (OFF_T) -9999999L) return 9;
3417   if (value < (OFF_T) -999999L) return 8;
3418   if (value < (OFF_T) -99999L) return 7;
3419   if (value < (OFF_T) -9999L) return 6;
3420   if (value < (OFF_T) -999L) return 5;
3421   if (value < (OFF_T) -99L) return 4;
3422   if (value < (OFF_T) -9L) return 3;
3423   if (value < (OFF_T) 0L) return 2;
3424   if (value < (OFF_T) 10L) return 1;
3425   if (value < (OFF_T) 100L) return 2;
3426   if (value < (OFF_T) 1000L) return 3;
3427   if (value < (OFF_T) 10000L) return 4;
3428   if (value < (OFF_T) 100000L) return 5;
3429   if (value < (OFF_T) 1000000L) return 6;
3430   if (value < (OFF_T) 10000000L) return 7;
3431   if (value < (OFF_T) 100000000L) return 8;
3432   if (value < (OFF_T) 1000000000L) return 9;
3433   if (value < (OFF_T) 10000000000L) return 10;
3434   if (value < (OFF_T) 100000000000L) return 11;
3435   if (value < (OFF_T) 1000000000000L) return 12;
3436   if (value < (OFF_T) 10000000000000L) return 13;
3437   if (value < (OFF_T) 100000000000000L) return 14;
3438   if (value < (OFF_T) 1000000000000000L) return 15;
3439   if (value < (OFF_T) 10000000000000000L) return 16;
3440   if (value < (OFF_T) 100000000000000000L) return 17;
3441   if (value < (OFF_T) 1000000000000000000L) return 18;
3442 #endif
3443   return 19;
3444 }
3445 
3446 /******************************************************************************
3447 * ParseCacheSizes.
3448 * It can be assumed that there is at least one character in `sizes' or QOP
3449 * would have failed.
3450 ******************************************************************************/
3451 
ParseCacheSizes(sizes,workingCache,stageCache,compressCache)3452 Logical  ParseCacheSizes (sizes, workingCache, stageCache, compressCache)
3453 char *sizes;
3454 long *workingCache;
3455 long *stageCache;
3456 long *compressCache;
3457 {
3458   char *p, *size, tmp[MAX_CACHESIZES_LEN+1];
3459   /****************************************************************************
3460   * Initialize all cache sizes in case only some have been specified.
3461   ****************************************************************************/
3462   *workingCache = useDEFAULTcacheSIZE;
3463   *stageCache = useDEFAULTcacheSIZE;
3464   *compressCache = useDEFAULTcacheSIZE;
3465   /****************************************************************************
3466   * Move cache sizes to a temporary buffer and remove all spacing.
3467   ****************************************************************************/
3468   strcpyX (tmp, sizes, MAX_CACHESIZES_LEN);
3469   RemoveWhiteSpace (tmp);
3470   p = tmp;
3471   /****************************************************************************
3472   * Check for (and skip) parenthesis on VMS systems.
3473   ****************************************************************************/
3474 #if defined(vms)
3475   if (*p == '(') {
3476     char *lastChar = p + strlen(p) - 1;
3477     if (*lastChar != ')') return FALSE;
3478     p++;
3479     *lastChar = NUL;
3480   }
3481 #endif
3482   /****************************************************************************
3483   * Scan the list of cache sizes...
3484   ****************************************************************************/
3485   for (;;) {
3486      /*************************************************************************
3487      * Save the location of the size and increment to the next non-decimal
3488      * character (ie. past the size).
3489      *************************************************************************/
3490      size = p;
3491      while (Decimal(*p)) p++;
3492      /*************************************************************************
3493      * Based on the non-decimal character reached...
3494      *************************************************************************/
3495      switch (*p) {
3496        case 's':
3497 	 if (sscanf(size,"%lds",stageCache) != 1) return FALSE;
3498 	 break;
3499        case 'c':
3500 	 if (sscanf(size,"%ldc",compressCache) != 1) return FALSE;
3501 	 break;
3502        case 'd':
3503 	 if (sscanf(size,"%ldd,",workingCache) != 1) return FALSE;
3504 	 break;
3505        case ',':
3506 	 if (sscanf(size,"%ld,",workingCache) != 1) return FALSE;
3507 	 break;
3508        case NUL:
3509 	 if (sscanf(size,"%ld",workingCache) != 1) return FALSE;
3510 	 return TRUE;
3511        default:
3512 	 return FALSE;
3513      }
3514      /*************************************************************************
3515      * Increment to the beginning of the next cache size (or to the end of the
3516      * sizes).
3517      *************************************************************************/
3518      if (*p != ',') p++;
3519      if (*p == ',') p++;
3520      if (*p == NUL) return TRUE;
3521   }
3522 }
3523 
3524 /******************************************************************************
3525 *  Remove the ".skt" file extension from the given file name if it's there.
3526 *  It ignores the case.
3527 *  Example:
3528 *      mydata.skt => mydata
3529 ******************************************************************************/
3530 
RemoveCDFSktExtension(sktName,sktPath)3531 void RemoveCDFSktExtension (sktName, sktPath)
3532 char *sktName;         /* CDF skeleton table file name. */
3533 char *sktPath;         /* The string holding file name without extension. */
3534 {
3535     int ptr = -1;
3536 
3537     strcpyX (sktPath, sktName, CDF_PATHNAME_LEN);
3538     if (EndsWithIgCase (sktPath, ".skt")) {
3539       ptr = StrLaststrIgCase(sktPath, ".skt");
3540       if (ptr != -1) ((char *) sktPath)[ptr] = (char) '\0';
3541     }
3542     return;
3543 }
3544 
3545 /******************************************************************************
3546 * GetNumTokens.
3547 ******************************************************************************/
3548 
GetNumTokens(token,string)3549 int GetNumTokens (token, string)
3550 int  token;
3551 char *string;
3552 {
3553   int count = 0;
3554   char *temp1, *temp2;
3555   char *ptr1, terminator;
3556   /****************************************************************************
3557   * Check that the entered list of tokens is not a NUL string, that there are
3558   * some possible tokens to match, etc.
3559   ****************************************************************************/
3560   if (NULstring(string)) {
3561     return 0;     /* Obviously, no tokens were found. */
3562   }
3563   /****************************************************************************
3564   * Scan the entered string of tokens searching for matches with the token.
3565   * First determine the starting character position and the * ending delimiter.
3566   ****************************************************************************/
3567   switch (string[0]) {
3568     case '(':           /* VMS-style. */
3569       terminator = ')';
3570       ptr1 = string + 1;
3571       break;
3572     case '"':           /* UNIX-style on a Mac (double quotes not stripped). */
3573       terminator = '"';
3574       ptr1 = string + 1;
3575       break;
3576     default:            /* UNIX-style on a UNIX machine or IBM PC. */
3577       terminator = NUL;
3578       ptr1 = string;
3579       break;
3580   }
3581   temp1 = ptr1;
3582   temp2 = ptr1 + strlen(ptr1) - 1;
3583   while (temp1 <= temp2) {
3584     if ((int) *temp1 == token) count++;
3585     temp1++;
3586   }
3587   count++;
3588   return count;
3589 }
3590 
3591 /******************************************************************************
3592 * ParseStringForTokens.
3593 ******************************************************************************/
3594 
ParseStringForTokens(token,string,items)3595 void ParseStringForTokens (token, string, items)
3596 int   token;
3597 char *string;
3598 char *items[];
3599 {
3600   int  tokenN; size_t tokenLen;
3601   char *ptr1, *ptr2, terminator;
3602   /****************************************************************************
3603   * Check that the entered list of tokens is not a NUL string, that there are
3604   * some possible tokens to match, etc.
3605   ****************************************************************************/
3606   if (NULstring(string)) {
3607     return;     /* Obviously, no tokens were found. */
3608   }
3609   /****************************************************************************
3610   * Scan the entered string of tokens searching for matches with the token.
3611   * First determine the starting character position and the * ending delimiter.
3612   ****************************************************************************/
3613   switch (string[0]) {
3614     case '(':           /* VMS-style. */
3615       terminator = ')';
3616       ptr1 = string + 1;
3617       break;
3618     case '"':           /* UNIX-style on a Mac (double quotes not stripped). */
3619       terminator = '"';
3620       ptr1 = string + 1;
3621       break;
3622     default:            /* UNIX-style on a UNIX machine or IBM PC. */
3623       terminator = NUL;
3624       ptr1 = string;
3625       break;
3626   }
3627   tokenN = 0;
3628   for (;;) {
3629      /*************************************************************************
3630      * Find beginning of the next token in list (skipping past any leading
3631      * blanks).  If the end of the list is reached instead, then there are
3632      * no more tokens.
3633      *************************************************************************/
3634      while (*ptr1 == ' ') ptr1++;
3635      if (*ptr1 == terminator) return;
3636      /*************************************************************************
3637      * Find the end of the token and copy.  The token is ended by either a
3638      * blank, comma, or the terminator.
3639      *************************************************************************/
3640      ptr2 = ptr1 + 1;
3641      while ((int) *ptr2 != token && *ptr2 != terminator) ptr2++;
3642      tokenLen = (size_t) (ptr2 - ptr1);
3643      strcpyX (items[tokenN], ptr1, tokenLen);
3644      tokenN++;
3645      /*************************************************************************
3646      * Setup to search for next token in list.
3647      *************************************************************************/
3648      if ((int) *ptr2 == token)
3649        /*********************************************************************
3650        * The last token was ended by a comma.  The next token begins one
3651        * character beyond the comma.
3652        *********************************************************************/
3653        ptr1 = ptr2 + 1;
3654      else
3655        /*********************************************************************
3656        * The terminator must have ended the last token.
3657        *********************************************************************/
3658        return;
3659   }
3660 }
3661 
3662 
3663