/******************************************************************************
*
* NSSDC/CDF Toolbox of routines for CDF Toolkit (Miscellaneous).
*
* Version 1.6b, 3-Mar-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 13-Dec-94, J Love CDF V2.5.
* V1.2a 13-Jan-95, J Love Changed `IsCDF' to allow all possible
* extensions on Macintosh machines also.
* V1.2b 20-Jan-95, J Love IRIX 6.x (64-bit).
* V1.2c 3-Mar-95, J Love Moved `EncodeKeyDefinitions', etc. to
* `windoz.c'.
* V1.3 21-Mar-95, J Love POSIX.
* V1.3a 18-Apr-95, J Love More POSIX.
* V1.4 22-May-95, J Love `ASSIGNx', `EQx', etc. moved here (and some
* calling sequences changed).
* V1.5 14-Sep-95, J Love Added routines used by CDFexport. Hyper
* groups.
* V1.5a 19-Sep-95, J Love Macintosh event handling.
* V1.6 9-Sep-96, J Love CDF V2.6.
* V1.6a 21-Feb-97, J Love Removed RICE.
* V1.6b 3-Mar-97, J Love Windows NT for MS Visual C/C++ on an IBM PC.
* V1.6c 18-Dec-98, M Liu Add the missing cases for ALPHAVMSi in
* WhichEncoding and EncodingToken.
* V1.7 05-May-04, M Liu Changed function AllocateBuffers when the
* record count is 1 or more.
* V1.8 11-Jul-05, M Liu Added MingW port for PC.
* V1.9 13-Oct-06, M Liu Changed to allow upper and lower case CDF
* name to be used on win32.
*
******************************************************************************/
#include "cdftools.h"
/******************************************************************************
* Macros.
******************************************************************************/
#if defined(dos)
#define MAXnBYTESperALLOCATION 50000L /* Remember 64Kb limit. */
#else
#if defined(mac)
#define MAXnBYTESperALLOCATION 50000L
#else
#define MAXnBYTESperALLOCATION 500000L
#endif
#endif
/******************************************************************************
* Local function prototypes.
******************************************************************************/
static Logical EqStringsIgLTws PROTOARGs((char *string1, char *string2));
static Logical DecodeInt32 PROTOARGs((char *, Int32 *));
static Logical DecodeInt32u PROTOARGs((char *, uInt32 *));
static char *strnchr PROTOARGs((char *string, int chr, int n));
static QOP *ParseSlashStyle PROTOARGs((
int argc, char *argv[], char *validQuals[], int optRequired[]
));
static QOP *ParseHyphenStyle PROTOARGs((
int argc, char *argv[], char *validQuals[], int optRequired[]
));
static void FreeArgvT PROTOARGs((int lastArgN, char *argvT[]));
static QOP *BuildQOP PROTOARGs((
int Nparms, char *parms[], char *validQuals[], int *qualEntered,
char *qualOpt[]
));
static Logical AttemptAllocations PROTOARGs((
long nScalarValues, int nScalars, long nHyperValues, int nHypers,
Byte **handles[], size_t nValueBytes[]
));
/******************************************************************************
* EncodeRecordJustify.
******************************************************************************/
void EncodeRecordJustify (string, recN, minWidth)
char *string;
long recN;
int minWidth; /* If zero, no minimum width. If positive, right justified.
If negative, left justified. */
{
sprintf (string, "%ld", recN + 1);
Justify (string, minWidth);
return;
}
/******************************************************************************
* EncodeIndicesJustify.
******************************************************************************/
void EncodeIndicesJustify (string, numDims, indices, minWidth)
char *string;
long numDims;
long indices[];
int minWidth; /* If zero, no minimum width. If positive, right justified.
If negative, left justified. */
{
int n;
strcpyX (string, "[", 0);
for (n = 0; n < numDims; n++) {
if (n > 0) strcatX (string, ",", 0);
sprintf (EofS(string), "%ld", indices[n] + 1);
}
strcatX (string, "]", 0);
Justify (string, minWidth);
return;
}
/******************************************************************************
* EncodeRecordIndicesJustify.
******************************************************************************/
void EncodeRecordIndicesJustify (string, recN, numDims, indices, minWidth)
char *string;
long recN;
long numDims;
long indices[];
int minWidth; /* If zero, no minimum width. If positive, right justified.
If negative, left justified. */
{
EncodeRecordJustify (string, recN, 0);
EncodeIndicesJustify (EofS(string), numDims, indices, 0);
Justify (string, minWidth);
return;
}
/******************************************************************************
* Justify.
******************************************************************************/
void Justify (string, minWidth)
char *string;
int minWidth; /* If zero, no minimum width. If positive, right justified.
If negative, left justified. */
{
if (minWidth < 0) {
int pad = -minWidth - strlen(string);
if (pad > 0) CatNcharacters (string, pad, (int) ' ');
}
else {
if (minWidth > 0) {
int i, stringL = strlen(string);
int shift = minWidth - stringL;
if (shift > 0) {
memmove (&(string[shift]), string, stringL + 1);
for (i = 0; i < shift; i++) string[i] = ' ';
}
}
}
return;
}
/******************************************************************************
* CatString.
******************************************************************************/
void CatToString (string, cat, length, justify, more)
char *string;
char *cat;
int length;
int justify;
char *more;
{
int catL = (int) strlen (cat);
int moreL = (int) strlen (more);
if (catL > length)
if (moreL >= length)
CatNcharacters (string, length, '*');
else {
strcatX (string, cat, strlen(string) + (length - moreL));
strcatX (string, more, 0);
}
else
switch (justify) {
case LEFT_JUSTIFY:
strcatX (string, cat, 0);
CatNcharacters (string, length - catL, ' ');
break;
case CENTER_JUSTIFY: {
int after = (length - catL) / 2;
int before = (length - catL) - after;
CatNcharacters (string, before, ' ');
strcatX (string, cat, 0);
CatNcharacters (string, after, ' ');
break;
}
case RIGHT_JUSTIFY:
CatNcharacters (string, length - catL, ' ');
strcatX (string, cat, 0);
break;
}
return;
}
/******************************************************************************
* RemoveLeadingBlanks.
******************************************************************************/
void RemoveLeadingBlanks (string)
char *string;
{
while (string[0] == ' ') memmove (string, &string[1], strlen(string));
return;
}
/******************************************************************************
* RemoveTrailingBlanks.
******************************************************************************/
void RemoveTrailingBlanks (string)
char *string;
{
int i;
for (i = strlen(string) - 1; i >= 0; i--) {
if (string[i] == ' ') string[i] = NUL;
}
return;
}
/******************************************************************************
* RemoveWhiteSpace.
******************************************************************************/
void RemoveWhiteSpace (string)
char *string;
{
char *c = string;
while (*c != NUL) {
if (Spacing(*c))
memmove (c, c + 1, strlen(c+1) + 1);
else
c++;
}
return;
}
/******************************************************************************
* CopyToField.
* Copies a string to a field and blank pads to the end of the field.
******************************************************************************/
void CopyToField (string, field, length)
char *string;
char *field;
int length;
{
strcpyX (field, string, length);
BlankPadRight (field, length - strlen(string));
return;
}
/******************************************************************************
* CopyFromField.
* Copies from a field to a string and removes trailing blanks. It is
* assumed that the string is large enough.
******************************************************************************/
void CopyFromField (field, length, string)
char *field;
int length;
char *string;
{
strcpyX (string, field, length);
RemoveTrailingBlanks (string);
return;
}
/******************************************************************************
* SystemClock.
******************************************************************************/
double SystemClock () {
return ((double) time(NULL));
}
/******************************************************************************
* ParsePath.
******************************************************************************/
void ParsePath (path, dir, name)
char *path;
char dir[DU_MAX_DIR_LEN+1];
char name[DU_MAX_NAME_LEN+1];
{
char *cp;
size_t len;
char dirT[DU_MAX_DIR_LEN+1];
char nameT[DU_MAX_NAME_LEN+1];
#if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \
defined(posixSHELL)
if (IsDir(path)) {
strcpyX (dirT, path, DU_MAX_DIR_LEN);
nameT[0] = NUL;
}
else {
cp = strrchr (path, '/');
if (cp == NULL) {
dirT[0] = NUL;
strcpyX (nameT, path, DU_MAX_NAME_LEN);
}
else {
len = cp - path; /* No trailing '/'. */
strcpyX (dirT, path, MINIMUM(len,DU_MAX_DIR_LEN));
strcpyX (nameT, cp + 1, DU_MAX_NAME_LEN);
}
}
#endif
#if defined(dos) || defined(win32) || defined(__CYGWIN__) || \
defined(__MINGW32__)
if (IsDir(path)) {
strcpyX (dirT, path, DU_MAX_DIR_LEN);
nameT[0] = NUL;
}
else {
char *cp1 = strrchr (path, ':');
char *cp2 = strrchr (path, '\\');
cp = (cp1 > cp2 ? cp1 : cp2);
if (cp == NULL) {
dirT[0] = NUL;
strcpyX (nameT, path, DU_MAX_NAME_LEN);
}
else {
if (cp1 == NULL) {
len = (size_t) (cp2 - path); /* No trailing '\'. */
strcpyX (dirT, path, MINIMUM(len,DU_MAX_DIR_LEN));
}
else {
if (cp2 == NULL) {
len = (size_t) (cp1 - path + 1); /* Trailing ':'. */
strcpyX (dirT, path, MINIMUM(len,DU_MAX_DIR_LEN));
}
else {
if (cp1 + 1 == cp2)
len = (size_t) (cp2 - path + 1); /* Trailing ':'. */
else
len = (size_t) (cp2 - path); /* No trailing ':'. */
strcpyX (dirT, path, MINIMUM(len,DU_MAX_DIR_LEN));
}
}
strcpyX (nameT, cp + 1, DU_MAX_NAME_LEN);
}
}
#endif
#if defined(vms)
char *cp1 = strrchr (path, ':');
char *cp2 = strrchr (path, ']');
cp = (cp1 > cp2 ? cp1 : cp2);
if (cp == NULL) {
dirT[0] = NUL;
strcpyX (nameT, path, DU_MAX_NAME_LEN);
}
else {
len = cp - path + 1; /* Trailing ':' or ']' */
strcpyX (dirT, path, MINIMUM(len,DU_MAX_DIR_LEN));
strcpyX (nameT, cp + 1, DU_MAX_NAME_LEN);
}
#endif
#if defined(mac)
if (IsDir(path)) {
strcpyX (dirT, path, DU_MAX_DIR_LEN);
nameT[0] = NUL;
}
else {
cp = strrchr (path, ':');
if (cp == NULL) {
dirT[0] = NUL;
strcpyX (nameT, path, DU_MAX_NAME_LEN);
}
else {
len = cp - path + 1; /* Trailing ':'. */
strcpyX (dirT, path, MINIMUM(len,DU_MAX_DIR_LEN));
strcpyX (nameT, cp + 1, DU_MAX_NAME_LEN);
}
}
#endif
if (dir != NULL) strcpyX (dir, dirT, DU_MAX_DIR_LEN);
if (name != NULL) strcpyX (name, nameT, DU_MAX_NAME_LEN);
return;
}
/******************************************************************************
* IsDir (directory).
* `stat' on MS-DOS systems will indicate a directory if the pathname
* contains a wildcard character.
******************************************************************************/
Logical IsDir (path)
char *path;
{
char pathX[DU_MAX_PATH_LEN+1];
size_t len;
#if (!defined(unix) && !defined(posixSHELL)) || defined(__CYGWIN__) || \
defined(__MINGW32__)
int lastChar;
#endif
#if defined(unix) || defined(dos) || defined(posixSHELL) || defined(win32)
struct stat st;
#endif
ExpandPath (path, pathX);
len = strlen (pathX);
if (len == 0) return FALSE;
#if (!defined(unix) && !defined(posixSHELL)) || defined(__CYGWIN__) || \
defined(__MINGW32__)
lastChar = len - 1;
#endif
#if defined(unix) || defined(dos) || defined(posixSHELL) || defined(win32)
/****************************************************************************
* UNIX/POSIXshell, DOS, and Windows.
****************************************************************************/
#if defined(dos) || defined(win32) || defined(__CYGWIN__) || \
defined(__MINGW32__)
/****************************************************************************
* DOS/Windows: Check for wildcard character in the pathname.
****************************************************************************/
if (strchr(pathX,'*') != NULL) return FALSE;
if (strchr(pathX,'?') != NULL) return FALSE;
/****************************************************************************
* DOS/Windows: Strip trailing backslash (if present).
****************************************************************************/
if (pathX[lastChar] == '\\') {
pathX[lastChar] = NUL; /* Strip trailing '\' */
len--;
}
/****************************************************************************
* DOS/Windows: Check for disk drive specification.
****************************************************************************/
if (len == 2)
if (Alphabetic(pathX[0]) && pathX[1] == ':') return TRUE;
#endif
#if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \
defined(posixSHELL)
/****************************************************************************
* UNIX: Check for wildcard character in the pathname.
****************************************************************************/
if (strchr(pathX,'*') != NULL) return FALSE;
if (strchr(pathX,'?') != NULL) return FALSE;
#endif
/****************************************************************************
* Call `stat' to determine type of file.
****************************************************************************/
if (stat(pathX, &st) == 0) {
#if defined(SALFORDC) /* Salford's `stat' is broken. */
return (st.st_size == 0);
#else
#if defined(S_ISDIR)
return S_ISDIR(st.st_mode);
#else
return (st.st_mode & S_IFDIR);
#endif
#endif
}
else
return FALSE;
#endif
#if defined(vms)
/****************************************************************************
* VMS.
****************************************************************************/
/****************************************************************************
* Check for wildcard character in the pathname.
****************************************************************************/
if (strchr(pathX,'*') != NULL) return FALSE;
if (strchr(pathX,'%') != NULL) return FALSE;
/****************************************************************************
* Check for possible logical name defined to be a full file specification
* (not just a directory).
****************************************************************************/
if (IsReg(pathX))
return FALSE;
else
/**************************************************************************
* If not, check if the path ends with a ':' (logical name) or ']'
* (directory).
**************************************************************************/
if (pathX[lastChar] == ':' || pathX[lastChar] == ']')
return TRUE;
else
return FALSE;
#endif
#if defined(mac)
/****************************************************************************
* MAC: Check to see if specification ends with a `:' (and assume it to be a
* directory without actually checking). If specification doesn't end with
* a `:', check if it is a directory anyway.
****************************************************************************/
if (pathX[lastChar] == ':')
return TRUE;
else {
return MacDirSpecified (pathX, NULL, NULL);
}
#endif
}
/******************************************************************************
* IsWild (Wildcard specification in name).
******************************************************************************/
Logical IsWild (path)
char *path;
{
char dir[DU_MAX_DIR_LEN+1];
char name[DU_MAX_NAME_LEN+1];
ParsePath (path, dir, name);
if (strchr(name,'*') != NULL) return TRUE;
#if defined(vms)
if (strchr(name,'%') != NULL) return TRUE;
#else
if (strchr(name,'?') != NULL) return TRUE;
#endif
return FALSE;
}
/******************************************************************************
* IsCDF.
* Determines if the specified pathname is that of a CDF. Because of
* inconsistent behavior of CD-ROM drivers on various UNIX/POSIXshell machines
* and the Macintosh, the following extensions are tried: `.cdf', `.CDF',
* `.cdf;1', and `.CDF;1'.
******************************************************************************/
Logical IsCDF (pathname)
char *pathname;
{
char pathnameX[DU_MAX_PATH_LEN+1];
ExpandPath (pathname, pathnameX);
if (IsReg(pathnameX)) return TRUE;
strcatX (pathnameX, ".cdf", DU_MAX_PATH_LEN);
if (IsReg(pathnameX)) return TRUE;
#if defined(unix) || defined(mac) || defined(posixSHELL)
ExpandPath (pathname, pathnameX);
strcatX (pathnameX, ".cdf;1", DU_MAX_PATH_LEN);
if (IsReg(pathnameX)) return TRUE;
ExpandPath (pathname, pathnameX);
strcatX (pathnameX, ".CDF", DU_MAX_PATH_LEN);
if (IsReg(pathnameX)) return TRUE;
ExpandPath (pathname, pathnameX);
strcatX (pathnameX, ".CDF;1", DU_MAX_PATH_LEN);
if (IsReg(pathnameX)) return TRUE;
#endif
return FALSE;
}
/******************************************************************************
* Qop.
******************************************************************************/
QOP *Qop (argc, argv, validQuals, optRequired)
int argc;
char *argv[];
char *validQuals[];
int optRequired[];
{
/****************************************************************************
* Check to see if a style definition has been specified. (A slash or hyphen
* as the first command line argument.)
****************************************************************************/
if (argc > 1) {
if (!strcmp(argv[1],"/")) return ParseSlashStyle (argc - 1, &argv[1],
validQuals, optRequired);
if (!strcmp(argv[1],"-")) return ParseHyphenStyle (argc - 1, &argv[1],
validQuals,optRequired);
}
/****************************************************************************
* No style definition, parse according to default for operating system
* being used.
****************************************************************************/
#if defined(vms)
return ParseSlashStyle (argc, argv, validQuals, optRequired);
#else
return ParseHyphenStyle (argc, argv, validQuals, optRequired);
#endif
}
/******************************************************************************
* ParseSlashStyle.
* Assume qualifiers begin with a slash (/).
******************************************************************************/
static QOP *ParseSlashStyle (argc, argv, validQuals, optRequired)
int argc;
char *argv[];
char *validQuals[];
int optRequired[];
{
QOP *qop; /* Pointer to QOP structure. */
int argN, /* Argument number. */
qualNv, /* Qualifier number (from list of valid
qualifiers). */
qualNe, /* Qualifier number (from list of qualifiers
entered). */
Nparms = 0, /* Number of parameters entered. */
Nquals = 0, /* Number of qualifiers entered. */
matchQualNv, /* Matching qualifier number (from list of
valid qualifiers). */
qualEntered[QOP_MAX_QUALs];
/* TRUE if the corresponding qualifier was
entered. */
char *parms[QOP_MAX_PARMs], /* Pointers to the parameters entered. */
*qualOpt[QOP_MAX_QUALs], /* Pointers to the options of the qualifiers
entered (indexed to correspond to the list
of valid qualifiers). */
*argvT[QOP_MAX_ARGVs], /* Pointers to temporary `argv' strings. */
*quals[QOP_MAX_QUALs], /* Pointers to the qualifiers entered (in the
order they were entered). */
*opts[QOP_MAX_QUALs], /* Pointers to the options entered (in the
order they were entered). */
*ptr; /* Pointer into character string. */
enum modes { UNKNOWN_,
START_OF_PARM_,
FIND_PARM_END_,
START_OF_QUAL_,
FIND_QUAL_END_,
START_OF_OPT_,
FIND_OPT_END_ } mode; /* The current mode when scanning the
list of command line arguments. */
/****************************************************************************
* Determine parameters and qualifiers/options.
****************************************************************************/
for (argN = 1; argN < argc; argN++) {
char nChars = strlen (argv[argN]);
argvT[argN] = (char *) cdf_AllocateMemory (nChars + 1, FatalError);
strcpyX (argvT[argN], argv[argN], nChars);
mode = UNKNOWN_;
for (ptr = argvT[argN]; *ptr != NUL;) {
switch (mode) {
case UNKNOWN_:
if (*ptr == '/') {
mode = START_OF_QUAL_;
ptr++;
}
else
mode = START_OF_PARM_;
break;
case START_OF_PARM_:
Nparms++;
if (Nparms <= QOP_MAX_PARMs)
parms[Nparms-1] = ptr;
else {
DisplayError ("Too many parameters.");
FreeArgvT (argN, argvT);
return NULL;
}
mode = FIND_PARM_END_;
ptr++;
break;
case FIND_PARM_END_:
if (*ptr == '/')
if (*(ptr+1) == '/')
memmove (ptr, ptr+1, strlen(ptr+1) + 1);
else {
*ptr = NUL;
mode = START_OF_QUAL_;
}
ptr++;
break;
case START_OF_QUAL_:
if (*ptr == '/')
mode = START_OF_PARM_;
else {
Nquals++;
if (Nquals <= QOP_MAX_QUALs)
quals[Nquals-1] = ptr;
else {
DisplayError ("Too many qualifiers.");
FreeArgvT (argN, argvT);
return NULL;
}
mode = FIND_QUAL_END_;
ptr++;
}
break;
case FIND_QUAL_END_:
switch (*ptr) {
case '/':
*ptr = NUL;
opts[Nquals-1] = NULL;
mode = START_OF_QUAL_;
break;
case '=':
*ptr = NUL;
mode = START_OF_OPT_;
break;
}
ptr++;
break;
case START_OF_OPT_:
if (*ptr == '/')
if (*(ptr+1) == '/') {
opts[Nquals-1] = ptr + 1;
ptr += 2;
mode = FIND_OPT_END_;
}
else {
char tempS[MAX_MESSAGE_TEXT_LEN+1];
sprintf (tempS, "Missing option for qualifier `/%s'.",
quals[Nquals-1]);
DisplayError (tempS);
FreeArgvT (argN, argvT);
return NULL;
}
else {
opts[Nquals-1] = ptr;
mode = FIND_OPT_END_;
ptr++;
}
break;
case FIND_OPT_END_:
if (*ptr == '/')
if (*(ptr+1) == '/')
memmove (ptr, ptr+1, strlen(ptr+1) + 1);
else {
*ptr = NUL;
mode = START_OF_QUAL_;
}
ptr++;
break;
}
}
switch (mode) {
case UNKNOWN_:
/* Logic error. */
break;
case START_OF_PARM_:
/* Logic error. */
break;
case START_OF_QUAL_:
DisplayError ("Missing qualifier body (/).");
FreeArgvT (argN, argvT);
return NULL;
case FIND_QUAL_END_:
/* Qualifier already NUL-terminated */
opts[Nquals-1] = NULL;
break;
case FIND_PARM_END_:
/* Parameter already NUL-terminated */
break;
case START_OF_OPT_: {
char tempS[MAX_MESSAGE_TEXT_LEN+1];
sprintf (tempS,"Missing option for qualifier `/%s'.",quals[Nquals-1]);
DisplayError (tempS);
FreeArgvT (argN, argvT);
return NULL;
}
case FIND_OPT_END_:
/* Option already NUL-terminated */
break;
}
}
/****************************************************************************
* Set up to scan command line arguments (while checking number of valid
* qualifiers).
****************************************************************************/
for (qualNv = 0; validQuals[qualNv] != NULL; qualNv++) {
if (qualNv < QOP_MAX_QUALs) {
qualEntered[qualNv] = FALSE;
qualOpt[qualNv] = NULL;
}
else {
WriteOut (stdout, "Too many valid qualifiers.\n");
FreeArgvT (argc - 1, argvT);
return NULL;
}
}
/****************************************************************************
* Determine which qualifiers/options were entered.
****************************************************************************/
for (qualNe = 0; qualNe < Nquals; qualNe++) {
matchQualNv = FindUniqueMatch (quals[qualNe], validQuals);
switch (matchQualNv) {
case NOMATCH: {
char tempS[MAX_MESSAGE_TEXT_LEN+1];
sprintf (tempS, "Unknown qualifier (/%s).", quals[qualNe]);
DisplayError (tempS);
FreeArgvT (argc - 1, argvT);
return NULL;
}
case MATCHES: {
char tempS[MAX_MESSAGE_TEXT_LEN+1];
sprintf (tempS, "Ambiguous qualifier (/%s).", quals[qualNe]);
DisplayError (tempS);
FreeArgvT (argc - 1, argvT);
return NULL;
}
default: {
if (optRequired[matchQualNv] && opts[qualNe] == NULL) {
char tempS[MAX_MESSAGE_TEXT_LEN+1];
sprintf (tempS, "Option missing for qualifier `/%s'.",
validQuals[matchQualNv]);
DisplayError (tempS);
FreeArgvT (argc - 1, argvT);
return NULL;
}
if (!optRequired[matchQualNv] && opts[qualNe] != NULL) {
char tempS[MAX_MESSAGE_TEXT_LEN+1];
sprintf (tempS, "Extraneous option for qualifier `/%s'.",
validQuals[matchQualNv]);
DisplayError (tempS);
FreeArgvT (argc - 1, argvT);
return NULL;
}
if (qualEntered[matchQualNv]) {
char tempS[MAX_MESSAGE_TEXT_LEN+1];
sprintf (tempS, "Redundant qualifier (/%s).",
validQuals[matchQualNv]);
DisplayError (tempS);
FreeArgvT (argc - 1, argvT);
return NULL;
}
qualEntered[matchQualNv] = TRUE;
qualOpt[matchQualNv] = opts[qualNe];
break;
}
}
}
/****************************************************************************
* Build QOP structure.
****************************************************************************/
qop = BuildQOP (Nparms, parms, validQuals, qualEntered, qualOpt);
/****************************************************************************
* Free memory used and return QOP structure.
****************************************************************************/
FreeArgvT (argc - 1, argvT);
return qop;
}
/******************************************************************************
* ParseHyphenStyle.
* Assume qualifiers begin with a hyphen (-).
******************************************************************************/
static QOP *ParseHyphenStyle (argc, argv, validQuals, optRequired)
int argc;
char *argv[];
char *validQuals[];
int optRequired[];
{
QOP *qop; /* Pointer to a QOP structure. */
int argN, /* Command line argument number. */
qualNv, /* Qualifier number from `valids' list. */
Nparms = 0, /* Number of parameters entered. */
matchQualNv, /* Matching qualifier number (from list of
valid qualifiers). */
qualEntered[QOP_MAX_QUALs];
/* TRUE if the corresponding qualifier was
entered. */
char *parms[QOP_MAX_PARMs], /* Pointers to the parameters entered. */
*qualOpt[QOP_MAX_QUALs]; /* Pointers to the options of the qualifiers
entered (indexed to correspond to the list
of valid qualifiers). */
/****************************************************************************
* Set up to scan command line arguments (while checking number of valid
* qualifiers).
****************************************************************************/
for (qualNv = 0; validQuals[qualNv] != NULL; qualNv++) {
if (qualNv < QOP_MAX_QUALs) {
qualEntered[qualNv] = FALSE;
qualOpt[qualNv] = NULL;
}
else {
DisplayError ("Too many valid qualifiers.");
return NULL;
}
}
/****************************************************************************
* Determine which qualifiers were entered (the rest being parameters).
****************************************************************************/
for (argN = 1; argN < argc; argN++) {
if (argv[argN][0] == '-' && argv[argN][1] != '-') {
matchQualNv = FindUniqueMatch (&argv[argN][1], validQuals);
switch (matchQualNv) {
case NOMATCH: {
char tempS[MAX_MESSAGE_TEXT_LEN+1];
sprintf (tempS, "Unknown qualifier (-%s).", &argv[argN][1]);
DisplayError (tempS);
return NULL;
}
case MATCHES: {
char tempS[MAX_MESSAGE_TEXT_LEN+1];
sprintf (tempS, "Ambiguous qualifier (-%s).", &argv[argN][1]);
DisplayError (tempS);
return NULL;
}
default: {
if (qualEntered[matchQualNv]) {
char tempS[MAX_MESSAGE_TEXT_LEN+1];
sprintf (tempS, "Redundant qualifier (-%s).",
validQuals[matchQualNv]);
DisplayError (tempS);
return NULL;
}
else
qualEntered[matchQualNv] = TRUE;
if (optRequired[matchQualNv]) {
if (argN+1 < argc) {
qualOpt[matchQualNv] = argv[argN+1];
argN++;
}
else {
char tempS[MAX_MESSAGE_TEXT_LEN+1];
sprintf (tempS, "Option missing for qualifier `-%s'.",
validQuals[matchQualNv]);
DisplayError (tempS);
return NULL;
}
}
}
}
}
else {
Nparms++;
if (Nparms <= QOP_MAX_PARMs)
parms[Nparms-1] = BOO(strncmp(argv[argN],"--",2),
argv[argN],argv[argN] + 1);
else {
DisplayError ("Too many parameters.");
return NULL;
}
}
}
/****************************************************************************
* Build QOP structure.
****************************************************************************/
qop = BuildQOP (Nparms, parms, validQuals, qualEntered, qualOpt);
/****************************************************************************
* Return QOP structure.
****************************************************************************/
return qop;
}
/******************************************************************************
* BuildQOP.
******************************************************************************/
static QOP *BuildQOP (Nparms, parms, validQuals, qualEntered, qualOpt)
int Nparms;
char *parms[];
char *validQuals[];
int *qualEntered;
char *qualOpt[];
{
QOP *qop; /* Pointer to a QOP structure. */
int parmN, /* Parameter number. */
qualNv, /* Qualifier number (in list of valid qualifiers. */
strCount = 0; /* Number of characters in the strings to be contained
in the QOP structure. */
char *strOffset; /* Offset into the QOP structure of a string
(parameter/option). */
for (parmN = 0; parmN < Nparms; parmN++)
strCount += strlen(parms[parmN]) + 1;
for (qualNv = 0; validQuals[qualNv] != NULL; qualNv++)
if (qualEntered[qualNv])
if (qualOpt[qualNv] != NULL) strCount += strlen(qualOpt[qualNv]) + 1;
qop = (QOP *) cdf_AllocateMemory (sizeof(QOP) + strCount,
FatalError);
strOffset = (char *) qop + sizeof(QOP);
qop->Nparms = Nparms;
for (parmN = 0; parmN < Nparms; parmN++) {
qop->parms[parmN] = strOffset;
strOffset += strlen(parms[parmN]) + 1;
strcpyX (qop->parms[parmN], parms[parmN], 0);
}
for (qualNv = 0; validQuals[qualNv] != NULL; qualNv++) {
qop->qualEntered[qualNv] = qualEntered[qualNv];
if (qualEntered[qualNv]) {
if (qualOpt[qualNv] != NULL) {
qop->qualOpt[qualNv] = strOffset;
strOffset += strlen(qualOpt[qualNv]) + 1;
strcpyX (qop->qualOpt[qualNv], qualOpt[qualNv], 0);
}
else
qop->qualOpt[qualNv] = NULL;
}
}
return qop;
}
/******************************************************************************
* FreeArgvT.
******************************************************************************/
static void FreeArgvT (lastArgN, argvT)
int lastArgN;
char *argvT[];
{
int argN;
for (argN = 1; argN <= lastArgN; argN++) cdf_FreeMemory (argvT[argN],
FatalError);
return;
}
/******************************************************************************
* ASSIGNx.
******************************************************************************/
void ASSIGNx (dst, src, dataType, numElems)
void *dst;
void *src;
long dataType;
long numElems;
{
memmove (dst, src, (size_t) (CDFelemSize(dataType) * numElems));
return;
}
/******************************************************************************
* EQx.
******************************************************************************/
Logical EQx (a, b, dataType, numElems)
void *a;
void *b;
long dataType;
long numElems;
{
if (dataType != CDF_EPOCH16)
return BOO(memcmp(a,b,(size_t)(CDFelemSize(dataType)*numElems)),FALSE,TRUE);
else {
double epoch16_a[2], epoch16_b[2];
epoch16_a[0] = *((double *) a);
epoch16_a[1] = *(((double *) a)+1);
epoch16_b[0] = *((double *) b);
epoch16_b[1] = *(((double *) b)+1);
if (epoch16_a[0] == epoch16_b[0] && epoch16_a[1] == epoch16_b[1])
return TRUE;
return FALSE;
}
}
/******************************************************************************
* NEx.
******************************************************************************/
Logical NEx (a, b, dataType, numElems)
void *a;
void *b;
long dataType;
long numElems;
{
if (dataType != CDF_EPOCH16)
return BOO(memcmp(a,b,(size_t)(CDFelemSize(dataType)*numElems)),TRUE,FALSE);
else {
double epoch16_a[2], epoch16_b[2];
epoch16_a[0] = *((double *) a);
epoch16_a[1] = *(((double *) a)+1);
epoch16_b[0] = *((double *) b);
epoch16_b[1] = *(((double *) b)+1);
if (epoch16_a[0] == epoch16_b[0] && epoch16_a[1] == epoch16_b[1])
return FALSE;
return TRUE;
}
}
/******************************************************************************
* LEx.
******************************************************************************/
Logical LEx (a, b, dataType, numElems)
void *a;
void *b;
long dataType;
long numElems;
{
switch (dataType) {
case CDF_BYTE:
case CDF_INT1:
return (*((sChar *) a) <= *((sChar *) b));
case CDF_UINT1:
return (*((uChar *) a) <= *((uChar *) b));
case CDF_INT2:
return (*((Int16 *) a) <= *((Int16 *) b));
case CDF_UINT2:
return (*((uInt16 *) a) <= *((uInt16 *) b));
case CDF_INT4:
return (*((Int32 *) a) <= *((Int32 *) b));
case CDF_UINT4:
return (*((uInt32 *) a) <= *((uInt32 *) b));
case CDF_REAL4:
case CDF_FLOAT:
return (*((float *) a) <= *((float *) b));
case CDF_REAL8:
case CDF_DOUBLE:
case CDF_EPOCH:
return (*((double *) a) <= *((double *) b));
case CDF_EPOCH16: {
double epoch16_a[2], epoch16_b[2];
epoch16_a[0] = *((double *) a);
epoch16_a[1] = *(((double *) a)+1);
epoch16_b[0] = *((double *) b);
epoch16_b[1] = *(((double *) b)+1);
if (epoch16_a[0] > epoch16_b[0]) return FALSE;
if (epoch16_a[0] == epoch16_b[0] && epoch16_a[1] > epoch16_b[1])
return FALSE;
return TRUE;
}
case CDF_CHAR:
case CDF_UCHAR:
return BOO(memcmp(a,b,(size_t)numElems) <= 0,TRUE,FALSE);
}
return FALSE;
}
/******************************************************************************
* LTx.
******************************************************************************/
Logical LTx (a, b, dataType, numElems)
void *a;
void *b;
long dataType;
long numElems;
{
switch (dataType) {
case CDF_BYTE:
case CDF_INT1:
return (*((sChar *) a) < *((sChar *) b));
case CDF_UINT1:
return (*((uChar *) a) < *((uChar *) b));
case CDF_INT2:
return (*((Int16 *) a) < *((Int16 *) b));
case CDF_UINT2:
return (*((uInt16 *) a) < *((uInt16 *) b));
case CDF_INT4:
return (*((Int32 *) a) < *((Int32 *) b));
case CDF_UINT4:
return (*((uInt32 *) a) < *((uInt32 *) b));
case CDF_REAL4:
case CDF_FLOAT:
return (*((float *) a) < *((float *) b));
case CDF_REAL8:
case CDF_DOUBLE:
case CDF_EPOCH:
return (*((double *) a) < *((double *) b));
case CDF_EPOCH16: {
double epoch16_a[2], epoch16_b[2];
epoch16_a[0] = *((double *) a);
epoch16_a[1] = *(((double *) a)+1);
epoch16_b[0] = *((double *) b);
epoch16_b[1] = *(((double *) b)+1);
if (epoch16_a[0] > epoch16_b[0]) return FALSE;
if (epoch16_a[0] == epoch16_b[0] && epoch16_a[1] >= epoch16_b[1])
return FALSE;
return TRUE;
}
case CDF_CHAR:
case CDF_UCHAR:
return BOO(memcmp(a,b,(size_t)numElems) < 0,TRUE,FALSE);
}
return FALSE;
}
/******************************************************************************
* GEx.
******************************************************************************/
Logical GEx (a, b, dataType, numElems)
void *a;
void *b;
long dataType;
long numElems;
{
switch (dataType) {
case CDF_BYTE:
case CDF_INT1:
return (*((sChar *) a) >= *((sChar *) b));
case CDF_UINT1:
return (*((uChar *) a) >= *((uChar *) b));
case CDF_INT2:
return (*((Int16 *) a) >= *((Int16 *) b));
case CDF_UINT2:
return (*((uInt16 *) a) >= *((uInt16 *) b));
case CDF_INT4:
return (*((Int32 *) a) >= *((Int32 *) b));
case CDF_UINT4:
return (*((uInt32 *) a) >= *((uInt32 *) b));
case CDF_REAL4:
case CDF_FLOAT:
return (*((float *) a) >= *((float *) b));
case CDF_REAL8:
case CDF_DOUBLE:
case CDF_EPOCH:
return (*((double *) a) >= *((double *) b));
case CDF_EPOCH16: {
double epoch16_a[2], epoch16_b[2];
epoch16_a[0] = *((double *) a);
epoch16_a[1] = *(((double *) a)+1);
epoch16_b[0] = *((double *) b);
epoch16_b[1] = *(((double *) b)+1);
if (epoch16_a[0] < epoch16_b[0]) return FALSE;
if (epoch16_a[0] == epoch16_b[0] && epoch16_a[1] < epoch16_b[1])
return FALSE;
return TRUE;
}
case CDF_CHAR:
case CDF_UCHAR:
return BOO(memcmp(a,b,(size_t)numElems) >= 0,TRUE,FALSE);
}
return FALSE;
}
/******************************************************************************
* GTx.
******************************************************************************/
Logical GTx (a, b, dataType, numElems)
void *a;
void *b;
long dataType;
long numElems;
{
switch (dataType) {
case CDF_BYTE:
case CDF_INT1:
return (*((sChar *) a) > *((sChar *) b));
case CDF_UINT1:
return (*((uChar *) a) > *((uChar *) b));
case CDF_INT2:
return (*((Int16 *) a) > *((Int16 *) b));
case CDF_UINT2:
return (*((uInt16 *) a) > *((uInt16 *) b));
case CDF_INT4:
return (*((Int32 *) a) > *((Int32 *) b));
case CDF_UINT4:
return (*((uInt32 *) a) > *((uInt32 *) b));
case CDF_REAL4:
case CDF_FLOAT:
return (*((float *) a) > *((float *) b));
case CDF_REAL8:
case CDF_DOUBLE:
case CDF_EPOCH:
return (*((double *) a) > *((double *) b));
case CDF_EPOCH16: {
double epoch16_a[2], epoch16_b[2];
epoch16_a[0] = *((double *) a);
epoch16_a[1] = *(((double *) a)+1);
epoch16_b[0] = *((double *) b);
epoch16_b[1] = *(((double *) b)+1);
if (epoch16_a[0] < epoch16_b[0]) return FALSE;
if (epoch16_a[0] == epoch16_b[0] && epoch16_a[1] <= epoch16_b[1])
return FALSE;
return TRUE;
}
case CDF_CHAR:
case CDF_UCHAR:
return BOO(memcmp(a,b,(size_t)numElems) > 0,TRUE,FALSE);
}
return FALSE;
}
/******************************************************************************
* IncrRecordIndicesFirstLast.
* Rolls over to `first' indices if at `last' indices (and increments record).
******************************************************************************/
void IncrRecordIndicesFirstLast (rowMajor, recordN, numDims, first, last,
indices)
Logical rowMajor;
long *recordN;
long numDims;
long first[];
long last[];
long indices[];
{
if (numDims > 0) {
int firstDim = BOO(rowMajor,(int)(numDims - 1),0);
int lastDim = BOO(rowMajor,0,(int)(numDims - 1));
int dimIncr = BOO(rowMajor,-1,1);
int doneDim = lastDim + dimIncr, dimN;
for (dimN = firstDim; dimN != doneDim; dimN += dimIncr) {
if (indices[dimN] == last[dimN]) {
indices[dimN] = first[dimN];
if (dimN == lastDim) (*recordN)++;
}
else {
indices[dimN]++;
break;
}
}
}
else
(*recordN)++;
return;
}
/******************************************************************************
* IncrIndicesFirstLastRow.
* Rolls over to `first' indices if at `last' indices.
******************************************************************************/
void IncrIndicesFirstLastRow (numDims, first, last, indices)
long numDims;
long first[];
long last[];
long indices[];
{
int dimN;
for (dimN = (int) (numDims - 1); dimN >= 0; dimN--) {
if (indices[dimN] == last[dimN])
indices[dimN] = first[dimN];
else {
indices[dimN]++;
break;
}
}
return;
}
/******************************************************************************
* IncrIndicesFirstLastCol.
* Rolls over to `first' indices if at `last' indices.
******************************************************************************/
void IncrIndicesFirstLastCol (numDims, first, last, indices)
long numDims;
long first[];
long last[];
long indices[];
{
int dimN;
for (dimN = 0; dimN < numDims; dimN++) {
if (indices[dimN] == last[dimN])
indices[dimN] = first[dimN];
else {
indices[dimN]++;
break;
}
}
return;
}
/******************************************************************************
* AllocateBuffers.
******************************************************************************/
Logical AllocateBuffers (nRecords, numDims, dimSizes, groups, nScalarBuffers,
nHyperBuffers, handles, nValueBytes, rowMajor,
minNofHypers, fatalFnc)
long nRecords;
long numDims;
long dimSizes[];
struct GroupStruct *groups;
int nScalarBuffers;
int nHyperBuffers;
Byte **handles[];
size_t nValueBytes[];
Logical rowMajor;
int minNofHypers;
void (*fatalFnc) PROTOARGs((char *msg));
{
int lsDimN; /* Least significant dimension number. */
int msDimN; /* Most significant dimension number. */
int dimStep; /* How to increment dimension number from most
significant to least significant. */
int dimN, dN;
long nValuesPerRec, nValuesPerDim[CDF_MAX_DIMS], count, nHypersSoFar;
/****************************************************************************
* Setup for majority.
****************************************************************************/
lsDimN = BOO(rowMajor,(int)(numDims-1),0);
msDimN = BOO(rowMajor,0,(int)(numDims-1));
dimStep = BOO(rowMajor,1,-1);
/****************************************************************************
* Calculate number of values per record/dimension.
****************************************************************************/
if (numDims > 0) {
nValuesPerDim[lsDimN] = 1;
for (dimN = lsDimN - dimStep; dimN != msDimN - dimStep; dimN -= dimStep) {
nValuesPerDim[dimN] = dimSizes[dimN+dimStep] *
nValuesPerDim[dimN+dimStep];
}
nValuesPerRec = dimSizes[msDimN] * nValuesPerDim[msDimN];
}
else
nValuesPerRec = 1;
/****************************************************************************
* Check if full records can be allocated.
****************************************************************************/
count = nRecords;
while (count >= 1 ) {
long nRecGroups = nRecords/count + BOO(nRecords % count == 0,0,1);
if (nRecGroups >= minNofHypers || count == 1) {
if (AttemptAllocations(count,nScalarBuffers,count*nValuesPerRec,
nHyperBuffers,handles,nValueBytes)) {
groups->nRecGroups = nRecGroups;
groups->firstRecCount = count;
groups->lastRecCount = BOO(nRecords % count == 0,
count,nRecords % count);
groups->recGroupN = 1;
for (dimN = msDimN; dimN != lsDimN + dimStep; dimN += dimStep) {
groups->nDimGroups[dimN] = 1;
groups->firstDimCount[dimN] = dimSizes[dimN];
groups->lastDimCount[dimN] = dimSizes[dimN];
groups->dimGroupN[dimN] = 1;
}
return TRUE;
}
}
if (count == 1) break;
count = (count + BOO(count % 2 == 0,0,1)) / 2;
}
groups->nRecGroups = nRecords;
groups->firstRecCount = 1;
groups->lastRecCount = 1;
groups->recGroupN = 1;
nHypersSoFar = nRecords;
/****************************************************************************
* Check how much of each dimension can be allocated.
****************************************************************************/
for (dimN = msDimN; dimN != lsDimN + dimStep; dimN += dimStep) {
count = dimSizes[dimN];
while (count > 1) {
long nDimGroups = (dimSizes[dimN] / count) +
BOO(dimSizes[dimN] % count == 0,0,1);
if (nHypersSoFar * nDimGroups >= minNofHypers) {
if (AttemptAllocations(1L,nScalarBuffers,count*nValuesPerDim[dimN],
nHyperBuffers,handles,nValueBytes)) {
groups->nDimGroups[dimN] = nDimGroups;
groups->firstDimCount[dimN] = count;
groups->lastDimCount[dimN] = BOO(dimSizes[dimN] % count == 0,
count,dimSizes[dimN] % count);
groups->dimGroupN[dimN] = 1;
for (dN = dimN + dimStep; dN != lsDimN + dimStep; dN += dimStep) {
groups->nDimGroups[dN] = 1;
groups->firstDimCount[dN] = dimSizes[dN];
groups->lastDimCount[dN] = dimSizes[dN];
groups->dimGroupN[dN] = 1;
}
return TRUE;
}
}
count = (count + 1) / 2;
}
groups->nDimGroups[dimN] = dimSizes[dimN];
groups->firstDimCount[dimN] = 1;
groups->lastDimCount[dimN] = 1;
groups->dimGroupN[dimN] = 1;
nHypersSoFar *= dimSizes[dimN];
}
if (AttemptAllocations(1L,nScalarBuffers,1L,nHyperBuffers,
handles,nValueBytes)) return TRUE;
/****************************************************************************
* Not all of the buffers can be allocated even at only one value per buffer.
****************************************************************************/
if (fatalFnc != NULL) (*fatalFnc)("Unable to allocate memory buffers.");
return FALSE;
}
/******************************************************************************
* AttemptAllocations.
******************************************************************************/
static Logical AttemptAllocations (nScalarValues, nScalarBuffers, nHyperValues,
nHyperBuffers, handles, nValueBytes)
long nScalarValues;
int nScalarBuffers;
long nHyperValues;
int nHyperBuffers;
Byte **handles[];
size_t nValueBytes[];
{
int bN, bNt; uLong maxBytes = 1, nBytes;
#if defined(mac) || defined(dos)
void *ptr;
#endif
/****************************************************************************
* First allocate scalar buffers.
****************************************************************************/
for (bN = 0; bN < nScalarBuffers; bN++) {
nBytes = nScalarValues * nValueBytes[bN];
if (nBytes > MAXnBYTESperALLOCATION)
*handles[bN] = NULL;
else
*handles[bN] = cdf_AllocateMemory ((size_t) nBytes, NULL);
if (*handles[bN] == NULL) {
for (bNt = bN - 1; bNt >= 0; bNt--) cdf_FreeMemory (*handles[bNt],
NULL);
return FALSE;
}
maxBytes = MAXIMUM(maxBytes,nBytes);
}
/****************************************************************************
* Then allocate hyper buffers.
****************************************************************************/
for (bN = nScalarBuffers; bN < nScalarBuffers + nHyperBuffers; bN++) {
nBytes = nHyperValues * nValueBytes[bN];
if (nBytes > MAXnBYTESperALLOCATION)
*handles[bN] = NULL;
else
*handles[bN] = cdf_AllocateMemory ((size_t) nBytes, NULL);
if (*handles[bN] == NULL) {
for (bNt = bN - 1; bNt >= 0; bNt--) cdf_FreeMemory (*handles[bNt],
NULL);
return FALSE;
}
maxBytes = MAXIMUM(maxBytes,nBytes);
}
/****************************************************************************
* Allocate and then free a buffer twice the size of the largest buffer
* allocated. This will save some space on the heap for other uses.
****************************************************************************/
#if defined(mac) || defined(dos)
ptr = cdf_AllocateMemory ((size_t) (2 * maxBytes), NULL);
if (ptr == NULL) {
for (bNt = nScalarBuffers + nHyperBuffers - 1; bNt >= 0; bNt--) {
cdf_FreeMemory (*handles[bNt], NULL);
}
return FALSE;
}
cdf_FreeMemory (ptr, NULL);
#endif
/****************************************************************************
* All allocations succeeded, return TRUE.
****************************************************************************/
return TRUE;
}
/******************************************************************************
* HyperFullRecord.
******************************************************************************/
Logical HyperFullRecord (groups, numDims)
struct GroupStruct *groups;
long numDims;
{
int dimN;
for (dimN = 0; dimN < numDims; dimN++) {
if (groups->nDimGroups[dimN] > 1) return FALSE;
}
return TRUE;
}
/******************************************************************************
* HypersPerRecord.
******************************************************************************/
long HypersPerRecord (groups, numDims)
struct GroupStruct *groups;
long numDims;
{
int dimN; long nHypers = 1;
for (dimN = 0; dimN < numDims; dimN++) {
nHypers *= groups->nDimGroups[dimN];
}
return nHypers;
}
/******************************************************************************
* HyperStartRecord.
******************************************************************************/
Logical HyperStartOfRecord (hyper, numDims)
struct HyperStruct *hyper;
long numDims;
{
int dimN;
for (dimN = 0; dimN < numDims; dimN++) {
if (hyper->dimIndices[dimN] > 0) return FALSE;
}
return TRUE;
}
/******************************************************************************
* InitHyperParms.
******************************************************************************/
void InitHyperParms (hyper, groups, numDims, nHypers, nValues)
struct HyperStruct *hyper;
struct GroupStruct *groups;
long numDims;
long *nHypers;
long *nValues;
{
int dimN;
*nHypers = groups->nRecGroups;
for (dimN = 0; dimN < numDims; dimN++) *nHypers *= groups->nDimGroups[dimN];
hyper->recNumber = 0;
hyper->recCount = groups->firstRecCount;
hyper->recInterval = 1;
for (dimN = 0; dimN < numDims; dimN++) {
hyper->dimIndices[dimN] = 0;
hyper->dimCounts[dimN] = groups->firstDimCount[dimN];
hyper->dimIntervals[dimN] = 1;
}
*nValues = hyper->recCount;
for (dimN = 0; dimN < numDims; dimN++) *nValues *= hyper->dimCounts[dimN];
return;
}
/******************************************************************************
* IncrHyperParms.
******************************************************************************/
void IncrHyperParms (hyper, groups, numDims, rowMajor, nValues)
struct HyperStruct *hyper;
struct GroupStruct *groups;
long numDims;
Logical rowMajor;
long *nValues;
{
int lsDimN; /* Least significant dimension number. */
int msDimN; /* Most significant dimension number. */
int dimStep; /* How to increment dimension number from most
significant to least significant. */
int dimN;
/****************************************************************************
* Setup for majority.
****************************************************************************/
lsDimN = BOO(rowMajor,(int)(numDims-1),0);
msDimN = BOO(rowMajor,0,(int)(numDims-1));
dimStep = BOO(rowMajor,1,-1);
/****************************************************************************
* Increment indices.
****************************************************************************/
for (dimN = lsDimN; dimN != msDimN - dimStep; dimN -= dimStep) {
if (groups->dimGroupN[dimN] < groups->nDimGroups[dimN]) {
groups->dimGroupN[dimN]++;
if (groups->dimGroupN[dimN] < groups->nDimGroups[dimN]) {
hyper->dimIndices[dimN] += groups->firstDimCount[dimN];
hyper->dimCounts[dimN] = groups->firstDimCount[dimN];
}
else {
hyper->dimIndices[dimN] += groups->firstDimCount[dimN];
hyper->dimCounts[dimN] = groups->lastDimCount[dimN];
}
*nValues = hyper->recCount;
for (dimN = 0; dimN < numDims; dimN++) {
*nValues *= hyper->dimCounts[dimN];
}
return;
}
else {
groups->dimGroupN[dimN] = 1;
hyper->dimIndices[dimN] = 0;
hyper->dimCounts[dimN] = groups->firstDimCount[dimN];
}
}
/****************************************************************************
* Increment record.
****************************************************************************/
groups->recGroupN++;
hyper->recNumber += groups->firstRecCount;
hyper->recCount = BOO(groups->recGroupN < groups->nRecGroups,
groups->firstRecCount,groups->lastRecCount);
*nValues = hyper->recCount;
for (dimN = 0; dimN < numDims; dimN++) *nValues *= hyper->dimCounts[dimN];
return;
}
/******************************************************************************
* WriteOutPct.
******************************************************************************/
void WriteOutPct (pct)
int pct;
{
char text[8+1];
strcpyX (text, "\b\b\b\b", 8);
if (pct < 10) strcatX (text, ".", 8);
if (pct < 100) strcatX (text, ".", 8);
sprintf (EofS(text), "%d", pct);
strcatX (text, "%", 8);
WriteOut (stdout, text);
return;
}
/******************************************************************************
* SwitchMajority.
******************************************************************************/
Logical SwitchMajority (buffer, rowMajor, numDims, dimSizes, recCount,
nValueBytes)
Byte *buffer;
Logical rowMajor;
long numDims;
long dimSizes[];
long recCount;
size_t nValueBytes;
{
int dimN; long nRecordBytes, recX; Byte *offset; void *tBuffer;
/****************************************************************************
* If less than two dimensions no switching needs to be done.
****************************************************************************/
if (numDims < 2) return TRUE;
/****************************************************************************
* Calculate number of bytes per record.
****************************************************************************/
nRecordBytes = nValueBytes;
for (dimN = 0; dimN < numDims; dimN++) nRecordBytes *= dimSizes[dimN];
/****************************************************************************
* Attempt to allocate a temporary buffer for one record.
****************************************************************************/
#if defined(dos)
if (TOObigIBMpc(nRecordBytes))
tBuffer = NULL;
else
#endif
tBuffer = cdf_AllocateMemory ((size_t) nRecordBytes, NULL);
if (tBuffer == NULL) return FALSE;
/****************************************************************************
* Switch majority.
****************************************************************************/
for (recX = 0, offset = buffer; recX < recCount;
recX++, offset += (size_t) nRecordBytes) {
if (rowMajor)
ROWtoCOL (offset, tBuffer, numDims, dimSizes, (long) nValueBytes);
else
COLtoROW (offset, tBuffer, numDims, dimSizes, (long) nValueBytes);
memmove (offset, tBuffer, (size_t) nRecordBytes);
}
/****************************************************************************
* Free temporary buffer and return success.
****************************************************************************/
cdf_FreeMemory (tBuffer, FatalError);
return TRUE;
}
/******************************************************************************
* CompressedCDF.
******************************************************************************/
Logical CompressedCDF (CDFpath)
char *CDFpath;
{
CDFstatus status; long cType, cParms[CDF_MAX_PARMS];
OFF_T cFileSize, uFileSize;
status = CDFlib (GET_, CDF_INFO_, CDFpath, &cType, cParms,
&cFileSize, &uFileSize,
NULL_);
if (StatusBAD(status)) return FALSE;
return ((Logical) (cType != NO_COMPRESSION));
}
/******************************************************************************
* SameCompressions.
******************************************************************************/
Logical SameCompressions (cType1, cParms1, cType2, cParms2)
long cType1;
long cParms1[CDF_MAX_PARMS];
long cType2;
long cParms2[CDF_MAX_PARMS];
{
int parmN, pCount;
/****************************************************************************
* Compare compression types.
****************************************************************************/
if (cType1 != cType2) return FALSE;
/****************************************************************************
* If same types, compare compression parameters (if any).
****************************************************************************/
pCount = CompressionParmsCount(cType1);
for (parmN = 0; parmN < pCount; parmN++) {
if (cParms1[parmN] != cParms2[parmN]) return FALSE;
}
/****************************************************************************
* Compressions must be the same.
****************************************************************************/
return TRUE;
}
/******************************************************************************
* SameSparsenesses.
******************************************************************************/
Logical SameSparsenesses (sRecordsType1, sArraysType1, sArraysParms1,
sRecordsType2, sArraysType2, sArraysParms2)
long sRecordsType1;
long sArraysType1;
long sArraysParms1[CDF_MAX_PARMS];
long sRecordsType2;
long sArraysType2;
long sArraysParms2[CDF_MAX_PARMS];
{
int parmN, pCount;
/****************************************************************************
* Compare sparse records.
****************************************************************************/
if (sRecordsType1 != sRecordsType2) return FALSE;
/****************************************************************************
* Compare sparse array types.
****************************************************************************/
if (sArraysType1 != sArraysType2) return FALSE;
/****************************************************************************
* If same types, compare sparse array parameters (if any).
****************************************************************************/
pCount = SparsenessParmsCount(sArraysType1);
for (parmN = 0; parmN < pCount; parmN++) {
if (sArraysParms1[parmN] != sArraysParms2[parmN]) return FALSE;
}
/****************************************************************************
* Sparsenesses must be the same.
****************************************************************************/
return TRUE;
}
/******************************************************************************
* WhichFormat.
******************************************************************************/
long WhichFormat (token)
char *token;
{
if (strncmpIgCase(token,"SINGLE",6) != 0) return SINGLE_FILE;
if (strncmpIgCase(token,"MULTI",5) != 0) return MULTI_FILE;
return -1;
}
/******************************************************************************
* WhichMajority.
******************************************************************************/
long WhichMajority (token)
char *token;
{
if (strncmpIgCase(token,"ROW",3) != 0) return ROW_MAJOR;
if ((strncmpIgCase(token,"COL",3) != 0) ||
(strncmpIgCase(token,"COLUMN",6) != 0)) return COLUMN_MAJOR;
return -1;
}
/******************************************************************************
* WhichRecSparseness.
******************************************************************************/
long WhichRecSparseness (token)
char *token;
{
if (strncmpIgCase(token,"None",4) != 0) return NO_SPARSERECORDS;
if (strncmpIgCase(token,"sRecords.PAD",12) != 0) return PAD_SPARSERECORDS;
if (strncmpIgCase(token,"sRecords.PREV",13) != 0) return PREV_SPARSERECORDS;
return -1;
}
/******************************************************************************
* WhichCompression
******************************************************************************/
long WhichCompression (token, compression, cParms)
char *token;
long *compression;
long cParms[CDF_MAX_PARMS];
{
*compression = -1;
cParms[0] = 0;
if (strncmpIgCase(token,"No",2) != 0) *compression = NO_COMPRESSION;
else if (strncmpIgCase(token,"RLE",3) != 0) *compression = RLE_COMPRESSION;
else if (strncmpIgCase(token,"HUFF",4) != 0) *compression = HUFF_COMPRESSION;
else if (strncmpIgCase(token,"AHUFF",5) != 0) *compression = AHUFF_COMPRESSION;
else if (strncmpIgCase(token,"GZIP",4) != 0) {
#if defined(__osf__)
int clevel;
if (sscanf(token,"GZIP.%d",&clevel) == 1)
#else
long clevel;
if (sscanf(token,"GZIP.%1d",&clevel) == 1)
#endif
if (INCLUSIVE(1,clevel,9)) {
*compression = GZIP_COMPRESSION;
cParms[0] = (long) clevel;
}
}
/* if (strncmpIgCase(token,"ZLIB",4)) *compression = ZLIB_COMPRESSION; */
return (long) *compression;
}
/******************************************************************************
* WhichEncoding. `MIPSEL' (DECstation) and `MIPSEB' (SGi) are valid synonyms
* in order to remain compatible with previous releases of CDF.
******************************************************************************/
long WhichEncoding (token)
char *token;
{
if (strncmpIgCase(token,"HOST",4) != 0) return HOST_ENCODING;
if (strncmpIgCase(token,"NETWORK",6) != 0) return NETWORK_ENCODING;
if (strncmpIgCase(token,"VAX",3) != 0) return VAX_ENCODING;
if (strncmpIgCase(token,"SUN",3) != 0) return SUN_ENCODING;
if ((strncmpIgCase(token,"SGi",3) != 0) ||
(strncmpIgCase(token,"MIPSEB",6) != 0)) return SGi_ENCODING;
if ((strncmpIgCase(token,"DECSTATION",10) != 0) ||
(strncmpIgCase(token,"MIPSEL",6) != 0)) return DECSTATION_ENCODING;
if (strncmpIgCase(token,"IBMRS",5) != 0) return IBMRS_ENCODING;
if (strncmpIgCase(token,"IBMPC",5) != 0) return IBMPC_ENCODING;
if (strncmpIgCase(token,"HP",2) != 0) return HP_ENCODING;
if (strncmpIgCase(token,"NeXT",4) != 0) return NeXT_ENCODING;
if (strncmpIgCase(token,"ALPHAOSF1",9) != 0) return ALPHAOSF1_ENCODING;
if (strncmpIgCase(token,"ALPHAVMSd",9) != 0) return ALPHAVMSd_ENCODING;
if (strncmpIgCase(token,"ALPHAVMSg",9) != 0) return ALPHAVMSg_ENCODING;
if (strncmpIgCase(token,"ALPHAVMSi",9) != 0) return ALPHAVMSi_ENCODING;
if (strncmpIgCase(token,"MAC",3) != 0) return MAC_ENCODING;
return -1;
}
/******************************************************************************
* WhichDataType.
******************************************************************************/
long WhichDataType (token)
char *token;
{
if (strncmpIgCase(token,"BYTE",4) != 0) return CDF_BYTE;
if (strncmpIgCase(token,"INT1",4) != 0) return CDF_INT1;
if (strncmpIgCase(token,"UINT1",5) != 0) return CDF_UINT1;
if (strncmpIgCase(token,"INT2",4) != 0) return CDF_INT2;
if (strncmpIgCase(token,"UINT2",5) != 0) return CDF_UINT2;
if (strncmpIgCase(token,"INT4",4) != 0) return CDF_INT4;
if (strncmpIgCase(token,"UINT4",5) != 0) return CDF_UINT4;
if (strncmpIgCase(token,"REAL4",5) != 0) return CDF_REAL4;
if (strncmpIgCase(token,"FLOAT",5) != 0) return CDF_FLOAT;
if (strncmpIgCase(token,"REAL8",5) != 0) return CDF_REAL8;
if (strncmpIgCase(token,"DOUBLE",6) != 0) return CDF_DOUBLE;
if (strncmpIgCase(token,"CHAR",4) != 0) return CDF_CHAR;
if (strncmpIgCase(token,"UCHAR",5) != 0) return CDF_UCHAR;
if (strncmpIgCase(token,"EPOCH",5) != 0) return CDF_EPOCH;
if (strncmpIgCase(token,"EPOCH16",7) != 0) return CDF_EPOCH16;
if (strncmpIgCase(token,"CDF_BYTE",8) != 0) return CDF_BYTE;
if (strncmpIgCase(token,"CDF_INT1",8) != 0) return CDF_INT1;
if (strncmpIgCase(token,"CDF_UINT1",9) != 0) return CDF_UINT1;
if (strncmpIgCase(token,"CDF_INT2",8) != 0) return CDF_INT2;
if (strncmpIgCase(token,"CDF_UINT2",9) != 0) return CDF_UINT2;
if (strncmpIgCase(token,"CDF_INT4",8) != 0) return CDF_INT4;
if (strncmpIgCase(token,"CDF_UINT4",9) != 0) return CDF_UINT4;
if (strncmpIgCase(token,"CDF_REAL4",9) != 0) return CDF_REAL4;
if (strncmpIgCase(token,"CDF_FLOAT",9) != 0) return CDF_FLOAT;
if (strncmpIgCase(token,"CDF_REAL8",9) != 0) return CDF_REAL8;
if (strncmpIgCase(token,"CDF_DOUBLE",10) != 0) return CDF_DOUBLE;
if (strncmpIgCase(token,"CDF_CHAR",8) != 0) return CDF_CHAR;
if (strncmpIgCase(token,"CDF_UCHAR",9) != 0) return CDF_UCHAR;
if (strncmpIgCase(token,"CDF_EPOCH",9) != 0) return CDF_EPOCH;
if (strncmpIgCase(token,"CDF_EPOCH16",11) != 0) return CDF_EPOCH16;
return -1;
}
/******************************************************************************
* WhichChecksum.
******************************************************************************/
long WhichChecksum (token)
char *token;
{
if ((strncmpIgCase(token,"NO",2) != 0) ||
(strncmpIgCase(token,"NONE",4) != 0)) return NO_CHECKSUM;
if (strncmpIgCase(token,"MD5",3) != 0) return MD5_CHECKSUM;
if (strncmpIgCase(token,"OTHER",5) != 0) return OTHER_CHECKSUM;
return -1;
}
/******************************************************************************
* EncodingToken.
* Returns address of character string for encoding.
******************************************************************************/
char *EncodingToken (encoding)
long encoding;
{
switch (encoding) {
case NETWORK_ENCODING: return "NETWORK";
case VAX_ENCODING: return "VAX";
case SUN_ENCODING: return "SUN";
case DECSTATION_ENCODING: return "DECSTATION";
case SGi_ENCODING: return "SGi";
case IBMRS_ENCODING: return "IBMRS";
case IBMPC_ENCODING: return "IBMPC";
case HP_ENCODING: return "HP";
case NeXT_ENCODING: return "NeXT";
case ALPHAOSF1_ENCODING: return "ALPHAOSF1";
case ALPHAVMSd_ENCODING: return "ALPHAVMSd";
case ALPHAVMSg_ENCODING: return "ALPHAVMSg";
case ALPHAVMSi_ENCODING: return "ALPHAVMSi";
case MAC_ENCODING: return "MAC";
default: return "?";
}
}
/******************************************************************************
* MajorityToken.
* Returns address of character string for majority.
******************************************************************************/
char *MajorityToken (majority)
long majority;
{
switch (majority) {
case ROW_MAJOR: return "ROW";
case COLUMN_MAJOR: return "COLUMN";
default: return "?";
}
}
/******************************************************************************
* FormatToken.
* Returns address of character string for format.
******************************************************************************/
char *FormatToken (format)
long format;
{
switch (format) {
case SINGLE_FILE: return "SINGLE";
case MULTI_FILE: return "MULTI";
default: return "?";
}
}
/******************************************************************************
* ChecksumToken.
* Returns address of character string for checksum.
******************************************************************************/
char *ChecksumToken (checksum)
long checksum;
{
switch (checksum) {
case NO_CHECKSUM: return "None";
case MD5_CHECKSUM: return "MD5";
case OTHER_CHECKSUM: return "Other";
default: return "?";
}
}
/******************************************************************************
* ScopeToken.
* Returns address of character string for scope.
******************************************************************************/
char *ScopeToken (scope)
long scope;
{
switch (scope) {
case GLOBAL_SCOPE: return "GLOBAL";
case VARIABLE_SCOPE: return "VARIABLE";
default: return "?";
}
}
/******************************************************************************
* VarianceToken.
* Returns address of character string for variance.
******************************************************************************/
char *VarianceToken (variance)
long variance;
{
switch (variance) {
case VARY: return "VARY";
case NOVARY: return "NOVARY";
default: return "?";
}
}
/******************************************************************************
* TFvarianceToken.
* Returns address of character string for variance (T/F).
******************************************************************************/
char *TFvarianceToken (variance)
long variance;
{
switch (variance) {
case VARY: return "T";
case NOVARY: return "F";
default: return "?";
}
}
/******************************************************************************
* DataTypeToken.
* Returns address of character string for data type.
******************************************************************************/
char *DataTypeToken (dataType)
long dataType;
{
switch (dataType) {
case CDF_BYTE: return "BYTE";
case CDF_INT1: return "INT1";
case CDF_INT2: return "INT2";
case CDF_INT4: return "INT4";
case CDF_UINT1: return "UINT1";
case CDF_UINT2: return "UINT2";
case CDF_UINT4: return "UINT4";
case CDF_REAL4: return "REAL4";
case CDF_REAL8: return "REAL8";
case CDF_FLOAT: return "FLOAT";
case CDF_DOUBLE: return "DOUBLE";
case CDF_EPOCH: return "EPOCH";
case CDF_EPOCH16: return "EPOCH16";
case CDF_CHAR: return "CHAR";
case CDF_UCHAR: return "UCHAR";
default: return "?";
}
}
/******************************************************************************
* CompressionToken.
* Returns address of character string for compression type/parameters.
******************************************************************************/
char *CompressionToken (cType, cParms)
long cType;
long cParms[CDF_MAX_PARMS];
{
switch (cType) {
case NO_COMPRESSION:
return "None";
case RLE_COMPRESSION:
switch (cParms[0]) {
case RLE_OF_ZEROs: return "RLE.0";
default: return "RLE.?";
}
case HUFF_COMPRESSION:
switch (cParms[0]) {
case OPTIMAL_ENCODING_TREES: return "HUFF.0";
default: return "HUFF.?";
}
case AHUFF_COMPRESSION:
switch (cParms[0]) {
case OPTIMAL_ENCODING_TREES: return "AHUFF.0";
default: return "AHUFF.?";
}
case GZIP_COMPRESSION: {
static char token[MAX_GZIP_TOKEN_LEN+1];
sprintf (token, "GZIP.%d", (int) cParms[0]);
return token;
}
/*
case ZLIB_COMPRESSION:
switch (cParms[0]) {
case RLE_OF_ZEROs: return "ZLIB.0";
default: return "ZLIB.?";
}
*/
default: return "?";
}
}
/******************************************************************************
* SparsenessToken.
* Returns address of character string for sparseness types/parameters.
* Both record and array sparseness is encoded in the same string.
******************************************************************************/
char *SparsenessToken (sRecordsType, sArraysType, sArraysParms)
long sRecordsType;
long sArraysType;
long sArraysParms[CDF_MAX_PARMS];
{
if (sArraysParms[0] == 0) { }; /* Quiets some compilers. */
switch (sRecordsType) {
case NO_SPARSERECORDS:
switch (sArraysType) {
case NO_SPARSEARRAYS:
return "None";
default:
return "?";
}
case PAD_SPARSERECORDS:
switch (sArraysType) {
case NO_SPARSEARRAYS:
return "sRecords.PAD";
default:
return "?";
}
case PREV_SPARSERECORDS:
switch (sArraysType) {
case NO_SPARSEARRAYS:
return "sRecords.PREV";
default:
return "?";
}
default:
return "?";
}
}
/******************************************************************************
* PickDelimiter.
* Exclamation mark (`!') isn't used because it starts a comment in a
* skeleton table. Period (`.') isn't used because it ends a list of
* attribute entries (in a skeleton table). Left bracket (`[') isn't used
* because it starts a set of NRV indices (in a skeleton table).
******************************************************************************/
char PickDelimiter (string, N)
char *string;
size_t N;
{
static char choices[] = "\"'`^~:-,;|+=@#$%&*()/?<>{}]\\";
int i;
for (i = 0; choices[i] != NUL; i++) {
if (strnchr(string,choices[i],N) == NULL) return choices[i];
}
return NUL; /* Very bad, use character stuffing if this is a problem. */
}
/******************************************************************************
* strnchr.
******************************************************************************/
static char *strnchr (string, chr, n)
char *string;
int chr;
int n;
{
int i;
for (i = 0; i < n; i++) if (string[i] == chr) return &string[i];
return NULL;
}
/******************************************************************************
* sleep. Only for Microsoft C.
******************************************************************************/
#if defined(MICROSOFTC)
void sleep (seconds)
uInt seconds;
{
time_t start_time;
time_t current_time;
time (&start_time);
time (¤t_time);
while (current_time - start_time < seconds) time (¤t_time);
return;
}
#endif
/******************************************************************************
* strstrIgCase.
******************************************************************************/
char *strstrIgCase (string, substring)
char *string;
char *substring;
{
int stringL = strlen(string);
int substringL = strlen(substring);
int i, j;
if (stringL == 0 || substringL == 0) return NULL;
if (stringL < substringL) return NULL;
for (i = 0; i < stringL; i++) {
for (j = 0; j < substringL; j++) {
if (MakeLower(substring[j]) != MakeLower(string[i+j])) break;
}
if (j == substringL) return &string[i];
}
return NULL;
}
/******************************************************************************
* strcmpIgCase.
* It returns 1 if compared strings are identical with the same length
* 0 if compared (sub)strings are not same
******************************************************************************/
int strcmpIgCase (string1, string2)
char *string1;
char *string2;
{
int string1L = strlen(string1);
int string2L = strlen(string2);
int i;
if (string1L != string2L) return 0;
for (i = 0; i < string1L; i++) {
if (MakeLower(string1[i]) != MakeLower(string2[i]))
return 0;
}
return 1;
}
/******************************************************************************
* strncmpIgCase... Assuming count is the length from one of passed strings.
* It compares characters upto the passed count.
* It returns 1 if compared strings are identical with same length
* 0 if compared (sub)strings are not same
******************************************************************************/
int strncmpIgCase (string1, string2, count)
char *string1;
char *string2;
size_t count;
{
int string1L = (int) strlen(string1);
int string2L = (int) strlen(string2);
int maxL, i;
maxL = MAXIMUM(string1L,string2L);
maxL = MINIMUM(maxL,(int)count);
for (i = 0; i < maxL; i++) {
if (i == string1L || i == string2L) break;
if (MakeLower(string1[i]) != MakeLower(string2[i])) {
return 0;
}
}
if (string1L == string2L) return 1;
else return 0;
}
/******************************************************************************
* strncmpIgCasePattern.
* It returns 0 if compared strings are the same for the specified length
* <>0 if compared (sub)strings do not have the same pattern
******************************************************************************/
int strncmpIgCasePattern (string1, string2, count)
char *string1;
char *string2;
size_t count;
{
int string1L = (int) strlen(string1);
int string2L = (int) strlen(string2);
int maxL, i;
maxL = MAXIMUM(string1L,string2L);
maxL = MINIMUM(maxL,(int)count);
for (i = 0; i < maxL; i++) {
if (MakeLower(string1[i]) != MakeLower(string2[i])) {
return ((int) (string1[i] - string2[i]));
}
}
return 0;
}
/******************************************************************************
* strchrIgCase.
******************************************************************************/
char *strchrIgCase (str, chr)
char *str;
int chr;
{
int strL = strlen(str);
int i;
if (strL == 0) return NULL;
for (i = 0; i < strL; i++) {
if (MakeLower(chr) == MakeLower(str[i])) return &str[i];
}
return NULL;
}
/******************************************************************************
* WriteEntryValue.
******************************************************************************/
void WriteEntryValue (fp, dataType, numElements, value, ccc, MaXcc)
FILE *fp;
long dataType;
long numElements;
void *value;
int ccc; /* Current Cursor Column (at start). */
int MaXcc; /* Maximum Cursor Column at which to output. */
{
if (STRINGdataType(dataType))
WriteStringValue (fp, numElements, value, ccc, MaXcc);
else {
int i, elemN, n, cccBase = ccc;
char evalue[80+1];
Logical newLine = TRUE;
for (elemN = 0; elemN < numElements; elemN++) {
n = EncodeValue (dataType, (Byte *) value + elemN*CDFelemSize(dataType),
evalue, EPOCH0_STYLE);
if (ccc + (newLine ? 0 : 1) + n +
(elemN != numElements - 1 ? 1 : 0) > MaXcc) {
WriteOut (fp, "\n");
for (i = 0; i < cccBase; i++) WriteOut (fp, " ");
ccc = cccBase;
newLine = TRUE;
}
if (!newLine) ccc += WriteOut (fp, " ");
ccc += WriteOut (fp, evalue);
if (elemN != numElements - 1) ccc += WriteOut (fp, ",");
newLine = FALSE;
}
}
return;
}
/******************************************************************************
* WriteStringValue.
* Note that control characters may exist in the string being written (even
* a NUL character). Control characters are to be replaced with `.'. For this
* reason `memmove' is used to move around strings/substrings.
******************************************************************************/
void WriteStringValue (fp, numChars, value, ccc, MaXcc)
FILE *fp;
long numChars;
void *value;
int ccc; /* Current Cursor Column (at start). */
int MaXcc; /* Maximum Cursor Column at which to output. */
{
int cccBase = ccc, i;
char *string = (char *) value;
char delim;
size_t textL = MaXcc + 1; /* MaXcc + 1. */
char *text = (char *) cdf_AllocateMemory ((size_t) (textL + 1),
FatalError);
if (ccc + 1 + numChars + 1 - 1 <= MaXcc) {
delim = PickDelimiter (string, (size_t) numChars);
text[0] = delim;
memmove (&text[1], string, (size_t) numChars);
text[(int)numChars+1] = delim;
text[(int)numChars+2] = NUL;
for (i = 1; i <= numChars; i++) {
if (!Printable(text[i])) text[i] = '.';
}
WriteOut (fp, text);
}
else {
int sss = MaXcc - ccc - 4 + 1; /* 4 for starting `"' and ending `" -'
(assuming `"' is the delimeter). */
char *substring = (char *) cdf_AllocateMemory ((size_t) (sss + 1),
FatalError);
int x = 0, len;
while (x + sss < numChars) {
if (string[x+sss] == ' ') /* First character next line will be a blank.*/
len = sss;
else {
if (string[x+sss-1] == ' ') /* Last character on line is a blank. */
len = sss;
else { /* Look for a blank at which to break line. */
for (i = x + sss - 2; i > x; i--) if (string[i] == ' ') break;
if (i > x)
len = i - x + 1;
else
len = sss;
}
}
memmove (substring, &string[x], len);
substring[len] = NUL;
for (i = 0; i < len; i++) {
if (!Printable(substring[i])) substring[i] = '.';
}
delim = PickDelimiter (substring, strlen(substring));
sprintf (text, "%c%s%c -", delim, substring, delim);
WriteOut (fp, text);
WriteOut (fp, "\n");
for (i = 0; i < cccBase; i++) WriteOut (fp, " ");
x += len;
}
len = (size_t) (numChars - x);
memmove (substring, &string[x], len);
substring[len] = NUL;
for (i = 0; i < len; i++) {
if (!Printable(substring[i])) substring[i] = '.';
}
delim = PickDelimiter (substring, strlen(substring));
sprintf (text, "%c%s%c", delim, substring, delim);
WriteOut (fp, text);
cdf_FreeMemory (substring, FatalError);
}
cdf_FreeMemory (text, FatalError);
return;
}
/******************************************************************************
* ConvertDataType.
******************************************************************************/
void ConvertDataType (fromDataType, fromNumElems, fromPtr, toDataType,
toNumElems, toPtr)
long fromDataType;
long fromNumElems; /* Only used if character data type. */
void *fromPtr;
long toDataType;
long toNumElems; /* Only used if character data type. */
void *toPtr;
{
switch (fromDataType) {
/**************************************************************************
* 1-byte signed integer to...
**************************************************************************/
case CDF_BYTE:
case CDF_INT1:
switch (toDataType) {
case CDF_BYTE:
case CDF_INT1:
*((sChar *) toPtr) = (sChar) *((sChar *) fromPtr);
break;
case CDF_UINT1:
*((uChar *) toPtr) = (uChar) *((sChar *) fromPtr);
break;
case CDF_INT2:
*((Int16 *) toPtr) = (Int16) *((sChar *) fromPtr);
break;
case CDF_UINT2:
*((uInt16 *) toPtr) = (uInt16) *((sChar *) fromPtr);
break;
case CDF_INT4:
*((Int32 *) toPtr) = (Int32) *((sChar *) fromPtr);
break;
case CDF_UINT4:
*((uInt32 *) toPtr) = (uInt32) *((sChar *) fromPtr);
break;
case CDF_FLOAT:
case CDF_REAL4:
*((float *) toPtr) = (float) *((sChar *) fromPtr);
break;
case CDF_EPOCH:
case CDF_DOUBLE:
case CDF_REAL8:
*((double *) toPtr) = (double) *((sChar *) fromPtr);
break;
case CDF_EPOCH16:
*((double *) toPtr) = (double) *((sChar *) fromPtr);
*(((double *) toPtr) + 1) = (double) *(((sChar *) fromPtr) + 1);
break;
case CDF_CHAR:
case CDF_UCHAR: {
int i, len;
char tmp[MAX_nonSTRING_VALUE_LEN+1];
sprintf (tmp, "%d", *((sChar *) fromPtr));
for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
*((char *) toPtr + i) = (i < len ? tmp[i] : ' ');
}
break;
}
}
break;
/**************************************************************************
* 1-byte unsigned integer to...
**************************************************************************/
case CDF_UINT1:
switch (toDataType) {
case CDF_BYTE:
case CDF_INT1:
*((sChar *) toPtr) = (sChar) *((uChar *) fromPtr);
break;
case CDF_UINT1:
*((uChar *) toPtr) = (uChar) *((uChar *) fromPtr);
break;
case CDF_INT2:
*((Int16 *) toPtr) = (Int16) *((uChar *) fromPtr);
break;
case CDF_UINT2:
*((uInt16 *) toPtr) = (uInt16) *((uChar *) fromPtr);
break;
case CDF_INT4:
*((Int32 *) toPtr) = (Int32) *((uChar *) fromPtr);
break;
case CDF_UINT4:
*((uInt32 *) toPtr) = (uInt32) *((uChar *) fromPtr);
break;
case CDF_FLOAT:
case CDF_REAL4:
*((float *) toPtr) = (float) *((uChar *) fromPtr);
break;
case CDF_EPOCH:
case CDF_DOUBLE:
case CDF_REAL8:
*((double *) toPtr) = (double) *((uChar *) fromPtr);
break;
case CDF_EPOCH16:
*((double *) toPtr) = (double) *((uChar *) fromPtr);
*(((double *) toPtr) + 1) = (double) *(((uChar *) fromPtr) + 1);
break;
case CDF_CHAR:
case CDF_UCHAR: {
int i, len;
char tmp[MAX_nonSTRING_VALUE_LEN+1];
sprintf (tmp, "%u", *((uChar *) fromPtr));
for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
*((char *) toPtr + i) = (i < len ? tmp[i] : ' ');
}
break;
}
}
break;
/**************************************************************************
* 2-byte signed integer to...
**************************************************************************/
case CDF_INT2:
switch (toDataType) {
case CDF_BYTE:
case CDF_INT1:
*((sChar *) toPtr) = (sChar) *((Int16 *) fromPtr);
break;
case CDF_UINT1:
*((uChar *) toPtr) = (uChar) *((Int16 *) fromPtr);
break;
case CDF_INT2:
*((Int16 *) toPtr) = (Int16) *((Int16 *) fromPtr);
break;
case CDF_UINT2:
*((uInt16 *) toPtr) = (uInt16) *((Int16 *) fromPtr);
break;
case CDF_INT4:
*((Int32 *) toPtr) = (Int32) *((Int16 *) fromPtr);
break;
case CDF_UINT4:
*((uInt32 *) toPtr) = (uInt32) *((Int16 *) fromPtr);
break;
case CDF_FLOAT:
case CDF_REAL4:
*((float *) toPtr) = (float) *((Int16 *) fromPtr);
break;
case CDF_EPOCH:
case CDF_DOUBLE:
case CDF_REAL8:
*((double *) toPtr) = (double) *((Int16 *) fromPtr);
break;
case CDF_EPOCH16:
*((double *) toPtr) = (double) *((Int16 *) fromPtr);
*(((double *) toPtr) + 1) = (double) *(((Int16 *) fromPtr) + 1);
break;
case CDF_CHAR:
case CDF_UCHAR: {
int i, len;
char tmp[MAX_nonSTRING_VALUE_LEN+1];
sprintf (tmp, "%d", (int) *((Int16 *) fromPtr));
for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
*((char *) toPtr + i) = (i < len ? tmp[i] : ' ');
}
break;
}
}
break;
/**************************************************************************
* 2-byte unsigned integer to...
**************************************************************************/
case CDF_UINT2:
switch (toDataType) {
case CDF_BYTE:
case CDF_INT1:
*((sChar *) toPtr) = (sChar) *((uInt16 *) fromPtr);
break;
case CDF_UINT1:
*((uChar *) toPtr) = (uChar) *((uInt16 *) fromPtr);
break;
case CDF_INT2:
*((Int16 *) toPtr) = (Int16) *((uInt16 *) fromPtr);
break;
case CDF_UINT2:
*((uInt16 *) toPtr) = (uInt16) *((uInt16 *) fromPtr);
break;
case CDF_INT4:
*((Int32 *) toPtr) = (Int32) *((uInt16 *) fromPtr);
break;
case CDF_UINT4:
*((uInt32 *) toPtr) = (uInt32) *((uInt16 *) fromPtr);
break;
case CDF_FLOAT:
case CDF_REAL4:
*((float *) toPtr) = (float) *((uInt16 *) fromPtr);
break;
case CDF_EPOCH:
case CDF_DOUBLE:
case CDF_REAL8:
*((double *) toPtr) = (double) *((uInt16 *) fromPtr);
break;
case CDF_EPOCH16:
*((double *) toPtr) = (double) *((uInt16 *) fromPtr);
*(((double *) toPtr) + 1) = (double) *(((uInt16 *) fromPtr) + 1);
break;
case CDF_CHAR:
case CDF_UCHAR: {
int i, len;
char tmp[MAX_nonSTRING_VALUE_LEN+1];
sprintf (tmp, "%u", (int) *((uInt16 *) fromPtr));
for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
*((char *) toPtr + i) = (i < len ? tmp[i] : ' ');
}
break;
}
}
break;
/**************************************************************************
* 4-byte signed integer to...
**************************************************************************/
case CDF_INT4:
switch (toDataType) {
case CDF_BYTE:
case CDF_INT1:
*((sChar *) toPtr) = (sChar) *((Int32 *) fromPtr);
break;
case CDF_UINT1:
*((uChar *) toPtr) = (uChar) *((Int32 *) fromPtr);
break;
case CDF_INT2:
*((Int16 *) toPtr) = (Int16) *((Int32 *) fromPtr);
break;
case CDF_UINT2:
*((uInt16 *) toPtr) = (uInt16) *((Int32 *) fromPtr);
break;
case CDF_INT4:
*((Int32 *) toPtr) = (Int32) *((Int32 *) fromPtr);
break;
case CDF_UINT4:
*((uInt32 *) toPtr) = (uInt32) *((Int32 *) fromPtr);
break;
case CDF_FLOAT:
case CDF_REAL4:
*((float *) toPtr) = (float) *((Int32 *) fromPtr);
break;
case CDF_EPOCH:
case CDF_DOUBLE:
case CDF_REAL8:
*((double *) toPtr) = (double) *((Int32 *) fromPtr);
break;
case CDF_EPOCH16:
*((double *) toPtr) = (double) *((Int32 *) fromPtr);
*(((double *) toPtr) + 1) = (double) *(((Int32 *) fromPtr) + 1);
break;
case CDF_CHAR:
case CDF_UCHAR: {
int i, len;
char tmp[MAX_nonSTRING_VALUE_LEN+1];
sprintf (tmp, "%ld", (long) *((Int32 *) fromPtr));
for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
*((char *) toPtr + i) = (i < len ? tmp[i] : ' ');
}
break;
}
}
break;
/**************************************************************************
* 4-byte unsigned integer to...
**************************************************************************/
case CDF_UINT4:
switch (toDataType) {
case CDF_BYTE:
case CDF_INT1:
*((sChar *) toPtr) = (sChar) *((uInt32 *) fromPtr);
break;
case CDF_UINT1:
*((uChar *) toPtr) = (uChar) *((uInt32 *) fromPtr);
break;
case CDF_INT2:
*((Int16 *) toPtr) = (Int16) *((uInt32 *) fromPtr);
break;
case CDF_UINT2:
*((uInt16 *) toPtr) = (uInt16) *((uInt32 *) fromPtr);
break;
case CDF_INT4:
*((Int32 *) toPtr) = (Int32) *((uInt32 *) fromPtr);
break;
case CDF_UINT4:
*((uInt32 *) toPtr) = (uInt32) *((uInt32 *) fromPtr);
break;
case CDF_FLOAT:
case CDF_REAL4:
*((float *) toPtr) = (float) *((uInt32 *) fromPtr);
break;
case CDF_EPOCH:
case CDF_DOUBLE:
case CDF_REAL8:
*((double *) toPtr) = (double) *((uInt32 *) fromPtr);
break;
case CDF_EPOCH16:
*((double *) toPtr) = (double) *((uInt32 *) fromPtr);
*(((double *) toPtr) + 1) = (double) *(((uInt32 *) fromPtr) + 1);
break;
case CDF_CHAR:
case CDF_UCHAR: {
int i, len;
char tmp[MAX_nonSTRING_VALUE_LEN+1];
sprintf (tmp, "%lu", (uLong) *((uInt32 *) fromPtr));
for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
*((char *) toPtr + i) = (i < len ? tmp[i] : ' ');
}
break;
}
}
break;
/**************************************************************************
* 4-byte floating-point to...
**************************************************************************/
case CDF_FLOAT:
case CDF_REAL4:
switch (toDataType) {
case CDF_BYTE:
case CDF_INT1:
*((sChar *) toPtr) = (sChar) *((float *) fromPtr);
break;
case CDF_UINT1:
*((uChar *) toPtr) = (uChar) *((float *) fromPtr);
break;
case CDF_INT2:
*((Int16 *) toPtr) = (Int16) *((float *) fromPtr);
break;
case CDF_UINT2:
*((uInt16 *) toPtr) = (uInt16) *((float *) fromPtr);
break;
case CDF_INT4:
*((Int32 *) toPtr) = (Int32) *((float *) fromPtr);
break;
case CDF_UINT4:
*((uInt32 *) toPtr) = (uInt32) *((float *) fromPtr);
break;
case CDF_FLOAT:
case CDF_REAL4:
*((float *) toPtr) = (float) *((float *) fromPtr);
break;
case CDF_EPOCH:
case CDF_DOUBLE:
case CDF_REAL8:
*((double *) toPtr) = (double) *((float *) fromPtr);
break;
case CDF_EPOCH16:
*((double *) toPtr) = (double) *((float *) fromPtr);
*(((double *) toPtr) + 1) = (double) *(((float *) fromPtr) + 1);
break;
case CDF_CHAR:
case CDF_UCHAR: {
int i, len;
char tmp[MAX_nonSTRING_VALUE_LEN+1];
sprintf (tmp, "%f", *((float *) fromPtr));
for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
*((char *) toPtr + i) = (i < len ? tmp[i] : ' ');
}
break;
}
}
break;
/**************************************************************************
* 8-byte floating-point to...
**************************************************************************/
case CDF_EPOCH:
case CDF_DOUBLE:
case CDF_REAL8:
switch (toDataType) {
case CDF_BYTE:
case CDF_INT1:
*((sChar *) toPtr) = (sChar) *((double *) fromPtr);
break;
case CDF_UINT1:
*((uChar *) toPtr) = (uChar) *((double *) fromPtr);
break;
case CDF_INT2:
*((Int16 *) toPtr) = (Int16) *((double *) fromPtr);
break;
case CDF_UINT2:
*((uInt16 *) toPtr) = (uInt16) *((double *) fromPtr);
break;
case CDF_INT4:
*((Int32 *) toPtr) = (Int32) *((double *) fromPtr);
break;
case CDF_UINT4:
*((uInt32 *) toPtr) = (uInt32) *((double *) fromPtr);
break;
case CDF_FLOAT:
case CDF_REAL4:
*((float *) toPtr) = (float) *((double *) fromPtr);
break;
case CDF_EPOCH:
case CDF_DOUBLE:
case CDF_REAL8:
*((double *) toPtr) = (double) *((double *) fromPtr);
break;
case CDF_CHAR:
case CDF_UCHAR: {
int i, len;
char tmp[MAX_nonSTRING_VALUE_LEN+1];
sprintf (tmp, "%f", *((double *) fromPtr));
for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
*((char *) toPtr + i) = (i < len ? tmp[i] : ' ');
}
break;
}
}
break;
/**************************************************************************
* 16-byte floating-point to...
**************************************************************************/
case CDF_EPOCH16:
switch (toDataType) {
case CDF_BYTE:
case CDF_INT1:
*((sChar *) toPtr) = (sChar) *((double *) fromPtr);
*(((sChar *) toPtr) + 1) = (sChar) *(((double *) fromPtr) + 1);
break;
case CDF_UINT1:
*((uChar *) toPtr) = (uChar) *((double *) fromPtr);
*(((uChar *) toPtr) + 1) = (uChar) *(((double *) fromPtr) + 1);
break;
case CDF_INT2:
*((Int16 *) toPtr) = (Int16) *((double *) fromPtr);
*(((Int16 *) toPtr) + 1) = (Int16) *(((double *) fromPtr) + 1);
break;
case CDF_UINT2:
*((uInt16 *) toPtr) = (uInt16) *((double *) fromPtr);
*(((uInt16 *) toPtr) + 1) = (uInt16) *(((double *) fromPtr) + 1);
break;
case CDF_INT4:
*((Int32 *) toPtr) = (Int32) *((double *) fromPtr);
*(((Int32 *) toPtr) + 1) = (Int32) *(((double *) fromPtr) + 1);
break;
case CDF_UINT4:
*((uInt32 *) toPtr) = (uInt32) *((double *) fromPtr);
*(((uInt32 *) toPtr) + 1) = (uInt32) *(((double *) fromPtr) + 1);
break;
case CDF_FLOAT:
case CDF_REAL4:
*((float *) toPtr) = (float) *((double *) fromPtr);
*(((float *) toPtr) + 1) = (float) *(((double *) fromPtr) + 1);
break;
case CDF_EPOCH:
case CDF_DOUBLE:
case CDF_REAL8:
*((double *) toPtr) = (double) *((double *) fromPtr);
*(((double *) toPtr) + 1) = (double) *(((double *) fromPtr) + 1);
break;
case CDF_EPOCH16:
*((double *) toPtr) = (double) *((double *) fromPtr);
*(((double *) toPtr) + 1) = (double) *(((double *) fromPtr) + 1);
break;
case CDF_CHAR:
case CDF_UCHAR: {
int i, j, len;
char tmp[MAX_nonSTRING_VALUE_LEN+1];
sprintf (tmp, "%f", *((double *) fromPtr));
for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
*((char *) toPtr + i) = (i < len ? tmp[i] : ' ');
}
sprintf (tmp, "%f", *(((double *) fromPtr) + 1));
j = i;
for (i = 0, len = strlen(tmp); i < toNumElems; i++) {
*((char *) toPtr + j) = (i < len ? tmp[i] : ' ');
}
break;
}
}
break;
/**************************************************************************
* character (string) to...
**************************************************************************/
case CDF_CHAR:
case CDF_UCHAR: {
size_t nBytes = (size_t) (fromNumElems + 1);
char *str = (char *) cdf_AllocateMemory (nBytes, FatalError);
memmove (str, fromPtr, (size_t) fromNumElems);
str[(int)fromNumElems] = NUL;
switch (toDataType) {
case CDF_BYTE:
case CDF_INT1: {
int tmp;
if (sscanf(str,"%d",&tmp) < 1)
*((sChar *) toPtr) = 0;
else
*((sChar *) toPtr) = (sChar) tmp;
break;
}
case CDF_UINT1: {
uInt tmp;
if (sscanf(str,"%u",&tmp) < 1)
*((uChar *) toPtr) = 0;
else
*((uChar *) toPtr) = (uChar) tmp;
break;
}
case CDF_INT2: {
int tmp;
if (sscanf(str,"%d",&tmp) < 1)
*((Int16 *) toPtr) = 0;
else
*((Int16 *) toPtr) = (Int16) tmp;
break;
}
case CDF_UINT2: {
uInt tmp;
if (sscanf(str,"%u",&tmp) < 1)
*((uInt16 *) toPtr) = 0;
else
*((uInt16 *) toPtr) = (uInt16) tmp;
break;
}
case CDF_INT4: {
long tmp;
if (sscanf(str,"%ld",&tmp) < 1)
*((Int32 *) toPtr) = 0;
else
*((Int32 *) toPtr) = (Int32) tmp;
break;
}
case CDF_UINT4: {
uLong tmp;
if (sscanf(str,"%lu",&tmp) < 1)
*((uInt32 *) toPtr) = 0;
else
*((uInt32 *) toPtr) = (uInt32) tmp;
break;
}
case CDF_FLOAT:
case CDF_REAL4: {
float tmp;
if (sscanf(str,"%g",&tmp) < 1)
*((float *) toPtr) = (float) 0.0;
else
*((float *) toPtr) = tmp;
break;
}
case CDF_EPOCH:
case CDF_DOUBLE:
case CDF_REAL8: {
double tmp;
if (sscanf(str,"%lg",&tmp) < 1)
*((double *) toPtr) = 0.0;
else
*((double *) toPtr) = tmp;
break;
}
case CDF_EPOCH16: {
double tmp1, tmp2;
if (sscanf(str,"%lg %lg",&tmp1, &tmp2) < 2) {
*((double *) toPtr) = 0.0;
*(((double *) toPtr) + 1) = 0.0;
} else {
*((double *) toPtr) = tmp1;
*(((double *) toPtr) + 1) = tmp2;
}
break;
}
case CDF_CHAR:
case CDF_UCHAR: {
int i;
for (i = 0; i < toNumElems; i++) {
*((char *) toPtr + i) = (i < fromNumElems ? str[i] : ' ');
}
break;
}
}
cdf_FreeMemory (str, FatalError);
break;
}
}
return;
}
/******************************************************************************
* DecodeValues.
* Memory for the values is allocated here but is NOT freed (unless an
* error occurred.)
******************************************************************************/
Logical DecodeValues (string, dataType, numElems, values, style)
char *string;
long dataType;
long *numElems;
void **values;
int style; /* EPOCH style. */
{
if (STRINGdataType(dataType)) {
/****************************************************************************
* Delimited character string.
****************************************************************************/
char delim;
char *firstDelim, *secondDelim;
char *ptr = string;
while (*ptr != NUL && Spacing(*ptr)) ptr++; /* Skip to delimiter. */
if (*ptr == NUL) return FALSE; /* Null-string. */
delim = *ptr;
firstDelim = ptr;
secondDelim = strchr (ptr + 1, delim);
if (secondDelim == NULL) return FALSE;
*numElems = secondDelim - firstDelim - 1;
*values = cdf_AllocateMemory ((size_t) (*numElems + 1), FatalError);
memmove (*values, firstDelim + 1, (size_t) *numElems);
((char *) *values)[(int)(*numElems)] = NUL;
}
else {
/****************************************************************************
* Comma separated values.
****************************************************************************/
int i, Ncommas; char *ptr;
for (Ncommas = 0, i = 0; string[i] != NUL; i++) /* Count commas. */
if (string[i] == ',') Ncommas++;
*numElems = Ncommas + 1;
*values = cdf_AllocateMemory ((size_t) (*numElems * CDFelemSize(dataType)),
FatalError);
for (ptr = string, i = 0; i < *numElems; i++) {
switch (dataType) {
case CDF_BYTE:
case CDF_INT1: {
int temp;
if (sscanf(ptr,"%d",&temp) != 1) {
cdf_FreeMemory (*values, FatalError);
return FALSE;
}
if (temp < -128 || temp > 127) {
cdf_FreeMemory (*values, FatalError);
return FALSE;
}
*((sChar *) *values + i) = (sChar) temp;
break;
}
case CDF_UINT1: {
int temp;
if (sscanf(ptr,"%d",&temp) != 1) {
cdf_FreeMemory (*values, FatalError);
return FALSE;
}
if (temp < 0 || temp > 255) {
cdf_FreeMemory (*values, FatalError);
return FALSE;
}
*((uChar *) *values + i) = (uChar) temp;
break;
}
case CDF_INT2: {
if (sscanf(ptr,"%hd",(Int16 *) *values + i) != 1) {
cdf_FreeMemory (*values, FatalError);
return FALSE;
}
break;
}
case CDF_UINT2: {
long temp;
if (sscanf(ptr,"%ld",&temp) != 1) {
cdf_FreeMemory (*values, FatalError);
return FALSE;
}
if (temp < 0 || temp > 65535L) {
cdf_FreeMemory (*values, FatalError);
return FALSE;
}
*((uInt16 *) *values + i) = (uInt16) temp;
break;
}
case CDF_INT4:
if (!DecodeInt32(ptr,(Int32 *) *values + i)) {
cdf_FreeMemory (*values, FatalError);
return FALSE;
}
break;
case CDF_UINT4:
if (!DecodeInt32u(ptr,(uInt32 *) *values + i)) {
cdf_FreeMemory (*values, FatalError);
return FALSE;
}
break;
case CDF_REAL4:
case CDF_FLOAT:
if (sscanf(ptr,"%f",(float *) *values + i) != 1) {
cdf_FreeMemory (*values, FatalError);
return FALSE;
}
break;
case CDF_REAL8:
case CDF_DOUBLE:
if (sscanf(ptr,"%lf",(double *) *values + i) != 1) {
cdf_FreeMemory (*values, FatalError);
return FALSE;
}
break;
case CDF_EPOCH: {
double value;
switch (style) {
case EPOCH0_STYLE:
value = parseEPOCH (ptr);
break;
case EPOCH1_STYLE:
value = parseEPOCH1 (ptr);
break;
case EPOCH2_STYLE:
value = parseEPOCH2 (ptr);
break;
case EPOCH3_STYLE:
value = parseEPOCH3 (ptr);
break;
case EPOCHf_STYLE:
cdf_FreeMemory (*values, FatalError);
return DecodeValues(string,CDF_DOUBLE,numElems,values,style);
case EPOCHx_STYLE:
value = parseEPOCH (ptr); /* Assume EPOCH0_STYLE instead. */
break;
}
if (value == ILLEGAL_EPOCH_VALUE) {
cdf_FreeMemory (*values, FatalError);
return FALSE;
}
else
*((double *) *values + i) = value;
break;
}
case CDF_EPOCH16: {
double value[2], dummy;
switch (style) {
case EPOCH0_STYLE:
dummy = parseEPOCH16 (ptr, value);
break;
case EPOCH1_STYLE:
dummy = parseEPOCH16_1 (ptr, value);
break;
case EPOCH2_STYLE:
dummy = parseEPOCH16_2 (ptr, value);
break;
case EPOCH3_STYLE:
dummy = parseEPOCH16_3 (ptr, value);
break;
case EPOCHf_STYLE:
cdf_FreeMemory (*values, FatalError);
return DecodeValues(string,CDF_DOUBLE,numElems,values,style);
case EPOCHx_STYLE: /* Assume EPOCH0_STYLE instead. */
dummy = parseEPOCH16 (ptr, value);
break;
}
if (dummy == ILLEGAL_EPOCH_VALUE ||
value[0] == ILLEGAL_EPOCH_VALUE ||
value[1] == ILLEGAL_EPOCH_VALUE) {
cdf_FreeMemory (*values, FatalError);
return FALSE;
}
else {
int j = 2 * i;
*((double *) *values + j) = value[0];
*(((double *) *values + j) + 1) = value[1];
}
break;
}
}
ptr = strchr (ptr, ',') + 1; /* Garbage last time, doesn't matter. */
}
}
return TRUE;
}
/******************************************************************************
* DecodeInt32.
* This routine is necessary because DEC Alphas running OpenVMS do not
* decode "-2147483648" properly.
******************************************************************************/
static Logical DecodeInt32 (text, binary)
char *text;
Int32 *binary;
{
if (EqStringsIgLTws(text,"-2147483648"))
#if defined(dos)
*binary = (Int32) -2147483648L;
#else
*binary = (Int32) 0x80000000;
#endif
else
if (sscanf(text,Int32FORMAT,binary) != 1) return FALSE;
return TRUE;
}
/******************************************************************************
* DecodeInt32u.
* This routine is necessary because VAX/VMS systems do not properly decode
* unsigned values.
******************************************************************************/
static Logical DecodeInt32u (text, binary)
char *text;
uInt32 *binary;
{
char *start = text;
char *end, temp[MAX_ENCODED_INT4_LEN+1];
int len; uLong tempB;
while (*start != NUL && Spacing(*start)) start++;
if (*start == NUL) return FALSE;
end = start;
while (*end != NUL && Decimal(*end)) end++;
len = (int) (end - start);
if (len > MAX_ENCODED_INT4_LEN) return FALSE;
strcpyX (temp, start, MINIMUM(len,MAX_ENCODED_INT4_LEN));
if (len < MAX_ENCODED_INT4_LEN) {
if (sscanf(temp,"%ld",&tempB) != 1) return FALSE;
}
else {
if (strcmp(temp,"4294967295") > 0) return FALSE;
if (sscanf(&temp[1],"%ld",&tempB) != 1) return FALSE;
#if defined(dos)
tempB += (1000000000UL * (temp[0] - '0'));
#else
tempB += ((uLong) 1000000000 * (temp[0] - '0'));
#endif
}
*binary = (uInt32) tempB;
return TRUE;
}
/******************************************************************************
* EqStringsIgLTws.
* Compares two strings ignoring leading and trailing white space.
******************************************************************************/
static Logical EqStringsIgLTws (string1, string2)
char *string1;
char *string2;
{
char *tString1, *tString2, *ptr;
size_t nChars;
Logical returnValue;
/****************************************************************************
* Strip leading and trailing white space from 1st string.
****************************************************************************/
ptr = string1;
while (*ptr != NUL && Spacing(*ptr)) ptr++;
nChars = strlen (ptr);
tString1 = (char *) cdf_AllocateMemory (nChars + 1, FatalError);
strcpyX (tString1, ptr, 0);
ptr = tString1 + nChars;
while (ptr != tString1 && Spacing(*(ptr-1))) ptr--;
*ptr = NUL;
/****************************************************************************
* Strip leading and trailing white space from 2nd string.
****************************************************************************/
ptr = string2;
while (*ptr != NUL && Spacing(*ptr)) ptr++;
nChars = strlen (ptr);
tString2 = (char *) cdf_AllocateMemory (nChars + 1, FatalError);
strcpyX (tString2, ptr, 0);
ptr = tString2 + nChars;
while (ptr != tString2 && Spacing(*(ptr-1))) ptr--;
*ptr = NUL;
/****************************************************************************
* Free temporary strings and return result of comparison.
****************************************************************************/
returnValue = (!strcmp(tString1,tString2) ? TRUE : FALSE);
cdf_FreeMemory (tString1, FatalError);
cdf_FreeMemory (tString2, FatalError);
return returnValue;
}
/******************************************************************************
* LongWidth.
******************************************************************************/
int LongWidth (value)
long value;
{
if (value < -999999999L) return 11;
if (value < -99999999L) return 10;
if (value < -9999999L) return 9;
if (value < -999999L) return 8;
if (value < -99999L) return 7;
if (value < -9999L) return 6;
if (value < -999L) return 5;
if (value < -99L) return 4;
if (value < -9L) return 3;
if (value < 0L) return 2;
if (value < 10L) return 1;
if (value < 100L) return 2;
if (value < 1000L) return 3;
if (value < 10000L) return 4;
if (value < 100000L) return 5;
if (value < 1000000L) return 6;
if (value < 10000000L) return 7;
if (value < 100000000L) return 8;
if (value < 1000000000L) return 9;
return 10;
}
/******************************************************************************
* Long64Width.
******************************************************************************/
int Long64Width (value)
OFF_T value;
{
#if !defined(win32) && !defined(__osf__)
if (value < (OFF_T) -999999999999999999LL) return 20;
if (value < (OFF_T) -99999999999999999LL) return 19;
if (value < (OFF_T) -9999999999999999LL) return 18;
if (value < (OFF_T) -999999999999999LL) return 17;
if (value < (OFF_T) -99999999999999LL) return 16;
if (value < (OFF_T) -9999999999999LL) return 15;
if (value < (OFF_T) -999999999999LL) return 14;
if (value < (OFF_T) -99999999999LL) return 13;
if (value < (OFF_T) -9999999999LL) return 12;
if (value < (OFF_T) -999999999LL) return 11;
if (value < (OFF_T) -99999999LL) return 10;
if (value < (OFF_T) -9999999LL) return 9;
if (value < (OFF_T) -999999LL) return 8;
if (value < (OFF_T) -99999LL) return 7;
if (value < (OFF_T) -9999LL) return 6;
if (value < (OFF_T) -999LL) return 5;
if (value < (OFF_T) -99LL) return 4;
if (value < (OFF_T) -9LL) return 3;
if (value < (OFF_T) 0LL) return 2;
if (value < (OFF_T) 10LL) return 1;
if (value < (OFF_T) 100LL) return 2;
if (value < (OFF_T) 1000LL) return 3;
if (value < (OFF_T) 10000LL) return 4;
if (value < (OFF_T) 100000LL) return 5;
if (value < (OFF_T) 1000000LL) return 6;
if (value < (OFF_T) 10000000LL) return 7;
if (value < (OFF_T) 100000000LL) return 8;
if (value < (OFF_T) 1000000000LL) return 9;
if (value < (OFF_T) 10000000000LL) return 10;
if (value < (OFF_T) 100000000000LL) return 11;
if (value < (OFF_T) 1000000000000LL) return 12;
if (value < (OFF_T) 10000000000000LL) return 13;
if (value < (OFF_T) 100000000000000LL) return 14;
if (value < (OFF_T) 1000000000000000LL) return 15;
if (value < (OFF_T) 10000000000000000LL) return 16;
if (value < (OFF_T) 100000000000000000LL) return 17;
if (value < (OFF_T) 1000000000000000000LL) return 18;
#else
if (value < (OFF_T) -999999999999999999L) return 20;
if (value < (OFF_T) -99999999999999999L) return 19;
if (value < (OFF_T) -9999999999999999L) return 18;
if (value < (OFF_T) -999999999999999L) return 17;
if (value < (OFF_T) -99999999999999L) return 16;
if (value < (OFF_T) -9999999999999L) return 15;
if (value < (OFF_T) -999999999999L) return 14;
if (value < (OFF_T) -99999999999L) return 13;
if (value < (OFF_T) -9999999999L) return 12;
if (value < (OFF_T) -999999999L) return 11;
if (value < (OFF_T) -99999999L) return 10;
if (value < (OFF_T) -9999999L) return 9;
if (value < (OFF_T) -999999L) return 8;
if (value < (OFF_T) -99999L) return 7;
if (value < (OFF_T) -9999L) return 6;
if (value < (OFF_T) -999L) return 5;
if (value < (OFF_T) -99L) return 4;
if (value < (OFF_T) -9L) return 3;
if (value < (OFF_T) 0L) return 2;
if (value < (OFF_T) 10L) return 1;
if (value < (OFF_T) 100L) return 2;
if (value < (OFF_T) 1000L) return 3;
if (value < (OFF_T) 10000L) return 4;
if (value < (OFF_T) 100000L) return 5;
if (value < (OFF_T) 1000000L) return 6;
if (value < (OFF_T) 10000000L) return 7;
if (value < (OFF_T) 100000000L) return 8;
if (value < (OFF_T) 1000000000L) return 9;
if (value < (OFF_T) 10000000000L) return 10;
if (value < (OFF_T) 100000000000L) return 11;
if (value < (OFF_T) 1000000000000L) return 12;
if (value < (OFF_T) 10000000000000L) return 13;
if (value < (OFF_T) 100000000000000L) return 14;
if (value < (OFF_T) 1000000000000000L) return 15;
if (value < (OFF_T) 10000000000000000L) return 16;
if (value < (OFF_T) 100000000000000000L) return 17;
if (value < (OFF_T) 1000000000000000000L) return 18;
#endif
return 19;
}
/******************************************************************************
* ParseCacheSizes.
* It can be assumed that there is at least one character in `sizes' or QOP
* would have failed.
******************************************************************************/
Logical ParseCacheSizes (sizes, workingCache, stageCache, compressCache)
char *sizes;
long *workingCache;
long *stageCache;
long *compressCache;
{
char *p, *size, tmp[MAX_CACHESIZES_LEN+1];
/****************************************************************************
* Initialize all cache sizes in case only some have been specified.
****************************************************************************/
*workingCache = useDEFAULTcacheSIZE;
*stageCache = useDEFAULTcacheSIZE;
*compressCache = useDEFAULTcacheSIZE;
/****************************************************************************
* Move cache sizes to a temporary buffer and remove all spacing.
****************************************************************************/
strcpyX (tmp, sizes, MAX_CACHESIZES_LEN);
RemoveWhiteSpace (tmp);
p = tmp;
/****************************************************************************
* Check for (and skip) parenthesis on VMS systems.
****************************************************************************/
#if defined(vms)
if (*p == '(') {
char *lastChar = p + strlen(p) - 1;
if (*lastChar != ')') return FALSE;
p++;
*lastChar = NUL;
}
#endif
/****************************************************************************
* Scan the list of cache sizes...
****************************************************************************/
for (;;) {
/*************************************************************************
* Save the location of the size and increment to the next non-decimal
* character (ie. past the size).
*************************************************************************/
size = p;
while (Decimal(*p)) p++;
/*************************************************************************
* Based on the non-decimal character reached...
*************************************************************************/
switch (*p) {
case 's':
if (sscanf(size,"%lds",stageCache) != 1) return FALSE;
break;
case 'c':
if (sscanf(size,"%ldc",compressCache) != 1) return FALSE;
break;
case 'd':
if (sscanf(size,"%ldd,",workingCache) != 1) return FALSE;
break;
case ',':
if (sscanf(size,"%ld,",workingCache) != 1) return FALSE;
break;
case NUL:
if (sscanf(size,"%ld",workingCache) != 1) return FALSE;
return TRUE;
default:
return FALSE;
}
/*************************************************************************
* Increment to the beginning of the next cache size (or to the end of the
* sizes).
*************************************************************************/
if (*p != ',') p++;
if (*p == ',') p++;
if (*p == NUL) return TRUE;
}
}
/******************************************************************************
* Remove the ".skt" file extension from the given file name if it's there.
* It ignores the case.
* Example:
* mydata.skt => mydata
******************************************************************************/
void RemoveCDFSktExtension (sktName, sktPath)
char *sktName; /* CDF skeleton table file name. */
char *sktPath; /* The string holding file name without extension. */
{
int ptr = -1;
strcpyX (sktPath, sktName, CDF_PATHNAME_LEN);
if (EndsWithIgCase (sktPath, ".skt")) {
ptr = StrLaststrIgCase(sktPath, ".skt");
if (ptr != -1) ((char *) sktPath)[ptr] = (char) '\0';
}
return;
}
/******************************************************************************
* GetNumTokens.
******************************************************************************/
int GetNumTokens (token, string)
int token;
char *string;
{
int count = 0;
char *temp1, *temp2;
char *ptr1, terminator;
/****************************************************************************
* Check that the entered list of tokens is not a NUL string, that there are
* some possible tokens to match, etc.
****************************************************************************/
if (NULstring(string)) {
return 0; /* Obviously, no tokens were found. */
}
/****************************************************************************
* Scan the entered string of tokens searching for matches with the token.
* First determine the starting character position and the * ending delimiter.
****************************************************************************/
switch (string[0]) {
case '(': /* VMS-style. */
terminator = ')';
ptr1 = string + 1;
break;
case '"': /* UNIX-style on a Mac (double quotes not stripped). */
terminator = '"';
ptr1 = string + 1;
break;
default: /* UNIX-style on a UNIX machine or IBM PC. */
terminator = NUL;
ptr1 = string;
break;
}
temp1 = ptr1;
temp2 = ptr1 + strlen(ptr1) - 1;
while (temp1 <= temp2) {
if ((int) *temp1 == token) count++;
temp1++;
}
count++;
return count;
}
/******************************************************************************
* ParseStringForTokens.
******************************************************************************/
void ParseStringForTokens (token, string, items)
int token;
char *string;
char *items[];
{
int tokenN; size_t tokenLen;
char *ptr1, *ptr2, terminator;
/****************************************************************************
* Check that the entered list of tokens is not a NUL string, that there are
* some possible tokens to match, etc.
****************************************************************************/
if (NULstring(string)) {
return; /* Obviously, no tokens were found. */
}
/****************************************************************************
* Scan the entered string of tokens searching for matches with the token.
* First determine the starting character position and the * ending delimiter.
****************************************************************************/
switch (string[0]) {
case '(': /* VMS-style. */
terminator = ')';
ptr1 = string + 1;
break;
case '"': /* UNIX-style on a Mac (double quotes not stripped). */
terminator = '"';
ptr1 = string + 1;
break;
default: /* UNIX-style on a UNIX machine or IBM PC. */
terminator = NUL;
ptr1 = string;
break;
}
tokenN = 0;
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;
/*************************************************************************
* Find the end of the token and copy. The token is ended by either a
* blank, comma, or the terminator.
*************************************************************************/
ptr2 = ptr1 + 1;
while ((int) *ptr2 != token && *ptr2 != terminator) ptr2++;
tokenLen = (size_t) (ptr2 - ptr1);
strcpyX (items[tokenN], ptr1, tokenLen);
tokenN++;
/*************************************************************************
* Setup to search for next token in list.
*************************************************************************/
if ((int) *ptr2 == token)
/*********************************************************************
* The last token was ended by a comma. The next token begins one
* character beyond the comma.
*********************************************************************/
ptr1 = ptr2 + 1;
else
/*********************************************************************
* The terminator must have ended the last token.
*********************************************************************/
return;
}
}
syntax highlighted by Code2HTML, v. 0.9.1