/****************************************************************************** * * 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; } }