1 /******************************************************************************
2 *
3 * NSSDC/CDF Toolbox of routines for CDF Toolkit (General).
4 *
5 * Version 1.5d, 23-Nov-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 15-Dec-94, J Love CDF V2.5.
15 * V1.2a 13-Jan-95, J Love Allow mixed-case in tokens. Changed
16 * `CDFdirList' to allow all possible extensions
17 * on Macintosh machines also.
18 * V1.2b 6-Mar-95, J Love Added macro definition checking to catch
19 * bug in directory listing system calls. Pass
20 * `char' as `int'.
21 * V1.3 21-Mar-95, J Love POSIX.
22 * V1.3a 18-Apr-95, J Love More POSIX.
23 * V1.3b 24-Apr-95, J Love Fixed `EncodeString' to not overflow the
24 * maximum length if the string won't fit.
25 * V1.4 25-May-95, J Love Added `GetCdataType'. EPOCH styles.
26 * SOLARISbsdDIRUTILSbug.
27 * V1.4a 12-Jun-95, J Love EPOCH custom format. catchrX.
28 * V1.4b 5-Sep-95, J Love Allow NULL for output fields not needed.
29 * NUL-terminate decoded string in `DecodeValues'.
30 * V1.4c 19-Sep-95, J Love Macintosh event handling.
31 * V1.4d 27-Sep-95, J Love Reduced TextEdit text size for Think C.
32 * V1.5 27-Aug-96, J Love CDF V2.6.
33 * V1.5a 2-Nov-96, J Love Changed `DisplayIdentification' to not print
34 * a `blank' sub-increment.
35 * V1.5b 21-Feb-97, J Love Removed RICE.
36 * V1.5c 3-Mar-97, J Love Windows NT for MS Visual C/C++ on an IBM PC.
37 * V1.5d 23-Nov-97, J Love More Windows NT.
38 * V1.6 10-May-01, M Liu New port for Cygwin
39 * V1.7 11-Jul-05, M Liu Added MingW port for PC.
40 * V1.8 13-Oct-06, M Liu Changed to allow upper and lower case CDF
41 * name to be used on win32.
42 *
43 ******************************************************************************/
44
45 #define TOOLBOX1
46 #include "cdftools.h"
47
48 /******************************************************************************
49 * Local macros.
50 ******************************************************************************/
51
52 #define MAX_cFORMAT_LEN 10
53
54 /******************************************************************************
55 * Local enumerators.
56 ******************************************************************************/
57
58 #if (defined(unix) && !defined(__MINGW32__)) || defined(mac) || \
59 defined(posixSHELL)
60 enum typeENUM {TBD, STR, WILD1, WILDn};
61 #endif
62
63 /******************************************************************************
64 * Local structures.
65 ******************************************************************************/
66
67 struct FILEstruct {
68 char *name;
69 struct FILEstruct *next;
70 };
71
72 /******************************************************************************
73 * Local function prototypes.
74 ******************************************************************************/
75
76 static Logical FtoCformat PROTOARGs((long, char *, long *, char *));
77 static int UseCformat PROTOARGs((long, long, char *, void *, char *));
78 static long GetCdataType PROTOARGs((char *, long *));
79 static void AddToList PROTOARGs((struct FILEstruct **FILEhead,
80 struct FILEstruct *FILEptr));
81 #if (defined(unix) && !defined(__MINGW32__)) || defined(mac) || \
82 defined(posixSHELL)
83 static int PatternMatch PROTOARGs((char *pattern, char *name));
84 static int CheckPattern PROTOARGs((int nTypes, enum typeENUM types[],
85 char *strings[], char *name));
86 #endif
87
88 /******************************************************************************
89 * FatalError.
90 ******************************************************************************/
91
FatalError(message)92 void FatalError (message)
93 char *message;
94 {
95 #if defined(mac)
96 MacMessageDialog ("FATAL ERROR!", message);
97 #else
98 #if defined(win32) && !defined(ALONE)
99 WinMessageDialog ("FATAL ERROR!", message);
100 #else
101 WriteOut (stdout, "FATAL ERROR! ");
102 WriteOut (stdout, message);
103 WriteOut (stdout, "\n");
104 #endif
105 #endif
106 ExitBAD;
107 }
108
109 /******************************************************************************
110 * DisplayError.
111 ******************************************************************************/
112
DisplayError(message)113 void DisplayError (message)
114 char *message;
115 {
116 #if defined(mac)
117 MacMessageDialog ("Error!", message);
118 #else
119 #if defined(win32) && !defined(ALONE)
120 WinMessageDialog ("Error!", message);
121 #else
122 WriteOut (stdout, "Error! ");
123 WriteOut (stdout, message);
124 WriteOut (stdout, "\n");
125 #endif
126 #endif
127 return;
128 }
129
130 /******************************************************************************
131 * DisplayWarning.
132 * It is assumed that the message contains at least one character.
133 ******************************************************************************/
134
DisplayWarning(message)135 void DisplayWarning (message)
136 char *message;
137 {
138 #if defined(mac)
139 MacMessageDialog ("Warning...", message);
140 #else
141 WriteOut (stdout, "Warning: ");
142 WriteOut (stdout, message);
143 WriteOut (stdout, "\n");
144 #endif
145 return;
146 }
147
148 /******************************************************************************
149 * DisplayInfo.
150 ******************************************************************************/
151
DisplayInfo(message)152 void DisplayInfo (message)
153 char *message;
154 {
155 #if defined(mac)
156 MacMessageDialog ("", message);
157 #else
158 WriteOut (stdout, message);
159 WriteOut (stdout, "\n");
160 #endif
161 return;
162 }
163
164 /******************************************************************************
165 * DecodeVariances.
166 ******************************************************************************/
167
DecodeVariances(mask,numDims,recVary,dimVarys)168 Logical DecodeVariances (mask, numDims, recVary, dimVarys)
169 char *mask;
170 long numDims;
171 long *recVary;
172 long dimVarys[];
173 {
174 int dimN, charN;
175
176 switch (mask[0]) {
177 case 'T':
178 case 't':
179 *recVary = VARY;
180 break;
181 case 'F':
182 case 'f':
183 *recVary = NOVARY;
184 break;
185 default:
186 return FALSE;
187 }
188
189 for (dimN = 0, charN = 2; dimN < numDims; dimN++, charN++) {
190 switch (mask[charN]) {
191 case 'T':
192 case 't':
193 dimVarys[dimN] = VARY;
194 break;
195 case 'F':
196 case 'f':
197 dimVarys[dimN] = NOVARY;
198 break;
199 default:
200 return FALSE;
201 }
202 }
203
204 return TRUE;
205 }
206
207 /******************************************************************************
208 * DecodeDelimitedString.
209 ******************************************************************************/
210
DecodeDelimitedString(dString,pString)211 Logical DecodeDelimitedString (dString, pString)
212 char *dString; /* Delimited string. */
213 char *pString; /* Parsed (decoded) string. */
214 {
215 char *d1 = dString; /* First delimiter. */
216 char *d2; /* Second delimiter. */
217 size_t len; /* Size of decoded string. */
218
219 while (*d1 != NUL && Spacing(*d1)) d1++;
220 if (*d1 == NUL) return FALSE;
221
222 d2 = d1 + 1;
223 while (*d2 != NUL && *d2 != *d1) d2++;
224 if (*d2 == NUL) return FALSE;
225
226 len = (size_t) (d2 - d1 - 1);
227 memmove (pString, d1 + 1, len);
228 pString[len] = NUL;
229
230 return TRUE;
231 }
232
233 /******************************************************************************
234 * DecodeDimensionality.
235 ******************************************************************************/
236
DecodeDimensionality(string,numDims,dimSizes)237 Logical DecodeDimensionality (string, numDims, dimSizes)
238 char *string;
239 long *numDims;
240 long *dimSizes;
241 {
242 char *cp;
243 /****************************************************************************
244 * The number of dimensions should be first.
245 ****************************************************************************/
246 cp = NextNonSpace (string);
247 if (sscanf(cp,"%ld",numDims) != 1) return FALSE;
248 if (*numDims < 0) return FALSE;
249 cp = NextNonDigit (cp);
250 /****************************************************************************
251 * Skip past the `:' and `['.
252 ****************************************************************************/
253 cp = NextNonSpace (cp);
254 if (*cp != ':') return FALSE;
255 cp = NextNonSpace (cp+1);
256 if (*cp != '[') return FALSE;
257 cp = NextNonSpace (cp+1);
258 /****************************************************************************
259 * Decode each dimension size.
260 ****************************************************************************/
261 if (*numDims > 0) {
262 int dimN, lastDim = (int) (*numDims - 1);
263 for (dimN = 0; dimN <= lastDim; dimN++) {
264 if (sscanf(cp,"%ld",&dimSizes[dimN]) != 1) return FALSE;
265 cp = NextNonDigit (cp);
266 cp = NextNonSpace (cp);
267 if (dimN != lastDim) {
268 if (*cp != ',') return FALSE;
269 cp = NextNonSpace (cp+1);
270 }
271 }
272 }
273 /****************************************************************************
274 * Check for a trailing `]'.
275 ****************************************************************************/
276 if (*cp != ']') return FALSE;
277 /****************************************************************************
278 * Everything went Ok, return TRUE;
279 ****************************************************************************/
280 return TRUE;
281 }
282
283 /******************************************************************************
284 * DecodeRecordAndIndices.
285 ******************************************************************************/
286
DecodeRecordAndIndices(string,recN,nIndices,indices)287 Logical DecodeRecordAndIndices (string, recN, nIndices, indices)
288 char *string;
289 long *recN; /* Can be NULL if not needed. */
290 long *nIndices;
291 long indices[CDF_MAX_DIMS];
292 {
293 char *cp; long recNt;
294 /****************************************************************************
295 * The record number will be first if it exists;
296 ****************************************************************************/
297 cp = NextNonSpace (string);
298 if (*cp == '[') {
299 recNt = 0;
300 }
301 else {
302 if (sscanf(cp,"%ld",&recNt) != 1) return FALSE;
303 recNt -= 1;
304 if (recNt < 0) return FALSE;
305 cp = NextNonDigit (cp);
306 cp = NextNonSpace (cp);
307 if (*cp != ':') return FALSE;
308 cp = NextNonSpace (cp+1);
309 if (*cp != '[') return FALSE;
310 }
311 ASSIGNnotNULL (recN, recNt)
312 cp = NextNonSpace (cp+1);
313 /****************************************************************************
314 * Decode each index while counting how many there are.
315 ****************************************************************************/
316 *nIndices = 0;
317 if (*cp == ']') return TRUE;
318 for (;;) {
319 if (*nIndices == CDF_MAX_DIMS) return FALSE; /* Too many indices. */
320 if (sscanf(cp,"%ld",&indices[(int)(*nIndices)]) != 1) return FALSE;
321 indices[(int)(*nIndices)] -= 1;
322 if (indices[(int)(*nIndices)] < 0) return FALSE;
323 *nIndices += 1;
324 cp = NextNonDigit (cp); /* Skip to space, comma, or `]'. */
325 cp = NextNonSpace (cp); /* Skip past spaces. */
326 switch (*cp) {
327 case ']':
328 return TRUE;
329 case ',':
330 cp = NextNonSpace (cp + 1);
331 break;
332 default:
333 return FALSE;
334 }
335 }
336 }
337
338 /******************************************************************************
339 * NextNonSpace.
340 ******************************************************************************/
341
NextNonSpace(cp)342 char *NextNonSpace (cp)
343 char *cp;
344 {
345 while (Spacing(*cp)) cp++;
346 return cp;
347 }
348
349 /******************************************************************************
350 * NextNonDigit.
351 ******************************************************************************/
352
NextNonDigit(cp)353 char *NextNonDigit (cp)
354 char *cp;
355 {
356 while (Decimal(*cp)) cp++;
357 return cp;
358 }
359
360 /******************************************************************************
361 * FormatWidth.
362 * Returns width of a format specifier [or zero if the width is unknown or
363 * illegal].
364 ******************************************************************************/
365
FormatWidth(format)366 int FormatWidth (format)
367 char *format;
368 {
369 int width; char *ptr = format;
370 /****************************************************************************
371 * Skip past Fortran repeat count (eg. the `20' in `20I8' or `20(I8)').
372 * Note that this won't skip past a C `%'.
373 ****************************************************************************/
374 while (*ptr != NUL && (*ptr == '(' ||
375 Spacing(*ptr) ||
376 Decimal(*ptr))) ptr++;
377 if (*ptr == NUL) return 0;
378 /****************************************************************************
379 * Skip past Fortran format type (eg. the `F' in `F4.1') or C `%' and/or
380 * flags (one of which might be a `0').
381 ****************************************************************************/
382 while (*ptr != NUL && (!Decimal(*ptr) || *ptr == '0')) ptr++;
383 if (*ptr == NUL) return 0;
384 /****************************************************************************
385 * Decode format width.
386 ****************************************************************************/
387 if (sscanf(ptr,"%d",&width) != 1) width = 0;
388 return width;
389 }
390
391 /******************************************************************************
392 * FormatPrecision.
393 * Returns precision of a format specifier [or zero if the precision doesn't
394 * exist [eg. integer format]).
395 ******************************************************************************/
396
FormatPrecision(format)397 int FormatPrecision (format)
398 char *format;
399 {
400 int precision;
401 char *ptr = strchr (format, '.');
402 if (ptr == NULL)
403 precision = 0;
404 else
405 if (sscanf(ptr+1,"%d",&precision) != 1) precision = 0;
406 return precision;
407 }
408
409 /******************************************************************************
410 * EncodeValuesFormat. Returns width of encoded values.
411 ******************************************************************************/
412
EncodeValuesFormat(dataType,numElems,binary,text,format,minWidth,maxWidth,style)413 int EncodeValuesFormat (dataType, numElems, binary, text, format, minWidth,
414 maxWidth, style)
415 long dataType; /* Data type of values. */
416 long numElems; /* Number of elements (values). */
417 void *binary; /* In: Values in binary. */
418 char *text; /* Out: Encoded values. */
419 char *format; /* If NULL, use default formats. Not applicable if
420 a string data type. */
421 int minWidth; /* Minimum width (including delimeters if a string
422 data type. If zero, no minimum width (no blank
423 padding). If positive, right justified (padding
424 on left side). If negative, left justified
425 (padding on right side). */
426 int maxWidth; /* Maximum width (including delimeters if a string
427 data type. If zero, no maximum width (no
428 truncating). */
429 int style; /* EPOCH style. */
430 {
431 /****************************************************************************
432 * Encode value(s).
433 ****************************************************************************/
434 if (STRINGdataType(dataType))
435 EncodeString (numElems, binary, text, minWidth, maxWidth);
436 else {
437 long elemN;
438 char tText[MAX_nonSTRING_VALUE_LEN+1];
439 strcpyX (text, "", maxWidth);
440 for (elemN = 0; elemN < numElems; elemN++) {
441 /***********************************************************************
442 * Encode each value (if it fits).
443 ***********************************************************************/
444 EncodeValueFormat (dataType, (Byte *) binary +
445 (size_t) (elemN*CDFelemSize(dataType)),
446 tText, format, 0, 0, style);
447 if (maxWidth > 0) {
448 int n = strlen(tText);
449 if (strlen(text) + (elemN > 0 ? 2 : 0) + n > (size_t) maxWidth) {
450 /*******************************************************************
451 * This value won't fit. Find a comma after which to put the
452 * truncation symbol (`...'). `i' starts at the NUL just in case
453 * this is the first value (`text' is a null-string).
454 *******************************************************************/
455 int i;
456 for (i = strlen(text); i != 0; i--) {
457 if (text[i] == ',' &&
458 (i + strlen(" ...") < (size_t) maxWidth)) break;
459 }
460 if (i != 0)
461 strcpyX (&text[i+1], " ...", maxWidth);
462 else {
463 switch (elemN) {
464 case 0:
465 CpyNcharacters (text, maxWidth, (int) '*');
466 break;
467 case 1:
468 if (strlen(text) + strlen(", ...") <= (size_t) maxWidth)
469 strcatX (text, ", ...", maxWidth);
470 else {
471 CpyNcharacters (text, maxWidth, (int) '*');
472 }
473 break;
474 default:
475 CpyNcharacters (text, maxWidth, (int) '*');
476 break;
477 }
478 }
479 break;
480 }
481 else
482 sprintf (&text[strlen(text)], "%s%s", (elemN > 0 ? ", " : ""),
483 tText);
484 }
485 else
486 sprintf (&text[strlen(text)], "%s%s", (elemN > 0 ? ", " : ""), tText);
487 }
488 /**************************************************************************
489 * Blank pad to `minWidth' if necessary.
490 **************************************************************************/
491 if (minWidth != 0) {
492 int n = strlen(text);
493 if (minWidth > 0) { /* Right justify. */
494 if (n < minWidth) {
495 int i, pad = minWidth - n;
496 memmove (&text[pad], text, n + 1);
497 for (i = 0; i < pad; i++) text[i] = ' ';
498 }
499 }
500 else { /* Left justify. */
501 int min = -minWidth;
502 if (n < min) {
503 int pad = min - n;
504 CatNcharacters (text, pad, (int) ' ');
505 }
506 }
507 }
508 }
509 /****************************************************************************
510 * Return length of encoded value(s).
511 ****************************************************************************/
512 return strlen(text);
513 }
514
515 /******************************************************************************
516 * EncodeValueFormat.
517 * Returns width of encoded value. Not for use with character string data
518 * types (CDF_CHAR or CDF_UCHAR).
519 ******************************************************************************/
520
EncodeValueFormat(dataType,binary,text,format,minWidth,maxWidth,style)521 int EncodeValueFormat (dataType, binary, text, format, minWidth, maxWidth,
522 style)
523 long dataType; /* Data type of value being encoded. */
524 void *binary; /* In: Value in binary. */
525 char *text; /* Out: Encoded value. */
526 char *format; /* Format string to be used. */
527 int minWidth; /* Minimum width (including delimeters if a string
528 data type. If zero, no minimum width (no blank
529 padding). If positive, right justified (padding
530 on left side). If negative, left justified
531 (padding on right side). */
532 int maxWidth; /* Maximum width. If zero, no maximum width (no
533 asteriks if too big). */
534 int style; /* EPOCH style. */
535 {
536 long CdataType;
537 char Cformat[MAX_cFORMAT_LEN+1];
538 char tText[MAX_nonSTRING_VALUE_LEN+1];
539 /****************************************************************************
540 * Encode value.
541 ****************************************************************************/
542 if (EPOCHdataType(dataType)) {
543 switch (style) {
544 case EPOCHf_STYLE:
545 return EncodeValueFormat(CDF_DOUBLE,binary,text,
546 format,minWidth,maxWidth,0);
547 case EPOCHx_STYLE:
548 encodeEPOCHx (*((double *) binary), format, tText);
549 break;
550 default:
551 EncodeValue (CDF_EPOCH, binary, tText, style);
552 break;
553 }
554 } else if (EPOCH16dataType(dataType)) {
555 switch (style) {
556 case EPOCHf_STYLE:
557 return EncodeValueFormat(CDF_DOUBLE,binary,text,
558 format,minWidth,maxWidth,0);
559 case EPOCHx_STYLE:
560 encodeEPOCHx (*((double *) binary), format, tText);
561 break;
562 default:
563 EncodeValue (CDF_EPOCH16, binary, tText, style);
564 break;
565 }
566 }
567 else
568 if (format == NULL)
569 EncodeValue (dataType, binary, tText, 0);
570 else
571 if (strchr(format,'%') != NULL)
572 if (GetCdataType(format,&CdataType))
573 UseCformat (dataType, CdataType, format, binary, tText);
574 else
575 EncodeValue (dataType, binary, tText, 0);
576 else
577 if (FtoCformat(dataType,format,&CdataType,Cformat))
578 UseCformat (dataType, CdataType, Cformat, binary, tText);
579 else
580 EncodeValue (dataType, binary, tText, 0);
581 /****************************************************************************
582 * Fill in asteriks if encoded value is too big. Otherwise, copy encoded
583 * value.
584 ****************************************************************************/
585 if (maxWidth > 0) {
586 int n = strlen(tText);
587 if (n > maxWidth)
588 CpyNcharacters (text, maxWidth, (int) '*');
589 else
590 strcpyX (text, tText, maxWidth);
591 }
592 else
593 strcpyX (text, tText, maxWidth);
594 /****************************************************************************
595 * Blank pad to `minWidth' if necessary.
596 ****************************************************************************/
597 if (minWidth != 0) {
598 int n = strlen(text);
599 if (minWidth > 0) { /* Right justify. */
600 if (n < minWidth) {
601 int i, pad = minWidth - n;
602 memmove (&text[pad], text, n + 1);
603 for (i = 0; i < pad; i++) text[i] = ' ';
604 }
605 }
606 else { /* Left justify. */
607 int min = -minWidth;
608 if (n < min) {
609 int pad = min - n;
610 CatNcharacters (text, pad, (int) ' ');
611 }
612 }
613 }
614 /****************************************************************************
615 * Return length of encoded value.
616 ****************************************************************************/
617 return strlen(text);
618 }
619
620 /******************************************************************************
621 * EncodeValue.
622 * Returns width of encoded value.
623 ******************************************************************************/
624
EncodeValue(dataType,binary,text,style)625 int EncodeValue (dataType, binary, text, style)
626 long dataType; /* CDF data type. */
627 void *binary; /* In: Value to encode. */
628 char *text; /* Out: Encoded value. */
629 int style; /* In: EPOCH style. */
630 {
631 MakeNUL (text);
632 switch (dataType) {
633 case CDF_BYTE:
634 case CDF_INT1:
635 sprintf (text, "%d", (int) *((sChar *) binary));
636 break;
637 case CDF_INT2:
638 sprintf (text, "%d", (int) *((Int16 *) binary));
639 break;
640 case CDF_INT4:
641 sprintf (text, Int32FORMAT, *((Int32 *) binary));
642 break;
643 case CDF_UINT1:
644 sprintf (text, "%u", (uInt) *((uChar *) binary));
645 break;
646 case CDF_UINT2:
647 sprintf (text, "%u", (uInt) *((uInt16 *) binary));
648 break;
649 case CDF_UINT4:
650 sprintf (text, Int32uFORMAT, *((uInt32 *) binary));
651 break;
652 case CDF_REAL4:
653 case CDF_FLOAT: {
654 if (NegativeZeroReal4((float *) binary))
655 strcpyX (text, NEGATIVEzeroSYMBOL, 0);
656 else {
657 size_t len;
658 char *ePtr, tText[80+1];
659 sprintf (text, "%g", *((float *) binary));
660 if ((ePtr = strchr(text,'e')) == NULL) { /* eg., 0 */
661 if (strchr(text,'.') == NULL) strcatX (text,".0", 0);
662 }
663 else {
664 if (strchr(text,'.') == NULL) { /* eg., 1e+07 */
665 len = (size_t) (ePtr - text);
666 strcpyX (tText, text, MINIMUM(len,80));
667 strcatX (tText, ".0", 0);
668 strcatX (tText, ePtr, 0);
669 strcpyX (text, tText, 0);
670 }
671 }
672 }
673 break;
674 }
675 case CDF_REAL8:
676 case CDF_DOUBLE: {
677 if (NegativeZeroReal8((double *) binary))
678 strcpyX (text, NEGATIVEzeroSYMBOL, 0);
679 else {
680 size_t len;
681 char *ePtr, tText[80+1];
682 sprintf (text, "%g", *((double *) binary));
683 if ((ePtr = strchr(text,'e')) == NULL) { /* eg., 0 */
684 if (strchr(text,'.') == NULL) strcatX (text,".0", 0);
685 }
686 else {
687 if (strchr(text,'.') == NULL) { /* eg., 1e+07 */
688 len = (size_t) (ePtr - text);
689 strcpyX (tText, text, MINIMUM(len,80));
690 strcatX (tText, ".0", 0);
691 strcatX (tText, ePtr, 0);
692 strcpyX (text, tText, 0);
693 }
694 }
695 }
696 break;
697 }
698 case CDF_CHAR:
699 sprintf (text, "%c", *((sChar *) binary));
700 break;
701 case CDF_UCHAR:
702 sprintf (text, "%c", *((uChar *) binary));
703 break;
704 case CDF_EPOCH:
705 switch (style) {
706 case EPOCH0_STYLE:
707 encodeEPOCH (*((double *) binary), text);
708 break;
709 case EPOCH1_STYLE:
710 encodeEPOCH1 (*((double *) binary), text);
711 break;
712 case EPOCH2_STYLE:
713 encodeEPOCH2 (*((double *) binary), text);
714 break;
715 case EPOCH3_STYLE:
716 encodeEPOCH3 (*((double *) binary), text);
717 break;
718 case EPOCHf_STYLE:
719 return EncodeValue(CDF_DOUBLE,binary,text,0);
720 case EPOCHx_STYLE:
721 /* Unsupported (a format specification is needed). */
722 break;
723 }
724 break;
725 case CDF_EPOCH16:
726 switch (style) {
727 case EPOCH0_STYLE:
728 encodeEPOCH16 ((double *) binary, text);
729 break;
730 case EPOCH1_STYLE:
731 encodeEPOCH16_1 ((double *) binary, text);
732 break;
733 case EPOCH2_STYLE:
734 encodeEPOCH16_2 ((double *) binary, text);
735 break;
736 case EPOCH3_STYLE:
737 encodeEPOCH16_3 ((double *) binary, text);
738 break;
739 case EPOCHf_STYLE:
740 return EncodeValue(CDF_DOUBLE,binary,text,0);
741 case EPOCHx_STYLE:
742 /* Unsupported (a format specification is needed). */
743 break;
744 }
745 break;
746 }
747 return strlen(text);
748 }
749
750 /******************************************************************************
751 * EncodeString. Returns width of encoded string (including delimeters).
752 ******************************************************************************/
753
EncodeString(nChars,iString,oString,minWidth,maxWidth)754 int EncodeString (nChars, iString, oString, minWidth, maxWidth)
755 long nChars; /* Number of characters (elements). */
756 char *iString; /* String to encode (input). */
757 char *oString; /* Encoded string (output). */
758 int minWidth; /* Minimum width (including delimeters if a string
759 data type. If zero, no minimum width (no blank
760 padding). If positive, right justified (padding
761 on left side). If negative, left justified
762 (padding on right side). */
763 int maxWidth; /* Maximum width (including delimeters). If zero,
764 no maximum width (no truncating). */
765 {
766 char delim = PickDelimiter (iString, (size_t) nChars); int i;
767 /****************************************************************************
768 * Encode string.
769 ****************************************************************************/
770 if (nChars + 2 > BOO(maxWidth == 0,(int)(nChars + 2),maxWidth)) {
771 /**************************************************************************
772 * Won't fit. Should at least encode `"a..."'. If not enough room, fill
773 * in with astericks.
774 **************************************************************************/
775 if (maxWidth < 6) {
776 CpyNcharacters (oString, maxWidth, (int) '*');
777 }
778 else {
779 oString[0] = delim;
780 for (i = 0; i < maxWidth - 5; i++) {
781 oString[i+1] = BOO(Printable(iString[i]),iString[i],'.');
782 }
783 oString[i+1] = '.';
784 oString[i+2] = '.';
785 oString[i+3] = '.';
786 oString[i+4] = delim;
787 oString[i+5] = NUL;
788 }
789 }
790 else {
791 /**************************************************************************
792 * Fits.
793 **************************************************************************/
794 oString[0] = delim;
795 for (i = 0; i < nChars; i++) {
796 oString[i+1] = BOO(Printable(iString[i]),iString[i],'.');
797 }
798 oString[i+1] = delim;
799 oString[i+2] = NUL;
800 }
801 /****************************************************************************
802 * Blank pad to `minWidth' if necessary.
803 ****************************************************************************/
804 if (minWidth != 0) {
805 int n = strlen(oString);
806 if (minWidth > 0) { /* Right justify. */
807 if (n < minWidth) {
808 int i, pad = minWidth - n;
809 memmove (&oString[pad], oString, n + 1);
810 for (i = 0; i < pad; i++) oString[i] = ' ';
811 }
812 }
813 else { /* Left justify. */
814 int min = -minWidth;
815 if (n < min) {
816 int pad = min - n;
817 CatNcharacters (oString, pad, (int) ' ');
818 }
819 }
820 }
821 /****************************************************************************
822 * Return length of encoded string.
823 ****************************************************************************/
824 return strlen(oString);
825 }
826
827 /******************************************************************************
828 * EncodeNegativeZero.
829 ******************************************************************************/
830
EncodeNegativeZero(string,format)831 void EncodeNegativeZero (string, format)
832 char *string;
833 char *format;
834 {
835 char *ptr;
836 /****************************************************************************
837 * Encode 0.0 using format then check if the value was successfully encoded.
838 ****************************************************************************/
839 string[0] = NUL;
840 sprintf(string, format, 0.0);
841 if (NULstring(string)) {
842 strcpyX (string, "-0.0(bad FORMAT)", 0);
843 return;
844 }
845 /****************************************************************************
846 * 0.0 was successfully encoded - put a negative sign at the beginning
847 * (increasing the length of the string if necessary).
848 ****************************************************************************/
849 ptr = string;
850 while (*ptr == ' ') ptr++;
851 if (ptr == string) {
852 memmove (&string[1], string, strlen(string) + 1);
853 string[0] = '-';
854 }
855 else
856 *(ptr - 1) = '-';
857 return;
858 }
859
860 /******************************************************************************
861 * UseCformat.
862 * Returns width of encoded value. Not for use with CDF_EPOCH or CDF_(U)CHAR
863 * values.
864 ******************************************************************************/
865
UseCformat(dataType,CdataType,Cformat,binary,text)866 static int UseCformat (dataType, CdataType, Cformat, binary, text)
867 long dataType; /* Value's actual data type. This should never be
868 CDF_EPOCH. */
869 long CdataType; /* Data type corresponding to C format. This should
870 never be CDF_EPOCH. */
871 char *Cformat; /* C format specification. */
872 void *binary; /* Value to be encoded. */
873 char *text; /* String into which to encode the value. */
874 {
875 switch (dataType) {
876 case CDF_BYTE:
877 case CDF_INT1:
878 switch (CdataType) {
879 case CDF_BYTE:
880 case CDF_INT1:
881 sprintf (text, Cformat, (sChar) *((sChar *) binary));
882 break;
883 case CDF_UINT1:
884 sprintf (text, Cformat, (uChar) *((sChar *) binary));
885 break;
886 case CDF_INT2:
887 sprintf (text, Cformat, (Int16) *((sChar *) binary));
888 break;
889 case CDF_UINT2:
890 sprintf (text, Cformat, (uInt16) *((sChar *) binary));
891 break;
892 case CDF_INT4:
893 sprintf (text, Cformat, (Int32) *((sChar *) binary));
894 break;
895 case CDF_UINT4:
896 sprintf (text, Cformat, (uInt32) *((sChar *) binary));
897 break;
898 case CDF_REAL4:
899 case CDF_FLOAT:
900 sprintf (text, Cformat, (float) *((sChar *) binary));
901 break;
902 case CDF_REAL8:
903 case CDF_DOUBLE:
904 sprintf (text, Cformat, (double) *((sChar *) binary));
905 break;
906 }
907 break;
908 case CDF_UINT1:
909 switch (CdataType) {
910 case CDF_BYTE:
911 case CDF_INT1:
912 sprintf (text, Cformat, (sChar) *((uChar *) binary));
913 break;
914 case CDF_UINT1:
915 sprintf (text, Cformat, (uChar) *((uChar *) binary));
916 break;
917 case CDF_INT2:
918 sprintf (text, Cformat, (Int16) *((uChar *) binary));
919 break;
920 case CDF_UINT2:
921 sprintf (text, Cformat, (uInt16) *((uChar *) binary));
922 break;
923 case CDF_INT4:
924 sprintf (text, Cformat, (Int32) *((uChar *) binary));
925 break;
926 case CDF_UINT4:
927 sprintf (text, Cformat, (uInt32) *((uChar *) binary));
928 break;
929 case CDF_REAL4:
930 case CDF_FLOAT:
931 sprintf (text, Cformat, (float) *((uChar *) binary));
932 break;
933 case CDF_REAL8:
934 case CDF_DOUBLE:
935 sprintf (text, Cformat, (double) *((uChar *) binary));
936 break;
937 }
938 break;
939 case CDF_INT2:
940 switch (CdataType) {
941 case CDF_BYTE:
942 case CDF_INT1:
943 sprintf (text, Cformat, (sChar) *((Int16 *) binary));
944 break;
945 case CDF_UINT1:
946 sprintf (text, Cformat, (uChar) *((Int16 *) binary));
947 break;
948 case CDF_INT2:
949 sprintf (text, Cformat, (Int16) *((Int16 *) binary));
950 break;
951 case CDF_UINT2:
952 sprintf (text, Cformat, (uInt16) *((Int16 *) binary));
953 break;
954 case CDF_INT4:
955 sprintf (text, Cformat, (Int32) *((Int16 *) binary));
956 break;
957 case CDF_UINT4:
958 sprintf (text, Cformat, (uInt32) *((Int16 *) binary));
959 break;
960 case CDF_REAL4:
961 case CDF_FLOAT:
962 sprintf (text, Cformat, (float) *((Int16 *) binary));
963 break;
964 case CDF_REAL8:
965 case CDF_DOUBLE:
966 sprintf (text, Cformat, (double) *((Int16 *) binary));
967 break;
968 }
969 break;
970 case CDF_UINT2:
971 switch (CdataType) {
972 case CDF_BYTE:
973 case CDF_INT1:
974 sprintf (text, Cformat, (sChar) *((uInt16 *) binary));
975 break;
976 case CDF_UINT1:
977 sprintf (text, Cformat, (uChar) *((uInt16 *) binary));
978 break;
979 case CDF_INT2:
980 sprintf (text, Cformat, (Int16) *((uInt16 *) binary));
981 break;
982 case CDF_UINT2:
983 sprintf (text, Cformat, (uInt16) *((uInt16 *) binary));
984 break;
985 case CDF_INT4:
986 sprintf (text, Cformat, (Int32) *((uInt16 *) binary));
987 break;
988 case CDF_UINT4:
989 sprintf (text, Cformat, (uInt32) *((uInt16 *) binary));
990 break;
991 case CDF_REAL4:
992 case CDF_FLOAT:
993 sprintf (text, Cformat, (float) *((uInt16 *) binary));
994 break;
995 case CDF_REAL8:
996 case CDF_DOUBLE:
997 sprintf (text, Cformat, (double) *((uInt16 *) binary));
998 break;
999 }
1000 break;
1001 case CDF_INT4:
1002 switch (CdataType) {
1003 case CDF_BYTE:
1004 case CDF_INT1:
1005 sprintf (text, Cformat, (sChar) *((Int32 *) binary));
1006 break;
1007 case CDF_UINT1:
1008 sprintf (text, Cformat, (uChar) *((Int32 *) binary));
1009 break;
1010 case CDF_INT2:
1011 sprintf (text, Cformat, (Int16) *((Int32 *) binary));
1012 break;
1013 case CDF_UINT2:
1014 sprintf (text, Cformat, (uInt16) *((Int32 *) binary));
1015 break;
1016 case CDF_INT4:
1017 sprintf (text, Cformat, (Int32) *((Int32 *) binary));
1018 break;
1019 case CDF_UINT4:
1020 sprintf (text, Cformat, (uInt32) *((Int32 *) binary));
1021 break;
1022 case CDF_REAL4:
1023 case CDF_FLOAT:
1024 sprintf (text, Cformat, (float) *((Int32 *) binary));
1025 break;
1026 case CDF_REAL8:
1027 case CDF_DOUBLE:
1028 sprintf (text, Cformat, (double) *((Int32 *) binary));
1029 break;
1030 }
1031 break;
1032 case CDF_UINT4:
1033 switch (CdataType) {
1034 case CDF_BYTE:
1035 case CDF_INT1:
1036 sprintf (text, Cformat, (sChar) *((uInt32 *) binary));
1037 break;
1038 case CDF_UINT1:
1039 sprintf (text, Cformat, (uChar) *((uInt32 *) binary));
1040 break;
1041 case CDF_INT2:
1042 sprintf (text, Cformat, (Int16) *((uInt32 *) binary));
1043 break;
1044 case CDF_UINT2:
1045 sprintf (text, Cformat, (uInt16) *((uInt32 *) binary));
1046 break;
1047 case CDF_INT4:
1048 sprintf (text, Cformat, (Int32) *((uInt32 *) binary));
1049 break;
1050 case CDF_UINT4:
1051 sprintf (text, Cformat, (uInt32) *((uInt32 *) binary));
1052 break;
1053 case CDF_REAL4:
1054 case CDF_FLOAT:
1055 sprintf (text, Cformat, (float) *((uInt32 *) binary));
1056 break;
1057 case CDF_REAL8:
1058 case CDF_DOUBLE:
1059 sprintf (text, Cformat, (double) *((uInt32 *) binary));
1060 break;
1061 }
1062 break;
1063 case CDF_REAL4:
1064 case CDF_FLOAT:
1065 switch (CdataType) {
1066 case CDF_BYTE:
1067 case CDF_INT1:
1068 sprintf (text, Cformat, (sChar) *((float *) binary));
1069 break;
1070 case CDF_UINT1:
1071 sprintf (text, Cformat, (uChar) *((float *) binary));
1072 break;
1073 case CDF_INT2:
1074 sprintf (text, Cformat, (Int16) *((float *) binary));
1075 break;
1076 case CDF_UINT2:
1077 sprintf (text, Cformat, (uInt16) *((float *) binary));
1078 break;
1079 case CDF_INT4:
1080 sprintf (text, Cformat, (Int32) *((float *) binary));
1081 break;
1082 case CDF_UINT4:
1083 sprintf (text, Cformat, (uInt32) *((float *) binary));
1084 break;
1085 case CDF_REAL4:
1086 case CDF_FLOAT:
1087 if (NegativeZeroReal4((float *) binary))
1088 EncodeNegativeZero (text, Cformat);
1089 else
1090 sprintf (text, Cformat, (float) *((float *) binary));
1091 break;
1092 case CDF_REAL8:
1093 case CDF_DOUBLE:
1094 if (NegativeZeroReal4((float *) binary))
1095 EncodeNegativeZero (text, Cformat);
1096 else
1097 sprintf (text, Cformat, (double) *((float *) binary));
1098 break;
1099 }
1100 break;
1101 case CDF_REAL8:
1102 case CDF_DOUBLE:
1103 switch (CdataType) {
1104 case CDF_BYTE:
1105 case CDF_INT1:
1106 sprintf (text, Cformat, (sChar) *((double *) binary));
1107 break;
1108 case CDF_UINT1:
1109 sprintf (text, Cformat, (uChar) *((double *) binary));
1110 break;
1111 case CDF_INT2:
1112 sprintf (text, Cformat, (Int16) *((double *) binary));
1113 break;
1114 case CDF_UINT2:
1115 sprintf (text, Cformat, (uInt16) *((double *) binary));
1116 break;
1117 case CDF_INT4:
1118 sprintf (text, Cformat, (Int32) *((double *) binary));
1119 break;
1120 case CDF_UINT4:
1121 sprintf (text, Cformat, (uInt32) *((double *) binary));
1122 break;
1123 case CDF_REAL4:
1124 case CDF_FLOAT:
1125 if (NegativeZeroReal8((double *) binary))
1126 EncodeNegativeZero (text, Cformat);
1127 else
1128 sprintf (text, Cformat, (float) *((double *) binary));
1129 break;
1130 case CDF_REAL8:
1131 case CDF_DOUBLE:
1132 if (NegativeZeroReal8((double *) binary))
1133 EncodeNegativeZero (text, Cformat);
1134 else
1135 sprintf (text, Cformat, (double) *((double *) binary));
1136 break;
1137 }
1138 break;
1139 }
1140
1141 /* Change ...e+0.. (3 numbers after +/-) from win32 to ...e+.. (2 numbers
1142 after +/-) just like other systems */
1143 #if defined(win32)
1144 if (strchr(text, 'e') != NULL || strchr(text, 'E') != NULL) {
1145 int ilen = strlen(text);
1146 char *ie;
1147 char *to0;
1148 ie = strchr(text, 'e');
1149 if (ie == NULL) ie = strchr(text, 'E');
1150 to0 = strstr(ie, "+0");
1151 if (to0 == NULL) to0 = strstr(ie, "-0");
1152 if (to0 != NULL) {
1153 if (strlen(ie) == 5) {
1154 char *newText;
1155 int itrail;
1156 newText = (char *) malloc(ilen-1);
1157 itrail = strlen(ie);
1158 memmove(newText, text, ilen-itrail+2);
1159 memmove(newText+ilen-itrail+2, text+ilen-itrail+3,
1160 itrail-3);
1161 newText[ilen-1] = NUL;
1162 strcpy(text, newText);
1163 }
1164 }
1165 }
1166 #endif
1167
1168 return strlen(text);
1169 }
1170
1171 /******************************************************************************
1172 * FtoCformat.
1173 * Returns TRUE if valid FORTRAN format specification.
1174 ******************************************************************************/
1175
FtoCformat(dataType,Fformat,CdataType,Cformat)1176 static Logical FtoCformat (dataType, Fformat, CdataType, Cformat)
1177 long dataType; /* Value's actual data type. This should never be
1178 CDF_EPOCH. */
1179 char *Fformat; /* FORTRAN format specification. */
1180 long *CdataType; /* Data type implied by C format specification. */
1181 char *Cformat; /* C format specification. */
1182 {
1183 int nFound;
1184 int w, m, d;
1185 /****************************************************************************
1186 * Change `Fformat' to point to first non-blank, non-digit, non-`('
1187 * character. This will skip over a Fortran repeat count (eg. the `20' in
1188 * `20F8.4' or `20(F8.4)').
1189 ****************************************************************************/
1190 while (*Fformat != NUL && (*Fformat == '(' ||
1191 Spacing(*Fformat) ||
1192 Decimal(*Fformat))) Fformat++;
1193 if (*Fformat == NUL) return FALSE;
1194 /****************************************************************************
1195 * Encode C format specification.
1196 ****************************************************************************/
1197 switch (Fformat[0]) {
1198 /**************************************************************************
1199 * Integer/decimal.
1200 **************************************************************************/
1201 case 'I':
1202 case 'i':
1203 nFound = sscanf (&Fformat[1], "%d.%d", &w, &m);
1204 switch (nFound) {
1205 case 0:
1206 return FALSE;
1207 case 1:
1208 switch (dataType) {
1209 case CDF_BYTE:
1210 case CDF_INT1:
1211 sprintf (Cformat, "%%%dd", w);
1212 *CdataType = CDF_INT1;
1213 return TRUE;
1214 case CDF_UINT1:
1215 sprintf (Cformat, "%%%du", w);
1216 *CdataType = CDF_UINT1;
1217 return TRUE;
1218 case CDF_INT2:
1219 sprintf (Cformat, "%%%dd", w);
1220 *CdataType = CDF_INT2;
1221 return TRUE;
1222 case CDF_UINT2:
1223 sprintf (Cformat, "%%%du", w);
1224 *CdataType = CDF_UINT2;
1225 return TRUE;
1226 case CDF_INT4:
1227 sprintf (Cformat, "%%%d%sd", w, Int32FORMATmod);
1228 *CdataType = CDF_INT4;
1229 return TRUE;
1230 case CDF_UINT4:
1231 sprintf (Cformat, "%%%d%su", w, Int32FORMATmod);
1232 *CdataType = CDF_UINT4;
1233 return TRUE;
1234 case CDF_REAL4:
1235 case CDF_FLOAT:
1236 case CDF_REAL8:
1237 case CDF_DOUBLE:
1238 sprintf (Cformat, "%%%d%sd", w, Int32FORMATmod);
1239 *CdataType = CDF_INT4;
1240 return TRUE;
1241 }
1242 return FALSE;
1243 case 2:
1244 switch (dataType) {
1245 case CDF_BYTE:
1246 case CDF_INT1:
1247 sprintf (Cformat, "%%%d.%dd", w, m);
1248 *CdataType = CDF_INT1;
1249 return TRUE;
1250 case CDF_UINT1:
1251 sprintf (Cformat, "%%%d.%du", w, m);
1252 *CdataType = CDF_UINT1;
1253 return TRUE;
1254 case CDF_INT2:
1255 sprintf (Cformat, "%%%d.%dd", w, m);
1256 *CdataType = CDF_INT2;
1257 return TRUE;
1258 case CDF_UINT2:
1259 sprintf (Cformat, "%%%d.%du", w, m);
1260 *CdataType = CDF_UINT2;
1261 return TRUE;
1262 case CDF_INT4:
1263 sprintf (Cformat, "%%%d.%d%sd", w, m, Int32FORMATmod);
1264 *CdataType = CDF_INT4;
1265 return TRUE;
1266 case CDF_UINT4:
1267 sprintf (Cformat, "%%%d.%d%su", w, m, Int32FORMATmod);
1268 *CdataType = CDF_UINT4;
1269 return TRUE;
1270 case CDF_REAL4:
1271 case CDF_FLOAT:
1272 case CDF_REAL8:
1273 case CDF_DOUBLE:
1274 sprintf (Cformat, "%%%d.%d%sd", w, m, Int32FORMATmod);
1275 *CdataType = CDF_INT4;
1276 return TRUE;
1277 }
1278 return FALSE;
1279 }
1280 return FALSE;
1281 /**************************************************************************
1282 * Integer/octal.
1283 **************************************************************************/
1284 case 'O':
1285 case 'o':
1286 nFound = sscanf (&Fformat[1], "%d.%d", &w, &m);
1287 switch (nFound) {
1288 case 0:
1289 return FALSE;
1290 case 1:
1291 switch (dataType) {
1292 case CDF_BYTE:
1293 case CDF_INT1:
1294 sprintf (Cformat, "%%%do", w);
1295 *CdataType = CDF_UINT1;
1296 return TRUE;
1297 case CDF_UINT1:
1298 sprintf (Cformat, "%%%do", w);
1299 *CdataType = CDF_UINT1;
1300 return TRUE;
1301 case CDF_INT2:
1302 sprintf (Cformat, "%%%do", w);
1303 *CdataType = CDF_UINT2;
1304 return TRUE;
1305 case CDF_UINT2:
1306 sprintf (Cformat, "%%%do", w);
1307 *CdataType = CDF_UINT2;
1308 return TRUE;
1309 case CDF_INT4:
1310 sprintf (Cformat, "%%%d%so", w, Int32FORMATmod);
1311 *CdataType = CDF_UINT4;
1312 return TRUE;
1313 case CDF_UINT4:
1314 sprintf (Cformat, "%%%d%so", w, Int32FORMATmod);
1315 *CdataType = CDF_UINT4;
1316 return TRUE;
1317 case CDF_REAL4:
1318 case CDF_FLOAT:
1319 case CDF_REAL8:
1320 case CDF_DOUBLE:
1321 sprintf (Cformat, "%%%d%so", w, Int32FORMATmod);
1322 *CdataType = CDF_UINT4;
1323 return TRUE;
1324 }
1325 return FALSE;
1326 case 2:
1327 switch (dataType) {
1328 case CDF_BYTE:
1329 case CDF_INT1:
1330 sprintf (Cformat, "%%%d.%do", w, m);
1331 *CdataType = CDF_UINT1;
1332 return TRUE;
1333 case CDF_UINT1:
1334 sprintf (Cformat, "%%%d.%do", w, m);
1335 *CdataType = CDF_UINT1;
1336 return TRUE;
1337 case CDF_INT2:
1338 sprintf (Cformat, "%%%d.%do", w, m);
1339 *CdataType = CDF_UINT2;
1340 return TRUE;
1341 case CDF_UINT2:
1342 sprintf (Cformat, "%%%d.%do", w, m);
1343 *CdataType = CDF_UINT2;
1344 return TRUE;
1345 case CDF_INT4:
1346 sprintf (Cformat, "%%%d.%d%so", w, m, Int32FORMATmod);
1347 *CdataType = CDF_UINT4;
1348 return TRUE;
1349 case CDF_UINT4:
1350 sprintf (Cformat, "%%%d.%d%so", w, m, Int32FORMATmod);
1351 *CdataType = CDF_UINT4;
1352 return TRUE;
1353 case CDF_REAL4:
1354 case CDF_FLOAT:
1355 case CDF_REAL8:
1356 case CDF_DOUBLE:
1357 sprintf (Cformat, "%%%d.%d%so", w, m, Int32FORMATmod);
1358 *CdataType = CDF_UINT4;
1359 return TRUE;
1360 }
1361 return FALSE;
1362 }
1363 return FALSE;
1364 /**************************************************************************
1365 * Integer/hexadecimal.
1366 **************************************************************************/
1367 case 'Z':
1368 case 'z':
1369 nFound = sscanf (&Fformat[1], "%d.%d", &w, &m);
1370 switch (nFound) {
1371 case 0:
1372 return FALSE;
1373 case 1:
1374 switch (dataType) {
1375 case CDF_BYTE:
1376 case CDF_INT1:
1377 sprintf (Cformat, "%%%dX", w);
1378 *CdataType = CDF_UINT1;
1379 return TRUE;
1380 case CDF_UINT1:
1381 sprintf (Cformat, "%%%dX", w);
1382 *CdataType = CDF_UINT1;
1383 return TRUE;
1384 case CDF_INT2:
1385 sprintf (Cformat, "%%%dX", w);
1386 *CdataType = CDF_UINT2;
1387 return TRUE;
1388 case CDF_UINT2:
1389 sprintf (Cformat, "%%%dX", w);
1390 *CdataType = CDF_UINT2;
1391 return TRUE;
1392 case CDF_INT4:
1393 sprintf (Cformat, "%%%d%sX", w, Int32FORMATmod);
1394 *CdataType = CDF_UINT4;
1395 return TRUE;
1396 case CDF_UINT4:
1397 sprintf (Cformat, "%%%d%sX", w, Int32FORMATmod);
1398 *CdataType = CDF_UINT4;
1399 return TRUE;
1400 case CDF_REAL4:
1401 case CDF_FLOAT:
1402 case CDF_REAL8:
1403 case CDF_DOUBLE:
1404 sprintf (Cformat, "%%%d%sX", w, Int32FORMATmod);
1405 *CdataType = CDF_UINT4;
1406 return TRUE;
1407 }
1408 return FALSE;
1409 case 2:
1410 switch (dataType) {
1411 case CDF_BYTE:
1412 case CDF_INT1:
1413 sprintf (Cformat, "%%%d.%dX", w, m);
1414 *CdataType = CDF_UINT1;
1415 return TRUE;
1416 case CDF_UINT1:
1417 sprintf (Cformat, "%%%d.%dX", w, m);
1418 *CdataType = CDF_UINT1;
1419 return TRUE;
1420 case CDF_INT2:
1421 sprintf (Cformat, "%%%d.%dX", w, m);
1422 *CdataType = CDF_UINT2;
1423 return TRUE;
1424 case CDF_UINT2:
1425 sprintf (Cformat, "%%%d.%dX", w, m);
1426 *CdataType = CDF_UINT2;
1427 return TRUE;
1428 case CDF_INT4:
1429 sprintf (Cformat, "%%%d.%d%sX", w, m, Int32FORMATmod);
1430 *CdataType = CDF_UINT4;
1431 return TRUE;
1432 case CDF_UINT4:
1433 sprintf (Cformat, "%%%d.%d%sX", w, m, Int32FORMATmod);
1434 *CdataType = CDF_UINT4;
1435 return TRUE;
1436 case CDF_REAL4:
1437 case CDF_FLOAT:
1438 case CDF_REAL8:
1439 case CDF_DOUBLE:
1440 sprintf (Cformat, "%%%d.%d%sX", w, m, Int32FORMATmod);
1441 *CdataType = CDF_UINT4;
1442 return TRUE;
1443 }
1444 return FALSE;
1445 }
1446 return FALSE;
1447 /**************************************************************************
1448 * Floating-point/non-scientific notation (which is called...
1449 **************************************************************************/
1450 case 'F':
1451 case 'f':
1452 nFound = sscanf (&Fformat[1], "%d.%d", &w, &d);
1453 switch (nFound) {
1454 case 2:
1455 sprintf (Cformat, "%%%d.%df", w, d);
1456 *CdataType = CDF_DOUBLE;
1457 return TRUE;
1458 }
1459 return FALSE;
1460 /**************************************************************************
1461 * Floating-point/scientific notation.
1462 **************************************************************************/
1463 case 'E':
1464 case 'e':
1465 case 'D':
1466 case 'd':
1467 nFound = sscanf (&Fformat[1], "%d.%d", &w, &d);
1468 switch (nFound) {
1469 case 2:
1470 sprintf (Cformat, "%%%d.%de", w, d);
1471 *CdataType = CDF_DOUBLE;
1472 return TRUE;
1473 }
1474 return FALSE;
1475 /**************************************************************************
1476 * Floating-point/notation depends on value.
1477 **************************************************************************/
1478 case 'G':
1479 case 'g':
1480 nFound = sscanf (&Fformat[1], "%d.%d", &w, &d);
1481 switch (nFound) {
1482 case 2:
1483 sprintf (Cformat, "%%%d.%dg", w, d);
1484 *CdataType = CDF_DOUBLE;
1485 return TRUE;
1486 }
1487 return FALSE;
1488 /**************************************************************************
1489 * Character.
1490 **************************************************************************/
1491 case 'A':
1492 case 'a':
1493 nFound = sscanf (&Fformat[1], "%d", &w);
1494 switch (nFound) {
1495 case 1:
1496 sprintf (Cformat, "%%%d.%ds", w, w);
1497 *CdataType = CDF_CHAR;
1498 return TRUE;
1499 }
1500 return FALSE;
1501 }
1502 return FALSE; /* Unknown FORTRAN format character. */
1503 }
1504
1505 /******************************************************************************
1506 * GetCdataType.
1507 * Given a C format specification, returns the corresponding C data type.
1508 ******************************************************************************/
1509
GetCdataType(Cformat,CdataType)1510 static long GetCdataType (Cformat, CdataType)
1511 char *Cformat; /* C format specification. */
1512 long *CdataType; /* Corresponding C data type. */
1513 {
1514 char *ptrB; /* Beginning of specification. */
1515 char *ptrE; /* End of specification. */
1516 /****************************************************************************
1517 * Find beginning of specification.
1518 ****************************************************************************/
1519 ptrB = Cformat;
1520 while (*ptrB != NUL && Spacing(*ptrB)) ptrB++;
1521 if (*ptrB != '%') return FALSE;
1522 /****************************************************************************
1523 * Find end of specification.
1524 ****************************************************************************/
1525 ptrE = Cformat + strlen(Cformat) - 1;
1526 while (ptrE != ptrB && Spacing(*ptrE)) ptrE--;
1527 if (ptrE == ptrB) return FALSE;
1528 /****************************************************************************
1529 * Choose a data type based on the conversion character and possible modifier.
1530 ****************************************************************************/
1531 switch (*ptrE) {
1532 case 'd':
1533 case 'i':
1534 switch (*(ptrE-1)) {
1535 case 'l':
1536 *CdataType = CDF_INT4;
1537 break;
1538 case 'h':
1539 *CdataType = CDF_INT2;
1540 break;
1541 default:
1542 #if defined(dos)
1543 *CdataType = CDF_INT2;
1544 #else
1545 *CdataType = CDF_INT4;
1546 #endif
1547 break;
1548 }
1549 break;
1550 case 'x':
1551 case 'X':
1552 case 'o':
1553 case 'u':
1554 switch (*(ptrE-1)) {
1555 case 'l':
1556 *CdataType = CDF_UINT4;
1557 break;
1558 case 'h':
1559 *CdataType = CDF_UINT2;
1560 break;
1561 default:
1562 #if defined(dos)
1563 *CdataType = CDF_UINT2;
1564 #else
1565 *CdataType = CDF_UINT4;
1566 #endif
1567 break;
1568 }
1569 break;
1570 case 'c':
1571 case 's':
1572 *CdataType = CDF_CHAR;
1573 break;
1574 case 'f':
1575 case 'e':
1576 case 'E':
1577 case 'g':
1578 case 'G':
1579 *CdataType = CDF_DOUBLE;
1580 break;
1581 default:
1582 return FALSE; /* Unknown C format description. */
1583 }
1584 return TRUE;
1585 }
1586
1587 /******************************************************************************
1588 * EncodeDimensionality. Returns width of encoded dimensionality
1589 ******************************************************************************/
1590
EncodeDimensionality(string,numDims,dimSizes)1591 int EncodeDimensionality (string, numDims, dimSizes)
1592 char *string;
1593 long numDims;
1594 long *dimSizes;
1595 {
1596 int dimN;
1597 sprintf (string, "%ld:[", numDims);
1598 for (dimN = 0; dimN < numDims; dimN++)
1599 sprintf (&(string[strlen(string)]), "%s%ld", (dimN > 0 ? "," : ""),
1600 dimSizes[dimN]);
1601 strcatX (string, "]", 0);
1602 return strlen(string);
1603 }
1604
1605 /******************************************************************************
1606 * EncodeVariances. Returns width of encoded variances.
1607 ******************************************************************************/
1608
EncodeVariances(string,recVary,numDims,dimVarys)1609 int EncodeVariances (string, recVary, numDims, dimVarys)
1610 char *string;
1611 long recVary;
1612 long numDims;
1613 long *dimVarys;
1614 {
1615 int dimN;
1616 strcpyX (string, TFvarianceToken(recVary), 0);
1617 strcatX (string, "/", 0);
1618 for (dimN = 0; dimN < numDims; dimN++)
1619 strcatX (string, TFvarianceToken(dimVarys[dimN]), 0);
1620 return strlen(string);
1621 }
1622
1623 /******************************************************************************
1624 * EncodeRecordIndices.
1625 * Uses `*' for record/dimension variances of NOVARY. Returns width of
1626 * record/indices.
1627 ******************************************************************************/
1628
EncodeRecordIndices(string,recNum,recVary,numDims,indices,dimVarys)1629 int EncodeRecordIndices (string, recNum, recVary, numDims, indices, dimVarys)
1630 char *string;
1631 long recNum;
1632 long recVary;
1633 long numDims;
1634 long indices[];
1635 long dimVarys[];
1636 {
1637 int dimN;
1638 if (recVary)
1639 sprintf (string, "%ld", recNum + 1);
1640 else
1641 strcpyX (string, "*", 0);
1642 strcatX (string, ":[", 0);
1643 for (dimN = 0; dimN < numDims; dimN++) {
1644 if (dimN != 0) strcatX (string, ",", 0);
1645 if (dimVarys[dimN])
1646 sprintf (&string[strlen(string)], "%ld", indices[dimN] + 1);
1647 else
1648 strcatX (string, "*", 0);
1649 }
1650 strcatX (string, "]", 0);
1651 return strlen(string);
1652 }
1653
1654 /******************************************************************************
1655 * EncodeRecordIndicesVARY. Force record/dimension variances to VARY.
1656 ******************************************************************************/
1657
EncodeRecordIndicesVARY(string,recNum,numDims,indices)1658 int EncodeRecordIndicesVARY (string, recNum, numDims, indices)
1659 char *string;
1660 long recNum;
1661 long numDims;
1662 long indices[];
1663 {
1664 static long recVary = VARY;
1665 static long dimVarys[CDF_MAX_DIMS] = { VARY, VARY, VARY, VARY, VARY,
1666 VARY, VARY, VARY, VARY, VARY };
1667 EncodeRecordIndices (string, recNum, recVary, numDims, indices, dimVarys);
1668 return strlen(string);
1669 }
1670
1671 /*****************************************************************************
1672 * OnlineHelpFP.
1673 *
1674 * UNIX: The full pathname of the executable is not passed in via `argv[0]'.
1675 * The command which was entered on the command line is passed in (aliases
1676 * are, however, evaluated).
1677 *
1678 ******************************************************************************/
1679
OnlineHelpFP(filename,execpath)1680 FILE *OnlineHelpFP (filename, execpath)
1681 char *filename; /* Name of help file. */
1682 char *execpath; /* Pathname of executable (argv[0]). */
1683 {
1684 FILE *fp;
1685 char pathname[DU_MAX_PATH_LEN+1];
1686 #if !defined(mac)
1687 char execname[DU_MAX_NAME_LEN+1];
1688 char *envPtr;
1689 #endif
1690 #if defined(mac)
1691 execpath; /* Quites the MPW C compiler. */
1692 #endif
1693 /****************************************************************************
1694 * Try to use logical name (VMS) or environment variable (UNIX/POSIXshell,
1695 * DOS, & Windows).
1696 ****************************************************************************/
1697 #if defined(vms)
1698 strcpyX (pathname, "CDF$HELP:", DU_MAX_PATH_LEN);
1699 AppendToDir (pathname, filename);
1700 fp = fopen (pathname, "r");
1701 if (fp != NULL) return fp;
1702 #endif
1703 #if (defined(unix) && !defined(__MINGW32__)) || defined(dos) || \
1704 defined(posixSHELL) || defined(win32)
1705 envPtr = getenv ("CDF_HELP");
1706 if (envPtr != NULL) {
1707 strcpyX (pathname, envPtr, DU_MAX_PATH_LEN);
1708 AppendToDir (pathname, filename);
1709 #if defined(__CYGWIN__) || defined(__MINGW32__)
1710 fp = fopen (pathname, "rt");
1711 #else
1712 fp = fopen (pathname, "r");
1713 #endif
1714 if (fp != NULL) return fp;
1715 }
1716 #endif
1717 /***************************************************************************
1718 * If not on a Macintosh...
1719 * Try relative paths from location of executable in the following order...
1720 * 1. From standard executable/binary directory.
1721 * 2. From source directory.
1722 * 3. Same directory as that containing the executable.
1723 ***************************************************************************/
1724 #if !defined(mac)
1725 if (execpath != NULL) {
1726 if (execpath[0] != NUL) {
1727 ParsePath (execpath, pathname, execname);
1728 #if defined(vms)
1729 pathname[strlen(pathname)-1] = NUL; /* Wipes out trailing `]'. */
1730 strcatX (pathname, "-.HELP]", DU_MAX_PATH_LEN);
1731 #endif
1732 #if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \
1733 defined(posixSHELL)
1734 AppendToDir (pathname, "../lib/cdf/help");
1735 #endif
1736 #if defined(dos) || defined(win32) || defined(__CYGWIN__) || \
1737 defined(__MINGW32__)
1738 AppendToDir (pathname, "..\\help");
1739 #endif
1740 AppendToDir (pathname, filename);
1741 #if defined(__CYGWIN__) || defined(__MINGW32__)
1742 fp = fopen (pathname, "rt");
1743 #else
1744 fp = fopen (pathname, "r");
1745 #endif
1746 if (fp != NULL) return fp;
1747 ParsePath (execpath, pathname, execname);
1748 #if defined(vms)
1749 pathname[strlen(pathname)-1] = NUL; /* Wipes out trailing `]'. */
1750 strcatX (pathname, "-.-.HELP]", DU_MAX_PATH_LEN);
1751 #endif
1752 #if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \
1753 defined(posixSHELL)
1754 AppendToDir (pathname, "../help");
1755 #endif
1756 #if defined(dos) || defined(win32) || defined(__CYGWIN__) || \
1757 defined(__MINGW32__)
1758 AppendToDir (pathname, "..\\..\\help");
1759 #endif
1760 AppendToDir (pathname, filename);
1761 #if defined(__CYGWIN__) || defined(__MINGW32__)
1762 fp = fopen (pathname, "rt");
1763 #else
1764 fp = fopen (pathname, "r");
1765 #endif
1766 if (fp != NULL) return fp;
1767 ParsePath (execpath, pathname, execname);
1768 AppendToDir (pathname, filename);
1769 fp = fopen (pathname, "r");
1770 if (fp != NULL) return fp;
1771 }
1772 }
1773 #endif
1774 /***************************************************************************
1775 * If on a Macintosh...try relative (partial) paths to the `help' file.
1776 ***************************************************************************/
1777 #if defined(mac)
1778 strcpyX (pathname, "::help", DU_MAX_PATH_LEN);
1779 AppendToDir (pathname, filename);
1780 fp = fopen (pathname, "r");
1781 if (fp != NULL) return fp;
1782 strcpyX (pathname, ":::help", DU_MAX_PATH_LEN);
1783 AppendToDir (pathname, filename);
1784 fp = fopen (pathname, "r");
1785 if (fp != NULL) return fp;
1786 #endif
1787 /***************************************************************************
1788 * If on a UNIX/POSIXshell or DOS/Windows system, assume that the `bin'
1789 * directory has been added to the `path' and try a relative path from each
1790 * `path' entry.
1791 ***************************************************************************/
1792 #if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL) || \
1793 defined(dos) || defined(win32)
1794 #if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL)
1795 #define SEP_CHAR ':'
1796 #else
1797 #define SEP_CHAR ';'
1798 #endif
1799 envPtr = getenv ("PATH");
1800 if (envPtr != NULL) {
1801 char *path = (char *) cdf_AllocateMemory (strlen(envPtr) + 1, FatalError);
1802 char *p1 = path;
1803 strcpyX (path, envPtr, 0);
1804 for (;;) {
1805 char *sepPtr = strchr (p1, SEP_CHAR);
1806 if (sepPtr != NULL) *sepPtr = NUL;
1807 strcpyX (pathname, p1, DU_MAX_PATH_LEN);
1808 #if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \
1809 defined(posixSHELL)
1810 AppendToDir (pathname, "../lib/cdf/help");
1811 #else
1812 AppendToDir (pathname, "..\\help");
1813 #endif
1814 AppendToDir (pathname, filename);
1815 #if defined(__CYGWIN__) || defined(__MINGW32__)
1816 fp = fopen (pathname, "rt");
1817 #else
1818 fp = fopen (pathname, "r");
1819 #endif
1820 if (fp != NULL) {
1821 cdf_FreeMemory (path, FatalError);
1822 return fp;
1823 }
1824 if (sepPtr == NULL) break;
1825 p1 = sepPtr + 1;
1826 }
1827 cdf_FreeMemory (path, FatalError);
1828 }
1829 #endif
1830 /***************************************************************************
1831 * Try pathes from the current directory.
1832 ***************************************************************************/
1833 #if defined(vms)
1834 strcpyX (pathname, "[-.HELP]", DU_MAX_PATH_LEN);
1835 #endif
1836 #if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \
1837 defined(posixSHELL)
1838 strcpyX (pathname, "../help", DU_MAX_PATH_LEN);
1839 #endif
1840 #if defined(dos) || defined(win32) || defined(__CYGWIN__) || \
1841 defined(__MINGW32__)
1842 strcpyX (pathname, "..\\help", DU_MAX_PATH_LEN);
1843 #endif
1844 AppendToDir (pathname, filename);
1845 #if defined(__CYGWIN__) || defined(__MINGW32__)
1846 fp = fopen (pathname, "rt");
1847 #else
1848 fp = fopen (pathname, "r");
1849 #endif
1850 if (fp != NULL) return fp;
1851 #if defined(vms)
1852 strcpyX (pathname, "[-.-.HELP]", DU_MAX_PATH_LEN);
1853 #endif
1854 #if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \
1855 defined(posixSHELL)
1856 strcpyX (pathname, "../../help", DU_MAX_PATH_LEN);
1857 #endif
1858 #if defined(dos) || defined(win32) || defined(__CYGWIN__) || \
1859 defined(__MINGW32__)
1860 strcpyX (pathname, "..\\..\\help", DU_MAX_PATH_LEN);
1861 #endif
1862 AppendToDir (pathname, filename);
1863 #if defined(__CYGWIN__) || defined(__MINGW32__)
1864 fp = fopen (pathname, "rt");
1865 #else
1866 fp = fopen (pathname, "r");
1867 #endif
1868 if (fp != NULL) return fp;
1869 #if defined(vms)
1870 strcpyX (pathname, "[-.-.-.HELP]", DU_MAX_PATH_LEN);
1871 #endif
1872 #if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \
1873 defined(posixSHELL)
1874 strcpyX (pathname, "../../../help", DU_MAX_PATH_LEN);
1875 #endif
1876 #if defined(dos) || defined(win32) || defined(__CYGWIN__) || \
1877 defined(__MINGW32__)
1878 strcpyX (pathname, "..\\..\\..\\help", DU_MAX_PATH_LEN);
1879 #endif
1880 AppendToDir (pathname, filename);
1881 #if defined(__CYGWIN__) || defined(__MINGW32__)
1882 fp = fopen (pathname, "rt");
1883 #else
1884 fp = fopen (pathname, "r");
1885 #endif
1886 if (fp != NULL) return fp;
1887 #if defined(win32) || defined(__CYGWIN__) || defined(__MINGW32__)
1888 strcpyX (pathname, "help", DU_MAX_PATH_LEN);
1889 #endif
1890 AppendToDir (pathname, filename);
1891 #if defined(__CYGWIN__) || defined(__MINGW32__)
1892 fp = fopen (pathname, "rt");
1893 #else
1894 fp = fopen (pathname, "r");
1895 #endif
1896 if (fp != NULL) return fp;
1897 /***************************************************************************
1898 * Try current directory.
1899 ***************************************************************************/
1900 #if defined(__CYGWIN__) || defined(__MINGW32__)
1901 fp = fopen (pathname, "rt");
1902 #else
1903 fp = fopen (pathname, "r");
1904 #endif
1905 if (fp != NULL) return fp;
1906 /***************************************************************************
1907 * Give up.
1908 ***************************************************************************/
1909 return NULL;
1910 }
1911
1912 /*****************************************************************************
1913 * PageOLH.
1914 *****************************************************************************/
1915
PageOLH(olhFile,argv0)1916 void PageOLH (olhFile, argv0)
1917 char *olhFile;
1918 char *argv0;
1919 {
1920 FILE *fp;
1921 char line[MAX_SCREENLINE_LEN+1+1];
1922 int nestLevel = 0; /* Depth into `#ifos's. */
1923 int osMask = 0; /* When 0, display line. Note that bit
1924 0 is not used (eg. nesting depth of
1925 1 uses bit 1, etc.). */
1926 #if defined(vms)
1927 static char thisOS[] = "vms";
1928 #endif
1929 #if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \
1930 defined(posixSHELL)
1931 static char thisOS[] = "unix";
1932 #endif
1933 #if defined(dos) || defined(__CYGWIN__) || defined(__MINGW32__) || \
1934 (defined(win32) && defined(ALONE))
1935 static char thisOS[] = "dos";
1936 #endif
1937 #if defined(mac)
1938 static char thisOS[] = "mac";
1939 #endif
1940 #if defined(win32) && !defined(ALONE)
1941 static char thisOS[] = "win";
1942 #endif
1943 static char *openErrorMsg = {
1944 "Error opening online help file - contact CDFsupport.\n"
1945 };
1946 static char *syntaxErrorMsg = {
1947 "Syntax error in online help file - contact CDFsupport.\n"
1948 };
1949 /****************************************************************************
1950 * Open online help file.
1951 ****************************************************************************/
1952 fp = OnlineHelpFP (olhFile, argv0);
1953 if (fp == NULL) {
1954 WriteOut (stdout, openErrorMsg);
1955 return;
1956 }
1957 /****************************************************************************
1958 * Read online help file - passing appropriate lines through for display.
1959 ****************************************************************************/
1960 while (fgets(line,MAX_SCREENLINE_LEN+1+1,fp) != NULL) {
1961 /**************************************************************************
1962 * Check if an operating system directive. If not, display the line if
1963 * all of the bits in the operating system mask are clear.
1964 **************************************************************************/
1965 if (line[0] == '#') {
1966 line[strlen(line)-1] = NUL;
1967 /************************************************************************
1968 * Check for a `#ifos' directive. If this operating system is not
1969 * specified, then set the bit in the operating system mask for this
1970 * nesting level.
1971 ************************************************************************/
1972 if (!strncmp(line,"#ifos",5)) {
1973 nestLevel++;
1974 if (strstr(line,thisOS) == NULL) SETBIT (osMask, nestLevel);
1975 continue;
1976 }
1977 /************************************************************************
1978 * Check for a `#else' directive. Simply flip the bit in the operating
1979 * system mask for this nesting level.
1980 ************************************************************************/
1981 if (!strcmp(line,"#else")) {
1982 if (nestLevel < 1) {
1983 WriteOut (stdout, syntaxErrorMsg);
1984 break;
1985 }
1986 FLPBIT (osMask, nestLevel);
1987 continue;
1988 }
1989 /************************************************************************
1990 * Check for a `#endos' directive. Clear the bit in the operating system
1991 * mask for this nesting level and decrement the nesting level.
1992 ************************************************************************/
1993 if (!strcmp(line,"#endos")) {
1994 if (nestLevel < 1) {
1995 WriteOut (stdout, syntaxErrorMsg);
1996 break;
1997 }
1998 CLRBIT (osMask, nestLevel);
1999 nestLevel--;
2000 continue;
2001 }
2002 /************************************************************************
2003 * An unknown directive has been encountered - assume it to be a comment.
2004 ************************************************************************/
2005 continue;
2006 }
2007 else {
2008 if (osMask == 0) WriteOut (stdout, line);
2009 }
2010 }
2011 if (nestLevel != 0) WriteOut (stdout, syntaxErrorMsg);
2012 fclose (fp);
2013 return;
2014 }
2015
2016 /******************************************************************************
2017 * OutputWithMargin.
2018 * Outputs a long text string to multiple lines of a file (or stdout)
2019 * breaking the lines at blanks if possible.
2020 ******************************************************************************/
2021
OutputWithMargin(fp,text,maxLen,marginLen)2022 void OutputWithMargin (fp, text, maxLen, marginLen)
2023 FILE *fp;
2024 char *text;
2025 int maxLen; /* Maximum length of line (including margin). */
2026 int marginLen; /* Length of margin preceeding text on each line. */
2027 {
2028 char *ptr = text, *ptrT;
2029 int maxLenT = maxLen - marginLen; /* Maximum number of characters per
2030 line (excluding the margin). */
2031 for (;;) {
2032 /*************************************************************************
2033 * If the remaining characters will fit on a line, print them and return.
2034 * This also covers the case where the entire text will fit on one line.
2035 *************************************************************************/
2036 if (strlen(ptr) <= (size_t) maxLenT) {
2037 if (marginLen > 0) Ncharacters (fp, marginLen, (int) ' ');
2038 WriteOut (fp, ptr);
2039 WriteOut (fp, "\n");
2040 return;
2041 }
2042 /*************************************************************************
2043 * Otherwise, find a blank character at which to break the characters. The
2044 * blank is not printed on either line.
2045 *************************************************************************/
2046 for (ptrT = ptr + maxLenT; ptrT != ptr; ptrT--) {
2047 if (*ptrT == ' ') {
2048 char *string = NULedString (ptr, (int) (ptrT - ptr));
2049 if (marginLen > 0) Ncharacters (fp, marginLen, (int) ' ');
2050 WriteOut (fp, string);
2051 WriteOut (fp, "\n");
2052 ptr = ptrT + 1;
2053 cdf_FreeMemory (string, FatalError);
2054 break;
2055 }
2056 }
2057 /*************************************************************************
2058 * If a blank could not be found, break the characters at the end of the
2059 * maximum number per line.
2060 *************************************************************************/
2061 if (ptrT == ptr) {
2062 char *string = NULedString (ptr, maxLenT);
2063 if (marginLen > 0) Ncharacters (fp, marginLen, (int) ' ');
2064 WriteOut (fp, string);
2065 WriteOut (fp, "\n");
2066 ptr += maxLenT;
2067 cdf_FreeMemory (string, FatalError);
2068 }
2069 }
2070 }
2071
2072 /******************************************************************************
2073 * InitPctLog.
2074 ******************************************************************************/
2075
InitPctLog(lastPct,pctOn)2076 void InitPctLog (lastPct, pctOn)
2077 int *lastPct;
2078 Logical *pctOn;
2079 {
2080 WriteOut (stdout, "..0%");
2081 *lastPct = 0;
2082 *pctOn = TRUE;
2083 return;
2084 }
2085
2086 /******************************************************************************
2087 * UpdatePctLog.
2088 ******************************************************************************/
2089
UpdatePctLog(pct,lastPct)2090 void UpdatePctLog (pct, lastPct)
2091 int pct;
2092 int *lastPct;
2093 {
2094 if (pct != *lastPct) {
2095 char string[10+1];
2096 sprintf (string, "\b\b\b\b%s%d%%",
2097 (pct < 10 ? ".." : (pct < 100 ? "." : "")), pct);
2098 WriteOut (stdout, string);
2099 *lastPct = pct;
2100 }
2101 return;
2102 }
2103
2104 /******************************************************************************
2105 * RefreshPctLog.
2106 ******************************************************************************/
2107
RefreshPctLog(lastPct)2108 void RefreshPctLog (lastPct)
2109 int lastPct;
2110 {
2111 char string[6+1];
2112 sprintf (string, "%s%d%%",
2113 (lastPct < 10 ? ".." : (lastPct < 100 ? "." : "")), lastPct);
2114 WriteOut (stdout, string);
2115 return;
2116 }
2117
2118 /******************************************************************************
2119 * CleanupPctLog.
2120 * 100% is output in case there were no values (in which case 0% would be
2121 * currently displayed).
2122 ******************************************************************************/
2123
CleanupPctLog(pctOn)2124 void CleanupPctLog (pctOn)
2125 Logical *pctOn;
2126 {
2127 WriteOut (stdout, "\b\b\b\b100%\n");
2128 *pctOn = FALSE;
2129 return;
2130 }
2131
2132 /******************************************************************************
2133 * Ncharacters.
2134 * Outputs a specified number of a selected character to a file pointer.
2135 ******************************************************************************/
2136
Ncharacters(fp,nChars,chr)2137 void Ncharacters (fp, nChars, chr)
2138 FILE *fp;
2139 int nChars;
2140 int chr;
2141 {
2142 int i; char string[1+1];
2143 string[0] = (char) chr;
2144 string[1] = NUL;
2145 for (i = 0; i < nChars; i++) WriteOut (fp, string);
2146 return;
2147 }
2148
2149 /******************************************************************************
2150 * CatNcharacters.
2151 * Concatenates some number of a specified character to a string.
2152 ******************************************************************************/
2153
CatNcharacters(string,nChars,chr)2154 void CatNcharacters (string, nChars, chr)
2155 char *string;
2156 int nChars;
2157 int chr;
2158 {
2159 int i;
2160 for (i = 0; i < nChars; i++) catchrX (string, chr, 0);
2161 return;
2162 }
2163
2164 /******************************************************************************
2165 * CpyNcharacters.
2166 * Copies some number of a specified character to a string.
2167 ******************************************************************************/
2168
CpyNcharacters(string,nChars,chr)2169 void CpyNcharacters (string, nChars, chr)
2170 char *string;
2171 int nChars;
2172 int chr;
2173 {
2174 int i;
2175 for (i = 0; i < nChars; i++) string[i] = (char) chr;
2176 string[nChars] = NUL;
2177 return;
2178 }
2179
2180 /******************************************************************************
2181 * TFqualifier.
2182 ******************************************************************************/
2183
TFqualifier(qop,variable,Tx,Fx,defaultTF,conflictText)2184 Logical TFqualifier (qop, variable, Tx, Fx, defaultTF, conflictText)
2185 QOP *qop;
2186 Logical *variable;
2187 int Tx;
2188 int Fx;
2189 Logical defaultTF;
2190 char *conflictText;
2191 {
2192 int count = 0;
2193 if (qop->qualEntered[Tx]) count++;
2194 if (qop->qualEntered[Fx]) count++;
2195 switch (count) {
2196 case 0:
2197 *variable = defaultTF;
2198 return TRUE;
2199 case 1:
2200 *variable = (qop->qualEntered[Tx] ? TRUE : FALSE);
2201 return TRUE;
2202 default: {
2203 char tempS[MAX_MESSAGE_TEXT_LEN+1];
2204 sprintf (tempS, "Conflicting qualifiers (%s & no%s).",
2205 conflictText, conflictText);
2206 DisplayError (tempS);
2207 return FALSE;
2208 }
2209 }
2210 }
2211
2212 /******************************************************************************
2213 * S2qualifierLong.
2214 ******************************************************************************/
2215
S2qualifierLong(qop,variable,S1x,S1,S2x,S2,defaultS,conflictText)2216 Logical S2qualifierLong (qop, variable, S1x, S1, S2x, S2, defaultS,
2217 conflictText)
2218 QOP *qop;
2219 long *variable;
2220 int S1x;
2221 long S1;
2222 int S2x;
2223 long S2;
2224 long defaultS;
2225 char *conflictText;
2226 {
2227 int count = 0;
2228 if (qop->qualEntered[S1x]) count++;
2229 if (qop->qualEntered[S2x]) count++;
2230 switch (count) {
2231 case 0:
2232 *variable = defaultS;
2233 return TRUE;
2234 case 1:
2235 *variable = (qop->qualEntered[S1x] ? S1 : S2);
2236 return TRUE;
2237 default: {
2238 char tempS[MAX_MESSAGE_TEXT_LEN+1];
2239 sprintf (tempS, "Conflicting qualifiers (%s).", conflictText);
2240 DisplayError (tempS);
2241 return FALSE;
2242 }
2243 }
2244 }
2245
2246 /******************************************************************************
2247 * S3qualifierLong.
2248 ******************************************************************************/
2249
S3qualifierLong(qop,variable,S1x,S1,S2x,S2,S3x,S3,defaultS,conflictText)2250 Logical S3qualifierLong (qop, variable, S1x, S1, S2x, S2, S3x, S3, defaultS,
2251 conflictText)
2252 QOP *qop;
2253 long *variable;
2254 int S1x;
2255 long S1;
2256 int S2x;
2257 long S2;
2258 int S3x;
2259 long S3;
2260 long defaultS;
2261 char *conflictText;
2262 {
2263 int count = 0;
2264 if (qop->qualEntered[S1x]) count++;
2265 if (qop->qualEntered[S2x]) count++;
2266 if (qop->qualEntered[S3x]) count++;
2267 switch (count) {
2268 case 0:
2269 *variable = defaultS;
2270 return TRUE;
2271 case 1:
2272 *variable = BOO(qop->qualEntered[S1x],S1,
2273 BOO(qop->qualEntered[S2x],S2,S3));
2274 return TRUE;
2275 default: {
2276 char tempS[MAX_MESSAGE_TEXT_LEN+1];
2277 sprintf (tempS, "Conflicting qualifiers (%s).", conflictText);
2278 DisplayError (tempS);
2279 return FALSE;
2280 }
2281 }
2282 }
2283
2284 /******************************************************************************
2285 * BlankPadRight.
2286 * Concatenate blanks to the right end of a string.
2287 ******************************************************************************/
2288
BlankPadRight(string,count)2289 void BlankPadRight (string, count)
2290 char *string;
2291 int count;
2292 {
2293 int i;
2294 for (i = 0; i < count; i++) catchrX (string, (int) ' ', 0);
2295 return;
2296 }
2297
2298 /******************************************************************************
2299 * GetFormatEntry.
2300 * It is assumed that the current CDF has been selected.
2301 ******************************************************************************/
2302
GetFormatEntry(Z,varNum,format)2303 CDFstatus GetFormatEntry (Z, varNum, format)
2304 Logical Z;
2305 long varNum;
2306 char **format;
2307 {
2308 CDFstatus pStatus = CDF_OK, status; long dataType, numElems;
2309 status = CDFlib (SELECT_, ATTR_NAME_, "FORMAT",
2310 BOO(Z,zENTRY_,rENTRY_), varNum,
2311 GET_, BOO(Z,zENTRY_DATATYPE_,rENTRY_DATATYPE_), &dataType,
2312 BOO(Z,zENTRY_NUMELEMS_,rENTRY_NUMELEMS_), &numElems,
2313 NULL_);
2314 switch (status) {
2315 case NO_SUCH_ATTR:
2316 case NO_SUCH_ENTRY:
2317 *format = NULL;
2318 return pStatus;
2319 default:
2320 if (!sX(status,&pStatus)) {
2321 *format = NULL;
2322 return pStatus;
2323 }
2324 }
2325 if (!STRINGdataType(dataType)) {
2326 *format = NULL;
2327 return pStatus;
2328 }
2329 *format = (char *) cdf_AllocateMemory ((size_t) (numElems + 1),
2330 FatalError);
2331 status = CDFlib (GET_, BOO(Z,zENTRY_DATA_,rENTRY_DATA_), *format,
2332 NULL_);
2333 if (!sX(status,&pStatus)) {
2334 cdf_FreeMemory (*format, FatalError);
2335 *format = NULL;
2336 return pStatus;
2337 }
2338 (*format)[(int)numElems] = NUL;
2339 return pStatus;
2340 }
2341
2342 /******************************************************************************
2343 * ParseOptionList.
2344 ******************************************************************************/
2345
ParseOptionList(nTokens,tokens,list,present)2346 Logical ParseOptionList (nTokens, tokens, list, present)
2347 int nTokens;
2348 char *tokens[];
2349 char *list;
2350 Logical present[];
2351 {
2352 int tokenN, matchN; size_t tokenLen;
2353 char token[MAX_TOKEN_LEN+1], *ptr1, *ptr2, terminator;
2354 /****************************************************************************
2355 * Assume initially that none of the tokens were found.
2356 ****************************************************************************/
2357 for (tokenN = 0; tokenN < nTokens; tokenN++) present[tokenN] = FALSE;
2358 /****************************************************************************
2359 * Check that the entered list of tokens is not a NUL string, that there are
2360 * some possible tokens to match, etc.
2361 ****************************************************************************/
2362 if (NULstring(list)) return TRUE; /* Obviously, no tokens were found. */
2363 if (nTokens < 1) return FALSE; /* Probably a logic error. */
2364 /****************************************************************************
2365 * Scan the entered list of tokens searching for matches with the list of
2366 * possible tokens. First determine the starting character position and the
2367 * ending delimiter.
2368 ****************************************************************************/
2369 switch (list[0]) {
2370 case '(': /* VMS-style. */
2371 terminator = ')';
2372 ptr1 = list + 1;
2373 break;
2374 case '"': /* UNIX-style on a Mac (double quotes not stripped). */
2375 terminator = '"';
2376 ptr1 = list + 1;
2377 break;
2378 default: /* UNIX-style on a UNIX machine or IBM PC. */
2379 terminator = NUL;
2380 ptr1 = list;
2381 break;
2382 }
2383 for (;;) {
2384 /*************************************************************************
2385 * Find beginning of the next token in list (skipping past any leading
2386 * blanks). If the end of the list is reached instead, then there are
2387 * no more tokens.
2388 *************************************************************************/
2389 while (*ptr1 == ' ') ptr1++;
2390 if (*ptr1 == terminator) return TRUE;
2391 /*************************************************************************
2392 * Find the end of the token and copy. The token is ended by either a
2393 * blank, comma, or the terminator.
2394 *************************************************************************/
2395 ptr2 = ptr1 + 1;
2396 while (*ptr2 != ' ' && *ptr2 != ',' && *ptr2 != terminator) ptr2++;
2397 tokenLen = (size_t) (ptr2 - ptr1);
2398 strcpyX (token, ptr1, MINIMUM(tokenLen,MAX_TOKEN_LEN));
2399 /*************************************************************************
2400 * Search possible tokens for a match. If more than one match is found,
2401 * return an error.
2402 *************************************************************************/
2403 for (matchN = -1, tokenN = 0; tokenN < nTokens; tokenN++)
2404 if (strncmpIgCasePattern(token,tokens[tokenN],strlen(token)) == 0)
2405 if (matchN == -1)
2406 matchN = tokenN;
2407 else
2408 return FALSE;
2409 if (matchN == -1)
2410 return FALSE;
2411 else
2412 present[matchN] = TRUE;
2413 /*************************************************************************
2414 * Setup to search for next token in list.
2415 *************************************************************************/
2416 switch (*ptr2) {
2417 case ' ':
2418 /*********************************************************************
2419 * The last token was ended by a blank. Check to see if a comma is
2420 * the next non-blank character. If so, the next token begins one
2421 * character beyond the comma (leading blanks will be skipped when
2422 * the beginning of that token is located). Otherwise, the next token
2423 * begins at the non-blank character.
2424 *********************************************************************/
2425 ptr1 = ptr2 + 1;
2426 while (*ptr1 == ' ') ptr1++;
2427 if (*ptr1 == ',') ptr1++;
2428 break;
2429 case ',':
2430 /*********************************************************************
2431 * The last token was ended by a comma. The next token begins one
2432 * character beyond the comma.
2433 *********************************************************************/
2434 ptr1 = ptr2 + 1;
2435 break;
2436 default:
2437 /*********************************************************************
2438 * The terminator must have ended the last token.
2439 *********************************************************************/
2440 return TRUE;
2441 }
2442 }
2443 }
2444
2445 /******************************************************************************
2446 * NULedString.
2447 * Returns a pointer to a NUL-terminated string that was allocated here but
2448 * not freed. The caller must free the string when no longer needed. Also,
2449 * `len'+1 characters will be allocated for the new string (and copied to from
2450 * the existing string) regardless of whether or not a NUL appears in the first
2451 * `len' characters.
2452 ******************************************************************************/
2453
NULedString(ptr,len)2454 char *NULedString (ptr, len)
2455 char *ptr; /* Pointer to the string from which to extract
2456 the first `len' characters. */
2457 size_t len; /* Number of characters to extract. This does
2458 not include the terminating NUL that will
2459 be appended to the string being returned. */
2460 {
2461 char *string;
2462 string = (char *) cdf_AllocateMemory (len + 1, FatalError);
2463 memmove (string, ptr, len);
2464 string[len] = NUL;
2465 return string;
2466 }
2467
2468 /******************************************************************************
2469 * WriteOutSO.
2470 ******************************************************************************/
2471
2472 #if defined(STDARG)
WriteOutSO(char * format,...)2473 int WriteOutSO (char *format, ...)
2474 #else
2475 int WriteOutSO (va_alist)
2476 va_dcl
2477 #endif
2478 {
2479 #if !defined(STDARG)
2480 char *format;
2481 #endif
2482 int n;
2483 char text[MAX_oTEXT_LEN];
2484 va_list ap;
2485 #if defined(STDARG)
2486 va_start (ap, format);
2487 #else
2488 VA_START (ap);
2489 format = va_arg (ap, char *);
2490 #endif
2491 vsprintf (text, format, ap);
2492 n = WriteOut (stdout, text);
2493 va_end (ap);
2494 return n;
2495 }
2496
2497 /******************************************************************************
2498 * WriteOutFP.
2499 ******************************************************************************/
2500
2501 #if defined(STDARG)
WriteOutFP(FILE * fp,char * format,...)2502 int WriteOutFP (FILE *fp, char *format, ...)
2503 #else
2504 int WriteOutFP (va_alist)
2505 va_dcl
2506 #endif
2507 {
2508 #if !defined(STDARG)
2509 FILE *fp;
2510 char *format;
2511 #endif
2512 int n;
2513 char text[MAX_oTEXT_LEN];
2514 va_list ap;
2515 #if defined(STDARG)
2516 va_start (ap, format);
2517 #else
2518 VA_START (ap);
2519 fp = va_arg (ap, FILE *);
2520 format = va_arg (ap, char *);
2521 #endif
2522 vsprintf (text, format, ap);
2523 n = WriteOut (fp, text);
2524 va_end (ap);
2525 return n;
2526 }
2527
2528 /******************************************************************************
2529 * WriteOut.
2530 * Returns number of characters output.
2531 ******************************************************************************/
2532
WriteOut(fp,text)2533 int WriteOut (fp, text)
2534 FILE *fp;
2535 char *text;
2536 {
2537 /****************************************************************************
2538 * If the output is not going to `stdout', then assume it is going to a file
2539 * (and ignore paging if requested).
2540 ****************************************************************************/
2541 if (fp != stdout)
2542 fprintf (fp, "%s", text);
2543 else {
2544 /**************************************************************************
2545 * The output is going to `stdout'. Assume that `stdout' has not been
2546 * redirected away from the user's terminal (to a file). If `stdout' has
2547 * been redirected to a file, then hopefully the user had enough sense not
2548 * to request paging.
2549 **************************************************************************/
2550 #if defined(mac) || (defined(win32) && !defined(ALONE))
2551 #if defined(mac)
2552 WriteOutMacSO (text);
2553 #else
2554 #if defined(SO)
2555 WriteOutWin32 (text);
2556 #endif
2557 #endif
2558 #else
2559 char *ptr = text, *ptrNL; size_t len;
2560 /**************************************************************************
2561 * If paging is on, first prompt for `more...' if the end of the standard
2562 * output screen has been reached.
2563 **************************************************************************/
2564 for (;;) {
2565 /***********************************************************************
2566 * If paging on, check if the maximum number of lines have been written.
2567 ***********************************************************************/
2568 if (pagingOn) {
2569 if (soLineCount == MAX_LINES_WHEN_PAGING) {
2570 char key = NUL; static char prompt[] = "\nEnter RETURN for more...";
2571 WriteStringStdOut (prompt, strlen(prompt));
2572 ReadCharStdIn (&key);
2573 if (key != '\n') pagingOn = FALSE;
2574 WriteStringStdOut ("\n\n", 2);
2575 soLineCount = 0;
2576 }
2577 }
2578 /***********************************************************************
2579 * Write the string up to the next newline character. If there aren't
2580 * any(more) newline characters, write the rest of the string.
2581 ***********************************************************************/
2582 ptrNL = strchr (ptr, Nl);
2583 if (ptrNL == NULL) {
2584 len = strlen (ptr);
2585 WriteStringStdOut (ptr, len);
2586 break;
2587 }
2588 else {
2589 len = (int) (ptrNL - ptr + 1);
2590 WriteStringStdOut (ptr, len);
2591 if (pagingOn) soLineCount++;
2592 ptr = ptrNL + 1;
2593 if (*ptr == NUL) break;
2594 }
2595 }
2596 fflush (stdout);
2597 #endif
2598 }
2599 return strlen(text);
2600 }
2601
2602 /******************************************************************************
2603 * DirList.
2604 * If an error occurs (or no files found), zero (0) is returned.
2605 ******************************************************************************/
2606
DirList(dir,patternC,patternS,dirS,nameS)2607 int DirList (dir, patternC, patternS, dirS, nameS)
2608 char *dir; /* In: Directory to search. */
2609 int patternC; /* In: Pattern count. */
2610 char **patternS; /* In: Patterns to search for. */
2611 char ***dirS; /* Out: Directories. */
2612 char ***nameS; /* Out: File names. */
2613 {
2614 int i;
2615 int nFiles = 0;
2616 int tNameChars = 0;
2617 struct FILEstruct *FILEhead = NULL;
2618 struct FILEstruct *FILEptr;
2619 struct FILEstruct *FILEptrT;
2620 char *dirP, *nameP;
2621 size_t nNameChars;
2622
2623 #if defined(BORLANDC)
2624 char pathX[DU_MAX_PATH_LEN + 1];
2625 struct ffblk ffblk;
2626 int done;
2627 #endif
2628
2629 #if defined(MICROSOFTC)
2630 char pathX[DU_MAX_PATH_LEN + 1];
2631 struct find_t fileinfo;
2632 int done;
2633 #endif
2634
2635 #if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL)
2636 DIR *dirp;
2637 char dirX[DU_MAX_PATH_LEN + 1];
2638 char pattern[DU_MAX_NAME_LEN+1];
2639 #if defined(Mach)
2640 struct direct *dp;
2641 #else
2642 struct dirent *dp;
2643 #endif
2644 #endif
2645
2646 #if defined(vms)
2647 char pathX[DU_MAX_PATH_LEN + 1];
2648 char pathFound[DU_MAX_PATH_LEN + 1];
2649 struct dsc$descriptor_s pathDESCR;
2650 struct dsc$descriptor_s pathFoundDESCR;
2651 uLong context = 0;
2652 char name[DU_MAX_NAME_LEN + 1];
2653 uLong status;
2654 #endif
2655
2656 #if defined(mac)
2657 short vRefNum;
2658 long dirID;
2659 OSErr rCode;
2660 CInfoPBRec cParms;
2661 Str255 tempS;
2662 char *name;
2663 char pattern[DU_MAX_NAME_LEN+1];
2664 #endif
2665
2666 #if defined(win32)
2667 char pathX[DU_MAX_PATH_LEN + 1];
2668 long handle;
2669 struct _finddata_t fdata;
2670 int done;
2671 #endif
2672
2673 #if defined(win32)
2674 /****************************************************************************
2675 * Find files on Windows machine. Note that only one directory is possible
2676 * per path on Windows systems.
2677 ****************************************************************************/
2678 for (i = 0; i < patternC; i++) {
2679 ExpandPath (dir, pathX);
2680 AppendToDir (pathX, patternS[i]);
2681 handle = _findfirst (pathX, &fdata);
2682 if (handle != -1) {
2683 done = FALSE;
2684 while (!done) {
2685 /***********************************************************************
2686 * Allocate/setup file structure.
2687 ***********************************************************************/
2688 FILEptr = (struct FILEstruct *) cdf_AllocateMemory (sizeof(struct FILEstruct), FatalError);
2689 nNameChars = strlen (fdata.name);
2690 FILEptr->name = (char *) cdf_AllocateMemory (nNameChars + 1, FatalError);
2691 strcpyX (FILEptr->name, fdata.name, nNameChars);
2692 tNameChars += nNameChars + 1;
2693 nFiles++;
2694 FILEptr->next = NULL;
2695 AddToList (&FILEhead, FILEptr);
2696 /***********************************************************************
2697 * Get next matching file.
2698 ***********************************************************************/
2699 done = _findnext (handle, &fdata);
2700 }
2701 _findclose (handle);
2702 }
2703 }
2704 #endif
2705
2706 #if defined(dos)
2707 /****************************************************************************
2708 * Find files on MS-DOS machine. Note that only one directory is possible
2709 * per path on MS-DOS systems.
2710 ****************************************************************************/
2711 for (i = 0; i < patternC; i++) {
2712 ExpandPath (dir, pathX);
2713 AppendToDir (pathX, patternS[i]);
2714 #if defined(BORLANDC)
2715 done = findfirst (pathX, &ffblk, 0);
2716 #endif
2717 #if defined(MICROSOFTC)
2718 done = _dos_findfirst (pathX, 0, &fileinfo);
2719 #endif
2720 while (!done) {
2721 /***********************************************************************
2722 * Allocate/setup file structure.
2723 ***********************************************************************/
2724 FILEptr = (struct FILEstruct *)
2725 cdf_AllocateMemory (sizeof(struct FILEstruct),
2726 FatalError);
2727 #if defined(BORLANDC)
2728 nNameChars = strlen (ffblk.ff_name);
2729 FILEptr->name = (char *) cdf_AllocateMemory (nNameChars + 1, FatalError);
2730 strcpyX (FILEptr->name, ffblk.ff_name, nNameChars);
2731 #endif
2732 #if defined(MICROSOFTC)
2733 nNameChars = strlen (fileinfo.name);
2734 FILEptr->name = (char *) cdf_AllocateMemory (nNameChars + 1, FatalError);
2735 strcpyX (FILEptr->name, fileinfo.name, nNameChars);
2736 #endif
2737 tNameChars += nNameChars + 1;
2738 nFiles++;
2739 FILEptr->next = NULL;
2740 AddToList (&FILEhead, FILEptr);
2741 /***********************************************************************
2742 * Get next matching file.
2743 ***********************************************************************/
2744 #if defined(BORLANDC)
2745 done = findnext (&ffblk);
2746 #endif
2747 #if defined(MICROSOFTC)
2748 done = _dos_findnext (&fileinfo);
2749 #endif
2750 }
2751 }
2752 #endif
2753
2754 #if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL)
2755 /****************************************************************************
2756 * Find files on UNIX machine. Note that only one directory is possible per
2757 * path on UNIX systems.
2758 ****************************************************************************/
2759 ExpandPath (dir, dirX);
2760 if (NULstring(dirX)) strcpyX (dirX, ".", DU_MAX_PATH_LEN);
2761 /* Default to current dir. */
2762 dirp = opendir (dirX);
2763 if (dirp == NULL) return 0;
2764 dp = readdir (dirp);
2765 while (dp != NULL) {
2766 char *name = dp->d_name;
2767 #if SOLARISbsdDIRUTILSbug
2768 name -= 2;
2769 #endif
2770 for (i = 0; i < patternC; i++) {
2771 strcpyX (pattern, patternS[i], DU_MAX_NAME_LEN);
2772 if (NULstring(pattern)) strcpyX (pattern, "*", DU_MAX_NAME_LEN);
2773 /* Default to all files. */
2774 if (PatternMatch (pattern, name)) {
2775 /*********************************************************************
2776 * Allocate/setup file structure.
2777 *********************************************************************/
2778 FILEptr = (struct FILEstruct *)
2779 cdf_AllocateMemory (sizeof(struct FILEstruct),
2780 FatalError);
2781 nNameChars = strlen (name);
2782 FILEptr->name = (char *) cdf_AllocateMemory (nNameChars + 1, FatalError);
2783 strcpyX (FILEptr->name, name, nNameChars);
2784 tNameChars += nNameChars + 1;
2785 nFiles++;
2786 FILEptr->next = NULL;
2787 AddToList (&FILEhead, FILEptr);
2788 break;
2789 }
2790 }
2791 /**************************************************************************
2792 * Get next file.
2793 **************************************************************************/
2794 dp = readdir (dirp);
2795 }
2796 closedir (dirp);
2797 #endif
2798
2799 #if defined(vms)
2800 /****************************************************************************
2801 * Find files on VMS machine. Note that a logical name defined to be a set of
2802 * two or more directories may result in files from more than one directory
2803 * being found. In that case, the logical name would be returned as the name
2804 * of the directory (the VMS file system handles this when opening a file).
2805 * The actual directories are ignored.
2806 ****************************************************************************/
2807 pathFoundDESCR.dsc$w_length = sizeof(pathFound) - 1; /* Pass full string. */
2808 pathFoundDESCR.dsc$b_dtype = DSC$K_DTYPE_T;
2809 pathFoundDESCR.dsc$b_class = DSC$K_CLASS_S;
2810 pathFoundDESCR.dsc$a_pointer = pathFound;
2811 for (i = 0; i < patternC; i++) {
2812 ExpandPath (dir, pathX);
2813 AppendToDir (pathX, patternS[i]);
2814 pathDESCR.dsc$w_length = strlen(pathX); /* Pass part used. */
2815 pathDESCR.dsc$b_dtype = DSC$K_DTYPE_T;
2816 pathDESCR.dsc$b_class = DSC$K_CLASS_S;
2817 pathDESCR.dsc$a_pointer = pathX;
2818 while ((status = lib$find_file (&pathDESCR, &pathFoundDESCR, &context,
2819 NULL, NULL, NULL, NULL)) == RMS$_NORMAL) {
2820 /***********************************************************************
2821 * A file was found, NUL terminate and remove trailing blanks (version
2822 * number is left on).
2823 ***********************************************************************/
2824 pathFound[pathFoundDESCR.dsc$w_length] = NUL; /* NUL-terminate. */
2825 for (i = strlen(pathFound) - 1; i >= 0 && pathFound[i] == ' '; i--) {
2826 pathFound[i] = NUL;
2827 }
2828 ParsePath (pathFound, NULL, name);
2829 /***********************************************************************
2830 * Allocate/setup file structure.
2831 ***********************************************************************/
2832 FILEptr = (struct FILEstruct *)
2833 cdf_AllocateMemory (sizeof(struct FILEstruct),
2834 FatalError);
2835 nNameChars = strlen (name);
2836 FILEptr->name = (char *) cdf_AllocateMemory (nNameChars + 1,
2837 FatalError);
2838 strcpyX (FILEptr->name, name, nNameChars);
2839 tNameChars += nNameChars + 1;
2840 nFiles++;
2841 FILEptr->next = NULL;
2842 AddToList (&FILEhead, FILEptr);
2843 }
2844 status = lib$find_file_end (&context);
2845 }
2846 #endif
2847
2848 #if defined(mac)
2849 /****************************************************************************
2850 * Find files on a Macintosh. Note that only one directory is possible per
2851 * path on Macintosh systems.
2852 ****************************************************************************/
2853 if (!MacDirSpecified(dir,&vRefNum,&dirID)) {
2854 *nameS = NULL;
2855 *dirS = NULL;
2856 return 0;
2857 }
2858 cParms.hFileInfo.ioNamePtr = tempS;
2859 cParms.hFileInfo.ioVRefNum = vRefNum;
2860 cParms.hFileInfo.ioFDirIndex = 1;
2861 cParms.hFileInfo.ioDirID = dirID;
2862 rCode = PBGetCatInfo (&cParms, FALSE);
2863 while (rCode == noErr) {
2864 /**************************************************************************
2865 * Check if a file (rather than a directory).
2866 **************************************************************************/
2867 if (BITCLR(cParms.hFileInfo.ioFlAttrib,4)) {
2868 name = PtoCstr (cParms.hFileInfo.ioNamePtr);
2869 for (i = 0; i < patternC; i++) {
2870 strcpyX (pattern, patternS[i], DU_MAX_NAME_LEN);
2871 if (NULstring(pattern)) strcpyX (pattern, "*", DU_MAX_NAME_LEN);
2872 if (PatternMatch(pattern,name)) {
2873 /*******************************************************************
2874 * Allocate/setup file structure.
2875 *******************************************************************/
2876 FILEptr = (struct FILEstruct *)
2877 cdf_AllocateMemory (sizeof(struct FILEstruct),
2878 FatalError);
2879 nNameChars = strlen (name);
2880 FILEptr->name = (char *) cdf_AllocateMemory (nNameChars+1,
2881 FatalError);
2882 strcpyX (FILEptr->name, name, nNameChars);
2883 tNameChars += nNameChars + 1;
2884 nFiles++;
2885 FILEptr->next = NULL;
2886 AddToList (&FILEhead, FILEptr);
2887 break;
2888 }
2889 }
2890 }
2891 /**************************************************************************
2892 * Get next file.
2893 **************************************************************************/
2894 cParms.hFileInfo.ioDirID = dirID; /* This must be reset each time. */
2895 cParms.hFileInfo.ioFDirIndex++; /* Increment to next file. */
2896 rCode = PBGetCatInfo (&cParms, FALSE);
2897 }
2898 #endif
2899
2900 /****************************************************************************
2901 * Build directory/file arrays.
2902 ****************************************************************************/
2903 if (nFiles > 0) {
2904 /**************************************************************************
2905 * Setup to traverse linked list.
2906 **************************************************************************/
2907 *dirS = (char **) cdf_AllocateMemory ((nFiles*sizeof(char *))+strlen(dir)+1,
2908 FatalError);
2909 *nameS = (char **) cdf_AllocateMemory ((nFiles*sizeof(char *)) + tNameChars,
2910 FatalError);
2911 dirP = (char *) (*dirS) + nFiles*sizeof(char *);
2912 nameP = (char *) (*nameS) + nFiles*sizeof(char *);
2913 /**************************************************************************
2914 * Traverse linked list of file structures. Note that the second through
2915 * last directory strings actually point to the first directory string.
2916 **************************************************************************/
2917 for (FILEptr=FILEhead, i=0; FILEptr != NULL; FILEptr=FILEptr->next, i++) {
2918 if (i == 0) {
2919 strcpyX (dirP, dir, 0);
2920 (*dirS)[i] = dirP;
2921 }
2922 else
2923 (*dirS)[i] = (*dirS)[i-1];
2924 strcpyX (nameP, FILEptr->name, 0);
2925 (*nameS)[i] = nameP;
2926 nameP += strlen(FILEptr->name) + 1;
2927 }
2928 /**************************************************************************
2929 * Free linked list of file structures.
2930 **************************************************************************/
2931 FILEptr = FILEhead;
2932 while (FILEptr != NULL) {
2933 FILEptrT = FILEptr;
2934 FILEptr = FILEptr->next;
2935 cdf_FreeMemory (FILEptrT->name, FatalError);
2936 cdf_FreeMemory (FILEptrT, FatalError);
2937 }
2938 }
2939 else {
2940 /**************************************************************************
2941 * No files found.
2942 **************************************************************************/
2943 *nameS = NULL;
2944 *dirS = NULL;
2945 }
2946 return nFiles;
2947 }
2948
2949 /******************************************************************************
2950 * AddToList.
2951 ******************************************************************************/
2952
AddToList(FILEhead,FILEptr)2953 static void AddToList (FILEhead, FILEptr)
2954 struct FILEstruct **FILEhead;
2955 struct FILEstruct *FILEptr;
2956 {
2957 if (*FILEhead == NULL)
2958 *FILEhead = FILEptr;
2959 else
2960 if (strcmp(FILEptr->name,(*FILEhead)->name) < 0) {
2961 FILEptr->next = *FILEhead;
2962 *FILEhead = FILEptr;
2963 }
2964 else {
2965 struct FILEstruct *FILEptrT = *FILEhead;
2966 for (;;) {
2967 if (FILEptrT->next == NULL) {
2968 FILEptrT->next = FILEptr;
2969 break;
2970 }
2971 else
2972 if (strcmp(FILEptr->name,FILEptrT->next->name) < 0) {
2973 FILEptr->next = FILEptrT->next;
2974 FILEptrT->next = FILEptr;
2975 break;
2976 }
2977 FILEptrT = FILEptrT->next;
2978 }
2979 }
2980 return;
2981 }
2982
2983 /******************************************************************************
2984 * PatternMatch. (Only used on UNIX/POSIXshell and Macintosh systems).
2985 ******************************************************************************/
2986
2987 #if (defined(unix) && !defined(__MINGW32__)) || defined(mac) || \
2988 defined(posixSHELL)
PatternMatch(pattern,name)2989 static int PatternMatch (pattern, name)
2990 char *pattern;
2991 char *name;
2992 {
2993 enum typeENUM types[DU_MAX_PATTERNS];
2994 char *strings[DU_MAX_PATTERNS];
2995 int nTypes = 0;
2996 int len, i, result;
2997
2998 for (i = 0; i < DU_MAX_PATTERNS; i++) types[i] = TBD;
2999
3000 for (i = 0; pattern[i] != NUL; i++)
3001 switch (pattern[i]) {
3002 case '?':
3003 types[nTypes++] = WILD1;
3004 break;
3005 case '*':
3006 if (nTypes == 0 || types[nTypes] != WILDn) types[nTypes++] = WILDn;
3007 break;
3008 default:
3009 if (types[nTypes] == TBD) {
3010 types[nTypes] = STR;
3011 strings[nTypes] = (char *) cdf_AllocateMemory (DU_MAX_NAME_LEN + 1,
3012 FatalError);
3013 strings[nTypes][0] = pattern[i];
3014 strings[nTypes][1] = NUL;
3015 nTypes++;
3016 }
3017 else {
3018 len = strlen (strings[nTypes-1]);
3019 strings[nTypes-1][len] = pattern[i];
3020 strings[nTypes-1][len+1] = NUL;
3021 }
3022 }
3023
3024 result = CheckPattern (nTypes, types, strings, name);
3025
3026 for (i = 0; i < DU_MAX_PATTERNS; i++) {
3027 if (types[i] == STR) cdf_FreeMemory (strings[i], FatalError);
3028 }
3029
3030 return result;
3031 }
3032 #endif
3033
3034 /******************************************************************************
3035 * CheckPattern. (Only used on UNIX/POSIXshell and Macintosh systems).
3036 ******************************************************************************/
3037
3038 #if (defined(unix) && !defined(__MINGW32__)) || defined(mac) || \
3039 defined(posixSHELL)
CheckPattern(nTypes,types,strings,name)3040 static int CheckPattern (nTypes, types, strings, name)
3041 int nTypes;
3042 enum typeENUM types[];
3043 char *strings[];
3044 char *name;
3045 {
3046 int sp = 0;
3047 int i, j;
3048
3049 for (i = 0; i < nTypes; i++) {
3050 switch (types[i]) {
3051 case TBD:
3052 /* Do nothing? */
3053 break;
3054 case STR:
3055 if (strncmp(&name[sp],strings[i],strlen(strings[i])) != 0)
3056 return FALSE;
3057 else
3058 sp += strlen(strings[i]);
3059 break;
3060 case WILD1:
3061 if (name[sp] == NUL)
3062 return FALSE;
3063 else
3064 sp++;
3065 break;
3066 case WILDn:
3067 if (i == nTypes-1) /* At last type to check? */
3068 return TRUE;
3069 else {
3070 for (j = i; name[j] != NUL; j++)
3071 if (CheckPattern (nTypes-i-1, &types[i+1],
3072 &strings[i+1], &name[j])) return TRUE;
3073 return FALSE;
3074 }
3075 }
3076 }
3077
3078 if (name[sp] == NUL)
3079 return TRUE;
3080 else
3081 return FALSE;
3082 }
3083 #endif
3084
3085 /******************************************************************************
3086 * CDFdirList.
3087 * Does a `DirList' using the possible CDF extensions (`.cdf' on all
3088 * platforms and also `.CDF', `.cdf;1', and `.CDF;1' on UNIX/POSIXshell and
3089 * Macintosh platforms because of CD-ROM inconsistencies
3090 ******************************************************************************/
3091
CDFdirList(path,dirS,nameS)3092 int CDFdirList (path, dirS, nameS)
3093 char *path;
3094 char ***dirS;
3095 char ***nameS;
3096 {
3097 #if (defined(unix) && !defined(__MINGW32__)) || defined(mac) || \
3098 defined(posixSHELL)
3099 /****************************************************************************
3100 * UNIX/POSIXshell and Macintosh.
3101 ****************************************************************************/
3102 char dir[DU_MAX_DIR_LEN+1];
3103 char pattern[DU_MAX_NAME_LEN+1];
3104 static char pattern1[DU_MAX_NAME_LEN+1];
3105 static char pattern2[DU_MAX_NAME_LEN+1];
3106 static char pattern3[DU_MAX_NAME_LEN+1];
3107 static char pattern4[DU_MAX_NAME_LEN+1];
3108 static char *patternS[4] = { pattern1, pattern2, pattern3, pattern4 };
3109 int nCDFs;
3110
3111 ParsePath (path, dir, pattern);
3112
3113 strcpyX (pattern1, pattern, DU_MAX_NAME_LEN);
3114 if (NULstring(pattern1)) strcatX (pattern1, "*", DU_MAX_NAME_LEN);
3115 strcatX (pattern1, ".cdf", DU_MAX_NAME_LEN);
3116
3117 strcpyX (pattern2, pattern, DU_MAX_NAME_LEN);
3118 if (NULstring(pattern2)) strcatX (pattern2, "*", DU_MAX_NAME_LEN);
3119 strcatX (pattern2, ".CDF", DU_MAX_NAME_LEN);
3120
3121 strcpyX (pattern3, pattern, DU_MAX_NAME_LEN);
3122 if (NULstring(pattern3)) strcatX (pattern3, "*", DU_MAX_NAME_LEN);
3123 strcatX (pattern3, ".cdf;1", DU_MAX_NAME_LEN);
3124
3125 strcpyX (pattern4, pattern, DU_MAX_NAME_LEN);
3126 if (NULstring(pattern4)) strcatX (pattern4, "*", DU_MAX_NAME_LEN);
3127 strcatX (pattern4, ".CDF;1", DU_MAX_NAME_LEN);
3128
3129 nCDFs = DirList (dir, 4, patternS, dirS, nameS);
3130 RemoveExtensions (nCDFs, *nameS);
3131
3132 return nCDFs;
3133 #endif
3134 #if defined(vms) || defined(dos) || defined(win32)
3135 /****************************************************************************
3136 * VMS, Windows, and MS-DOS.
3137 ****************************************************************************/
3138 char dir[DU_MAX_DIR_LEN+1];
3139 static char pattern[DU_MAX_NAME_LEN+1];
3140 static char *patternS[1] = { pattern };
3141 int nCDFs;
3142
3143 ParsePath (path, dir, pattern);
3144
3145 if (NULstring(pattern)) strcatX (pattern, "*", DU_MAX_NAME_LEN);
3146 strcatX (pattern, ".cdf", DU_MAX_NAME_LEN);
3147
3148 nCDFs = DirList (dir, 1, patternS, dirS, nameS);
3149 RemoveExtensions (nCDFs, *nameS);
3150
3151 return nCDFs;
3152 #endif
3153 }
3154
3155 /******************************************************************************
3156 * RemoveExtensions. Locates the last '.' in a file name and replaces it with
3157 * a NUL. This effectively removes the file extension. If
3158 * the file name does not have an extension and has a '.' in
3159 * its name, this could have undesired effects.
3160 ******************************************************************************/
3161
RemoveExtensions(nFiles,files)3162 void RemoveExtensions (nFiles, files)
3163 int nFiles;
3164 char *files[];
3165 {
3166 int i;
3167 char *ptr;
3168 for (i = 0; i < nFiles; i++)
3169 if ((ptr = strrchr(files[i],'.')) != NULL) *ptr = NUL;
3170 return;
3171 }
3172
3173 /******************************************************************************
3174 * WriteStringStdOut.
3175 ******************************************************************************/
3176
WriteStringStdOut(string,length)3177 void WriteStringStdOut (string, length)
3178 char *string;
3179 size_t length;
3180 {
3181 fprintf (stdout, "%*.*s", (int) length, (int) length, string);
3182 return;
3183 }
3184
3185 /******************************************************************************
3186 * ReadCharStdIn.
3187 ******************************************************************************/
3188
3189 #if !defined(mac)
ReadCharStdIn(key)3190 void ReadCharStdIn (key)
3191 char *key;
3192 {
3193 *key = (char) fgetc (stdin);
3194 return;
3195 }
3196 #endif
3197
3198 /******************************************************************************
3199 * DisplayStatistics.
3200 ******************************************************************************/
3201
DisplayStatistics(label,vStatsDotCDF,vStatsStage,vStatsCompress)3202 void DisplayStatistics (label, vStatsDotCDF, vStatsStage, vStatsCompress)
3203 char *label;
3204 vSTATS *vStatsDotCDF;
3205 vSTATS *vStatsStage;
3206 vSTATS *vStatsCompress;
3207 {
3208 char temp1[MAX_SCREENLINE_LEN+1], temp2[MAX_SCREENLINE_LEN+1],
3209 temp3[MAX_SCREENLINE_LEN+1], labelX[MAX_SCREENLINE_LEN+1];
3210 if (vStatsDotCDF->maxBuffers > 0) {
3211 strcpyX (labelX, label, MAX_SCREENLINE_LEN);
3212 strcatX (labelX, " DotCDF file", MAX_SCREENLINE_LEN);
3213 BuildStatistics (labelX, vStatsDotCDF, temp1, temp2, temp3);
3214 WriteOut (stdout, temp1);
3215 WriteOut (stdout, "\n");
3216 WriteOut (stdout, temp2);
3217 WriteOut (stdout, "\n");
3218 WriteOut (stdout, temp3);
3219 WriteOut (stdout, "\n");
3220 }
3221 if (vStatsStage->maxBuffers > 0) {
3222 strcpyX (labelX, label, MAX_SCREENLINE_LEN);
3223 strcatX (labelX, " staging file", MAX_SCREENLINE_LEN);
3224 BuildStatistics (labelX, vStatsStage, temp1, temp2, temp3);
3225 WriteOut (stdout, temp1);
3226 WriteOut (stdout, "\n");
3227 WriteOut (stdout, temp2);
3228 WriteOut (stdout, "\n");
3229 WriteOut (stdout, temp3);
3230 WriteOut (stdout, "\n");
3231 }
3232 if (vStatsCompress->maxBuffers > 0) {
3233 strcpyX (labelX, label, MAX_SCREENLINE_LEN);
3234 strcatX (labelX, " compression scratch file", MAX_SCREENLINE_LEN);
3235 BuildStatistics (labelX, vStatsCompress, temp1, temp2, temp3);
3236 WriteOut (stdout, temp1);
3237 WriteOut (stdout, "\n");
3238 WriteOut (stdout, temp2);
3239 WriteOut (stdout, "\n");
3240 WriteOut (stdout, temp3);
3241 WriteOut (stdout, "\n");
3242 }
3243 return;
3244 }
3245
3246 /******************************************************************************
3247 * BuildStatistics.
3248 ******************************************************************************/
3249
BuildStatistics(label,vStats,temp1,temp2,temp3)3250 void BuildStatistics (label, vStats, temp1, temp2, temp3)
3251 char *label;
3252 vSTATS *vStats;
3253 char temp1[MAX_SCREENLINE_LEN+1];
3254 char temp2[MAX_SCREENLINE_LEN+1];
3255 char temp3[MAX_SCREENLINE_LEN+1];
3256 {
3257 strcpyX (temp1, " Statistics", MAX_SCREENLINE_LEN);
3258 if (label != NULL) {
3259 strcatX (temp1, " for ", MAX_SCREENLINE_LEN);
3260 strcatX (temp1, label, MAX_SCREENLINE_LEN);
3261 }
3262 strcatX (temp1, ":", MAX_SCREENLINE_LEN);
3263 sprintf (temp2, " %d buffer%s used of the %d allowed, ", vStats->nBuffers,
3264 BOO(vStats->nBuffers == 1,"","s"), vStats->maxBuffers);
3265 sprintf (EofS(temp2), "[%ld reads, %ld writes] ", vStats->nV_reads,
3266 vStats->nV_writes);
3267 sprintf (temp3, " %ld page in%s, %ld page out%s, ",
3268 vStats->nPageIns, BOO(vStats->nPageIns==1,"","s"),
3269 vStats->nPageOuts, BOO(vStats->nPageOuts==1,"","s"));
3270 sprintf (EofS(temp3), "%ld block read%s, %ld block write%s ",
3271 vStats->nBlockReads, BOO(vStats->nBlockReads==1,"","s"),
3272 vStats->nBlockWrites, BOO(vStats->nBlockWrites==1,"","s"));
3273 return;
3274 }
3275
3276 /******************************************************************************
3277 * StatusCodeReportOptions.
3278 ******************************************************************************/
3279
StatusCodeReportOptions(e,w,i)3280 char *StatusCodeReportOptions (e,w,i)
3281 Logical e;
3282 Logical w;
3283 Logical i;
3284 {
3285 static char mask[MAX_REPORTMASK_LEN+1];
3286 #if defined(vms)
3287 strcpyX (mask, "(", MAX_REPORTMASK_LEN);
3288 #else
3289 strcpyX (mask, "\"", MAX_REPORTMASK_LEN);
3290 #endif
3291 strcatX (mask, (e ? "errors" : ""), MAX_REPORTMASK_LEN);
3292 strcatX (mask, (w ? (e ? ",warnings" : "warnings") : ""),
3293 MAX_REPORTMASK_LEN);
3294 strcatX (mask, (i ? (e || w ? ",informationals" : "informationals") : ""),
3295 MAX_REPORTMASK_LEN);
3296 #if defined(vms)
3297 strcatX (mask, ")", MAX_REPORTMASK_LEN);
3298 #else
3299 strcatX (mask, "\"", MAX_REPORTMASK_LEN);
3300 #endif
3301 #if defined(vms) || defined(dos)
3302 MakeUpperString (mask);
3303 #endif
3304 return mask;
3305 }
3306
3307 /******************************************************************************
3308 * DisplayIdentification.
3309 ******************************************************************************/
3310
DisplayIdentification(name)3311 void DisplayIdentification (name)
3312 char *name;
3313 {
3314 long version, release, increment; char subIncrement;
3315 char text[MAX_MESSAGE_TEXT_LEN+1]; CDFstatus status;
3316 status = CDFlib (GET_, LIB_VERSION_, &version,
3317 LIB_RELEASE_, &release,
3318 LIB_INCREMENT_, &increment,
3319 LIB_subINCREMENT_, &subIncrement,
3320 NULL_);
3321 if (StatusBAD(status))
3322 sprintf (text, "Error inquiring CDF library.");
3323 else {
3324 sprintf (text, "%s from the CDF V%ld.%ld.%ld",
3325 name, version, release, increment);
3326 if (subIncrement != ' ') sprintf (EofS(text), "%c", subIncrement);
3327 sprintf (EofS(text), " distribution.");
3328 }
3329 DisplayInfo (text);
3330 return;
3331 }
3332
3333 /******************************************************************************
3334 * FindUniqueMatch.
3335 * Returns: NOMATCH if a match was not found,
3336 * MATCHES if more than one match,
3337 * `index' if only one match.
3338 ******************************************************************************/
3339
FindUniqueMatch(target,strings)3340 int FindUniqueMatch (target, strings)
3341 char *target; /* Searching for this string. */
3342 char *strings[]; /* Terminated by a NULL pointer. */
3343 {
3344 int match, beyond; size_t targetL = strlen(target);
3345 for (match = 0; strings[match] != NULL; match++) {
3346 if (strncmpIgCasePattern(target,strings[match],targetL) == 0) {
3347 for (beyond = match + 1; strings[beyond] != NULL; beyond++) {
3348 if (strncmpIgCasePattern(target,strings[beyond],targetL) == 0)
3349 return MATCHES;
3350 }
3351 return match;
3352 }
3353 }
3354 return NOMATCH;
3355 }
3356
3357