/******************************************************************************
*
* NSSDC/CDF Toolbox of routines for CDF Toolkit (General).
*
* Version 1.5d, 23-Nov-97, Hughes STX.
*
* Modification history:
*
* V1.0 25-Jan-94, J Love Original version.
* V1.0a 6-Feb-94, J Love DEC Alpha/OpenVMS port.
* V1.1 10-Mar-94, J Love Modified `ParseOptionList' to make the
* enclosing parentheses optional (on any
* operating system).
* V1.2 15-Dec-94, J Love CDF V2.5.
* V1.2a 13-Jan-95, J Love Allow mixed-case in tokens. Changed
* `CDFdirList' to allow all possible extensions
* on Macintosh machines also.
* V1.2b 6-Mar-95, J Love Added macro definition checking to catch
* bug in directory listing system calls. Pass
* `char' as `int'.
* V1.3 21-Mar-95, J Love POSIX.
* V1.3a 18-Apr-95, J Love More POSIX.
* V1.3b 24-Apr-95, J Love Fixed `EncodeString' to not overflow the
* maximum length if the string won't fit.
* V1.4 25-May-95, J Love Added `GetCdataType'. EPOCH styles.
* SOLARISbsdDIRUTILSbug.
* V1.4a 12-Jun-95, J Love EPOCH custom format. catchrX.
* V1.4b 5-Sep-95, J Love Allow NULL for output fields not needed.
* NUL-terminate decoded string in `DecodeValues'.
* V1.4c 19-Sep-95, J Love Macintosh event handling.
* V1.4d 27-Sep-95, J Love Reduced TextEdit text size for Think C.
* V1.5 27-Aug-96, J Love CDF V2.6.
* V1.5a 2-Nov-96, J Love Changed `DisplayIdentification' to not print
* a `blank' sub-increment.
* V1.5b 21-Feb-97, J Love Removed RICE.
* V1.5c 3-Mar-97, J Love Windows NT for MS Visual C/C++ on an IBM PC.
* V1.5d 23-Nov-97, J Love More Windows NT.
* V1.6 10-May-01, M Liu New port for Cygwin
* V1.7 11-Jul-05, M Liu Added MingW port for PC.
* V1.8 13-Oct-06, M Liu Changed to allow upper and lower case CDF
* name to be used on win32.
*
******************************************************************************/
#define TOOLBOX1
#include "cdftools.h"
/******************************************************************************
* Local macros.
******************************************************************************/
#define MAX_cFORMAT_LEN 10
/******************************************************************************
* Local enumerators.
******************************************************************************/
#if (defined(unix) && !defined(__MINGW32__)) || defined(mac) || \
defined(posixSHELL)
enum typeENUM {TBD, STR, WILD1, WILDn};
#endif
/******************************************************************************
* Local structures.
******************************************************************************/
struct FILEstruct {
char *name;
struct FILEstruct *next;
};
/******************************************************************************
* Local function prototypes.
******************************************************************************/
static Logical FtoCformat PROTOARGs((long, char *, long *, char *));
static int UseCformat PROTOARGs((long, long, char *, void *, char *));
static long GetCdataType PROTOARGs((char *, long *));
static void AddToList PROTOARGs((struct FILEstruct **FILEhead,
struct FILEstruct *FILEptr));
#if (defined(unix) && !defined(__MINGW32__)) || defined(mac) || \
defined(posixSHELL)
static int PatternMatch PROTOARGs((char *pattern, char *name));
static int CheckPattern PROTOARGs((int nTypes, enum typeENUM types[],
char *strings[], char *name));
#endif
/******************************************************************************
* FatalError.
******************************************************************************/
void FatalError (message)
char *message;
{
#if defined(mac)
MacMessageDialog ("FATAL ERROR!", message);
#else
#if defined(win32) && !defined(ALONE)
WinMessageDialog ("FATAL ERROR!", message);
#else
WriteOut (stdout, "FATAL ERROR! ");
WriteOut (stdout, message);
WriteOut (stdout, "\n");
#endif
#endif
ExitBAD;
}
/******************************************************************************
* DisplayError.
******************************************************************************/
void DisplayError (message)
char *message;
{
#if defined(mac)
MacMessageDialog ("Error!", message);
#else
#if defined(win32) && !defined(ALONE)
WinMessageDialog ("Error!", message);
#else
WriteOut (stdout, "Error! ");
WriteOut (stdout, message);
WriteOut (stdout, "\n");
#endif
#endif
return;
}
/******************************************************************************
* DisplayWarning.
* It is assumed that the message contains at least one character.
******************************************************************************/
void DisplayWarning (message)
char *message;
{
#if defined(mac)
MacMessageDialog ("Warning...", message);
#else
WriteOut (stdout, "Warning: ");
WriteOut (stdout, message);
WriteOut (stdout, "\n");
#endif
return;
}
/******************************************************************************
* DisplayInfo.
******************************************************************************/
void DisplayInfo (message)
char *message;
{
#if defined(mac)
MacMessageDialog ("", message);
#else
WriteOut (stdout, message);
WriteOut (stdout, "\n");
#endif
return;
}
/******************************************************************************
* DecodeVariances.
******************************************************************************/
Logical DecodeVariances (mask, numDims, recVary, dimVarys)
char *mask;
long numDims;
long *recVary;
long dimVarys[];
{
int dimN, charN;
switch (mask[0]) {
case 'T':
case 't':
*recVary = VARY;
break;
case 'F':
case 'f':
*recVary = NOVARY;
break;
default:
return FALSE;
}
for (dimN = 0, charN = 2; dimN < numDims; dimN++, charN++) {
switch (mask[charN]) {
case 'T':
case 't':
dimVarys[dimN] = VARY;
break;
case 'F':
case 'f':
dimVarys[dimN] = NOVARY;
break;
default:
return FALSE;
}
}
return TRUE;
}
/******************************************************************************
* DecodeDelimitedString.
******************************************************************************/
Logical DecodeDelimitedString (dString, pString)
char *dString; /* Delimited string. */
char *pString; /* Parsed (decoded) string. */
{
char *d1 = dString; /* First delimiter. */
char *d2; /* Second delimiter. */
size_t len; /* Size of decoded string. */
while (*d1 != NUL && Spacing(*d1)) d1++;
if (*d1 == NUL) return FALSE;
d2 = d1 + 1;
while (*d2 != NUL && *d2 != *d1) d2++;
if (*d2 == NUL) return FALSE;
len = (size_t) (d2 - d1 - 1);
memmove (pString, d1 + 1, len);
pString[len] = NUL;
return TRUE;
}
/******************************************************************************
* DecodeDimensionality.
******************************************************************************/
Logical DecodeDimensionality (string, numDims, dimSizes)
char *string;
long *numDims;
long *dimSizes;
{
char *cp;
/****************************************************************************
* The number of dimensions should be first.
****************************************************************************/
cp = NextNonSpace (string);
if (sscanf(cp,"%ld",numDims) != 1) return FALSE;
if (*numDims < 0) return FALSE;
cp = NextNonDigit (cp);
/****************************************************************************
* Skip past the `:' and `['.
****************************************************************************/
cp = NextNonSpace (cp);
if (*cp != ':') return FALSE;
cp = NextNonSpace (cp+1);
if (*cp != '[') return FALSE;
cp = NextNonSpace (cp+1);
/****************************************************************************
* Decode each dimension size.
****************************************************************************/
if (*numDims > 0) {
int dimN, lastDim = (int) (*numDims - 1);
for (dimN = 0; dimN <= lastDim; dimN++) {
if (sscanf(cp,"%ld",&dimSizes[dimN]) != 1) return FALSE;
cp = NextNonDigit (cp);
cp = NextNonSpace (cp);
if (dimN != lastDim) {
if (*cp != ',') return FALSE;
cp = NextNonSpace (cp+1);
}
}
}
/****************************************************************************
* Check for a trailing `]'.
****************************************************************************/
if (*cp != ']') return FALSE;
/****************************************************************************
* Everything went Ok, return TRUE;
****************************************************************************/
return TRUE;
}
/******************************************************************************
* DecodeRecordAndIndices.
******************************************************************************/
Logical DecodeRecordAndIndices (string, recN, nIndices, indices)
char *string;
long *recN; /* Can be NULL if not needed. */
long *nIndices;
long indices[CDF_MAX_DIMS];
{
char *cp; long recNt;
/****************************************************************************
* The record number will be first if it exists;
****************************************************************************/
cp = NextNonSpace (string);
if (*cp == '[') {
recNt = 0;
}
else {
if (sscanf(cp,"%ld",&recNt) != 1) return FALSE;
recNt -= 1;
if (recNt < 0) return FALSE;
cp = NextNonDigit (cp);
cp = NextNonSpace (cp);
if (*cp != ':') return FALSE;
cp = NextNonSpace (cp+1);
if (*cp != '[') return FALSE;
}
ASSIGNnotNULL (recN, recNt)
cp = NextNonSpace (cp+1);
/****************************************************************************
* Decode each index while counting how many there are.
****************************************************************************/
*nIndices = 0;
if (*cp == ']') return TRUE;
for (;;) {
if (*nIndices == CDF_MAX_DIMS) return FALSE; /* Too many indices. */
if (sscanf(cp,"%ld",&indices[(int)(*nIndices)]) != 1) return FALSE;
indices[(int)(*nIndices)] -= 1;
if (indices[(int)(*nIndices)] < 0) return FALSE;
*nIndices += 1;
cp = NextNonDigit (cp); /* Skip to space, comma, or `]'. */
cp = NextNonSpace (cp); /* Skip past spaces. */
switch (*cp) {
case ']':
return TRUE;
case ',':
cp = NextNonSpace (cp + 1);
break;
default:
return FALSE;
}
}
}
/******************************************************************************
* NextNonSpace.
******************************************************************************/
char *NextNonSpace (cp)
char *cp;
{
while (Spacing(*cp)) cp++;
return cp;
}
/******************************************************************************
* NextNonDigit.
******************************************************************************/
char *NextNonDigit (cp)
char *cp;
{
while (Decimal(*cp)) cp++;
return cp;
}
/******************************************************************************
* FormatWidth.
* Returns width of a format specifier [or zero if the width is unknown or
* illegal].
******************************************************************************/
int FormatWidth (format)
char *format;
{
int width; char *ptr = format;
/****************************************************************************
* Skip past Fortran repeat count (eg. the `20' in `20I8' or `20(I8)').
* Note that this won't skip past a C `%'.
****************************************************************************/
while (*ptr != NUL && (*ptr == '(' ||
Spacing(*ptr) ||
Decimal(*ptr))) ptr++;
if (*ptr == NUL) return 0;
/****************************************************************************
* Skip past Fortran format type (eg. the `F' in `F4.1') or C `%' and/or
* flags (one of which might be a `0').
****************************************************************************/
while (*ptr != NUL && (!Decimal(*ptr) || *ptr == '0')) ptr++;
if (*ptr == NUL) return 0;
/****************************************************************************
* Decode format width.
****************************************************************************/
if (sscanf(ptr,"%d",&width) != 1) width = 0;
return width;
}
/******************************************************************************
* FormatPrecision.
* Returns precision of a format specifier [or zero if the precision doesn't
* exist [eg. integer format]).
******************************************************************************/
int FormatPrecision (format)
char *format;
{
int precision;
char *ptr = strchr (format, '.');
if (ptr == NULL)
precision = 0;
else
if (sscanf(ptr+1,"%d",&precision) != 1) precision = 0;
return precision;
}
/******************************************************************************
* EncodeValuesFormat. Returns width of encoded values.
******************************************************************************/
int EncodeValuesFormat (dataType, numElems, binary, text, format, minWidth,
maxWidth, style)
long dataType; /* Data type of values. */
long numElems; /* Number of elements (values). */
void *binary; /* In: Values in binary. */
char *text; /* Out: Encoded values. */
char *format; /* If NULL, use default formats. Not applicable if
a string data type. */
int minWidth; /* Minimum width (including delimeters if a string
data type. If zero, no minimum width (no blank
padding). If positive, right justified (padding
on left side). If negative, left justified
(padding on right side). */
int maxWidth; /* Maximum width (including delimeters if a string
data type. If zero, no maximum width (no
truncating). */
int style; /* EPOCH style. */
{
/****************************************************************************
* Encode value(s).
****************************************************************************/
if (STRINGdataType(dataType))
EncodeString (numElems, binary, text, minWidth, maxWidth);
else {
long elemN;
char tText[MAX_nonSTRING_VALUE_LEN+1];
strcpyX (text, "", maxWidth);
for (elemN = 0; elemN < numElems; elemN++) {
/***********************************************************************
* Encode each value (if it fits).
***********************************************************************/
EncodeValueFormat (dataType, (Byte *) binary +
(size_t) (elemN*CDFelemSize(dataType)),
tText, format, 0, 0, style);
if (maxWidth > 0) {
int n = strlen(tText);
if (strlen(text) + (elemN > 0 ? 2 : 0) + n > (size_t) maxWidth) {
/*******************************************************************
* This value won't fit. Find a comma after which to put the
* truncation symbol (`...'). `i' starts at the NUL just in case
* this is the first value (`text' is a null-string).
*******************************************************************/
int i;
for (i = strlen(text); i != 0; i--) {
if (text[i] == ',' &&
(i + strlen(" ...") < (size_t) maxWidth)) break;
}
if (i != 0)
strcpyX (&text[i+1], " ...", maxWidth);
else {
switch (elemN) {
case 0:
CpyNcharacters (text, maxWidth, (int) '*');
break;
case 1:
if (strlen(text) + strlen(", ...") <= (size_t) maxWidth)
strcatX (text, ", ...", maxWidth);
else {
CpyNcharacters (text, maxWidth, (int) '*');
}
break;
default:
CpyNcharacters (text, maxWidth, (int) '*');
break;
}
}
break;
}
else
sprintf (&text[strlen(text)], "%s%s", (elemN > 0 ? ", " : ""),
tText);
}
else
sprintf (&text[strlen(text)], "%s%s", (elemN > 0 ? ", " : ""), tText);
}
/**************************************************************************
* Blank pad to `minWidth' if necessary.
**************************************************************************/
if (minWidth != 0) {
int n = strlen(text);
if (minWidth > 0) { /* Right justify. */
if (n < minWidth) {
int i, pad = minWidth - n;
memmove (&text[pad], text, n + 1);
for (i = 0; i < pad; i++) text[i] = ' ';
}
}
else { /* Left justify. */
int min = -minWidth;
if (n < min) {
int pad = min - n;
CatNcharacters (text, pad, (int) ' ');
}
}
}
}
/****************************************************************************
* Return length of encoded value(s).
****************************************************************************/
return strlen(text);
}
/******************************************************************************
* EncodeValueFormat.
* Returns width of encoded value. Not for use with character string data
* types (CDF_CHAR or CDF_UCHAR).
******************************************************************************/
int EncodeValueFormat (dataType, binary, text, format, minWidth, maxWidth,
style)
long dataType; /* Data type of value being encoded. */
void *binary; /* In: Value in binary. */
char *text; /* Out: Encoded value. */
char *format; /* Format string to be used. */
int minWidth; /* Minimum width (including delimeters if a string
data type. If zero, no minimum width (no blank
padding). If positive, right justified (padding
on left side). If negative, left justified
(padding on right side). */
int maxWidth; /* Maximum width. If zero, no maximum width (no
asteriks if too big). */
int style; /* EPOCH style. */
{
long CdataType;
char Cformat[MAX_cFORMAT_LEN+1];
char tText[MAX_nonSTRING_VALUE_LEN+1];
/****************************************************************************
* Encode value.
****************************************************************************/
if (EPOCHdataType(dataType)) {
switch (style) {
case EPOCHf_STYLE:
return EncodeValueFormat(CDF_DOUBLE,binary,text,
format,minWidth,maxWidth,0);
case EPOCHx_STYLE:
encodeEPOCHx (*((double *) binary), format, tText);
break;
default:
EncodeValue (CDF_EPOCH, binary, tText, style);
break;
}
} else if (EPOCH16dataType(dataType)) {
switch (style) {
case EPOCHf_STYLE:
return EncodeValueFormat(CDF_DOUBLE,binary,text,
format,minWidth,maxWidth,0);
case EPOCHx_STYLE:
encodeEPOCHx (*((double *) binary), format, tText);
break;
default:
EncodeValue (CDF_EPOCH16, binary, tText, style);
break;
}
}
else
if (format == NULL)
EncodeValue (dataType, binary, tText, 0);
else
if (strchr(format,'%') != NULL)
if (GetCdataType(format,&CdataType))
UseCformat (dataType, CdataType, format, binary, tText);
else
EncodeValue (dataType, binary, tText, 0);
else
if (FtoCformat(dataType,format,&CdataType,Cformat))
UseCformat (dataType, CdataType, Cformat, binary, tText);
else
EncodeValue (dataType, binary, tText, 0);
/****************************************************************************
* Fill in asteriks if encoded value is too big. Otherwise, copy encoded
* value.
****************************************************************************/
if (maxWidth > 0) {
int n = strlen(tText);
if (n > maxWidth)
CpyNcharacters (text, maxWidth, (int) '*');
else
strcpyX (text, tText, maxWidth);
}
else
strcpyX (text, tText, maxWidth);
/****************************************************************************
* Blank pad to `minWidth' if necessary.
****************************************************************************/
if (minWidth != 0) {
int n = strlen(text);
if (minWidth > 0) { /* Right justify. */
if (n < minWidth) {
int i, pad = minWidth - n;
memmove (&text[pad], text, n + 1);
for (i = 0; i < pad; i++) text[i] = ' ';
}
}
else { /* Left justify. */
int min = -minWidth;
if (n < min) {
int pad = min - n;
CatNcharacters (text, pad, (int) ' ');
}
}
}
/****************************************************************************
* Return length of encoded value.
****************************************************************************/
return strlen(text);
}
/******************************************************************************
* EncodeValue.
* Returns width of encoded value.
******************************************************************************/
int EncodeValue (dataType, binary, text, style)
long dataType; /* CDF data type. */
void *binary; /* In: Value to encode. */
char *text; /* Out: Encoded value. */
int style; /* In: EPOCH style. */
{
MakeNUL (text);
switch (dataType) {
case CDF_BYTE:
case CDF_INT1:
sprintf (text, "%d", (int) *((sChar *) binary));
break;
case CDF_INT2:
sprintf (text, "%d", (int) *((Int16 *) binary));
break;
case CDF_INT4:
sprintf (text, Int32FORMAT, *((Int32 *) binary));
break;
case CDF_UINT1:
sprintf (text, "%u", (uInt) *((uChar *) binary));
break;
case CDF_UINT2:
sprintf (text, "%u", (uInt) *((uInt16 *) binary));
break;
case CDF_UINT4:
sprintf (text, Int32uFORMAT, *((uInt32 *) binary));
break;
case CDF_REAL4:
case CDF_FLOAT: {
if (NegativeZeroReal4((float *) binary))
strcpyX (text, NEGATIVEzeroSYMBOL, 0);
else {
size_t len;
char *ePtr, tText[80+1];
sprintf (text, "%g", *((float *) binary));
if ((ePtr = strchr(text,'e')) == NULL) { /* eg., 0 */
if (strchr(text,'.') == NULL) strcatX (text,".0", 0);
}
else {
if (strchr(text,'.') == NULL) { /* eg., 1e+07 */
len = (size_t) (ePtr - text);
strcpyX (tText, text, MINIMUM(len,80));
strcatX (tText, ".0", 0);
strcatX (tText, ePtr, 0);
strcpyX (text, tText, 0);
}
}
}
break;
}
case CDF_REAL8:
case CDF_DOUBLE: {
if (NegativeZeroReal8((double *) binary))
strcpyX (text, NEGATIVEzeroSYMBOL, 0);
else {
size_t len;
char *ePtr, tText[80+1];
sprintf (text, "%g", *((double *) binary));
if ((ePtr = strchr(text,'e')) == NULL) { /* eg., 0 */
if (strchr(text,'.') == NULL) strcatX (text,".0", 0);
}
else {
if (strchr(text,'.') == NULL) { /* eg., 1e+07 */
len = (size_t) (ePtr - text);
strcpyX (tText, text, MINIMUM(len,80));
strcatX (tText, ".0", 0);
strcatX (tText, ePtr, 0);
strcpyX (text, tText, 0);
}
}
}
break;
}
case CDF_CHAR:
sprintf (text, "%c", *((sChar *) binary));
break;
case CDF_UCHAR:
sprintf (text, "%c", *((uChar *) binary));
break;
case CDF_EPOCH:
switch (style) {
case EPOCH0_STYLE:
encodeEPOCH (*((double *) binary), text);
break;
case EPOCH1_STYLE:
encodeEPOCH1 (*((double *) binary), text);
break;
case EPOCH2_STYLE:
encodeEPOCH2 (*((double *) binary), text);
break;
case EPOCH3_STYLE:
encodeEPOCH3 (*((double *) binary), text);
break;
case EPOCHf_STYLE:
return EncodeValue(CDF_DOUBLE,binary,text,0);
case EPOCHx_STYLE:
/* Unsupported (a format specification is needed). */
break;
}
break;
case CDF_EPOCH16:
switch (style) {
case EPOCH0_STYLE:
encodeEPOCH16 ((double *) binary, text);
break;
case EPOCH1_STYLE:
encodeEPOCH16_1 ((double *) binary, text);
break;
case EPOCH2_STYLE:
encodeEPOCH16_2 ((double *) binary, text);
break;
case EPOCH3_STYLE:
encodeEPOCH16_3 ((double *) binary, text);
break;
case EPOCHf_STYLE:
return EncodeValue(CDF_DOUBLE,binary,text,0);
case EPOCHx_STYLE:
/* Unsupported (a format specification is needed). */
break;
}
break;
}
return strlen(text);
}
/******************************************************************************
* EncodeString. Returns width of encoded string (including delimeters).
******************************************************************************/
int EncodeString (nChars, iString, oString, minWidth, maxWidth)
long nChars; /* Number of characters (elements). */
char *iString; /* String to encode (input). */
char *oString; /* Encoded string (output). */
int minWidth; /* Minimum width (including delimeters if a string
data type. If zero, no minimum width (no blank
padding). If positive, right justified (padding
on left side). If negative, left justified
(padding on right side). */
int maxWidth; /* Maximum width (including delimeters). If zero,
no maximum width (no truncating). */
{
char delim = PickDelimiter (iString, (size_t) nChars); int i;
/****************************************************************************
* Encode string.
****************************************************************************/
if (nChars + 2 > BOO(maxWidth == 0,(int)(nChars + 2),maxWidth)) {
/**************************************************************************
* Won't fit. Should at least encode `"a..."'. If not enough room, fill
* in with astericks.
**************************************************************************/
if (maxWidth < 6) {
CpyNcharacters (oString, maxWidth, (int) '*');
}
else {
oString[0] = delim;
for (i = 0; i < maxWidth - 5; i++) {
oString[i+1] = BOO(Printable(iString[i]),iString[i],'.');
}
oString[i+1] = '.';
oString[i+2] = '.';
oString[i+3] = '.';
oString[i+4] = delim;
oString[i+5] = NUL;
}
}
else {
/**************************************************************************
* Fits.
**************************************************************************/
oString[0] = delim;
for (i = 0; i < nChars; i++) {
oString[i+1] = BOO(Printable(iString[i]),iString[i],'.');
}
oString[i+1] = delim;
oString[i+2] = NUL;
}
/****************************************************************************
* Blank pad to `minWidth' if necessary.
****************************************************************************/
if (minWidth != 0) {
int n = strlen(oString);
if (minWidth > 0) { /* Right justify. */
if (n < minWidth) {
int i, pad = minWidth - n;
memmove (&oString[pad], oString, n + 1);
for (i = 0; i < pad; i++) oString[i] = ' ';
}
}
else { /* Left justify. */
int min = -minWidth;
if (n < min) {
int pad = min - n;
CatNcharacters (oString, pad, (int) ' ');
}
}
}
/****************************************************************************
* Return length of encoded string.
****************************************************************************/
return strlen(oString);
}
/******************************************************************************
* EncodeNegativeZero.
******************************************************************************/
void EncodeNegativeZero (string, format)
char *string;
char *format;
{
char *ptr;
/****************************************************************************
* Encode 0.0 using format then check if the value was successfully encoded.
****************************************************************************/
string[0] = NUL;
sprintf(string, format, 0.0);
if (NULstring(string)) {
strcpyX (string, "-0.0(bad FORMAT)", 0);
return;
}
/****************************************************************************
* 0.0 was successfully encoded - put a negative sign at the beginning
* (increasing the length of the string if necessary).
****************************************************************************/
ptr = string;
while (*ptr == ' ') ptr++;
if (ptr == string) {
memmove (&string[1], string, strlen(string) + 1);
string[0] = '-';
}
else
*(ptr - 1) = '-';
return;
}
/******************************************************************************
* UseCformat.
* Returns width of encoded value. Not for use with CDF_EPOCH or CDF_(U)CHAR
* values.
******************************************************************************/
static int UseCformat (dataType, CdataType, Cformat, binary, text)
long dataType; /* Value's actual data type. This should never be
CDF_EPOCH. */
long CdataType; /* Data type corresponding to C format. This should
never be CDF_EPOCH. */
char *Cformat; /* C format specification. */
void *binary; /* Value to be encoded. */
char *text; /* String into which to encode the value. */
{
switch (dataType) {
case CDF_BYTE:
case CDF_INT1:
switch (CdataType) {
case CDF_BYTE:
case CDF_INT1:
sprintf (text, Cformat, (sChar) *((sChar *) binary));
break;
case CDF_UINT1:
sprintf (text, Cformat, (uChar) *((sChar *) binary));
break;
case CDF_INT2:
sprintf (text, Cformat, (Int16) *((sChar *) binary));
break;
case CDF_UINT2:
sprintf (text, Cformat, (uInt16) *((sChar *) binary));
break;
case CDF_INT4:
sprintf (text, Cformat, (Int32) *((sChar *) binary));
break;
case CDF_UINT4:
sprintf (text, Cformat, (uInt32) *((sChar *) binary));
break;
case CDF_REAL4:
case CDF_FLOAT:
sprintf (text, Cformat, (float) *((sChar *) binary));
break;
case CDF_REAL8:
case CDF_DOUBLE:
sprintf (text, Cformat, (double) *((sChar *) binary));
break;
}
break;
case CDF_UINT1:
switch (CdataType) {
case CDF_BYTE:
case CDF_INT1:
sprintf (text, Cformat, (sChar) *((uChar *) binary));
break;
case CDF_UINT1:
sprintf (text, Cformat, (uChar) *((uChar *) binary));
break;
case CDF_INT2:
sprintf (text, Cformat, (Int16) *((uChar *) binary));
break;
case CDF_UINT2:
sprintf (text, Cformat, (uInt16) *((uChar *) binary));
break;
case CDF_INT4:
sprintf (text, Cformat, (Int32) *((uChar *) binary));
break;
case CDF_UINT4:
sprintf (text, Cformat, (uInt32) *((uChar *) binary));
break;
case CDF_REAL4:
case CDF_FLOAT:
sprintf (text, Cformat, (float) *((uChar *) binary));
break;
case CDF_REAL8:
case CDF_DOUBLE:
sprintf (text, Cformat, (double) *((uChar *) binary));
break;
}
break;
case CDF_INT2:
switch (CdataType) {
case CDF_BYTE:
case CDF_INT1:
sprintf (text, Cformat, (sChar) *((Int16 *) binary));
break;
case CDF_UINT1:
sprintf (text, Cformat, (uChar) *((Int16 *) binary));
break;
case CDF_INT2:
sprintf (text, Cformat, (Int16) *((Int16 *) binary));
break;
case CDF_UINT2:
sprintf (text, Cformat, (uInt16) *((Int16 *) binary));
break;
case CDF_INT4:
sprintf (text, Cformat, (Int32) *((Int16 *) binary));
break;
case CDF_UINT4:
sprintf (text, Cformat, (uInt32) *((Int16 *) binary));
break;
case CDF_REAL4:
case CDF_FLOAT:
sprintf (text, Cformat, (float) *((Int16 *) binary));
break;
case CDF_REAL8:
case CDF_DOUBLE:
sprintf (text, Cformat, (double) *((Int16 *) binary));
break;
}
break;
case CDF_UINT2:
switch (CdataType) {
case CDF_BYTE:
case CDF_INT1:
sprintf (text, Cformat, (sChar) *((uInt16 *) binary));
break;
case CDF_UINT1:
sprintf (text, Cformat, (uChar) *((uInt16 *) binary));
break;
case CDF_INT2:
sprintf (text, Cformat, (Int16) *((uInt16 *) binary));
break;
case CDF_UINT2:
sprintf (text, Cformat, (uInt16) *((uInt16 *) binary));
break;
case CDF_INT4:
sprintf (text, Cformat, (Int32) *((uInt16 *) binary));
break;
case CDF_UINT4:
sprintf (text, Cformat, (uInt32) *((uInt16 *) binary));
break;
case CDF_REAL4:
case CDF_FLOAT:
sprintf (text, Cformat, (float) *((uInt16 *) binary));
break;
case CDF_REAL8:
case CDF_DOUBLE:
sprintf (text, Cformat, (double) *((uInt16 *) binary));
break;
}
break;
case CDF_INT4:
switch (CdataType) {
case CDF_BYTE:
case CDF_INT1:
sprintf (text, Cformat, (sChar) *((Int32 *) binary));
break;
case CDF_UINT1:
sprintf (text, Cformat, (uChar) *((Int32 *) binary));
break;
case CDF_INT2:
sprintf (text, Cformat, (Int16) *((Int32 *) binary));
break;
case CDF_UINT2:
sprintf (text, Cformat, (uInt16) *((Int32 *) binary));
break;
case CDF_INT4:
sprintf (text, Cformat, (Int32) *((Int32 *) binary));
break;
case CDF_UINT4:
sprintf (text, Cformat, (uInt32) *((Int32 *) binary));
break;
case CDF_REAL4:
case CDF_FLOAT:
sprintf (text, Cformat, (float) *((Int32 *) binary));
break;
case CDF_REAL8:
case CDF_DOUBLE:
sprintf (text, Cformat, (double) *((Int32 *) binary));
break;
}
break;
case CDF_UINT4:
switch (CdataType) {
case CDF_BYTE:
case CDF_INT1:
sprintf (text, Cformat, (sChar) *((uInt32 *) binary));
break;
case CDF_UINT1:
sprintf (text, Cformat, (uChar) *((uInt32 *) binary));
break;
case CDF_INT2:
sprintf (text, Cformat, (Int16) *((uInt32 *) binary));
break;
case CDF_UINT2:
sprintf (text, Cformat, (uInt16) *((uInt32 *) binary));
break;
case CDF_INT4:
sprintf (text, Cformat, (Int32) *((uInt32 *) binary));
break;
case CDF_UINT4:
sprintf (text, Cformat, (uInt32) *((uInt32 *) binary));
break;
case CDF_REAL4:
case CDF_FLOAT:
sprintf (text, Cformat, (float) *((uInt32 *) binary));
break;
case CDF_REAL8:
case CDF_DOUBLE:
sprintf (text, Cformat, (double) *((uInt32 *) binary));
break;
}
break;
case CDF_REAL4:
case CDF_FLOAT:
switch (CdataType) {
case CDF_BYTE:
case CDF_INT1:
sprintf (text, Cformat, (sChar) *((float *) binary));
break;
case CDF_UINT1:
sprintf (text, Cformat, (uChar) *((float *) binary));
break;
case CDF_INT2:
sprintf (text, Cformat, (Int16) *((float *) binary));
break;
case CDF_UINT2:
sprintf (text, Cformat, (uInt16) *((float *) binary));
break;
case CDF_INT4:
sprintf (text, Cformat, (Int32) *((float *) binary));
break;
case CDF_UINT4:
sprintf (text, Cformat, (uInt32) *((float *) binary));
break;
case CDF_REAL4:
case CDF_FLOAT:
if (NegativeZeroReal4((float *) binary))
EncodeNegativeZero (text, Cformat);
else
sprintf (text, Cformat, (float) *((float *) binary));
break;
case CDF_REAL8:
case CDF_DOUBLE:
if (NegativeZeroReal4((float *) binary))
EncodeNegativeZero (text, Cformat);
else
sprintf (text, Cformat, (double) *((float *) binary));
break;
}
break;
case CDF_REAL8:
case CDF_DOUBLE:
switch (CdataType) {
case CDF_BYTE:
case CDF_INT1:
sprintf (text, Cformat, (sChar) *((double *) binary));
break;
case CDF_UINT1:
sprintf (text, Cformat, (uChar) *((double *) binary));
break;
case CDF_INT2:
sprintf (text, Cformat, (Int16) *((double *) binary));
break;
case CDF_UINT2:
sprintf (text, Cformat, (uInt16) *((double *) binary));
break;
case CDF_INT4:
sprintf (text, Cformat, (Int32) *((double *) binary));
break;
case CDF_UINT4:
sprintf (text, Cformat, (uInt32) *((double *) binary));
break;
case CDF_REAL4:
case CDF_FLOAT:
if (NegativeZeroReal8((double *) binary))
EncodeNegativeZero (text, Cformat);
else
sprintf (text, Cformat, (float) *((double *) binary));
break;
case CDF_REAL8:
case CDF_DOUBLE:
if (NegativeZeroReal8((double *) binary))
EncodeNegativeZero (text, Cformat);
else
sprintf (text, Cformat, (double) *((double *) binary));
break;
}
break;
}
/* Change ...e+0.. (3 numbers after +/-) from win32 to ...e+.. (2 numbers
after +/-) just like other systems */
#if defined(win32)
if (strchr(text, 'e') != NULL || strchr(text, 'E') != NULL) {
int ilen = strlen(text);
char *ie;
char *to0;
ie = strchr(text, 'e');
if (ie == NULL) ie = strchr(text, 'E');
to0 = strstr(ie, "+0");
if (to0 == NULL) to0 = strstr(ie, "-0");
if (to0 != NULL) {
if (strlen(ie) == 5) {
char *newText;
int itrail;
newText = (char *) malloc(ilen-1);
itrail = strlen(ie);
memmove(newText, text, ilen-itrail+2);
memmove(newText+ilen-itrail+2, text+ilen-itrail+3,
itrail-3);
newText[ilen-1] = NUL;
strcpy(text, newText);
}
}
}
#endif
return strlen(text);
}
/******************************************************************************
* FtoCformat.
* Returns TRUE if valid FORTRAN format specification.
******************************************************************************/
static Logical FtoCformat (dataType, Fformat, CdataType, Cformat)
long dataType; /* Value's actual data type. This should never be
CDF_EPOCH. */
char *Fformat; /* FORTRAN format specification. */
long *CdataType; /* Data type implied by C format specification. */
char *Cformat; /* C format specification. */
{
int nFound;
int w, m, d;
/****************************************************************************
* Change `Fformat' to point to first non-blank, non-digit, non-`('
* character. This will skip over a Fortran repeat count (eg. the `20' in
* `20F8.4' or `20(F8.4)').
****************************************************************************/
while (*Fformat != NUL && (*Fformat == '(' ||
Spacing(*Fformat) ||
Decimal(*Fformat))) Fformat++;
if (*Fformat == NUL) return FALSE;
/****************************************************************************
* Encode C format specification.
****************************************************************************/
switch (Fformat[0]) {
/**************************************************************************
* Integer/decimal.
**************************************************************************/
case 'I':
case 'i':
nFound = sscanf (&Fformat[1], "%d.%d", &w, &m);
switch (nFound) {
case 0:
return FALSE;
case 1:
switch (dataType) {
case CDF_BYTE:
case CDF_INT1:
sprintf (Cformat, "%%%dd", w);
*CdataType = CDF_INT1;
return TRUE;
case CDF_UINT1:
sprintf (Cformat, "%%%du", w);
*CdataType = CDF_UINT1;
return TRUE;
case CDF_INT2:
sprintf (Cformat, "%%%dd", w);
*CdataType = CDF_INT2;
return TRUE;
case CDF_UINT2:
sprintf (Cformat, "%%%du", w);
*CdataType = CDF_UINT2;
return TRUE;
case CDF_INT4:
sprintf (Cformat, "%%%d%sd", w, Int32FORMATmod);
*CdataType = CDF_INT4;
return TRUE;
case CDF_UINT4:
sprintf (Cformat, "%%%d%su", w, Int32FORMATmod);
*CdataType = CDF_UINT4;
return TRUE;
case CDF_REAL4:
case CDF_FLOAT:
case CDF_REAL8:
case CDF_DOUBLE:
sprintf (Cformat, "%%%d%sd", w, Int32FORMATmod);
*CdataType = CDF_INT4;
return TRUE;
}
return FALSE;
case 2:
switch (dataType) {
case CDF_BYTE:
case CDF_INT1:
sprintf (Cformat, "%%%d.%dd", w, m);
*CdataType = CDF_INT1;
return TRUE;
case CDF_UINT1:
sprintf (Cformat, "%%%d.%du", w, m);
*CdataType = CDF_UINT1;
return TRUE;
case CDF_INT2:
sprintf (Cformat, "%%%d.%dd", w, m);
*CdataType = CDF_INT2;
return TRUE;
case CDF_UINT2:
sprintf (Cformat, "%%%d.%du", w, m);
*CdataType = CDF_UINT2;
return TRUE;
case CDF_INT4:
sprintf (Cformat, "%%%d.%d%sd", w, m, Int32FORMATmod);
*CdataType = CDF_INT4;
return TRUE;
case CDF_UINT4:
sprintf (Cformat, "%%%d.%d%su", w, m, Int32FORMATmod);
*CdataType = CDF_UINT4;
return TRUE;
case CDF_REAL4:
case CDF_FLOAT:
case CDF_REAL8:
case CDF_DOUBLE:
sprintf (Cformat, "%%%d.%d%sd", w, m, Int32FORMATmod);
*CdataType = CDF_INT4;
return TRUE;
}
return FALSE;
}
return FALSE;
/**************************************************************************
* Integer/octal.
**************************************************************************/
case 'O':
case 'o':
nFound = sscanf (&Fformat[1], "%d.%d", &w, &m);
switch (nFound) {
case 0:
return FALSE;
case 1:
switch (dataType) {
case CDF_BYTE:
case CDF_INT1:
sprintf (Cformat, "%%%do", w);
*CdataType = CDF_UINT1;
return TRUE;
case CDF_UINT1:
sprintf (Cformat, "%%%do", w);
*CdataType = CDF_UINT1;
return TRUE;
case CDF_INT2:
sprintf (Cformat, "%%%do", w);
*CdataType = CDF_UINT2;
return TRUE;
case CDF_UINT2:
sprintf (Cformat, "%%%do", w);
*CdataType = CDF_UINT2;
return TRUE;
case CDF_INT4:
sprintf (Cformat, "%%%d%so", w, Int32FORMATmod);
*CdataType = CDF_UINT4;
return TRUE;
case CDF_UINT4:
sprintf (Cformat, "%%%d%so", w, Int32FORMATmod);
*CdataType = CDF_UINT4;
return TRUE;
case CDF_REAL4:
case CDF_FLOAT:
case CDF_REAL8:
case CDF_DOUBLE:
sprintf (Cformat, "%%%d%so", w, Int32FORMATmod);
*CdataType = CDF_UINT4;
return TRUE;
}
return FALSE;
case 2:
switch (dataType) {
case CDF_BYTE:
case CDF_INT1:
sprintf (Cformat, "%%%d.%do", w, m);
*CdataType = CDF_UINT1;
return TRUE;
case CDF_UINT1:
sprintf (Cformat, "%%%d.%do", w, m);
*CdataType = CDF_UINT1;
return TRUE;
case CDF_INT2:
sprintf (Cformat, "%%%d.%do", w, m);
*CdataType = CDF_UINT2;
return TRUE;
case CDF_UINT2:
sprintf (Cformat, "%%%d.%do", w, m);
*CdataType = CDF_UINT2;
return TRUE;
case CDF_INT4:
sprintf (Cformat, "%%%d.%d%so", w, m, Int32FORMATmod);
*CdataType = CDF_UINT4;
return TRUE;
case CDF_UINT4:
sprintf (Cformat, "%%%d.%d%so", w, m, Int32FORMATmod);
*CdataType = CDF_UINT4;
return TRUE;
case CDF_REAL4:
case CDF_FLOAT:
case CDF_REAL8:
case CDF_DOUBLE:
sprintf (Cformat, "%%%d.%d%so", w, m, Int32FORMATmod);
*CdataType = CDF_UINT4;
return TRUE;
}
return FALSE;
}
return FALSE;
/**************************************************************************
* Integer/hexadecimal.
**************************************************************************/
case 'Z':
case 'z':
nFound = sscanf (&Fformat[1], "%d.%d", &w, &m);
switch (nFound) {
case 0:
return FALSE;
case 1:
switch (dataType) {
case CDF_BYTE:
case CDF_INT1:
sprintf (Cformat, "%%%dX", w);
*CdataType = CDF_UINT1;
return TRUE;
case CDF_UINT1:
sprintf (Cformat, "%%%dX", w);
*CdataType = CDF_UINT1;
return TRUE;
case CDF_INT2:
sprintf (Cformat, "%%%dX", w);
*CdataType = CDF_UINT2;
return TRUE;
case CDF_UINT2:
sprintf (Cformat, "%%%dX", w);
*CdataType = CDF_UINT2;
return TRUE;
case CDF_INT4:
sprintf (Cformat, "%%%d%sX", w, Int32FORMATmod);
*CdataType = CDF_UINT4;
return TRUE;
case CDF_UINT4:
sprintf (Cformat, "%%%d%sX", w, Int32FORMATmod);
*CdataType = CDF_UINT4;
return TRUE;
case CDF_REAL4:
case CDF_FLOAT:
case CDF_REAL8:
case CDF_DOUBLE:
sprintf (Cformat, "%%%d%sX", w, Int32FORMATmod);
*CdataType = CDF_UINT4;
return TRUE;
}
return FALSE;
case 2:
switch (dataType) {
case CDF_BYTE:
case CDF_INT1:
sprintf (Cformat, "%%%d.%dX", w, m);
*CdataType = CDF_UINT1;
return TRUE;
case CDF_UINT1:
sprintf (Cformat, "%%%d.%dX", w, m);
*CdataType = CDF_UINT1;
return TRUE;
case CDF_INT2:
sprintf (Cformat, "%%%d.%dX", w, m);
*CdataType = CDF_UINT2;
return TRUE;
case CDF_UINT2:
sprintf (Cformat, "%%%d.%dX", w, m);
*CdataType = CDF_UINT2;
return TRUE;
case CDF_INT4:
sprintf (Cformat, "%%%d.%d%sX", w, m, Int32FORMATmod);
*CdataType = CDF_UINT4;
return TRUE;
case CDF_UINT4:
sprintf (Cformat, "%%%d.%d%sX", w, m, Int32FORMATmod);
*CdataType = CDF_UINT4;
return TRUE;
case CDF_REAL4:
case CDF_FLOAT:
case CDF_REAL8:
case CDF_DOUBLE:
sprintf (Cformat, "%%%d.%d%sX", w, m, Int32FORMATmod);
*CdataType = CDF_UINT4;
return TRUE;
}
return FALSE;
}
return FALSE;
/**************************************************************************
* Floating-point/non-scientific notation (which is called...
**************************************************************************/
case 'F':
case 'f':
nFound = sscanf (&Fformat[1], "%d.%d", &w, &d);
switch (nFound) {
case 2:
sprintf (Cformat, "%%%d.%df", w, d);
*CdataType = CDF_DOUBLE;
return TRUE;
}
return FALSE;
/**************************************************************************
* Floating-point/scientific notation.
**************************************************************************/
case 'E':
case 'e':
case 'D':
case 'd':
nFound = sscanf (&Fformat[1], "%d.%d", &w, &d);
switch (nFound) {
case 2:
sprintf (Cformat, "%%%d.%de", w, d);
*CdataType = CDF_DOUBLE;
return TRUE;
}
return FALSE;
/**************************************************************************
* Floating-point/notation depends on value.
**************************************************************************/
case 'G':
case 'g':
nFound = sscanf (&Fformat[1], "%d.%d", &w, &d);
switch (nFound) {
case 2:
sprintf (Cformat, "%%%d.%dg", w, d);
*CdataType = CDF_DOUBLE;
return TRUE;
}
return FALSE;
/**************************************************************************
* Character.
**************************************************************************/
case 'A':
case 'a':
nFound = sscanf (&Fformat[1], "%d", &w);
switch (nFound) {
case 1:
sprintf (Cformat, "%%%d.%ds", w, w);
*CdataType = CDF_CHAR;
return TRUE;
}
return FALSE;
}
return FALSE; /* Unknown FORTRAN format character. */
}
/******************************************************************************
* GetCdataType.
* Given a C format specification, returns the corresponding C data type.
******************************************************************************/
static long GetCdataType (Cformat, CdataType)
char *Cformat; /* C format specification. */
long *CdataType; /* Corresponding C data type. */
{
char *ptrB; /* Beginning of specification. */
char *ptrE; /* End of specification. */
/****************************************************************************
* Find beginning of specification.
****************************************************************************/
ptrB = Cformat;
while (*ptrB != NUL && Spacing(*ptrB)) ptrB++;
if (*ptrB != '%') return FALSE;
/****************************************************************************
* Find end of specification.
****************************************************************************/
ptrE = Cformat + strlen(Cformat) - 1;
while (ptrE != ptrB && Spacing(*ptrE)) ptrE--;
if (ptrE == ptrB) return FALSE;
/****************************************************************************
* Choose a data type based on the conversion character and possible modifier.
****************************************************************************/
switch (*ptrE) {
case 'd':
case 'i':
switch (*(ptrE-1)) {
case 'l':
*CdataType = CDF_INT4;
break;
case 'h':
*CdataType = CDF_INT2;
break;
default:
#if defined(dos)
*CdataType = CDF_INT2;
#else
*CdataType = CDF_INT4;
#endif
break;
}
break;
case 'x':
case 'X':
case 'o':
case 'u':
switch (*(ptrE-1)) {
case 'l':
*CdataType = CDF_UINT4;
break;
case 'h':
*CdataType = CDF_UINT2;
break;
default:
#if defined(dos)
*CdataType = CDF_UINT2;
#else
*CdataType = CDF_UINT4;
#endif
break;
}
break;
case 'c':
case 's':
*CdataType = CDF_CHAR;
break;
case 'f':
case 'e':
case 'E':
case 'g':
case 'G':
*CdataType = CDF_DOUBLE;
break;
default:
return FALSE; /* Unknown C format description. */
}
return TRUE;
}
/******************************************************************************
* EncodeDimensionality. Returns width of encoded dimensionality
******************************************************************************/
int EncodeDimensionality (string, numDims, dimSizes)
char *string;
long numDims;
long *dimSizes;
{
int dimN;
sprintf (string, "%ld:[", numDims);
for (dimN = 0; dimN < numDims; dimN++)
sprintf (&(string[strlen(string)]), "%s%ld", (dimN > 0 ? "," : ""),
dimSizes[dimN]);
strcatX (string, "]", 0);
return strlen(string);
}
/******************************************************************************
* EncodeVariances. Returns width of encoded variances.
******************************************************************************/
int EncodeVariances (string, recVary, numDims, dimVarys)
char *string;
long recVary;
long numDims;
long *dimVarys;
{
int dimN;
strcpyX (string, TFvarianceToken(recVary), 0);
strcatX (string, "/", 0);
for (dimN = 0; dimN < numDims; dimN++)
strcatX (string, TFvarianceToken(dimVarys[dimN]), 0);
return strlen(string);
}
/******************************************************************************
* EncodeRecordIndices.
* Uses `*' for record/dimension variances of NOVARY. Returns width of
* record/indices.
******************************************************************************/
int EncodeRecordIndices (string, recNum, recVary, numDims, indices, dimVarys)
char *string;
long recNum;
long recVary;
long numDims;
long indices[];
long dimVarys[];
{
int dimN;
if (recVary)
sprintf (string, "%ld", recNum + 1);
else
strcpyX (string, "*", 0);
strcatX (string, ":[", 0);
for (dimN = 0; dimN < numDims; dimN++) {
if (dimN != 0) strcatX (string, ",", 0);
if (dimVarys[dimN])
sprintf (&string[strlen(string)], "%ld", indices[dimN] + 1);
else
strcatX (string, "*", 0);
}
strcatX (string, "]", 0);
return strlen(string);
}
/******************************************************************************
* EncodeRecordIndicesVARY. Force record/dimension variances to VARY.
******************************************************************************/
int EncodeRecordIndicesVARY (string, recNum, numDims, indices)
char *string;
long recNum;
long numDims;
long indices[];
{
static long recVary = VARY;
static long dimVarys[CDF_MAX_DIMS] = { VARY, VARY, VARY, VARY, VARY,
VARY, VARY, VARY, VARY, VARY };
EncodeRecordIndices (string, recNum, recVary, numDims, indices, dimVarys);
return strlen(string);
}
/*****************************************************************************
* OnlineHelpFP.
*
* UNIX: The full pathname of the executable is not passed in via `argv[0]'.
* The command which was entered on the command line is passed in (aliases
* are, however, evaluated).
*
******************************************************************************/
FILE *OnlineHelpFP (filename, execpath)
char *filename; /* Name of help file. */
char *execpath; /* Pathname of executable (argv[0]). */
{
FILE *fp;
char pathname[DU_MAX_PATH_LEN+1];
#if !defined(mac)
char execname[DU_MAX_NAME_LEN+1];
char *envPtr;
#endif
#if defined(mac)
execpath; /* Quites the MPW C compiler. */
#endif
/****************************************************************************
* Try to use logical name (VMS) or environment variable (UNIX/POSIXshell,
* DOS, & Windows).
****************************************************************************/
#if defined(vms)
strcpyX (pathname, "CDF$HELP:", DU_MAX_PATH_LEN);
AppendToDir (pathname, filename);
fp = fopen (pathname, "r");
if (fp != NULL) return fp;
#endif
#if (defined(unix) && !defined(__MINGW32__)) || defined(dos) || \
defined(posixSHELL) || defined(win32)
envPtr = getenv ("CDF_HELP");
if (envPtr != NULL) {
strcpyX (pathname, envPtr, DU_MAX_PATH_LEN);
AppendToDir (pathname, filename);
#if defined(__CYGWIN__) || defined(__MINGW32__)
fp = fopen (pathname, "rt");
#else
fp = fopen (pathname, "r");
#endif
if (fp != NULL) return fp;
}
#endif
/***************************************************************************
* If not on a Macintosh...
* Try relative paths from location of executable in the following order...
* 1. From standard executable/binary directory.
* 2. From source directory.
* 3. Same directory as that containing the executable.
***************************************************************************/
#if !defined(mac)
if (execpath != NULL) {
if (execpath[0] != NUL) {
ParsePath (execpath, pathname, execname);
#if defined(vms)
pathname[strlen(pathname)-1] = NUL; /* Wipes out trailing `]'. */
strcatX (pathname, "-.HELP]", DU_MAX_PATH_LEN);
#endif
#if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \
defined(posixSHELL)
AppendToDir (pathname, "../lib/cdf/help");
#endif
#if defined(dos) || defined(win32) || defined(__CYGWIN__) || \
defined(__MINGW32__)
AppendToDir (pathname, "..\\help");
#endif
AppendToDir (pathname, filename);
#if defined(__CYGWIN__) || defined(__MINGW32__)
fp = fopen (pathname, "rt");
#else
fp = fopen (pathname, "r");
#endif
if (fp != NULL) return fp;
ParsePath (execpath, pathname, execname);
#if defined(vms)
pathname[strlen(pathname)-1] = NUL; /* Wipes out trailing `]'. */
strcatX (pathname, "-.-.HELP]", DU_MAX_PATH_LEN);
#endif
#if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \
defined(posixSHELL)
AppendToDir (pathname, "../help");
#endif
#if defined(dos) || defined(win32) || defined(__CYGWIN__) || \
defined(__MINGW32__)
AppendToDir (pathname, "..\\..\\help");
#endif
AppendToDir (pathname, filename);
#if defined(__CYGWIN__) || defined(__MINGW32__)
fp = fopen (pathname, "rt");
#else
fp = fopen (pathname, "r");
#endif
if (fp != NULL) return fp;
ParsePath (execpath, pathname, execname);
AppendToDir (pathname, filename);
fp = fopen (pathname, "r");
if (fp != NULL) return fp;
}
}
#endif
/***************************************************************************
* If on a Macintosh...try relative (partial) paths to the `help' file.
***************************************************************************/
#if defined(mac)
strcpyX (pathname, "::help", DU_MAX_PATH_LEN);
AppendToDir (pathname, filename);
fp = fopen (pathname, "r");
if (fp != NULL) return fp;
strcpyX (pathname, ":::help", DU_MAX_PATH_LEN);
AppendToDir (pathname, filename);
fp = fopen (pathname, "r");
if (fp != NULL) return fp;
#endif
/***************************************************************************
* If on a UNIX/POSIXshell or DOS/Windows system, assume that the `bin'
* directory has been added to the `path' and try a relative path from each
* `path' entry.
***************************************************************************/
#if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL) || \
defined(dos) || defined(win32)
#if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL)
#define SEP_CHAR ':'
#else
#define SEP_CHAR ';'
#endif
envPtr = getenv ("PATH");
if (envPtr != NULL) {
char *path = (char *) cdf_AllocateMemory (strlen(envPtr) + 1, FatalError);
char *p1 = path;
strcpyX (path, envPtr, 0);
for (;;) {
char *sepPtr = strchr (p1, SEP_CHAR);
if (sepPtr != NULL) *sepPtr = NUL;
strcpyX (pathname, p1, DU_MAX_PATH_LEN);
#if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \
defined(posixSHELL)
AppendToDir (pathname, "../lib/cdf/help");
#else
AppendToDir (pathname, "..\\help");
#endif
AppendToDir (pathname, filename);
#if defined(__CYGWIN__) || defined(__MINGW32__)
fp = fopen (pathname, "rt");
#else
fp = fopen (pathname, "r");
#endif
if (fp != NULL) {
cdf_FreeMemory (path, FatalError);
return fp;
}
if (sepPtr == NULL) break;
p1 = sepPtr + 1;
}
cdf_FreeMemory (path, FatalError);
}
#endif
/***************************************************************************
* Try pathes from the current directory.
***************************************************************************/
#if defined(vms)
strcpyX (pathname, "[-.HELP]", DU_MAX_PATH_LEN);
#endif
#if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \
defined(posixSHELL)
strcpyX (pathname, "../help", DU_MAX_PATH_LEN);
#endif
#if defined(dos) || defined(win32) || defined(__CYGWIN__) || \
defined(__MINGW32__)
strcpyX (pathname, "..\\help", DU_MAX_PATH_LEN);
#endif
AppendToDir (pathname, filename);
#if defined(__CYGWIN__) || defined(__MINGW32__)
fp = fopen (pathname, "rt");
#else
fp = fopen (pathname, "r");
#endif
if (fp != NULL) return fp;
#if defined(vms)
strcpyX (pathname, "[-.-.HELP]", DU_MAX_PATH_LEN);
#endif
#if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \
defined(posixSHELL)
strcpyX (pathname, "../../help", DU_MAX_PATH_LEN);
#endif
#if defined(dos) || defined(win32) || defined(__CYGWIN__) || \
defined(__MINGW32__)
strcpyX (pathname, "..\\..\\help", DU_MAX_PATH_LEN);
#endif
AppendToDir (pathname, filename);
#if defined(__CYGWIN__) || defined(__MINGW32__)
fp = fopen (pathname, "rt");
#else
fp = fopen (pathname, "r");
#endif
if (fp != NULL) return fp;
#if defined(vms)
strcpyX (pathname, "[-.-.-.HELP]", DU_MAX_PATH_LEN);
#endif
#if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \
defined(posixSHELL)
strcpyX (pathname, "../../../help", DU_MAX_PATH_LEN);
#endif
#if defined(dos) || defined(win32) || defined(__CYGWIN__) || \
defined(__MINGW32__)
strcpyX (pathname, "..\\..\\..\\help", DU_MAX_PATH_LEN);
#endif
AppendToDir (pathname, filename);
#if defined(__CYGWIN__) || defined(__MINGW32__)
fp = fopen (pathname, "rt");
#else
fp = fopen (pathname, "r");
#endif
if (fp != NULL) return fp;
#if defined(win32) || defined(__CYGWIN__) || defined(__MINGW32__)
strcpyX (pathname, "help", DU_MAX_PATH_LEN);
#endif
AppendToDir (pathname, filename);
#if defined(__CYGWIN__) || defined(__MINGW32__)
fp = fopen (pathname, "rt");
#else
fp = fopen (pathname, "r");
#endif
if (fp != NULL) return fp;
/***************************************************************************
* Try current directory.
***************************************************************************/
#if defined(__CYGWIN__) || defined(__MINGW32__)
fp = fopen (pathname, "rt");
#else
fp = fopen (pathname, "r");
#endif
if (fp != NULL) return fp;
/***************************************************************************
* Give up.
***************************************************************************/
return NULL;
}
/*****************************************************************************
* PageOLH.
*****************************************************************************/
void PageOLH (olhFile, argv0)
char *olhFile;
char *argv0;
{
FILE *fp;
char line[MAX_SCREENLINE_LEN+1+1];
int nestLevel = 0; /* Depth into `#ifos's. */
int osMask = 0; /* When 0, display line. Note that bit
0 is not used (eg. nesting depth of
1 uses bit 1, etc.). */
#if defined(vms)
static char thisOS[] = "vms";
#endif
#if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \
defined(posixSHELL)
static char thisOS[] = "unix";
#endif
#if defined(dos) || defined(__CYGWIN__) || defined(__MINGW32__) || \
(defined(win32) && defined(ALONE))
static char thisOS[] = "dos";
#endif
#if defined(mac)
static char thisOS[] = "mac";
#endif
#if defined(win32) && !defined(ALONE)
static char thisOS[] = "win";
#endif
static char *openErrorMsg = {
"Error opening online help file - contact CDFsupport.\n"
};
static char *syntaxErrorMsg = {
"Syntax error in online help file - contact CDFsupport.\n"
};
/****************************************************************************
* Open online help file.
****************************************************************************/
fp = OnlineHelpFP (olhFile, argv0);
if (fp == NULL) {
WriteOut (stdout, openErrorMsg);
return;
}
/****************************************************************************
* Read online help file - passing appropriate lines through for display.
****************************************************************************/
while (fgets(line,MAX_SCREENLINE_LEN+1+1,fp) != NULL) {
/**************************************************************************
* Check if an operating system directive. If not, display the line if
* all of the bits in the operating system mask are clear.
**************************************************************************/
if (line[0] == '#') {
line[strlen(line)-1] = NUL;
/************************************************************************
* Check for a `#ifos' directive. If this operating system is not
* specified, then set the bit in the operating system mask for this
* nesting level.
************************************************************************/
if (!strncmp(line,"#ifos",5)) {
nestLevel++;
if (strstr(line,thisOS) == NULL) SETBIT (osMask, nestLevel);
continue;
}
/************************************************************************
* Check for a `#else' directive. Simply flip the bit in the operating
* system mask for this nesting level.
************************************************************************/
if (!strcmp(line,"#else")) {
if (nestLevel < 1) {
WriteOut (stdout, syntaxErrorMsg);
break;
}
FLPBIT (osMask, nestLevel);
continue;
}
/************************************************************************
* Check for a `#endos' directive. Clear the bit in the operating system
* mask for this nesting level and decrement the nesting level.
************************************************************************/
if (!strcmp(line,"#endos")) {
if (nestLevel < 1) {
WriteOut (stdout, syntaxErrorMsg);
break;
}
CLRBIT (osMask, nestLevel);
nestLevel--;
continue;
}
/************************************************************************
* An unknown directive has been encountered - assume it to be a comment.
************************************************************************/
continue;
}
else {
if (osMask == 0) WriteOut (stdout, line);
}
}
if (nestLevel != 0) WriteOut (stdout, syntaxErrorMsg);
fclose (fp);
return;
}
/******************************************************************************
* OutputWithMargin.
* Outputs a long text string to multiple lines of a file (or stdout)
* breaking the lines at blanks if possible.
******************************************************************************/
void OutputWithMargin (fp, text, maxLen, marginLen)
FILE *fp;
char *text;
int maxLen; /* Maximum length of line (including margin). */
int marginLen; /* Length of margin preceeding text on each line. */
{
char *ptr = text, *ptrT;
int maxLenT = maxLen - marginLen; /* Maximum number of characters per
line (excluding the margin). */
for (;;) {
/*************************************************************************
* If the remaining characters will fit on a line, print them and return.
* This also covers the case where the entire text will fit on one line.
*************************************************************************/
if (strlen(ptr) <= (size_t) maxLenT) {
if (marginLen > 0) Ncharacters (fp, marginLen, (int) ' ');
WriteOut (fp, ptr);
WriteOut (fp, "\n");
return;
}
/*************************************************************************
* Otherwise, find a blank character at which to break the characters. The
* blank is not printed on either line.
*************************************************************************/
for (ptrT = ptr + maxLenT; ptrT != ptr; ptrT--) {
if (*ptrT == ' ') {
char *string = NULedString (ptr, (int) (ptrT - ptr));
if (marginLen > 0) Ncharacters (fp, marginLen, (int) ' ');
WriteOut (fp, string);
WriteOut (fp, "\n");
ptr = ptrT + 1;
cdf_FreeMemory (string, FatalError);
break;
}
}
/*************************************************************************
* If a blank could not be found, break the characters at the end of the
* maximum number per line.
*************************************************************************/
if (ptrT == ptr) {
char *string = NULedString (ptr, maxLenT);
if (marginLen > 0) Ncharacters (fp, marginLen, (int) ' ');
WriteOut (fp, string);
WriteOut (fp, "\n");
ptr += maxLenT;
cdf_FreeMemory (string, FatalError);
}
}
}
/******************************************************************************
* InitPctLog.
******************************************************************************/
void InitPctLog (lastPct, pctOn)
int *lastPct;
Logical *pctOn;
{
WriteOut (stdout, "..0%");
*lastPct = 0;
*pctOn = TRUE;
return;
}
/******************************************************************************
* UpdatePctLog.
******************************************************************************/
void UpdatePctLog (pct, lastPct)
int pct;
int *lastPct;
{
if (pct != *lastPct) {
char string[10+1];
sprintf (string, "\b\b\b\b%s%d%%",
(pct < 10 ? ".." : (pct < 100 ? "." : "")), pct);
WriteOut (stdout, string);
*lastPct = pct;
}
return;
}
/******************************************************************************
* RefreshPctLog.
******************************************************************************/
void RefreshPctLog (lastPct)
int lastPct;
{
char string[6+1];
sprintf (string, "%s%d%%",
(lastPct < 10 ? ".." : (lastPct < 100 ? "." : "")), lastPct);
WriteOut (stdout, string);
return;
}
/******************************************************************************
* CleanupPctLog.
* 100% is output in case there were no values (in which case 0% would be
* currently displayed).
******************************************************************************/
void CleanupPctLog (pctOn)
Logical *pctOn;
{
WriteOut (stdout, "\b\b\b\b100%\n");
*pctOn = FALSE;
return;
}
/******************************************************************************
* Ncharacters.
* Outputs a specified number of a selected character to a file pointer.
******************************************************************************/
void Ncharacters (fp, nChars, chr)
FILE *fp;
int nChars;
int chr;
{
int i; char string[1+1];
string[0] = (char) chr;
string[1] = NUL;
for (i = 0; i < nChars; i++) WriteOut (fp, string);
return;
}
/******************************************************************************
* CatNcharacters.
* Concatenates some number of a specified character to a string.
******************************************************************************/
void CatNcharacters (string, nChars, chr)
char *string;
int nChars;
int chr;
{
int i;
for (i = 0; i < nChars; i++) catchrX (string, chr, 0);
return;
}
/******************************************************************************
* CpyNcharacters.
* Copies some number of a specified character to a string.
******************************************************************************/
void CpyNcharacters (string, nChars, chr)
char *string;
int nChars;
int chr;
{
int i;
for (i = 0; i < nChars; i++) string[i] = (char) chr;
string[nChars] = NUL;
return;
}
/******************************************************************************
* TFqualifier.
******************************************************************************/
Logical TFqualifier (qop, variable, Tx, Fx, defaultTF, conflictText)
QOP *qop;
Logical *variable;
int Tx;
int Fx;
Logical defaultTF;
char *conflictText;
{
int count = 0;
if (qop->qualEntered[Tx]) count++;
if (qop->qualEntered[Fx]) count++;
switch (count) {
case 0:
*variable = defaultTF;
return TRUE;
case 1:
*variable = (qop->qualEntered[Tx] ? TRUE : FALSE);
return TRUE;
default: {
char tempS[MAX_MESSAGE_TEXT_LEN+1];
sprintf (tempS, "Conflicting qualifiers (%s & no%s).",
conflictText, conflictText);
DisplayError (tempS);
return FALSE;
}
}
}
/******************************************************************************
* S2qualifierLong.
******************************************************************************/
Logical S2qualifierLong (qop, variable, S1x, S1, S2x, S2, defaultS,
conflictText)
QOP *qop;
long *variable;
int S1x;
long S1;
int S2x;
long S2;
long defaultS;
char *conflictText;
{
int count = 0;
if (qop->qualEntered[S1x]) count++;
if (qop->qualEntered[S2x]) count++;
switch (count) {
case 0:
*variable = defaultS;
return TRUE;
case 1:
*variable = (qop->qualEntered[S1x] ? S1 : S2);
return TRUE;
default: {
char tempS[MAX_MESSAGE_TEXT_LEN+1];
sprintf (tempS, "Conflicting qualifiers (%s).", conflictText);
DisplayError (tempS);
return FALSE;
}
}
}
/******************************************************************************
* S3qualifierLong.
******************************************************************************/
Logical S3qualifierLong (qop, variable, S1x, S1, S2x, S2, S3x, S3, defaultS,
conflictText)
QOP *qop;
long *variable;
int S1x;
long S1;
int S2x;
long S2;
int S3x;
long S3;
long defaultS;
char *conflictText;
{
int count = 0;
if (qop->qualEntered[S1x]) count++;
if (qop->qualEntered[S2x]) count++;
if (qop->qualEntered[S3x]) count++;
switch (count) {
case 0:
*variable = defaultS;
return TRUE;
case 1:
*variable = BOO(qop->qualEntered[S1x],S1,
BOO(qop->qualEntered[S2x],S2,S3));
return TRUE;
default: {
char tempS[MAX_MESSAGE_TEXT_LEN+1];
sprintf (tempS, "Conflicting qualifiers (%s).", conflictText);
DisplayError (tempS);
return FALSE;
}
}
}
/******************************************************************************
* BlankPadRight.
* Concatenate blanks to the right end of a string.
******************************************************************************/
void BlankPadRight (string, count)
char *string;
int count;
{
int i;
for (i = 0; i < count; i++) catchrX (string, (int) ' ', 0);
return;
}
/******************************************************************************
* GetFormatEntry.
* It is assumed that the current CDF has been selected.
******************************************************************************/
CDFstatus GetFormatEntry (Z, varNum, format)
Logical Z;
long varNum;
char **format;
{
CDFstatus pStatus = CDF_OK, status; long dataType, numElems;
status = CDFlib (SELECT_, ATTR_NAME_, "FORMAT",
BOO(Z,zENTRY_,rENTRY_), varNum,
GET_, BOO(Z,zENTRY_DATATYPE_,rENTRY_DATATYPE_), &dataType,
BOO(Z,zENTRY_NUMELEMS_,rENTRY_NUMELEMS_), &numElems,
NULL_);
switch (status) {
case NO_SUCH_ATTR:
case NO_SUCH_ENTRY:
*format = NULL;
return pStatus;
default:
if (!sX(status,&pStatus)) {
*format = NULL;
return pStatus;
}
}
if (!STRINGdataType(dataType)) {
*format = NULL;
return pStatus;
}
*format = (char *) cdf_AllocateMemory ((size_t) (numElems + 1),
FatalError);
status = CDFlib (GET_, BOO(Z,zENTRY_DATA_,rENTRY_DATA_), *format,
NULL_);
if (!sX(status,&pStatus)) {
cdf_FreeMemory (*format, FatalError);
*format = NULL;
return pStatus;
}
(*format)[(int)numElems] = NUL;
return pStatus;
}
/******************************************************************************
* ParseOptionList.
******************************************************************************/
Logical ParseOptionList (nTokens, tokens, list, present)
int nTokens;
char *tokens[];
char *list;
Logical present[];
{
int tokenN, matchN; size_t tokenLen;
char token[MAX_TOKEN_LEN+1], *ptr1, *ptr2, terminator;
/****************************************************************************
* Assume initially that none of the tokens were found.
****************************************************************************/
for (tokenN = 0; tokenN < nTokens; tokenN++) present[tokenN] = FALSE;
/****************************************************************************
* Check that the entered list of tokens is not a NUL string, that there are
* some possible tokens to match, etc.
****************************************************************************/
if (NULstring(list)) return TRUE; /* Obviously, no tokens were found. */
if (nTokens < 1) return FALSE; /* Probably a logic error. */
/****************************************************************************
* Scan the entered list of tokens searching for matches with the list of
* possible tokens. First determine the starting character position and the
* ending delimiter.
****************************************************************************/
switch (list[0]) {
case '(': /* VMS-style. */
terminator = ')';
ptr1 = list + 1;
break;
case '"': /* UNIX-style on a Mac (double quotes not stripped). */
terminator = '"';
ptr1 = list + 1;
break;
default: /* UNIX-style on a UNIX machine or IBM PC. */
terminator = NUL;
ptr1 = list;
break;
}
for (;;) {
/*************************************************************************
* Find beginning of the next token in list (skipping past any leading
* blanks). If the end of the list is reached instead, then there are
* no more tokens.
*************************************************************************/
while (*ptr1 == ' ') ptr1++;
if (*ptr1 == terminator) return TRUE;
/*************************************************************************
* Find the end of the token and copy. The token is ended by either a
* blank, comma, or the terminator.
*************************************************************************/
ptr2 = ptr1 + 1;
while (*ptr2 != ' ' && *ptr2 != ',' && *ptr2 != terminator) ptr2++;
tokenLen = (size_t) (ptr2 - ptr1);
strcpyX (token, ptr1, MINIMUM(tokenLen,MAX_TOKEN_LEN));
/*************************************************************************
* Search possible tokens for a match. If more than one match is found,
* return an error.
*************************************************************************/
for (matchN = -1, tokenN = 0; tokenN < nTokens; tokenN++)
if (strncmpIgCasePattern(token,tokens[tokenN],strlen(token)) == 0)
if (matchN == -1)
matchN = tokenN;
else
return FALSE;
if (matchN == -1)
return FALSE;
else
present[matchN] = TRUE;
/*************************************************************************
* Setup to search for next token in list.
*************************************************************************/
switch (*ptr2) {
case ' ':
/*********************************************************************
* The last token was ended by a blank. Check to see if a comma is
* the next non-blank character. If so, the next token begins one
* character beyond the comma (leading blanks will be skipped when
* the beginning of that token is located). Otherwise, the next token
* begins at the non-blank character.
*********************************************************************/
ptr1 = ptr2 + 1;
while (*ptr1 == ' ') ptr1++;
if (*ptr1 == ',') ptr1++;
break;
case ',':
/*********************************************************************
* The last token was ended by a comma. The next token begins one
* character beyond the comma.
*********************************************************************/
ptr1 = ptr2 + 1;
break;
default:
/*********************************************************************
* The terminator must have ended the last token.
*********************************************************************/
return TRUE;
}
}
}
/******************************************************************************
* NULedString.
* Returns a pointer to a NUL-terminated string that was allocated here but
* not freed. The caller must free the string when no longer needed. Also,
* `len'+1 characters will be allocated for the new string (and copied to from
* the existing string) regardless of whether or not a NUL appears in the first
* `len' characters.
******************************************************************************/
char *NULedString (ptr, len)
char *ptr; /* Pointer to the string from which to extract
the first `len' characters. */
size_t len; /* Number of characters to extract. This does
not include the terminating NUL that will
be appended to the string being returned. */
{
char *string;
string = (char *) cdf_AllocateMemory (len + 1, FatalError);
memmove (string, ptr, len);
string[len] = NUL;
return string;
}
/******************************************************************************
* WriteOutSO.
******************************************************************************/
#if defined(STDARG)
int WriteOutSO (char *format, ...)
#else
int WriteOutSO (va_alist)
va_dcl
#endif
{
#if !defined(STDARG)
char *format;
#endif
int n;
char text[MAX_oTEXT_LEN];
va_list ap;
#if defined(STDARG)
va_start (ap, format);
#else
VA_START (ap);
format = va_arg (ap, char *);
#endif
vsprintf (text, format, ap);
n = WriteOut (stdout, text);
va_end (ap);
return n;
}
/******************************************************************************
* WriteOutFP.
******************************************************************************/
#if defined(STDARG)
int WriteOutFP (FILE *fp, char *format, ...)
#else
int WriteOutFP (va_alist)
va_dcl
#endif
{
#if !defined(STDARG)
FILE *fp;
char *format;
#endif
int n;
char text[MAX_oTEXT_LEN];
va_list ap;
#if defined(STDARG)
va_start (ap, format);
#else
VA_START (ap);
fp = va_arg (ap, FILE *);
format = va_arg (ap, char *);
#endif
vsprintf (text, format, ap);
n = WriteOut (fp, text);
va_end (ap);
return n;
}
/******************************************************************************
* WriteOut.
* Returns number of characters output.
******************************************************************************/
int WriteOut (fp, text)
FILE *fp;
char *text;
{
/****************************************************************************
* If the output is not going to `stdout', then assume it is going to a file
* (and ignore paging if requested).
****************************************************************************/
if (fp != stdout)
fprintf (fp, "%s", text);
else {
/**************************************************************************
* The output is going to `stdout'. Assume that `stdout' has not been
* redirected away from the user's terminal (to a file). If `stdout' has
* been redirected to a file, then hopefully the user had enough sense not
* to request paging.
**************************************************************************/
#if defined(mac) || (defined(win32) && !defined(ALONE))
#if defined(mac)
WriteOutMacSO (text);
#else
#if defined(SO)
WriteOutWin32 (text);
#endif
#endif
#else
char *ptr = text, *ptrNL; size_t len;
/**************************************************************************
* If paging is on, first prompt for `more...' if the end of the standard
* output screen has been reached.
**************************************************************************/
for (;;) {
/***********************************************************************
* If paging on, check if the maximum number of lines have been written.
***********************************************************************/
if (pagingOn) {
if (soLineCount == MAX_LINES_WHEN_PAGING) {
char key = NUL; static char prompt[] = "\nEnter RETURN for more...";
WriteStringStdOut (prompt, strlen(prompt));
ReadCharStdIn (&key);
if (key != '\n') pagingOn = FALSE;
WriteStringStdOut ("\n\n", 2);
soLineCount = 0;
}
}
/***********************************************************************
* Write the string up to the next newline character. If there aren't
* any(more) newline characters, write the rest of the string.
***********************************************************************/
ptrNL = strchr (ptr, Nl);
if (ptrNL == NULL) {
len = strlen (ptr);
WriteStringStdOut (ptr, len);
break;
}
else {
len = (int) (ptrNL - ptr + 1);
WriteStringStdOut (ptr, len);
if (pagingOn) soLineCount++;
ptr = ptrNL + 1;
if (*ptr == NUL) break;
}
}
fflush (stdout);
#endif
}
return strlen(text);
}
/******************************************************************************
* DirList.
* If an error occurs (or no files found), zero (0) is returned.
******************************************************************************/
int DirList (dir, patternC, patternS, dirS, nameS)
char *dir; /* In: Directory to search. */
int patternC; /* In: Pattern count. */
char **patternS; /* In: Patterns to search for. */
char ***dirS; /* Out: Directories. */
char ***nameS; /* Out: File names. */
{
int i;
int nFiles = 0;
int tNameChars = 0;
struct FILEstruct *FILEhead = NULL;
struct FILEstruct *FILEptr;
struct FILEstruct *FILEptrT;
char *dirP, *nameP;
size_t nNameChars;
#if defined(BORLANDC)
char pathX[DU_MAX_PATH_LEN + 1];
struct ffblk ffblk;
int done;
#endif
#if defined(MICROSOFTC)
char pathX[DU_MAX_PATH_LEN + 1];
struct find_t fileinfo;
int done;
#endif
#if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL)
DIR *dirp;
char dirX[DU_MAX_PATH_LEN + 1];
char pattern[DU_MAX_NAME_LEN+1];
#if defined(Mach)
struct direct *dp;
#else
struct dirent *dp;
#endif
#endif
#if defined(vms)
char pathX[DU_MAX_PATH_LEN + 1];
char pathFound[DU_MAX_PATH_LEN + 1];
struct dsc$descriptor_s pathDESCR;
struct dsc$descriptor_s pathFoundDESCR;
uLong context = 0;
char name[DU_MAX_NAME_LEN + 1];
uLong status;
#endif
#if defined(mac)
short vRefNum;
long dirID;
OSErr rCode;
CInfoPBRec cParms;
Str255 tempS;
char *name;
char pattern[DU_MAX_NAME_LEN+1];
#endif
#if defined(win32)
char pathX[DU_MAX_PATH_LEN + 1];
long handle;
struct _finddata_t fdata;
int done;
#endif
#if defined(win32)
/****************************************************************************
* Find files on Windows machine. Note that only one directory is possible
* per path on Windows systems.
****************************************************************************/
for (i = 0; i < patternC; i++) {
ExpandPath (dir, pathX);
AppendToDir (pathX, patternS[i]);
handle = _findfirst (pathX, &fdata);
if (handle != -1) {
done = FALSE;
while (!done) {
/***********************************************************************
* Allocate/setup file structure.
***********************************************************************/
FILEptr = (struct FILEstruct *) cdf_AllocateMemory (sizeof(struct FILEstruct), FatalError);
nNameChars = strlen (fdata.name);
FILEptr->name = (char *) cdf_AllocateMemory (nNameChars + 1, FatalError);
strcpyX (FILEptr->name, fdata.name, nNameChars);
tNameChars += nNameChars + 1;
nFiles++;
FILEptr->next = NULL;
AddToList (&FILEhead, FILEptr);
/***********************************************************************
* Get next matching file.
***********************************************************************/
done = _findnext (handle, &fdata);
}
_findclose (handle);
}
}
#endif
#if defined(dos)
/****************************************************************************
* Find files on MS-DOS machine. Note that only one directory is possible
* per path on MS-DOS systems.
****************************************************************************/
for (i = 0; i < patternC; i++) {
ExpandPath (dir, pathX);
AppendToDir (pathX, patternS[i]);
#if defined(BORLANDC)
done = findfirst (pathX, &ffblk, 0);
#endif
#if defined(MICROSOFTC)
done = _dos_findfirst (pathX, 0, &fileinfo);
#endif
while (!done) {
/***********************************************************************
* Allocate/setup file structure.
***********************************************************************/
FILEptr = (struct FILEstruct *)
cdf_AllocateMemory (sizeof(struct FILEstruct),
FatalError);
#if defined(BORLANDC)
nNameChars = strlen (ffblk.ff_name);
FILEptr->name = (char *) cdf_AllocateMemory (nNameChars + 1, FatalError);
strcpyX (FILEptr->name, ffblk.ff_name, nNameChars);
#endif
#if defined(MICROSOFTC)
nNameChars = strlen (fileinfo.name);
FILEptr->name = (char *) cdf_AllocateMemory (nNameChars + 1, FatalError);
strcpyX (FILEptr->name, fileinfo.name, nNameChars);
#endif
tNameChars += nNameChars + 1;
nFiles++;
FILEptr->next = NULL;
AddToList (&FILEhead, FILEptr);
/***********************************************************************
* Get next matching file.
***********************************************************************/
#if defined(BORLANDC)
done = findnext (&ffblk);
#endif
#if defined(MICROSOFTC)
done = _dos_findnext (&fileinfo);
#endif
}
}
#endif
#if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL)
/****************************************************************************
* Find files on UNIX machine. Note that only one directory is possible per
* path on UNIX systems.
****************************************************************************/
ExpandPath (dir, dirX);
if (NULstring(dirX)) strcpyX (dirX, ".", DU_MAX_PATH_LEN);
/* Default to current dir. */
dirp = opendir (dirX);
if (dirp == NULL) return 0;
dp = readdir (dirp);
while (dp != NULL) {
char *name = dp->d_name;
#if SOLARISbsdDIRUTILSbug
name -= 2;
#endif
for (i = 0; i < patternC; i++) {
strcpyX (pattern, patternS[i], DU_MAX_NAME_LEN);
if (NULstring(pattern)) strcpyX (pattern, "*", DU_MAX_NAME_LEN);
/* Default to all files. */
if (PatternMatch (pattern, name)) {
/*********************************************************************
* Allocate/setup file structure.
*********************************************************************/
FILEptr = (struct FILEstruct *)
cdf_AllocateMemory (sizeof(struct FILEstruct),
FatalError);
nNameChars = strlen (name);
FILEptr->name = (char *) cdf_AllocateMemory (nNameChars + 1, FatalError);
strcpyX (FILEptr->name, name, nNameChars);
tNameChars += nNameChars + 1;
nFiles++;
FILEptr->next = NULL;
AddToList (&FILEhead, FILEptr);
break;
}
}
/**************************************************************************
* Get next file.
**************************************************************************/
dp = readdir (dirp);
}
closedir (dirp);
#endif
#if defined(vms)
/****************************************************************************
* Find files on VMS machine. Note that a logical name defined to be a set of
* two or more directories may result in files from more than one directory
* being found. In that case, the logical name would be returned as the name
* of the directory (the VMS file system handles this when opening a file).
* The actual directories are ignored.
****************************************************************************/
pathFoundDESCR.dsc$w_length = sizeof(pathFound) - 1; /* Pass full string. */
pathFoundDESCR.dsc$b_dtype = DSC$K_DTYPE_T;
pathFoundDESCR.dsc$b_class = DSC$K_CLASS_S;
pathFoundDESCR.dsc$a_pointer = pathFound;
for (i = 0; i < patternC; i++) {
ExpandPath (dir, pathX);
AppendToDir (pathX, patternS[i]);
pathDESCR.dsc$w_length = strlen(pathX); /* Pass part used. */
pathDESCR.dsc$b_dtype = DSC$K_DTYPE_T;
pathDESCR.dsc$b_class = DSC$K_CLASS_S;
pathDESCR.dsc$a_pointer = pathX;
while ((status = lib$find_file (&pathDESCR, &pathFoundDESCR, &context,
NULL, NULL, NULL, NULL)) == RMS$_NORMAL) {
/***********************************************************************
* A file was found, NUL terminate and remove trailing blanks (version
* number is left on).
***********************************************************************/
pathFound[pathFoundDESCR.dsc$w_length] = NUL; /* NUL-terminate. */
for (i = strlen(pathFound) - 1; i >= 0 && pathFound[i] == ' '; i--) {
pathFound[i] = NUL;
}
ParsePath (pathFound, NULL, name);
/***********************************************************************
* Allocate/setup file structure.
***********************************************************************/
FILEptr = (struct FILEstruct *)
cdf_AllocateMemory (sizeof(struct FILEstruct),
FatalError);
nNameChars = strlen (name);
FILEptr->name = (char *) cdf_AllocateMemory (nNameChars + 1,
FatalError);
strcpyX (FILEptr->name, name, nNameChars);
tNameChars += nNameChars + 1;
nFiles++;
FILEptr->next = NULL;
AddToList (&FILEhead, FILEptr);
}
status = lib$find_file_end (&context);
}
#endif
#if defined(mac)
/****************************************************************************
* Find files on a Macintosh. Note that only one directory is possible per
* path on Macintosh systems.
****************************************************************************/
if (!MacDirSpecified(dir,&vRefNum,&dirID)) {
*nameS = NULL;
*dirS = NULL;
return 0;
}
cParms.hFileInfo.ioNamePtr = tempS;
cParms.hFileInfo.ioVRefNum = vRefNum;
cParms.hFileInfo.ioFDirIndex = 1;
cParms.hFileInfo.ioDirID = dirID;
rCode = PBGetCatInfo (&cParms, FALSE);
while (rCode == noErr) {
/**************************************************************************
* Check if a file (rather than a directory).
**************************************************************************/
if (BITCLR(cParms.hFileInfo.ioFlAttrib,4)) {
name = PtoCstr (cParms.hFileInfo.ioNamePtr);
for (i = 0; i < patternC; i++) {
strcpyX (pattern, patternS[i], DU_MAX_NAME_LEN);
if (NULstring(pattern)) strcpyX (pattern, "*", DU_MAX_NAME_LEN);
if (PatternMatch(pattern,name)) {
/*******************************************************************
* Allocate/setup file structure.
*******************************************************************/
FILEptr = (struct FILEstruct *)
cdf_AllocateMemory (sizeof(struct FILEstruct),
FatalError);
nNameChars = strlen (name);
FILEptr->name = (char *) cdf_AllocateMemory (nNameChars+1,
FatalError);
strcpyX (FILEptr->name, name, nNameChars);
tNameChars += nNameChars + 1;
nFiles++;
FILEptr->next = NULL;
AddToList (&FILEhead, FILEptr);
break;
}
}
}
/**************************************************************************
* Get next file.
**************************************************************************/
cParms.hFileInfo.ioDirID = dirID; /* This must be reset each time. */
cParms.hFileInfo.ioFDirIndex++; /* Increment to next file. */
rCode = PBGetCatInfo (&cParms, FALSE);
}
#endif
/****************************************************************************
* Build directory/file arrays.
****************************************************************************/
if (nFiles > 0) {
/**************************************************************************
* Setup to traverse linked list.
**************************************************************************/
*dirS = (char **) cdf_AllocateMemory ((nFiles*sizeof(char *))+strlen(dir)+1,
FatalError);
*nameS = (char **) cdf_AllocateMemory ((nFiles*sizeof(char *)) + tNameChars,
FatalError);
dirP = (char *) (*dirS) + nFiles*sizeof(char *);
nameP = (char *) (*nameS) + nFiles*sizeof(char *);
/**************************************************************************
* Traverse linked list of file structures. Note that the second through
* last directory strings actually point to the first directory string.
**************************************************************************/
for (FILEptr=FILEhead, i=0; FILEptr != NULL; FILEptr=FILEptr->next, i++) {
if (i == 0) {
strcpyX (dirP, dir, 0);
(*dirS)[i] = dirP;
}
else
(*dirS)[i] = (*dirS)[i-1];
strcpyX (nameP, FILEptr->name, 0);
(*nameS)[i] = nameP;
nameP += strlen(FILEptr->name) + 1;
}
/**************************************************************************
* Free linked list of file structures.
**************************************************************************/
FILEptr = FILEhead;
while (FILEptr != NULL) {
FILEptrT = FILEptr;
FILEptr = FILEptr->next;
cdf_FreeMemory (FILEptrT->name, FatalError);
cdf_FreeMemory (FILEptrT, FatalError);
}
}
else {
/**************************************************************************
* No files found.
**************************************************************************/
*nameS = NULL;
*dirS = NULL;
}
return nFiles;
}
/******************************************************************************
* AddToList.
******************************************************************************/
static void AddToList (FILEhead, FILEptr)
struct FILEstruct **FILEhead;
struct FILEstruct *FILEptr;
{
if (*FILEhead == NULL)
*FILEhead = FILEptr;
else
if (strcmp(FILEptr->name,(*FILEhead)->name) < 0) {
FILEptr->next = *FILEhead;
*FILEhead = FILEptr;
}
else {
struct FILEstruct *FILEptrT = *FILEhead;
for (;;) {
if (FILEptrT->next == NULL) {
FILEptrT->next = FILEptr;
break;
}
else
if (strcmp(FILEptr->name,FILEptrT->next->name) < 0) {
FILEptr->next = FILEptrT->next;
FILEptrT->next = FILEptr;
break;
}
FILEptrT = FILEptrT->next;
}
}
return;
}
/******************************************************************************
* PatternMatch. (Only used on UNIX/POSIXshell and Macintosh systems).
******************************************************************************/
#if (defined(unix) && !defined(__MINGW32__)) || defined(mac) || \
defined(posixSHELL)
static int PatternMatch (pattern, name)
char *pattern;
char *name;
{
enum typeENUM types[DU_MAX_PATTERNS];
char *strings[DU_MAX_PATTERNS];
int nTypes = 0;
int len, i, result;
for (i = 0; i < DU_MAX_PATTERNS; i++) types[i] = TBD;
for (i = 0; pattern[i] != NUL; i++)
switch (pattern[i]) {
case '?':
types[nTypes++] = WILD1;
break;
case '*':
if (nTypes == 0 || types[nTypes] != WILDn) types[nTypes++] = WILDn;
break;
default:
if (types[nTypes] == TBD) {
types[nTypes] = STR;
strings[nTypes] = (char *) cdf_AllocateMemory (DU_MAX_NAME_LEN + 1,
FatalError);
strings[nTypes][0] = pattern[i];
strings[nTypes][1] = NUL;
nTypes++;
}
else {
len = strlen (strings[nTypes-1]);
strings[nTypes-1][len] = pattern[i];
strings[nTypes-1][len+1] = NUL;
}
}
result = CheckPattern (nTypes, types, strings, name);
for (i = 0; i < DU_MAX_PATTERNS; i++) {
if (types[i] == STR) cdf_FreeMemory (strings[i], FatalError);
}
return result;
}
#endif
/******************************************************************************
* CheckPattern. (Only used on UNIX/POSIXshell and Macintosh systems).
******************************************************************************/
#if (defined(unix) && !defined(__MINGW32__)) || defined(mac) || \
defined(posixSHELL)
static int CheckPattern (nTypes, types, strings, name)
int nTypes;
enum typeENUM types[];
char *strings[];
char *name;
{
int sp = 0;
int i, j;
for (i = 0; i < nTypes; i++) {
switch (types[i]) {
case TBD:
/* Do nothing? */
break;
case STR:
if (strncmp(&name[sp],strings[i],strlen(strings[i])) != 0)
return FALSE;
else
sp += strlen(strings[i]);
break;
case WILD1:
if (name[sp] == NUL)
return FALSE;
else
sp++;
break;
case WILDn:
if (i == nTypes-1) /* At last type to check? */
return TRUE;
else {
for (j = i; name[j] != NUL; j++)
if (CheckPattern (nTypes-i-1, &types[i+1],
&strings[i+1], &name[j])) return TRUE;
return FALSE;
}
}
}
if (name[sp] == NUL)
return TRUE;
else
return FALSE;
}
#endif
/******************************************************************************
* CDFdirList.
* Does a `DirList' using the possible CDF extensions (`.cdf' on all
* platforms and also `.CDF', `.cdf;1', and `.CDF;1' on UNIX/POSIXshell and
* Macintosh platforms because of CD-ROM inconsistencies
******************************************************************************/
int CDFdirList (path, dirS, nameS)
char *path;
char ***dirS;
char ***nameS;
{
#if (defined(unix) && !defined(__MINGW32__)) || defined(mac) || \
defined(posixSHELL)
/****************************************************************************
* UNIX/POSIXshell and Macintosh.
****************************************************************************/
char dir[DU_MAX_DIR_LEN+1];
char pattern[DU_MAX_NAME_LEN+1];
static char pattern1[DU_MAX_NAME_LEN+1];
static char pattern2[DU_MAX_NAME_LEN+1];
static char pattern3[DU_MAX_NAME_LEN+1];
static char pattern4[DU_MAX_NAME_LEN+1];
static char *patternS[4] = { pattern1, pattern2, pattern3, pattern4 };
int nCDFs;
ParsePath (path, dir, pattern);
strcpyX (pattern1, pattern, DU_MAX_NAME_LEN);
if (NULstring(pattern1)) strcatX (pattern1, "*", DU_MAX_NAME_LEN);
strcatX (pattern1, ".cdf", DU_MAX_NAME_LEN);
strcpyX (pattern2, pattern, DU_MAX_NAME_LEN);
if (NULstring(pattern2)) strcatX (pattern2, "*", DU_MAX_NAME_LEN);
strcatX (pattern2, ".CDF", DU_MAX_NAME_LEN);
strcpyX (pattern3, pattern, DU_MAX_NAME_LEN);
if (NULstring(pattern3)) strcatX (pattern3, "*", DU_MAX_NAME_LEN);
strcatX (pattern3, ".cdf;1", DU_MAX_NAME_LEN);
strcpyX (pattern4, pattern, DU_MAX_NAME_LEN);
if (NULstring(pattern4)) strcatX (pattern4, "*", DU_MAX_NAME_LEN);
strcatX (pattern4, ".CDF;1", DU_MAX_NAME_LEN);
nCDFs = DirList (dir, 4, patternS, dirS, nameS);
RemoveExtensions (nCDFs, *nameS);
return nCDFs;
#endif
#if defined(vms) || defined(dos) || defined(win32)
/****************************************************************************
* VMS, Windows, and MS-DOS.
****************************************************************************/
char dir[DU_MAX_DIR_LEN+1];
static char pattern[DU_MAX_NAME_LEN+1];
static char *patternS[1] = { pattern };
int nCDFs;
ParsePath (path, dir, pattern);
if (NULstring(pattern)) strcatX (pattern, "*", DU_MAX_NAME_LEN);
strcatX (pattern, ".cdf", DU_MAX_NAME_LEN);
nCDFs = DirList (dir, 1, patternS, dirS, nameS);
RemoveExtensions (nCDFs, *nameS);
return nCDFs;
#endif
}
/******************************************************************************
* RemoveExtensions. Locates the last '.' in a file name and replaces it with
* a NUL. This effectively removes the file extension. If
* the file name does not have an extension and has a '.' in
* its name, this could have undesired effects.
******************************************************************************/
void RemoveExtensions (nFiles, files)
int nFiles;
char *files[];
{
int i;
char *ptr;
for (i = 0; i < nFiles; i++)
if ((ptr = strrchr(files[i],'.')) != NULL) *ptr = NUL;
return;
}
/******************************************************************************
* WriteStringStdOut.
******************************************************************************/
void WriteStringStdOut (string, length)
char *string;
size_t length;
{
fprintf (stdout, "%*.*s", (int) length, (int) length, string);
return;
}
/******************************************************************************
* ReadCharStdIn.
******************************************************************************/
#if !defined(mac)
void ReadCharStdIn (key)
char *key;
{
*key = (char) fgetc (stdin);
return;
}
#endif
/******************************************************************************
* DisplayStatistics.
******************************************************************************/
void DisplayStatistics (label, vStatsDotCDF, vStatsStage, vStatsCompress)
char *label;
vSTATS *vStatsDotCDF;
vSTATS *vStatsStage;
vSTATS *vStatsCompress;
{
char temp1[MAX_SCREENLINE_LEN+1], temp2[MAX_SCREENLINE_LEN+1],
temp3[MAX_SCREENLINE_LEN+1], labelX[MAX_SCREENLINE_LEN+1];
if (vStatsDotCDF->maxBuffers > 0) {
strcpyX (labelX, label, MAX_SCREENLINE_LEN);
strcatX (labelX, " DotCDF file", MAX_SCREENLINE_LEN);
BuildStatistics (labelX, vStatsDotCDF, temp1, temp2, temp3);
WriteOut (stdout, temp1);
WriteOut (stdout, "\n");
WriteOut (stdout, temp2);
WriteOut (stdout, "\n");
WriteOut (stdout, temp3);
WriteOut (stdout, "\n");
}
if (vStatsStage->maxBuffers > 0) {
strcpyX (labelX, label, MAX_SCREENLINE_LEN);
strcatX (labelX, " staging file", MAX_SCREENLINE_LEN);
BuildStatistics (labelX, vStatsStage, temp1, temp2, temp3);
WriteOut (stdout, temp1);
WriteOut (stdout, "\n");
WriteOut (stdout, temp2);
WriteOut (stdout, "\n");
WriteOut (stdout, temp3);
WriteOut (stdout, "\n");
}
if (vStatsCompress->maxBuffers > 0) {
strcpyX (labelX, label, MAX_SCREENLINE_LEN);
strcatX (labelX, " compression scratch file", MAX_SCREENLINE_LEN);
BuildStatistics (labelX, vStatsCompress, temp1, temp2, temp3);
WriteOut (stdout, temp1);
WriteOut (stdout, "\n");
WriteOut (stdout, temp2);
WriteOut (stdout, "\n");
WriteOut (stdout, temp3);
WriteOut (stdout, "\n");
}
return;
}
/******************************************************************************
* BuildStatistics.
******************************************************************************/
void BuildStatistics (label, vStats, temp1, temp2, temp3)
char *label;
vSTATS *vStats;
char temp1[MAX_SCREENLINE_LEN+1];
char temp2[MAX_SCREENLINE_LEN+1];
char temp3[MAX_SCREENLINE_LEN+1];
{
strcpyX (temp1, " Statistics", MAX_SCREENLINE_LEN);
if (label != NULL) {
strcatX (temp1, " for ", MAX_SCREENLINE_LEN);
strcatX (temp1, label, MAX_SCREENLINE_LEN);
}
strcatX (temp1, ":", MAX_SCREENLINE_LEN);
sprintf (temp2, " %d buffer%s used of the %d allowed, ", vStats->nBuffers,
BOO(vStats->nBuffers == 1,"","s"), vStats->maxBuffers);
sprintf (EofS(temp2), "[%ld reads, %ld writes] ", vStats->nV_reads,
vStats->nV_writes);
sprintf (temp3, " %ld page in%s, %ld page out%s, ",
vStats->nPageIns, BOO(vStats->nPageIns==1,"","s"),
vStats->nPageOuts, BOO(vStats->nPageOuts==1,"","s"));
sprintf (EofS(temp3), "%ld block read%s, %ld block write%s ",
vStats->nBlockReads, BOO(vStats->nBlockReads==1,"","s"),
vStats->nBlockWrites, BOO(vStats->nBlockWrites==1,"","s"));
return;
}
/******************************************************************************
* StatusCodeReportOptions.
******************************************************************************/
char *StatusCodeReportOptions (e,w,i)
Logical e;
Logical w;
Logical i;
{
static char mask[MAX_REPORTMASK_LEN+1];
#if defined(vms)
strcpyX (mask, "(", MAX_REPORTMASK_LEN);
#else
strcpyX (mask, "\"", MAX_REPORTMASK_LEN);
#endif
strcatX (mask, (e ? "errors" : ""), MAX_REPORTMASK_LEN);
strcatX (mask, (w ? (e ? ",warnings" : "warnings") : ""),
MAX_REPORTMASK_LEN);
strcatX (mask, (i ? (e || w ? ",informationals" : "informationals") : ""),
MAX_REPORTMASK_LEN);
#if defined(vms)
strcatX (mask, ")", MAX_REPORTMASK_LEN);
#else
strcatX (mask, "\"", MAX_REPORTMASK_LEN);
#endif
#if defined(vms) || defined(dos)
MakeUpperString (mask);
#endif
return mask;
}
/******************************************************************************
* DisplayIdentification.
******************************************************************************/
void DisplayIdentification (name)
char *name;
{
long version, release, increment; char subIncrement;
char text[MAX_MESSAGE_TEXT_LEN+1]; CDFstatus status;
status = CDFlib (GET_, LIB_VERSION_, &version,
LIB_RELEASE_, &release,
LIB_INCREMENT_, &increment,
LIB_subINCREMENT_, &subIncrement,
NULL_);
if (StatusBAD(status))
sprintf (text, "Error inquiring CDF library.");
else {
sprintf (text, "%s from the CDF V%ld.%ld.%ld",
name, version, release, increment);
if (subIncrement != ' ') sprintf (EofS(text), "%c", subIncrement);
sprintf (EofS(text), " distribution.");
}
DisplayInfo (text);
return;
}
/******************************************************************************
* FindUniqueMatch.
* Returns: NOMATCH if a match was not found,
* MATCHES if more than one match,
* `index' if only one match.
******************************************************************************/
int FindUniqueMatch (target, strings)
char *target; /* Searching for this string. */
char *strings[]; /* Terminated by a NULL pointer. */
{
int match, beyond; size_t targetL = strlen(target);
for (match = 0; strings[match] != NULL; match++) {
if (strncmpIgCasePattern(target,strings[match],targetL) == 0) {
for (beyond = match + 1; strings[beyond] != NULL; beyond++) {
if (strncmpIgCasePattern(target,strings[beyond],targetL) == 0)
return MATCHES;
}
return match;
}
}
return NOMATCH;
}
syntax highlighted by Code2HTML, v. 0.9.1