/******************************************************************************
*
* NSSDC/CDF CDFcompare (differences).
*
* Version 2.7b, 21-Nov-97, Hughes STX.
*
* Modification history:
*
* V1.0 1-Jun-91, J Love Original version (for CDF V2.1).
* V1.1 25-Jun-91, J Love CDF_EPOCH added as a data type. Added QOP.
* Added PageInst.
* V1.2 6-Aug-91, J Love TRUE/FALSE. Use 'Exit'/'ExitBAD'. Use
* 'CDFlib'. Display message if no differences
* found.
* V1.3 10-Aug-91, J Love Optimized comparison of variable values.
* V2.0 17-May-92, J Love IBM PC & HP port.
* V2.1 17-Sep-92, J Love CDF V2.3 (shareable/NeXT/zVar).
* V2.1a 6-Oct-92, J Love Fixed freeing of `bufferX' when 1-dimensional.
* V2.2 25-Jan-94, J Love CDF V2.4.
* V2.2a 22-Feb-94, J Love Spelling lesson.
* V2.3 9-Mar-94, J Love Made parentheses enclosing zModes options (on
* all operating systems).
* V2.4 6-Dec-94, J Love CDF V2.5.
* V2.4a 10-Jan-95, J Love Uppercase file extensions on the Macintosh.
* V2.4b 16-Mar-95, J Love Display value(s) when a difference detected.
* V2.4c 6-Apr-95, J Love POSIX.
* V2.5 25-May-95, J Love EPOCH styles. Fixed rVariables vs. zVariable
* comparison.
* V2.5a 20-Jun-95, J Love Fixed variable number matching (in zMode).
* V2.6 1-Sep-95, J Love CDFexport-related changes. Hyper groups.
* V2.6a 19-Sep-95, J Love CHECKforABORTso.
* V2.6b 29-Sep-95, J Love Macintosh dialog filtering. Outline default
* button. Less CHECKforABORTso.
* V2.7 15-Aug-96, J Love CDF V2.6.
* V2.7a 21-Feb-97, J Love Removed RICE.
* V2.7b 21-Nov-97, J Love Windows NT/Visual C++.
* V2.8 26-Jan-02, M Liu Correct dimension sizes for zVariables.
* V2.9 17-Jun-02, M Liu Added tolerance option for float/double values
* comparison.
* V2.10 13-Oct-06, M Liu Changed to allow upper and lower case CDF
* name to be used on win32.
*
******************************************************************************/
#include "cdfcmp.h"
/******************************************************************************
* Increased stack size for Borland C on IBM PC.
******************************************************************************/
#if defined(BORLANDC)
extern unsigned _stklen = BORLANDC_STACK_SIZE;
#endif
/******************************************************************************
* Global variables.
******************************************************************************/
CDFid id1, id2;
long CDFcType1, CDFcParms1[CDF_MAX_PARMS], CDFcPct1;
long CDFcType2, CDFcParms2[CDF_MAX_PARMS], CDFcPct2;
long rNumDims1, rNumDims2;
long rDimSizes1[CDF_MAX_DIMS], rDimSizes2[CDF_MAX_DIMS];
long zNumDims1, zNumDims2;
long zDimSizes1[CDF_MAX_DIMS], zDimSizes2[CDF_MAX_DIMS];
long encoding1, encoding2;
long majority1, majority2;
long format1, format2;
long checksum1 = -999, checksum2 = -999;
char copyright1[CDF_COPYRIGHT_LEN+1], copyright2[CDF_COPYRIGHT_LEN+1];
long rNumVars1, rNumVars2;
long zNumVars1, zNumVars2;
long numAttrs1, numAttrs2;
long CDFmaxRec1, CDFmaxRec2;
long version1, version2;
long release1, release2;
long increment1, increment2;
long attrScope1, attrScope2;
long attrMAXgrEntry1, attrMAXgrEntry2;
long attrNUMgrEntries1, attrNUMgrEntries2;
long attrMAXzEntry1, attrMAXzEntry2;
long attrNUMzEntries1, attrNUMzEntries2;
long varMaxRec1, varMaxRec2;
long varDataType1, varDataType2;
long varNumElems1, varNumElems2;
long varRecVary1, varRecVary2;
long varDimVarys1[CDF_MAX_DIMS], varDimVarys2[CDF_MAX_DIMS];
long varBlocking1, varBlocking2;
Logical mLog, pctLog;
Logical cmpEtc;
Logical cmpNumbers;
Logical cmpVars;
Logical cmpAttrs;
Logical negToPosFp0;
Logical locations;
long *attrNumMatches1, *attrNumMatches2;
long *rVarNumMatches1, *rVarNumMatches2;
long *zVarNumMatches1, *zVarNumMatches2;
Logical diffFound;
long zMode_1, zMode_2;
static char rVariable[] = "rVariable";
static char zVariable[] = "zVariable";
static char gEntry[] = "gEntry";
static char rEntry[] = "rEntry";
static char zEntry[] = "zEntry";
char oText[MAX_oTEXT_LEN+1];
Logical report[3];
Logical dumpStatistics;
Logical displayValue;
long workingCache, stageCache, compressCache;
Logical floatSet = FALSE, doubleSet = FALSE;
float floatTolerance = (float) 0.0;
double doubleTolerance = (double) 0.0;
/******************************************************************************
* Main.
******************************************************************************/
#if !defined(win32) || (defined(win32) && defined(ALONE))
MAIN {
Logical success = TRUE;
strcpyX (pgmName, "CDFcompare", MAX_PROGRAM_NAME_LEN);
#if defined(mac)
MacExecuteSO (CompareCDFs, CompareQOPs);
#else
success = CompareCDFs (argc, argv);
#endif
#if defined(DEBUG)
if (cdf_FreeMemory(NULL,FatalError) > 0) DisplayWarning ("Abandoned buffers.");
#else
cdf_FreeMemory (NULL, FatalError);
#endif
return BOO(success,EXIT_SUCCESS_,EXIT_FAILURE_);
}
#endif
/******************************************************************************
* CompareCDFs.
******************************************************************************/
Logical CompareCDFs (argC, argV)
int argC;
char *argV[];
{
char CDFspec1[DU_MAX_PATH_LEN + 1], CDFspec2[DU_MAX_PATH_LEN + 1];
char **dirs1 = NULL, **dirs2 = NULL;
char **CDFs1 = NULL, **CDFs2 = NULL;
int numCDFs1, numCDFs2;
char CDFpath1[DU_MAX_PATH_LEN + 1], CDFpath2[DU_MAX_PATH_LEN + 1];
char dir1[DU_MAX_DIR_LEN + 1], dir2[DU_MAX_DIR_LEN + 1];
char CDF1[DU_MAX_NAME_LEN + 1], CDF2[DU_MAX_NAME_LEN + 1];
int i, j;
Logical qopError = FALSE;
QOP *qop;
static char *validQuals[] = {
"log", "nolog", "attr", "noattr", "var", "novar", "number", "nonumber",
"percent", "nopercent", "zmodes", "etc", "noetc", "neg2posfp0",
"noneg2posfp0", "location", "nolocation", "report", "page", "nopage",
"cache", "statistics", "nostatistics", "value", "novalue", "about",
"tolerance", "notolerance", NULL
};
static int optRequired[] = {
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
FALSE, FALSE, TRUE, FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE, TRUE, FALSE, FALSE,
TRUE, FALSE, FALSE, FALSE, FALSE, FALSE,
TRUE, FALSE, 0
};
static char *reportTokens[] = { "errors", "warnings", "informationals" };
static char logPctMsg[] = {
"Message logging must be specified with percentage logging."
};
static char no2ndMsg[] = "No CDFs found for 2nd specification.";
static char no1stMsg[] = "No CDFs found for 1st specification.";
static char noEitherMsg[] = "No CDFs for either specification.";
static char noMatch1Msg[] = "Matching CDF not found in 1st specification.";
static char noMatch2Msg[] = "Matching CDF not found in 2nd specification.";
/****************************************************************************
* Get qualifiers/options/parameters.
****************************************************************************/
switch (argC) {
case 1:
PageOLH ("cdfcmp.olh", argV[0]);
return TRUE;
case 2:
if (strcmp(argV[1],"-java") == 0) {
pagingOn = FALSE;
PageOLH ("cdfcmpj.olh", argV[0]);
return TRUE;
}
default:
qop = Qop (argC, argV, validQuals, optRequired);
if (qop == NULL) return FALSE;
/***********************************************************************
* Check for `about' qualifier.
***********************************************************************/
if (qop->qualEntered[ABOUTqual]) {
DisplayIdentification (pgmName);
cdf_FreeMemory (qop, FatalError);
return TRUE;
}
/************************************************************************
* Get CDF/paths to compare.
************************************************************************/
switch (qop->Nparms) {
case 0:
case 1:
DisplayError ("Missing parameter(s).");
qopError = TRUE;
break;
case 2:
strcpyX (CDFspec1, qop->parms[CDFSPEC1parm], DU_MAX_PATH_LEN);
strcpyX (CDFspec2, qop->parms[CDFSPEC2parm], DU_MAX_PATH_LEN);
#if defined(vms) || defined(dos)
MakeUpperString (CDFspec1);
MakeUpperString (CDFspec2);
#endif
break;
default:
DisplayError ("Too many parameters.");
qopError = TRUE;
break;
}
/************************************************************************
* Check for zMode qualifier.
************************************************************************/
if (qop->qualEntered[ZMODESqual]) {
char *modes = qop->qualOpt[ZMODESqual];
if (modes[0] == '(' && modes[strlen(modes)-1] == ')') modes++;
else if (modes[0] == '"' && modes[strlen(modes)-1] == '"') modes++;
switch (modes[0]) {
case '0': zMode_1 = zMODEoff; break;
case '1': zMode_1 = zMODEon1; break;
case '2': zMode_1 = zMODEon2; break;
default: {
DisplayError ("Illegal zModes.");
qopError = TRUE;
break;
}
}
switch (modes[2]) {
case '0': zMode_2 = zMODEoff; break;
case '1': zMode_2 = zMODEon1; break;
case '2': zMode_2 = zMODEon2; break;
default: {
DisplayError ("Illegal zModes.");
qopError = TRUE;
break;
}
}
}
else {
zMode_1 = DEFAULTzModeCMP;
zMode_2 = DEFAULTzModeCMP;
}
/************************************************************************
* Check for `report' qualifier. If absent, use defaults.
************************************************************************/
if (qop->qualEntered[REPORTqual]) {
if (!ParseOptionList(3,reportTokens,qop->qualOpt[REPORTqual],report)) {
DisplayError ("Illegal list of `report' options.");
qopError = TRUE;
}
}
else {
report[ERRORs] = REPORTerrorsDEFAULT;
report[WARNs] = REPORTwarningsDEFAULT;
report[INFOs] = REPORTinfosDEFAULT;
}
/************************************************************************
* Check for `page', `log', `attr', `var', `number', `percent', `etc',
* `neg2posfp0', `location', `value', and `statistics' qualifiers.
************************************************************************/
qopError = qopError | !TFqualifier(qop,&pagingOn,PAGEqual,NOPAGEqual,
DEFAULTpageCMP,"page");
qopError = qopError | !TFqualifier (qop,&mLog,LOGqual,NOLOGqual,
DEFAULTlogCMP,"log");
qopError = qopError | !TFqualifier (qop,&cmpAttrs,ATTRSqual,NOATTRSqual,
DEFAULTvarCMP,"attr");
qopError = qopError | !TFqualifier (qop,&cmpVars,VARSqual,NOVARSqual,
DEFAULTvarCMP,"var");
qopError = qopError | !TFqualifier (qop,&cmpNumbers,NUMBERSqual,
NONUMBERSqual,DEFAULTnumberCMP,
"number");
qopError = qopError | !TFqualifier (qop,&pctLog,PCTqual,NOPCTqual,
DEFAULTpctCMP,"percent");
qopError = qopError | !TFqualifier (qop,&cmpEtc,ETCqual,NOETCqual,
DEFAULTetcCMP,"etc");
qopError = qopError | !TFqualifier (qop,&negToPosFp0,NEG2POSqual,
NONEG2POSqual,DEFAULT_NEGtoPOSfp0,
"neg2posfp0");
qopError = qopError | !TFqualifier (qop,&locations,LOCSqual,NOLOCSqual,
DEFAULTlocationCMP,"location");
qopError = qopError | !TFqualifier (qop,&displayValue,VALUESqual,
NOVALUESqual,DEFAULTvalueCMP,
"value");
qopError = qopError | !TFqualifier (qop,&dumpStatistics,STATSqual,
NOSTATSqual,DEFAULTstatsCMP,
"statistics");
/************************************************************************
* Check for `cache' qualifier.
************************************************************************/
if (qop->qualEntered[CACHEqual]) {
if (!ParseCacheSizes(qop->qualOpt[CACHEqual],&workingCache,
&stageCache,&compressCache)) {
DisplayError ("Illegal cache size/type.");
qopError = TRUE;
}
}
else {
workingCache = useDEFAULTcacheSIZE;
stageCache = useDEFAULTcacheSIZE;
compressCache = useDEFAULTcacheSIZE;
}
/************************************************************************
* Check for `tolerance' qualifier.
************************************************************************/
if (qop->qualEntered[TOLERANCEqual]) {
if (!ParseTolerances(qop->qualOpt[TOLERANCEqual], &floatTolerance,
&floatSet, &doubleTolerance, &doubleSet)) {
DisplayError ("Illegal tolerance values.");
qopError = TRUE;
}
}
/************************************************************************
* Check for conflicting qualifiers.
************************************************************************/
if (pctLog && (!mLog)) {
DisplayError (logPctMsg);
qopError = TRUE;
}
/************************************************************************
* Free QOP memory and check for an error.
************************************************************************/
cdf_FreeMemory (qop, FatalError);
if (qopError) return FALSE;
break;
}
/****************************************************************************
* Compare the CDFs.
****************************************************************************/
if (!IsCDF(CDFspec1)) {
if (!IsCDF(CDFspec2)) {
/************************************************************************
* Both specifications are directories/wildcards.
************************************************************************/
numCDFs1 = CDFdirList (CDFspec1, &dirs1, &CDFs1);
numCDFs2 = CDFdirList (CDFspec2, &dirs2, &CDFs2);
if (numCDFs1 > 0)
if (numCDFs2 > 0) {
for (i = 0; i < numCDFs1; i++) {
strcpyX (CDFpath1, dirs1[i], DU_MAX_PATH_LEN);
AppendToDir (CDFpath1, CDFs1[i]);
for (j = 0; j < numCDFs2; j++) {
if (!strcmp(CDFs1[i],CDFs2[j])) {
strcpyX (CDFpath2, dirs2[j], DU_MAX_PATH_LEN);
AppendToDir (CDFpath2, CDFs2[j]);
CompareTwoCDFs (CDFpath1, CDFpath2);
break;
}
}
if (j == numCDFs2) {
char tempS[47+DU_MAX_PATH_LEN+1];
sprintf (tempS, "No matching CDF for \"%s\"", CDFpath1);
sprintf (EofS(tempS), " in second specification.");
OutputWithMargin (stdout, tempS, MAX_SCREENLINE_LEN, 0);
}
}
for (j = 0; j < numCDFs2; j++) {
strcpyX (CDFpath2, dirs2[j], DU_MAX_PATH_LEN);
AppendToDir (CDFpath2, CDFs2[j]);
for (i = 0; i < numCDFs1; i++) {
if (!strcmp(CDFs2[j],CDFs1[i])) break;
}
if (i == numCDFs1) {
char tempS[47+DU_MAX_PATH_LEN+1];
sprintf (tempS, "No matching CDF for \"%s\"", CDFpath2);
sprintf (EofS(tempS), " in first specification.");
OutputWithMargin (stdout, tempS, MAX_SCREENLINE_LEN, 0);
}
}
}
else
OutputWithMargin (stdout, no2ndMsg, MAX_SCREENLINE_LEN, 0);
else
if (numCDFs2 > 0)
OutputWithMargin (stdout, no1stMsg, MAX_SCREENLINE_LEN, 0);
else
OutputWithMargin (stdout, noEitherMsg, MAX_SCREENLINE_LEN, 0);
}
else {
/************************************************************************
* First specification is a directory/wildcard, second is a CDF path.
************************************************************************/
numCDFs1 = CDFdirList (CDFspec1, &dirs1, &CDFs1);
if (numCDFs1 > 0) {
ParsePath (CDFspec2, dir2, CDF2);
for (i = 0; i < numCDFs1; i++) {
if (!strcmp(CDFs1[i],CDF2)) {
strcpyX (CDFpath1, dirs1[i], DU_MAX_PATH_LEN);
AppendToDir (CDFpath1, CDFs1[i]);
CompareTwoCDFs (CDFpath1, CDFspec2);
break;
}
}
if (i == numCDFs1) OutputWithMargin (stdout, noMatch1Msg,
MAX_SCREENLINE_LEN, 0);
}
else
OutputWithMargin (stdout, no1stMsg, MAX_SCREENLINE_LEN, 0);
}
}
else {
if (!IsCDF(CDFspec2)) {
/************************************************************************
* First specification is a CDF path, second is a directory/wildcard.
************************************************************************/
numCDFs2 = CDFdirList (CDFspec2, &dirs2, &CDFs2);
if (numCDFs2 > 0) {
ParsePath (CDFspec1, dir1, CDF1);
for (i = 0; i < numCDFs2; i++)
if (!strcmp(CDF1,CDFs2[i])) {
strcpyX (CDFpath2, dirs2[i], DU_MAX_PATH_LEN);
AppendToDir (CDFpath2, CDFs2[i]);
CompareTwoCDFs (CDFspec1, CDFpath2);
break;
}
if (i == numCDFs2) OutputWithMargin (stdout, noMatch2Msg,
MAX_SCREENLINE_LEN, 0);
}
else
OutputWithMargin (stdout, no2ndMsg, MAX_SCREENLINE_LEN, 0);
}
else {
/************************************************************************
* Both specifications are CDF paths.
************************************************************************/
CompareTwoCDFs (CDFspec1, CDFspec2);
}
}
if (dirs1 != NULL) cdf_FreeMemory (dirs1, FatalError);
if (dirs2 != NULL) cdf_FreeMemory (dirs2, FatalError);
if (CDFs1 != NULL) cdf_FreeMemory (CDFs1, FatalError);
if (CDFs2 != NULL) cdf_FreeMemory (CDFs2, FatalError);
return TRUE;
}
/******************************************************************************
* CompareTwoCDFs.
******************************************************************************/
Logical CompareTwoCDFs (CDFpath1, CDFpath2)
char *CDFpath1;
char *CDFpath2;
{
return CompareTwoCDFx (CDFpath1, CDFpath2);
}
/******************************************************************************
* CompareTwoCDFx.
******************************************************************************/
Logical CompareTwoCDFx (CDFpath1, CDFpath2)
char *CDFpath1;
char *CDFpath2;
{
CDFstatus status;
static char noDiffMsg[] = "No differences detected.";
/****************************************************************************
* Display `comparing' message.
****************************************************************************/
strcpyX (oText, "Comparing \"", 0);
strcatX (oText, CDFpath1, 0);
if (!EndsWithIgCase(CDFpath1, ".cdf"))
strcatX (oText, ".cdf", 0);
strcatX (oText, "\" with \"", 0);
strcatX (oText, CDFpath2, 0);
if (!EndsWithIgCase(CDFpath2, ".cdf"))
strcatX (oText, ".cdf", 0);
strcatX (oText, "\"\n", 0);
/*
sprintf (oText, "Comparing \"%s\" with \"%s\"", CDFpath1, CDFpath2);
*/
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 0);
diffFound = FALSE;
/****************************************************************************
* Open CDFs.
****************************************************************************/
CHECKforABORTso
if (mLog) OutputWithMargin (stdout, "Opening CDF1", MAX_SCREENLINE_LEN, 2);
status = CDFlib (OPEN_, CDF_, CDFpath1, &id1,
NULL_);
if (!StatusHandlerCmp("CDF1",status)) return FALSE;
CHECKforABORTso
if (mLog) OutputWithMargin (stdout, "Opening CDF2", MAX_SCREENLINE_LEN, 2);
status = CDFlib (OPEN_, CDF_, CDFpath2, &id2,
NULL_);
if (!StatusHandlerCmp("CDF2",status)) {
CDFclose (id1);
return FALSE;
}
CHECKforABORTso
/****************************************************************************
* Select CDF modes.
****************************************************************************/
status = CDFlib (SELECT_, CDF_, id1,
CDF_READONLY_MODE_, READONLYon,
CDF_zMODE_, zMode_1,
CDF_NEGtoPOSfp0_MODE_, BOO(negToPosFp0,
NEGtoPOSfp0on,
NEGtoPOSfp0off),
CDF_CACHESIZE_, workingCache,
STAGE_CACHESIZE_, stageCache,
COMPRESS_CACHESIZE_, compressCache,
NULL_);
if (!StatusHandlerCmp("CDF1",status)) {
CDFclose (id1);
CDFclose (id2);
return FALSE;
}
status = CDFlib (SELECT_, CDF_, id2,
CDF_READONLY_MODE_, READONLYon,
CDF_zMODE_, zMode_2,
CDF_NEGtoPOSfp0_MODE_,BOO(negToPosFp0,
NEGtoPOSfp0on,
NEGtoPOSfp0off),
CDF_CACHESIZE_, workingCache,
STAGE_CACHESIZE_, stageCache,
COMPRESS_CACHESIZE_, compressCache,
NULL_);
if (!StatusHandlerCmp("CDF2",status)) {
CDFclose (id1);
CDFclose (id2);
return FALSE;
}
CHECKforABORTso
/****************************************************************************
* Inquire general CDF contents.
****************************************************************************/
status = CDFlib (SELECT_, CDF_, id1,
GET_, CDF_COMPRESSION_, &CDFcType1, CDFcParms1, &CDFcPct1,
CDF_ENCODING_, &encoding1,
CDF_MAJORITY_, &majority1,
CDF_FORMAT_, &format1,
CDF_COPYRIGHT_, copyright1,
CDF_NUMrVARS_, &rNumVars1,
CDF_NUMzVARS_, &zNumVars1,
CDF_NUMATTRS_, &numAttrs1,
CDF_VERSION_, &version1,
CDF_RELEASE_, &release1,
CDF_INCREMENT_, &increment1,
NULL_);
if (!StatusHandlerCmp("CDF1",status)) {
CDFclose (id1);
CDFclose (id2);
return FALSE;
}
status = CDFlib (SELECT_, CDF_, id1,
GET_, rVARs_NUMDIMS_, &rNumDims1,
rVARs_DIMSIZES_, rDimSizes1,
rVARs_MAXREC_, &CDFmaxRec1,
NULL_);
if (!StatusHandlerCmp("CDF1",status)) {
CDFclose (id1);
CDFclose (id2);
return FALSE;
}
if (!PriorTo ("3.2.0", version1, release1, release1)) {
status = CDFlib (SELECT_, CDF_, id1,
GET_, CDF_CHECKSUM_, &checksum1,
NULL_);
if (!StatusHandlerCmp("CDF1",status)) {
CDFclose (id1);
CDFclose (id2);
return FALSE;
}
}
status = CDFlib (SELECT_, CDF_, id2,
GET_, CDF_COMPRESSION_, &CDFcType2, CDFcParms2, &CDFcPct2,
CDF_ENCODING_, &encoding2,
CDF_MAJORITY_, &majority2,
CDF_FORMAT_, &format2,
CDF_COPYRIGHT_, copyright2,
CDF_NUMrVARS_, &rNumVars2,
CDF_NUMzVARS_, &zNumVars2,
CDF_NUMATTRS_, &numAttrs2,
CDF_VERSION_, &version2,
CDF_RELEASE_, &release2,
CDF_INCREMENT_, &increment2,
NULL_);
if (!StatusHandlerCmp("CDF2",status)) {
CDFclose (id1);
CDFclose (id2);
return FALSE;
}
status = CDFlib (SELECT_, CDF_, id2,
GET_, rVARs_NUMDIMS_, &rNumDims2,
rVARs_DIMSIZES_, rDimSizes2,
rVARs_MAXREC_, &CDFmaxRec2,
NULL_);
if (!StatusHandlerCmp("CDF2",status)) {
CDFclose (id1);
CDFclose (id2);
return FALSE;
}
if (!PriorTo ("3.2.0", version2, release2, release2)) {
status = CDFlib (SELECT_, CDF_, id2,
GET_, CDF_CHECKSUM_, &checksum2,
NULL_);
if (!StatusHandlerCmp("CDF2",status)) {
CDFclose (id1);
CDFclose (id2);
return FALSE;
}
}
CHECKforABORTso
/****************************************************************************
* Compare numbering.
****************************************************************************/
if (!AttrNumberMatches()) {
CDFclose (id1);
CDFclose (id2);
return FALSE;
}
if (!VarNumberMatches(FALSE)) {
CDFclose (id1);
CDFclose (id2);
return FALSE;
}
if (!VarNumberMatches(TRUE)) {
CDFclose (id1);
CDFclose (id2);
return FALSE;
}
CHECKforABORTso
/****************************************************************************
* Compare CDFs.
****************************************************************************/
if (!CompareGeneral()) {
CDFclose (id1);
CDFclose (id2);
return FALSE;
}
CHECKforABORTso
if (cmpAttrs) {
if (!CompareAttributes()) {
CDFclose (id1);
CDFclose (id2);
return FALSE;
}
}
if (cmpVars) {
if (!CompareZvsR()) {
CDFclose (id1);
CDFclose (id2);
return FALSE;
}
if (!CompareVariables(FALSE)) {
CDFclose (id1);
CDFclose (id2);
return FALSE;
}
if (!CompareVariables(TRUE)) {
CDFclose (id1);
CDFclose (id2);
return FALSE;
}
}
/****************************************************************************
* Close CDFs and set their id's to NULL.
****************************************************************************/
if (mLog) OutputWithMargin (stdout, "Closing CDFs", MAX_SCREENLINE_LEN, 2);
if (dumpStatistics) {
vSTATS vStatsDotCDF, vStatsStage, vStatsCompress;
status = CDFlib (SELECT_, CDF_, id1,
CLOSE_, CDFwithSTATS_, &vStatsDotCDF,
&vStatsStage,
&vStatsCompress,
NULL_);
if (!StatusHandlerCmp("CDF1",status)) {
CDFclose (id2);
return FALSE;
}
DisplayStatistics ("CDF1", &vStatsDotCDF, &vStatsStage, &vStatsCompress);
status = CDFlib (SELECT_, CDF_, id2,
CLOSE_, CDFwithSTATS_, &vStatsDotCDF,
&vStatsStage,
&vStatsCompress,
NULL_);
if (!StatusHandlerCmp("CDF2",status)) return FALSE;
DisplayStatistics ("CDF2", &vStatsDotCDF, &vStatsStage, &vStatsCompress);
}
else {
status = CDFlib (SELECT_, CDF_, id1,
CLOSE_, CDF_,
NULL_);
if (!StatusHandlerCmp("CDF1",status)) {
CDFclose (id2);
return FALSE;
}
status = CDFlib (SELECT_, CDF_, id2,
CLOSE_, CDF_,
NULL_);
if (!StatusHandlerCmp("CDF2",status)) return FALSE;
}
/****************************************************************************
* If no differences, display message and return.
****************************************************************************/
if ((!diffFound) && mLog) {
OutputWithMargin (stdout, noDiffMsg, MAX_SCREENLINE_LEN, 2);
}
/****************************************************************************
* Free memory used for number matching.
****************************************************************************/
if (attrNumMatches1 != NULL) cdf_FreeMemory (attrNumMatches1, FatalError);
if (attrNumMatches2 != NULL) cdf_FreeMemory (attrNumMatches2, FatalError);
if (rVarNumMatches1 != NULL) cdf_FreeMemory (rVarNumMatches1, FatalError);
if (rVarNumMatches2 != NULL) cdf_FreeMemory (rVarNumMatches2, FatalError);
if (zVarNumMatches1 != NULL) cdf_FreeMemory (zVarNumMatches1, FatalError);
if (zVarNumMatches2 != NULL) cdf_FreeMemory (zVarNumMatches2, FatalError);
return TRUE;
}
/******************************************************************************
* CompareGeneral.
******************************************************************************/
Logical CompareGeneral ()
{
int i, j;
/****************************************************************************
* Compare compressions.
****************************************************************************/
if (cmpEtc && (!SameCompressions(CDFcType1,CDFcParms1,
CDFcType2,CDFcParms2))) {
diffFound = TRUE;
sprintf (oText, "DIFFERENT CDF compressions (%s vs. ",
CompressionToken(CDFcType1,CDFcParms1));
sprintf (EofS(oText), "%s)", CompressionToken(CDFcType2,CDFcParms2));
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
if (cmpEtc && (CDFcPct1 != CDFcPct2)) {
diffFound = TRUE;
sprintf (oText, "DIFFERENT CDF compression percentages (%ld%% vs. %ld%%)",
CDFcPct1, CDFcPct2);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
/****************************************************************************
* Compare rVariable dimensionalities.
****************************************************************************/
if (rNumDims1 != rNumDims2) {
diffFound = TRUE;
sprintf (oText, "DIFFERENT number of rVariable dimensions (%ld vs. %ld)",
rNumDims1, rNumDims2);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
cmpVars = FALSE;
}
else {
if (rNumDims1 > 0)
for (i = 0; i < rNumDims1; i++)
if (rDimSizes1[i] != rDimSizes2[i]) {
diffFound = TRUE;
sprintf (oText, "DIFFERENT rVariable dimension sizes (");
for (j = 0; j < rNumDims1; j++) {
sprintf (EofS(oText), "%ld ", rDimSizes1[j]);
}
strcatX (oText, "vs.", MAX_oTEXT_LEN);
for (j = 0; j < rNumDims2; j++) {
sprintf (EofS(oText), " %ld", rDimSizes2[j]);
}
strcatX (oText, ")", MAX_oTEXT_LEN);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
cmpVars = FALSE;
break;
}
}
/****************************************************************************
* Compare encodings.
****************************************************************************/
if (cmpEtc && (encoding1 != encoding2)) {
diffFound = TRUE;
sprintf (oText, "DIFFERENT encodings (%s vs. %s)",
EncodingToken(encoding1), EncodingToken(encoding2));
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
/****************************************************************************
* Compare variable majorities.
****************************************************************************/
if (cmpEtc && (majority1 != majority2)) {
diffFound = TRUE;
sprintf (oText, "DIFFERENT majorities (%s vs. %s)",
MajorityToken(majority1), MajorityToken(majority2));
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
/****************************************************************************
* Compare formats.
****************************************************************************/
if (cmpEtc && (format1 != format2)) {
diffFound = TRUE;
sprintf (oText, "DIFFERENT formats (%s vs. %s)",
FormatToken(format1), FormatToken(format2));
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
/****************************************************************************
* Compare checksums if applicable.
****************************************************************************/
if (checksum1 != -999 || checksum2 != -999) {
if (cmpEtc && (checksum1 != checksum2)) {
diffFound = TRUE;
if (checksum1 == -999) checksum1 = 0;
if (checksum2 == -999) checksum2 = 0;
sprintf (oText, "DIFFERENT checksums (%s vs. %s)",
ChecksumToken(checksum1), ChecksumToken(checksum2));
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
}
/****************************************************************************
* Compare rVariable counts.
****************************************************************************/
if (rNumVars1 != rNumVars2) {
diffFound = TRUE;
sprintf (oText, "DIFFERENT number of rVariables (%ld vs. %ld)",
rNumVars1, rNumVars2);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
/****************************************************************************
* Compare zVariable counts.
****************************************************************************/
if (zNumVars1 != zNumVars2) {
diffFound = TRUE;
sprintf (oText, "DIFFERENT number of zVariables (%ld vs. %ld)",
zNumVars1, zNumVars2);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
/****************************************************************************
* Compare attribute counts.
****************************************************************************/
if (numAttrs1 != numAttrs2) {
diffFound = TRUE;
sprintf (oText, "DIFFERENT number of attributes (%ld vs. %ld)",
numAttrs1, numAttrs2);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
/****************************************************************************
* Compare rVariable record counts.
****************************************************************************/
if (CDFmaxRec1 != CDFmaxRec2) {
diffFound = TRUE;
sprintf (oText, "DIFFERENT maximum rVariable record (%ld vs. %ld)",
CDFmaxRec1 + 1, CDFmaxRec2 + 1);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
/****************************************************************************
* Compare version/release/increments.
****************************************************************************/
if (cmpEtc && (version1 != version2 ||
release1 != release2 ||
increment1 != increment2)) {
diffFound = TRUE;
strcpyX (oText, "DIFFERENT creation libraries", MAX_oTEXT_LEN);
sprintf (EofS(oText), " (V%ld.%ld.%ld vs. V%ld.%ld.%ld)",
version1, release1, increment1, version2, release2, increment2);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
return TRUE;
}
/******************************************************************************
* AttrNumberMatches. Determine attribute number matches.
******************************************************************************/
Logical AttrNumberMatches () {
CDFstatus status;
long attrN1, attrN2;
char attrName[CDF_ATTR_NAME_LEN256+1];
if (numAttrs1 > 0)
attrNumMatches1 = (long *) cdf_AllocateMemory ((size_t) (numAttrs1 *
sizeof(long)),
FatalError);
else
attrNumMatches1 = (long *) NULL;
for (attrN1 = 0; attrN1 < numAttrs1; attrN1++) {
status = CDFlib (SELECT_, CDF_, id1,
ATTR_, attrN1,
GET_, ATTR_NAME_, attrName,
NULL_);
if (!StatusHandlerCmp("CDF1",status)) return FALSE;
status = CDFlib (SELECT_, CDF_, id2,
GET_, ATTR_NUMBER_, attrName, &attrN2,
NULL_);
if (status == NO_SUCH_ATTR)
attrNumMatches1[(int)attrN1] = -1;
else {
if (!StatusHandlerCmp("CDF2",status)) return FALSE;
attrNumMatches1[(int)attrN1] = attrN2;
}
}
if (numAttrs2 > 0)
attrNumMatches2 = (long *) cdf_AllocateMemory ((size_t) (numAttrs2 *
sizeof(long)),
FatalError);
else
attrNumMatches2 = (long *) NULL;
for (attrN2 = 0; attrN2 < numAttrs2; attrN2++) {
status = CDFlib (SELECT_, CDF_, id2,
ATTR_, attrN2,
GET_, ATTR_NAME_, attrName,
NULL_);
if (!StatusHandlerCmp("CDF2",status)) return FALSE;
status = CDFlib (SELECT_, CDF_, id1,
GET_, ATTR_NUMBER_, attrName, &attrN1,
NULL_);
if (status == NO_SUCH_ATTR)
attrNumMatches2[(int)attrN2] = -1;
else {
if (!StatusHandlerCmp("CDF1",status)) return FALSE;
attrNumMatches2[(int)attrN2] = attrN1;
}
}
return TRUE;
}
/******************************************************************************
* VarNumberMatches. Determine variable number matches.
******************************************************************************/
Logical VarNumberMatches (Z)
Logical Z;
{
CDFstatus status;
long varN1, varN2;
char varName[CDF_VAR_NAME_LEN256+1];
/****************************************************************************
* Allocate matching number array for CDF1.
****************************************************************************/
if (BOO(Z,zNumVars1,rNumVars1) > 0) {
if (Z)
zVarNumMatches1 = (long *) cdf_AllocateMemory ((size_t) (zNumVars1 *
sizeof(long)),
FatalError);
else
rVarNumMatches1 = (long *) cdf_AllocateMemory ((size_t) (rNumVars1 *
sizeof(long)),
FatalError);
}
else
if (Z)
zVarNumMatches1 = NULL;
else
rVarNumMatches1 = NULL;
/****************************************************************************
* Find matching variable numbers for CDF1.
****************************************************************************/
for (varN1 = 0; varN1 < BOO(Z,zNumVars1,rNumVars1); varN1++) {
if (BOO(Z,zNumVars2,rNumVars2) > 0) {
status = CDFlib (SELECT_, CDF_, id1,
VAR(Z), varN1,
GET_, VAR_NAME(Z), varName,
NULL_);
if (!StatusHandlerCmp("CDF1",status)) return FALSE;
status = CDFlib (SELECT_, CDF_, id2,
GET_, VAR_NUMBER(Z), varName, &varN2,
NULL_);
if (status == NO_SUCH_VAR)
if (Z)
zVarNumMatches1[(int)varN1] = -1;
else
rVarNumMatches1[(int)varN1] = -1;
else {
if (!StatusHandlerCmp("CDF2",status)) return FALSE;
if (Z)
zVarNumMatches1[(int)varN1] = varN2;
else
rVarNumMatches1[(int)varN1] = varN2;
}
}
else
if (Z)
zVarNumMatches1[(int)varN1] = -1;
else
rVarNumMatches1[(int)varN1] = -1;
}
/****************************************************************************
* Allocate matching number array for CDF2.
****************************************************************************/
if (BOO(Z,zNumVars2,rNumVars2) > 0) {
if (Z)
zVarNumMatches2 = (long *) cdf_AllocateMemory ((size_t) (zNumVars2 *
sizeof(long)),
FatalError);
else
rVarNumMatches2 = (long *) cdf_AllocateMemory ((size_t) (rNumVars2 *
sizeof(long)),
FatalError);
}
else
if (Z)
zVarNumMatches2 = NULL;
else
rVarNumMatches2 = NULL;
/****************************************************************************
* Find matching variable numbers for CDF2.
****************************************************************************/
for (varN2 = 0; varN2 < BOO(Z,zNumVars2,rNumVars2); varN2++) {
if (BOO(Z,zNumVars1,rNumVars1) > 0) {
status = CDFlib (SELECT_, CDF_, id2,
VAR(Z), varN2,
GET_, VAR_NAME(Z), varName,
NULL_);
if (!StatusHandlerCmp("CDF2",status)) return FALSE;
status = CDFlib (SELECT_, CDF_, id1,
GET_, VAR_NUMBER(Z), varName, &varN1,
NULL_);
if (status == NO_SUCH_VAR)
if (Z)
zVarNumMatches2[(int)varN2] = -1;
else
rVarNumMatches2[(int)varN2] = -1;
else {
if (!StatusHandlerCmp("CDF1",status)) return FALSE;
if (Z)
zVarNumMatches2[(int)varN2] = varN1;
else
rVarNumMatches2[(int)varN2] = varN1;
}
}
else
if (Z)
zVarNumMatches2[(int)varN2] = -1;
else
rVarNumMatches2[(int)varN2] = -1;
}
return TRUE;
}
/******************************************************************************
* CompareAttributes.
******************************************************************************/
Logical CompareAttributes ()
{
CDFstatus status;
long attrN1, attrN2;
char attrName[CDF_ATTR_NAME_LEN256+1];
Logical cmpEntries;
for (attrN1 = 0; attrN1 < numAttrs1; attrN1++) {
if (attrNumMatches1[(int)attrN1] == -1) {
status = CDFlib (SELECT_, CDF_, id1,
ATTR_, attrN1,
GET_, ATTR_NAME_, attrName,
NULL_);
if (!StatusHandlerCmp("CDF1",status)) return FALSE;
diffFound = TRUE;
sprintf (oText, "Attribute \"%s\" does not exist in CDF2", attrName);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 2);
}
else {
status = CDFlib (SELECT_, CDF_, id1,
ATTR_, attrN1,
GET_, ATTR_NAME_, attrName,
ATTR_SCOPE_, &attrScope1,
NULL_);
if (!StatusHandlerCmp("CDF1",status)) return FALSE;
if (attrScope1 == GLOBAL_SCOPE) {
attrMAXzEntry1 = -1;
attrNUMzEntries1 = 0;
status = CDFlib (SELECT_, CDF_, id1,
GET_, ATTR_MAXgENTRY_, &attrMAXgrEntry1,
ATTR_NUMgENTRIES_, &attrNUMgrEntries1,
NULL_);
}
else
status = CDFlib (SELECT_, CDF_, id1,
GET_, ATTR_MAXrENTRY_, &attrMAXgrEntry1,
ATTR_NUMrENTRIES_, &attrNUMgrEntries1,
ATTR_MAXzENTRY_, &attrMAXzEntry1,
ATTR_NUMzENTRIES_, &attrNUMzEntries1,
NULL_);
if (!StatusHandlerCmp("CDF1",status)) return FALSE;
status = CDFlib (SELECT_, CDF_, id2,
ATTR_, attrNumMatches1[(int)attrN1],
GET_, ATTR_SCOPE_, &attrScope2,
NULL_);
if (!StatusHandlerCmp("CDF2",status)) return FALSE;
if (attrScope2 == GLOBAL_SCOPE) {
attrMAXzEntry2 = -1;
attrNUMzEntries2 = 0;
status = CDFlib (SELECT_, CDF_, id2,
GET_, ATTR_MAXgENTRY_, &attrMAXgrEntry2,
ATTR_NUMgENTRIES_, &attrNUMgrEntries2,
NULL_);
}
else
status = CDFlib (SELECT_, CDF_, id2,
GET_, ATTR_MAXrENTRY_, &attrMAXgrEntry2,
ATTR_NUMrENTRIES_, &attrNUMgrEntries2,
ATTR_MAXzENTRY_, &attrMAXzEntry2,
ATTR_NUMzENTRIES_, &attrNUMzEntries2,
NULL_);
if (!StatusHandlerCmp("CDF2",status)) return FALSE;
if (mLog) {
sprintf (oText, "Comparing attribute \"%s\"", attrName);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 2);
}
cmpEntries = TRUE;
if (cmpNumbers && (attrNumMatches1[(int)attrN1] != attrN1)) {
diffFound = TRUE;
strcpyX (oText, "DIFFERENT numbers for attribute", MAX_oTEXT_LEN);
sprintf (EofS(oText), " \"%s\" (%ld vs. %ld)",
attrName, attrN1 + 1, attrNumMatches1[(int)attrN1] + 1);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
if (attrScope1 != attrScope2) {
diffFound = TRUE;
sprintf (oText, "DIFFERENT scopes for attribute \"%s\" (%s vs. %s)",
attrName, ScopeToken(attrScope1), ScopeToken(attrScope2));
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
/* MAY STILL BE ABLE TO COMPARE ENTRIES. */
}
if (attrMAXgrEntry1 != attrMAXgrEntry2) {
diffFound = TRUE;
strcpyX (oText, "DIFFERENT maximum entry for attribute",
MAX_oTEXT_LEN);
sprintf (EofS(oText), " \"%s\" (%ld vs. %ld)",
attrName, attrMAXgrEntry1 + 1, attrMAXgrEntry2 + 1);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
if (attrNUMgrEntries1 != attrNUMgrEntries2) {
diffFound = TRUE;
strcpyX (oText, "DIFFERENT number of entries for attribute",
MAX_oTEXT_LEN);
sprintf (EofS(oText), " \"%s\" (%ld vs. %ld)",
attrName, attrNUMgrEntries1, attrNUMgrEntries2);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
if (attrMAXzEntry1 != attrMAXzEntry2) {
diffFound = TRUE;
strcpyX (oText, "DIFFERENT maximum zEntry for attribute",
MAX_oTEXT_LEN);
sprintf (EofS(oText), " \"%s\" (%ld vs. %ld)",
attrName, attrMAXzEntry1 + 1, attrMAXzEntry2 + 1);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
if (attrNUMzEntries1 != attrNUMzEntries2) {
diffFound = TRUE;
strcpyX (oText, "DIFFERENT number of zEntries for attribute",
MAX_oTEXT_LEN);
sprintf (EofS(oText), " \"%s\" (%ld vs. %ld)",
attrName, attrNUMzEntries1, attrNUMzEntries2);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
if (cmpEntries) CompareAttributeEntries (attrN1,
attrNumMatches1[(int)attrN1],
attrName);
}
CHECKforABORTso
}
for (attrN2 = 0; attrN2 < numAttrs2; attrN2++) {
if (attrNumMatches2[(int)attrN2] == -1) {
status = CDFlib (SELECT_, CDF_, id2,
ATTR_, attrN2,
GET_, ATTR_NAME_, attrName,
NULL_);
if (!StatusHandlerCmp("CDF2",status)) return FALSE;
diffFound = TRUE;
sprintf (oText, "Attribute \"%s\" does not exist in CDF1", attrName);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 2);
}
}
return TRUE;
}
/******************************************************************************
* CompareAttributeEntries.
******************************************************************************/
Logical CompareAttributeEntries (attrN1, attrN2, attrName)
long attrN1;
long attrN2;
char *attrName;
{
CDFstatus status;
long entryN;
if (mLog) OutputWithMargin (stdout, "Comparing entries...",
MAX_SCREENLINE_LEN, 4);
status = CDFlib (SELECT_, CDF_, id1,
ATTR_, attrN1,
NULL_);
if (!StatusHandlerCmp("CDF1",status)) return FALSE;
status = CDFlib (SELECT_, CDF_, id2,
ATTR_, attrN2,
NULL_);
if (!StatusHandlerCmp("CDF2",status)) return FALSE;
if (attrScope1 == GLOBAL_SCOPE) {
for (entryN = 0;
entryN <= MAXIMUM(attrMAXgrEntry1,attrMAXgrEntry2);
entryN++) CompareEntry (attrName, entryN, entryN, NULL, gENTRYt);
}
else {
CompareVscopeEntries (attrName, FALSE);
CompareVscopeEntries (attrName, TRUE);
}
return TRUE;
}
/******************************************************************************
* CompareVscopeEntries.
******************************************************************************/
Logical CompareVscopeEntries (attrName, Z)
char *attrName;
Logical Z;
{
CDFstatus status;
long entryN1;
long entryN2;
char varName[CDF_VAR_NAME_LEN256+1];
char *v = BOO(Z,zVariable,rVariable);
char *e = BOO(Z,zEntry,rEntry);
/****************************************************************************
* Check each entry in CDF1 up to the maximum entry for CDF1.
****************************************************************************/
for (entryN1 = 0;
entryN1 <= BOO(Z,attrMAXzEntry1,attrMAXgrEntry1);
entryN1++) {
if (entryN1 < BOO(Z,zNumVars1,rNumVars1)) {
if (BOO(Z,zVarNumMatches1[(int)entryN1],
rVarNumMatches1[(int)entryN1]) == -1) {
diffFound = TRUE;
sprintf (oText, "No corresponding %s in CDF2 for %s number", v, e);
sprintf (EofS(oText), " %ld of attribute \"%s\" in CDF1",
entryN1 + 1, attrName);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
else {
status = CDFlib (SELECT_, CDF_, id1,
VAR(Z), entryN1,
GET_, VAR_NAME(Z), varName,
NULL_);
if (!StatusHandlerCmp("CDF1",status)) return FALSE;
CompareEntry (attrName, entryN1, BOO(Z,zVarNumMatches1[(int)entryN1],
rVarNumMatches1[(int)entryN1]),
varName, BOO(Z,zENTRYt,rENTRYt));
}
}
else {
CompareEntry (attrName, entryN1, entryN1, NULL, BOO(Z,zENTRYt,rENTRYt));
}
}
for (entryN2 = 0;
entryN2 <= BOO(Z,attrMAXzEntry2,attrMAXgrEntry2);
entryN2++) {
if (entryN2 < BOO(Z,zNumVars2,rNumVars2)) {
if (BOO(Z,zVarNumMatches2[(int)entryN2],
rVarNumMatches2[(int)entryN2]) == -1) {
diffFound = TRUE;
sprintf (oText, "No corresponding %s in CDF1 for %s number", v, e);
sprintf (EofS(oText), " %ld of attribute \"%s\" in CDF2",
entryN2 + 1, attrName);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
}
else
CompareEntry (attrName, entryN2, entryN2, NULL, BOO(Z,zENTRYt,rENTRYt));
}
return TRUE;
}
/******************************************************************************
* CompareEntry. It is assumed that the attribute has already been selected
* in the two CDFs.
******************************************************************************/
Logical CompareEntry (attrName, entryN1, entryN2, varName, entryType)
char *attrName;
long entryN1;
long entryN2;
char *varName; /* If != NULL, then a variable name associated with
the entries. */
int entryType;
{
CDFstatus status, status1, status2;
long entryDataType1, entryDataType2;
long entryNumElems1, entryNumElems2;
void *entryValue1, *entryValue2;
char varNameField[VAR_NAME_FIELD_LEN];
char entryNumField[ENTRY_NUM_FIELD_LEN];
long Nbytes;
char *v = E3(entryType,NULL,rVariable,zVariable);
char *e = E3(entryType,gEntry,rEntry,zEntry);
Logical badStatus1 = FALSE, badStatus2 = FALSE, noSuch = FALSE;
if (varName == NULL) {
varNameField[0] = '\0';
sprintf (entryNumField, "%ld", entryN1 + 1);
}
else {
strcpyX (varNameField, " (", VAR_NAME_FIELD_LEN);
strcatX (varNameField, v, VAR_NAME_FIELD_LEN);
strcatX (varNameField, " \"", VAR_NAME_FIELD_LEN);
strcatX (varNameField, varName, VAR_NAME_FIELD_LEN);
strcatX (varNameField, "\")", VAR_NAME_FIELD_LEN);
if (entryN1 == entryN2)
sprintf (entryNumField, "%ld", entryN1 + 1);
else
sprintf (entryNumField, "%ld/%ld", entryN1 + 1, entryN2 + 1);
}
status1 = CDFlib (SELECT_, CDF_, id1,
CONFIRM_, ENTRY_EXISTENCE(entryType), entryN1,
SELECT_, ENTRY(entryType), entryN1,
GET_, ENTRY_DATATYPE(entryType), &entryDataType1,
ENTRY_NUMELEMS(entryType), &entryNumElems1,
NULL_);
status2 = CDFlib (SELECT_, CDF_, id2,
CONFIRM_, ENTRY_EXISTENCE(entryType), entryN2,
SELECT_, ENTRY(entryType), entryN2,
GET_, ENTRY_DATATYPE(entryType), &entryDataType2,
ENTRY_NUMELEMS(entryType), &entryNumElems2,
NULL_);
if (status1 == NO_SUCH_ENTRY && status2 == NO_SUCH_ENTRY) return TRUE;
if (status1 == NO_SUCH_ENTRY) {
diffFound = TRUE;
sprintf (oText, "No %s number %ld%s for attribute \"%s\" in CDF1",
e, entryN1 + 1, varNameField, attrName);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
noSuch = TRUE;
}
else
badStatus1 = !StatusHandlerCmp("CDF1",status1);
if (status2 == NO_SUCH_ENTRY) {
diffFound = TRUE;
sprintf (oText, "No %s number %ld%s for attribute \"%s\" in CDF2",
e, entryN2 + 1, varNameField, attrName);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
noSuch = TRUE;
}
else
badStatus2 = !StatusHandlerCmp("CDF2",status2);
if (noSuch) return TRUE;
if (badStatus1 || badStatus2) return FALSE;
if (cmpEtc && (entryDataType1 != entryDataType2)) {
diffFound = TRUE;
strcpyX (oText, "DIFFERENT data types for", MAX_oTEXT_LEN);
sprintf (EofS(oText), " %s number %s%s of attribute \"%s\" ",
e, entryNumField, varNameField, attrName);
sprintf (EofS(oText), "(CDF_%s vs. CDF_%s)",
DataTypeToken(entryDataType1), DataTypeToken(entryDataType2));
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
/* DON'T RETURN IF THIS DIFFERENCE FOUND - COMPARE STILL POSSIBLE. */
}
if (!EquivalentDataTypes(entryDataType1,entryDataType2)) {
diffFound = TRUE;
strcpyX (oText, "NON-EQUIVALENT data types for", MAX_oTEXT_LEN);
sprintf (EofS(oText), " %s number %s%s of attribute \"%s\" ",
e, entryNumField, varNameField, attrName);
sprintf (EofS(oText), "(CDF_%s vs. CDF_%s)",
DataTypeToken(entryDataType1), DataTypeToken(entryDataType2));
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
return TRUE;
}
if (entryNumElems1 != entryNumElems2) {
diffFound = TRUE;
sprintf (oText, "DIFFERENT number of elements for %s number %s",
e, entryNumField);
sprintf (EofS(oText), "%s of attribute \"%s\" (%ld vs. %ld)",
varNameField, attrName, entryNumElems1, entryNumElems2);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
return TRUE;
}
Nbytes = entryNumElems1 * CDFelemSize(entryDataType1);
entryValue1 = cdf_AllocateMemory ((size_t) Nbytes, FatalError);
entryValue2 = cdf_AllocateMemory ((size_t) Nbytes, FatalError);
status = CDFlib (SELECT_, CDF_, id1,
GET_, ENTRY_DATA(entryType), entryValue1,
NULL_);
if (!StatusHandlerCmp("CDF1",status)) return FALSE;
status = CDFlib (SELECT_, CDF_, id2,
GET_, ENTRY_DATA(entryType), entryValue2,
NULL_);
if (!StatusHandlerCmp("CDF2",status)) return FALSE;
if (memcmp(entryValue1,entryValue2,(size_t)Nbytes) != 0) {
if ((entryDataType1 == CDF_CHAR || entryDataType1 == CDF_UCHAR ||
entryDataType1 == CDF_INT1 || entryDataType1 == CDF_INT2 ||
entryDataType1 == CDF_INT4 || entryDataType1 == CDF_UINT1 ||
entryDataType1 == CDF_UINT2 || entryDataType1 == CDF_UINT4) ||
(!floatSet && (entryDataType1 == CDF_FLOAT ||
entryDataType1 == CDF_REAL4)) ||
(!doubleSet && (entryDataType1 == CDF_REAL8 ||
entryDataType1 == CDF_DOUBLE ||
entryDataType1 == CDF_EPOCH)) ||
(!doubleSet && (entryDataType1 == CDF_EPOCH16)) ||
(((floatSet && (entryDataType1 == CDF_FLOAT ||
entryDataType1 == CDF_REAL4)) ||
(doubleSet && (entryDataType1 == CDF_REAL8 ||
entryDataType1 == CDF_DOUBLE ||
entryDataType1 == CDF_EPOCH)) ||
(doubleSet && (entryDataType1 == CDF_EPOCH16))) &&
ValuesCmp(entryValue1, entryValue2, entryDataType1,
(double) floatTolerance, doubleTolerance))) {
diffFound = TRUE;
sprintf (oText,
"DIFFERENT value(s) for %s number %s%s of attribute \"%s\"",
e, entryNumField, varNameField, attrName);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
if (displayValue) {
WriteOut (stdout, " CDF1 value(s)> ");
WriteEntryValue (stdout, entryDataType1, entryNumElems1, entryValue1,
21, MAX_SCREENLINE_LEN-1);
WriteOut (stdout, "\n");
WriteOut (stdout, " CDF2 value(s)> ");
WriteEntryValue (stdout, entryDataType2, entryNumElems2, entryValue2,
21, MAX_SCREENLINE_LEN-1);
WriteOut (stdout, "\n");
}
}
}
cdf_FreeMemory (entryValue1, FatalError);
cdf_FreeMemory (entryValue2, FatalError);
CHECKforABORTso
return TRUE;
}
/******************************************************************************
* CompareZvsR.
******************************************************************************/
Logical CompareZvsR () {
CDFstatus status;
long varN1, varN2;
char varName1[CDF_VAR_NAME_LEN256+1];
/****************************************************************************
* If there are rVariables in CDF1 and zVariables in CDF2, see if any of the
* rVariables in CDF1 have the same name as a zVariable in CDF2.
****************************************************************************/
if (rNumVars1 > 0 && zNumVars2 > 0) {
for (varN1 = 0; varN1 < rNumVars1; varN1++) {
status = CDFlib (SELECT_, CDF_, id1,
rVAR_, varN1,
GET_, rVAR_NAME_, varName1,
NULL_);
if (!StatusHandlerCmp("CDF1",status)) return FALSE;
status = CDFlib (SELECT_, CDF_, id2,
GET_, zVAR_NUMBER_, varName1, &varN2,
NULL_);
switch (status) {
case CDF_OK:
sprintf (oText, "zVariable \"%s\" in CDF2 is an rVariable in CDF1",
varName1);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 2);
break;
case NO_SUCH_VAR:
break;
default:
if (!StatusHandlerCmp("CDF2",status)) return FALSE;
break;
}
CHECKforABORTso
}
}
/****************************************************************************
* If there are zVariables in CDF1 and rVariables in CDF2, see if any of the
* zVariables in CDF1 have the same name as an rVariable in CDF2.
****************************************************************************/
if (zNumVars1 > 0 && rNumVars2 > 0) {
for (varN1 = 0; varN1 < zNumVars1; varN1++) {
status = CDFlib (SELECT_, CDF_, id1,
zVAR_, varN1,
GET_, zVAR_NAME_, varName1,
NULL_);
if (!(StatusHandlerCmp("CDF1",status))) return FALSE;
status = CDFlib (SELECT_, CDF_, id2,
GET_, rVAR_NUMBER_, varName1, &varN2,
NULL_);
switch (status) {
case CDF_OK:
sprintf (oText, "zVariable \"%s\" in CDF1 is an rVariable in CDF2",
varName1);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 2);
break;
case NO_SUCH_VAR:
break;
default:
if (!StatusHandlerCmp("CDF2",status)) return FALSE;
break;
}
CHECKforABORTso
}
}
return TRUE;
}
/******************************************************************************
* CompareVariables.
******************************************************************************/
Logical CompareVariables (Z)
Logical Z;
{
CDFstatus status; long varN1, varN2; char varName[CDF_VAR_NAME_LEN256 + 1];
Logical cmpVarValues; int i, j; char *v = BOO(Z,zVariable,rVariable);
long VARcType1, VARcParms1[CDF_MAX_PARMS], VARcPct1;
long VARcType2, VARcParms2[CDF_MAX_PARMS], VARcPct2;
long VARsArraysType1, VARsArraysParms1[CDF_MAX_PARMS];
long VARsArraysPct1, VARsRecordsType1;
long VARsArraysType2, VARsArraysParms2[CDF_MAX_PARMS];
long VARsArraysPct2, VARsRecordsType2;
for (varN1 = 0; varN1 < BOO(Z,zNumVars1,rNumVars1); varN1++) {
if (BOO(Z,zVarNumMatches1[(int)varN1],
rVarNumMatches1[(int)varN1]) == -1) {
status = CDFlib (SELECT_, CDF_, id1,
VAR(Z), varN1,
GET_, VAR_NAME(Z), varName,
NULL_);
if (!StatusHandlerCmp("CDF1",status)) return FALSE;
diffFound = TRUE;
sprintf (oText, "%s \"%s\" does not exist in CDF2", v, varName);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 2);
}
else {
status = CDFlib (SELECT_, CDF_, id1,
VAR(Z), varN1,
GET_, VAR_NAME(Z), varName,
VAR_DATATYPE(Z), &varDataType1,
VAR_NUMELEMS(Z), &varNumElems1,
VAR_RECVARY(Z), &varRecVary1,
VAR_DIMVARYS(Z), varDimVarys1,
VAR_MAXREC(Z), &varMaxRec1,
VAR_COMPRESSION(Z), &VARcType1,
VARcParms1,
&VARcPct1,
VAR_SPARSEARRAYS(Z), &VARsArraysType1,
VARsArraysParms1,
&VARsArraysPct1,
VAR_SPARSERECORDS(Z), &VARsRecordsType1,
VAR_BLOCKINGFACTOR(Z), &varBlocking1,
NULL_);
if (!StatusHandlerCmp("CDF1",status)) return FALSE;
if (Z) {
status = CDFlib (SELECT_, CDF_, id1,
GET_, zVAR_NUMDIMS_, &zNumDims1,
zVAR_DIMSIZES_, zDimSizes1,
NULL_);
if (!StatusHandlerCmp("CDF1",status)) return FALSE;
}
status = CDFlib (SELECT_, CDF_, id2,
VAR(Z), BOO(Z,zVarNumMatches1[(int)varN1],
rVarNumMatches1[(int)varN1]),
GET_, VAR_DATATYPE(Z), &varDataType2,
VAR_NUMELEMS(Z), &varNumElems2,
VAR_RECVARY(Z), &varRecVary2,
VAR_DIMVARYS(Z),varDimVarys2,
VAR_MAXREC(Z), &varMaxRec2,
VAR_COMPRESSION(Z), &VARcType2,
VARcParms2,
&VARcPct2,
VAR_SPARSEARRAYS(Z), &VARsArraysType2,
VARsArraysParms2,
&VARsArraysPct2,
VAR_SPARSERECORDS(Z), &VARsRecordsType2,
VAR_BLOCKINGFACTOR(Z), &varBlocking2,
NULL_);
if (!StatusHandlerCmp("CDF2",status)) return FALSE;
if (Z) {
status = CDFlib (SELECT_, CDF_, id2,
GET_, zVAR_NUMDIMS_, &zNumDims2,
zVAR_DIMSIZES_, zDimSizes2,
NULL_);
if (!StatusHandlerCmp("CDF2",status)) return FALSE;
}
if (mLog) {
sprintf (oText, "Comparing %s \"%s\"", v, varName);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 2);
}
cmpVarValues = TRUE;
if (cmpNumbers)
if (BOO(Z,zVarNumMatches1[(int)varN1],
rVarNumMatches1[(int)varN1]) != varN1) {
diffFound = TRUE;
sprintf (oText, "DIFFERENT numbers for %s \"%s\" (%ld vs. %ld)",
v, varName, varN1+1, BOO(Z,zVarNumMatches1[(int)varN1],
rVarNumMatches1[(int)varN1])+1);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
if (cmpEtc && (!SameCompressions(VARcType1,VARcParms1,
VARcType2,VARcParms2))) {
diffFound = TRUE;
strcpyX (oText, "DIFFERENT compressions for", MAX_oTEXT_LEN);
sprintf (EofS(oText), " %s \"%s\" (%s vs. ",
v, varName, CompressionToken(VARcType1,VARcParms1));
sprintf (EofS(oText), "%s)", CompressionToken(VARcType2,VARcParms2));
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
if (cmpEtc && (VARcPct1 != VARcPct2)) {
diffFound = TRUE;
strcpyX (oText, "DIFFERENT compression percentages for",
MAX_oTEXT_LEN);
sprintf (EofS(oText), " %s \"%s\" (%ld vs. %ld)",
v, varName, VARcPct1, VARcPct2);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
if (cmpEtc && (!SameSparsenesses(VARsRecordsType1,VARsArraysType1,
VARsArraysParms1,VARsRecordsType2,
VARsArraysType2,VARsArraysParms2))) {
diffFound = TRUE;
strcpyX (oText, "DIFFERENT sparseness for", MAX_oTEXT_LEN);
sprintf (EofS(oText), " %s \"%s\" (%s vs. ", v, varName,
SparsenessToken(VARsRecordsType1,
VARsArraysType1,
VARsArraysParms1));
sprintf (EofS(oText), "%s)", SparsenessToken(VARsRecordsType2,
VARsArraysType2,
VARsArraysParms2));
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
if (cmpEtc && (VARsArraysPct1 != VARsArraysPct2)) {
diffFound = TRUE;
strcpyX (oText, "DIFFERENT sparse array percentages for",
MAX_oTEXT_LEN);
sprintf (EofS(oText), " %s \"%s\" (%ld vs. %ld)",
v, varName, VARsArraysPct1, VARsArraysPct2);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
if (cmpEtc && (varDataType1 != varDataType2)) {
diffFound = TRUE;
strcpyX (oText, "DIFFERENT data types for", MAX_oTEXT_LEN);
sprintf (EofS(oText), " %s \"%s\" (CDF_%s vs. CDF_%s)",
v, varName, DataTypeToken(varDataType1),
DataTypeToken(varDataType2));
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
if (!EquivalentDataTypes(varDataType1,varDataType2)) {
diffFound = TRUE;
strcpyX (oText, "Non-equivalent data types for", MAX_oTEXT_LEN);
sprintf (EofS(oText), " %s \"%s\" (CDF_%s vs. CDF_%s)",
v, varName, DataTypeToken(varDataType1),
DataTypeToken(varDataType2));
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
cmpVarValues = FALSE;
}
if (varNumElems1 != varNumElems2) {
diffFound = TRUE;
strcpyX (oText, "DIFFERENT number of elements for", MAX_oTEXT_LEN);
sprintf (EofS(oText), " %s \"%s\" (%ld vs. %ld)",
v, varName, varNumElems1, varNumElems2);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
cmpVarValues = FALSE;
}
if (Z) {
if (zNumDims1 != zNumDims2) {
diffFound = TRUE;
sprintf (oText, "DIFFERENT number of dimensions (%ld vs. %ld)",
zNumDims1, zNumDims2);
sprintf (EofS(oText), " for zVariable \"%s\"", varName);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
cmpVarValues = FALSE;
}
else {
if (zNumDims1 > 0) {
for (i = 0; i < zNumDims1; i++) {
if (zDimSizes1[i] != zDimSizes2[i]) {
diffFound = TRUE;
strcpyX (oText,"DIFFERENT dimension sizes (",MAX_oTEXT_LEN);
for (j = 0; j < zNumDims1; j++) {
sprintf (EofS(oText), "%ld ", zDimSizes1[j]);
}
strcatX (oText, "vs.", MAX_oTEXT_LEN);
for (j = 0; j < zNumDims2; j++) {
sprintf (EofS(oText), " %ld", zDimSizes2[j]);
}
sprintf (EofS(oText), ") for zVariable \"%s\"", varName);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
cmpVarValues = FALSE;
break;
}
}
}
}
}
if (varRecVary1 != varRecVary2) {
diffFound = TRUE;
strcpyX (oText, "DIFFERENT record variances for", MAX_oTEXT_LEN);
sprintf (EofS(oText), " %s \"%s\" (%s vs. %s)",
v, varName, TFvarianceToken(varRecVary1),
TFvarianceToken(varRecVary2));
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
if (Z) {
if (zNumDims1 == zNumDims2)
for (i = 0; i < zNumDims1; i++)
if (varDimVarys1[i] != varDimVarys2[i]) {
diffFound = TRUE;
strcpyX (oText,"DIFFERENT dimension variances for zVariable \"",
MAX_oTEXT_LEN);
strcatX (oText, varName, MAX_oTEXT_LEN);
strcatX (oText, "\" (", MAX_oTEXT_LEN);
for (j = 0; j < zNumDims1; j++)
sprintf (EofS(oText),"%s",TFvarianceToken(varDimVarys1[j]));
strcatX (oText, " vs. ", MAX_oTEXT_LEN);
for (j = 0; j < zNumDims2; j++)
sprintf (EofS(oText),"%s",TFvarianceToken(varDimVarys2[j]));
strcatX (oText, ")", MAX_oTEXT_LEN);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
break;
}
}
else {
for (i = 0; i < rNumDims1; i++)
if (varDimVarys1[i] != varDimVarys2[i]) {
diffFound = TRUE;
strcpyX (oText, "DIFFERENT dimension variances for rVariable \"",
MAX_oTEXT_LEN);
strcatX (oText, varName, MAX_oTEXT_LEN);
strcatX (oText, "\" (", MAX_oTEXT_LEN);
for (j = 0; j < rNumDims1; j++) {
sprintf (EofS(oText), "%s", TFvarianceToken(varDimVarys1[j]));
}
strcatX (oText, " vs. ", MAX_oTEXT_LEN);
for (j = 0; j < rNumDims2; j++) {
sprintf (EofS(oText), "%s", TFvarianceToken(varDimVarys2[j]));
}
strcatX (oText, ")", MAX_oTEXT_LEN);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
break;
}
}
if (varMaxRec1 != varMaxRec2) {
diffFound = TRUE;
sprintf (oText,"DIFFERENT maximum record for %s \"%s\" (%ld vs. %ld)",
v, varName, varMaxRec1 + 1, varMaxRec2 + 1);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
if (cmpEtc && (varBlocking1 != varBlocking2)) {
diffFound = TRUE;
sprintf(oText,"DIFFERENT blocking factor for %s \"%s\" (%ld vs. %ld)",
v, varName, varBlocking1, varBlocking2);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
if (cmpVarValues) {
if (!CompareVariableValues(varN1,
BOO(Z,zVarNumMatches1[(int)varN1],
rVarNumMatches1[(int)varN1]),
varName,Z)) return FALSE;
}
}
CHECKforABORTso
}
for (varN2 = 0; varN2 < BOO(Z,zNumVars2,rNumVars2); varN2++)
if (BOO(Z,zVarNumMatches2[(int)varN2],
rVarNumMatches2[(int)varN2]) == -1) {
status = CDFlib (SELECT_, CDF_, id2,
VAR(Z), varN2,
GET_, VAR_NAME(Z), varName,
NULL_);
if (!StatusHandlerCmp("CDF2",status)) return FALSE;
diffFound = TRUE;
sprintf (oText, "%s \"%s\" does not exist in CDF1", v, varName);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 2);
}
return TRUE;
}
/******************************************************************************
* CompareVariableValues.
******************************************************************************/
Logical CompareVariableValues (varN1, varN2, varName, Z)
long varN1;
long varN2;
char *varName;
Logical Z;
{
long numDims, dimSizes[CDF_MAX_DIMS], recVary, dimVarys[CDF_MAX_DIMS];
long nHypers, hyperN, nValuesPerRec, nValuesPerDim[CDF_MAX_DIMS];
char *v = BOO(Z,zVariable,rVariable);
void *padValue1, *padValue2;
CDFstatus status1, status2;
long maxRec; size_t nValueBytes[2];
Logical rowMajor1 = ROWmajor(majority1);
long recNumber, dimIndices[CDF_MAX_DIMS], valueN, NvalueBytes;
long valueDiffCount, recordDiffCount, lastRecordDiff, nValues;
struct GroupStruct groups; struct HyperStruct hyper;
Byte *value1, *value2, *buffer1, *buffer2, **handles[2];
int dimN, dimNt;
static char hyperMsg[] = {
" Comparing values with hyper reads..."
};
static char hyperSwitchMsg[] = {
" Comparing values with hyper reads/switching..."
};
static char hyperSingleMsg[] = {
" Comparing values with hyper/single reads..."
};
/****************************************************************************
* Select variables.
****************************************************************************/
status1 = CDFlib (SELECT_, CDF_, id1,
VAR(Z), varN1,
NULL_);
if (!StatusHandlerCmp("CDF1",status1)) return FALSE;
status2 = CDFlib (SELECT_, CDF_, id2,
VAR(Z), varN2,
NULL_);
if (!StatusHandlerCmp("CDF2",status2)) return FALSE;
/****************************************************************************
* Compare pad values.
****************************************************************************/
NvalueBytes = varNumElems1 * CDFelemSize(varDataType1);
padValue1 = cdf_AllocateMemory ((size_t) NvalueBytes, FatalError);
padValue2 = cdf_AllocateMemory ((size_t) NvalueBytes, FatalError);
status1 = CDFlib (SELECT_, CDF_, id1,
GET_, VAR_PADVALUE(Z), padValue1,
NULL_);
status2 = CDFlib (SELECT_, CDF_, id2,
GET_, VAR_PADVALUE(Z), padValue2,
NULL_);
if (status1 != NO_PADVALUE_SPECIFIED) {
if (!StatusHandlerCmp("CDF1",status1)) return FALSE;
if (status2 != NO_PADVALUE_SPECIFIED) {
if (!StatusHandlerCmp("CDF2",status2)) return FALSE;
if (memcmp(padValue1,padValue2,(size_t)NvalueBytes) != 0) {
if ((varDataType1 == CDF_CHAR || varDataType1 == CDF_UCHAR ||
varDataType1 == CDF_INT1 || varDataType1 == CDF_INT2 ||
varDataType1 == CDF_INT4 || varDataType1 == CDF_UINT1 ||
varDataType1 == CDF_UINT2 || varDataType1 == CDF_UINT4) ||
(!floatSet && (varDataType1 == CDF_FLOAT ||
varDataType1 == CDF_REAL4)) ||
(!doubleSet && (varDataType1 == CDF_REAL8 ||
varDataType1 == CDF_DOUBLE ||
varDataType1 == CDF_EPOCH)) ||
(!doubleSet && (varDataType1 == CDF_EPOCH16)) ||
(((floatSet && (varDataType1 == CDF_FLOAT ||
varDataType1 == CDF_REAL4)) ||
(doubleSet && (varDataType1 == CDF_REAL8 ||
varDataType1 == CDF_DOUBLE ||
varDataType1 == CDF_EPOCH)) ||
(doubleSet && (varDataType1 == CDF_EPOCH16))) &&
ValuesCmp(padValue1, padValue2, varDataType1,
(double) floatTolerance, doubleTolerance))) {
diffFound = TRUE;
sprintf (oText, "DIFFERENT pad values for %s \"%s\"", v, varName);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
if (displayValue) {
WriteOut (stdout, " CDF1 value> ");
EncodeValuesFormat (varDataType1, varNumElems1, padValue1, oText,
NULL, 0, MAX_SCREENLINE_LEN - 19, EPOCH0_STYLE);
WriteOut (stdout, oText);
WriteOut (stdout, "\n");
WriteOut (stdout, " CDF2 value> ");
EncodeValuesFormat (varDataType2, varNumElems2, padValue2, oText,
NULL, 0, MAX_SCREENLINE_LEN - 19, EPOCH0_STYLE);
WriteOut (stdout, oText);
WriteOut (stdout, "\n");
}
}
}
}
else {
diffFound = TRUE;
sprintf (oText, "No pad value for %s \"%s\" in CDF2", v, varName);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
}
else {
if (status2 != NO_PADVALUE_SPECIFIED) {
if (!StatusHandlerCmp("CDF2",status2)) return FALSE;
diffFound = TRUE;
sprintf (oText, "No pad value for %s \"%s\" in CDF1", v, varName);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
}
cdf_FreeMemory (padValue1, FatalError);
cdf_FreeMemory (padValue2, FatalError);
CHECKforABORTso
/****************************************************************************
* Hyper groups...
****************************************************************************/
maxRec = MAXIMUM(varMaxRec1,varMaxRec2);
recVary = (varRecVary1 || varRecVary2);
numDims = BOO(Z,zNumDims1,rNumDims1);
for (dimN = 0; dimN < numDims; dimN++) {
dimVarys[dimN] = (varDimVarys1[dimN] || varDimVarys2[dimN]);
if (dimVarys[dimN])
dimSizes[dimN] = BOO(Z,zDimSizes1[dimN],rDimSizes1[dimN]);
else
dimSizes[dimN] = 1;
}
for (dimN = 0, nValuesPerRec = 1; dimN < numDims; dimN++) {
if (dimVarys[dimN]) nValuesPerRec *= dimSizes[dimN];
}
for (dimN = 0; dimN < numDims; dimN++) {
nValuesPerDim[dimN] = 1;
if (rowMajor1) {
for (dimNt = dimN + 1; dimNt < numDims; dimNt++) {
nValuesPerDim[dimN] *= dimSizes[dimNt];
}
}
else {
for (dimNt = dimN - 1; dimNt >= 0; dimNt--) {
nValuesPerDim[dimN] *= dimSizes[dimNt];
}
}
}
handles[0] = &buffer1;
handles[1] = &buffer2;
nValueBytes[0] = (size_t) NvalueBytes;
nValueBytes[1] = (size_t) NvalueBytes;
valueDiffCount = 0;
recordDiffCount = 0;
lastRecordDiff = -1;
/****************************************************************************
* Check for zero or one dimensions or the same majorities (if two or more
* dimensions).
****************************************************************************/
if (numDims < 2 || majority1 == majority2) {
if (mLog) {
WriteOut (stdout, hyperMsg);
WriteOut (stdout, BOO(pctLog,"..0%","\n"));
}
AllocateBuffers (maxRec + 1, numDims, dimSizes, &groups, 0, 2, handles,
nValueBytes, rowMajor1, MINnHYPERS, FatalError);
InitHyperParms (&hyper, &groups, numDims, &nHypers, &nValues);
for (hyperN = 0; hyperN < nHypers; hyperN++) {
status1 = HYPER_READ (id1, Z, hyper, buffer1);
if (!StatusHandlerCmp("CDF1",status1)) return FALSE;
if (pctLog) WriteOutPct (PCT(hyperN,nHypers,1,3));
CHECKforABORTso
status2 = HYPER_READ (id2, Z, hyper, buffer2);
if (!StatusHandlerCmp("CDF2",status2)) return FALSE;
if (pctLog) WriteOutPct (PCT(hyperN,nHypers,2,3));
CHECKforABORTso
if (memcmp(buffer1,buffer2,(size_t)(nValues*NvalueBytes))) {
for (valueN = 0, value1 = buffer1, value2 = buffer2;
valueN < nValues; valueN++,
value1 += (size_t)NvalueBytes, value2 += (size_t)NvalueBytes) {
if (memcmp(value1,value2,(size_t)NvalueBytes)) {
if ((varDataType1 == CDF_CHAR || varDataType1 == CDF_UCHAR ||
varDataType1 == CDF_INT1 || varDataType1 == CDF_INT2 ||
varDataType1 == CDF_INT4 || varDataType1 == CDF_UINT1 ||
varDataType1 == CDF_UINT2 || varDataType1 == CDF_UINT4) ||
(!floatSet && (varDataType1 == CDF_FLOAT ||
varDataType1 == CDF_REAL4)) ||
(!doubleSet && (varDataType1 == CDF_REAL8 ||
varDataType1 == CDF_DOUBLE ||
varDataType1 == CDF_EPOCH)) ||
(!doubleSet && (varDataType1 == CDF_EPOCH16)) ||
(((floatSet && (varDataType1 == CDF_FLOAT ||
varDataType1 == CDF_REAL4)) ||
(doubleSet && (varDataType1 == CDF_REAL8 ||
varDataType1 == CDF_DOUBLE ||
varDataType1 == CDF_EPOCH)) ||
(doubleSet && (varDataType1 == CDF_EPOCH16))) &&
ValuesCmp(value1, value2, varDataType1,
(double) floatTolerance, doubleTolerance))) {
AtRecordIndices (&hyper, valueN, rowMajor1, numDims,
nValuesPerRec, nValuesPerDim, &recNumber,
dimIndices);
valueDiffCount++;
if (recNumber != lastRecordDiff) {
recordDiffCount++;
lastRecordDiff = recNumber;
}
ReportValueDifference (recNumber, recVary, numDims, dimIndices,
dimVarys, v, varName, value1, value2,
hyperMsg, PCT(hyperN,nHypers,2,3));
}
}
}
}
if (pctLog) WriteOutPct (PCT(hyperN,nHypers,3,3));
IncrHyperParms (&hyper, &groups, numDims, rowMajor1, &nValues);
CHECKforABORTso
}
cdf_FreeMemory (buffer1, FatalError);
cdf_FreeMemory (buffer2, FatalError);
if (pctLog) WriteOut (stdout, "\n");
ReportValueDifferenceTotals (recordDiffCount, valueDiffCount, varName, v);
return TRUE;
}
/****************************************************************************
* There must be two or more dimensions with different majorities. Attempt
* to allocate two buffers.
****************************************************************************/
AllocateBuffers (maxRec + 1, numDims, dimSizes, &groups, 0, 2, handles,
nValueBytes, rowMajor1, MINnHYPERS, FatalError);
/****************************************************************************
* Check if full records are being read. If so, switch the majority in one
* of the buffers before the comparison.
****************************************************************************/
if (HyperFullRecord(&groups,numDims)) {
long nBytesPerRecord = nValuesPerRec * NvalueBytes, recX;
if (mLog) {
WriteOut (stdout, hyperSwitchMsg);
WriteOut (stdout, BOO(pctLog,"..0%","\n"));
}
InitHyperParms (&hyper, &groups, numDims, &nHypers, &nValues);
for (hyperN = 0; hyperN < nHypers; hyperN++) {
status2 = HYPER_READ (id2, Z, hyper, buffer1);
if (!StatusHandlerCmp("CDF2",status2)) return FALSE;
if (pctLog) WriteOutPct (PCT(hyperN,nHypers,1,4));
CHECKforABORTso
for (recX = 0; recX < hyper.recCount; recX++) {
size_t offset = (size_t) (recX * nBytesPerRecord);
if (rowMajor1)
COLtoROW (buffer1 + offset, buffer2 + offset, numDims,
dimSizes, NvalueBytes);
else
ROWtoCOL (buffer1 + offset, buffer2 + offset, numDims,
dimSizes, NvalueBytes);
}
if (pctLog) WriteOutPct (PCT(hyperN,nHypers,2,4));
CHECKforABORTso
status1 = HYPER_READ (id1, Z, hyper, buffer1);
if (!StatusHandlerCmp("CDF1",status1)) return FALSE;
if (pctLog) WriteOutPct (PCT(hyperN,nHypers,3,4));
CHECKforABORTso
if (memcmp(buffer1,buffer2,(size_t)(nValues*NvalueBytes))) {
for (valueN = 0, value1 = buffer1, value2 = buffer2;
valueN < nValues; valueN++,
value1 += (size_t)NvalueBytes, value2 += (size_t)NvalueBytes) {
if (memcmp(value1,value2,(size_t)NvalueBytes)) {
if ((varDataType1 == CDF_CHAR || varDataType1 == CDF_UCHAR ||
varDataType1 == CDF_INT1 || varDataType1 == CDF_INT2 ||
varDataType1 == CDF_INT4 || varDataType1 == CDF_UINT1 ||
varDataType1 == CDF_UINT2 || varDataType1 == CDF_UINT4) ||
(!floatSet && (varDataType1 == CDF_FLOAT ||
varDataType1 == CDF_REAL4)) ||
(!doubleSet && (varDataType1 == CDF_REAL8 ||
varDataType1 == CDF_DOUBLE ||
varDataType1 == CDF_EPOCH)) ||
(!doubleSet && (varDataType1 == CDF_EPOCH16)) ||
(((floatSet && (varDataType1 == CDF_FLOAT ||
varDataType1 == CDF_REAL4)) ||
(doubleSet && (varDataType1 == CDF_REAL8 ||
varDataType1 == CDF_DOUBLE ||
varDataType1 == CDF_EPOCH)) ||
(doubleSet && (varDataType1 == CDF_EPOCH16))) &&
ValuesCmp(value1, value2, varDataType1,
(double) floatTolerance, doubleTolerance))) {
AtRecordIndices (&hyper, valueN, rowMajor1, numDims,
nValuesPerRec, nValuesPerDim, &recNumber,
dimIndices);
valueDiffCount++;
if (recNumber != lastRecordDiff) {
recordDiffCount++;
lastRecordDiff = recNumber;
}
ReportValueDifference (recNumber, recVary, numDims, dimIndices,
dimVarys, v, varName, value1, value2,
hyperSwitchMsg, PCT(hyperN,nHypers,3,4));
}
}
}
}
if (pctLog) WriteOutPct (PCT(hyperN,nHypers,4,4));
IncrHyperParms (&hyper, &groups, numDims, rowMajor1, &nValues);
CHECKforABORTso
}
cdf_FreeMemory (buffer1, FatalError);
cdf_FreeMemory (buffer2, FatalError);
if (pctLog) WriteOut (stdout, "\n");
ReportValueDifferenceTotals (recordDiffCount, valueDiffCount, varName, v);
return TRUE;
}
/****************************************************************************
* Less than full records are being read/written. Hyper read into the
* buffer but then use single writes to reverse the majority.
****************************************************************************/
cdf_FreeMemory (buffer2, FatalError);
value2 = cdf_AllocateMemory ((size_t) NvalueBytes, FatalError);
if (mLog) {
WriteOut (stdout, hyperSingleMsg);
WriteOut (stdout, BOO(pctLog,"..0%","\n"));
}
InitHyperParms (&hyper, &groups, numDims, &nHypers, &nValues);
for (hyperN = 0; hyperN < nHypers; hyperN++) {
status1 = HYPER_READ (id1, Z, hyper, buffer1);
if (!StatusHandlerCmp("CDF1",status1)) return FALSE;
if (pctLog) WriteOutPct (PCT(hyperN,nHypers,1,2));
CHECKforABORTso
status2 = CDFlib (SELECT_, CDF_, id2,
BOO(Z,zVAR_RECNUMBER_,
rVARs_RECNUMBER_), hyper.recNumber,
NULL_);
if (!StatusHandlerCmp("CDF2",status2)) return FALSE;
for (dimN = 0; dimN < numDims; dimN++) {
dimIndices[dimN] = hyper.dimIndices[dimN];
}
for (valueN = 0, value1 = buffer1; valueN < nValues;
valueN++, value1 += (size_t) NvalueBytes) {
status2 = CDFlib (SELECT_, BOO(Z,zVAR_DIMINDICES_,
rVARs_DIMINDICES_), dimIndices,
GET_, VAR_DATA(Z), value2,
NULL_);
if (!StatusHandlerCmp("CDF2",status2)) return FALSE;
if (memcmp(value1,value2,(size_t)NvalueBytes)) {
if ((varDataType1 == CDF_CHAR || varDataType1 == CDF_UCHAR ||
varDataType1 == CDF_INT1 || varDataType1 == CDF_INT2 ||
varDataType1 == CDF_INT4 || varDataType1 == CDF_UINT1 ||
varDataType1 == CDF_UINT2 || varDataType1 == CDF_UINT4) ||
(!floatSet && (varDataType1 == CDF_FLOAT ||
varDataType1 == CDF_REAL4)) ||
(!doubleSet && (varDataType1 == CDF_REAL8 ||
varDataType1 == CDF_DOUBLE ||
varDataType1 == CDF_EPOCH)) ||
(!doubleSet && (varDataType1 == CDF_EPOCH16)) ||
(((floatSet && (varDataType1 == CDF_FLOAT ||
varDataType1 == CDF_REAL4)) ||
(doubleSet && (varDataType1 == CDF_REAL8 ||
varDataType1 == CDF_DOUBLE ||
varDataType1 == CDF_EPOCH)) ||
(doubleSet && (varDataType1 == CDF_EPOCH16))) &&
ValuesCmp(value1, value2, varDataType1,
(double) floatTolerance, doubleTolerance))) {
valueDiffCount++;
if (hyper.recNumber != lastRecordDiff) {
recordDiffCount++;
lastRecordDiff = hyper.recNumber;
}
ReportValueDifference (hyper.recNumber, recVary, numDims,
dimIndices, dimVarys, v, varName,
value1, value2, hyperSingleMsg,
PCT(hyperN,nHypers,1,2));
}
}
if (rowMajor1)
INCRindicesROW (numDims, dimSizes, dimIndices);
else
INCRindicesCOL (numDims, dimSizes, dimIndices);
}
if (pctLog) WriteOutPct (PCT(hyperN,nHypers,2,2));
IncrHyperParms (&hyper, &groups, numDims, rowMajor1, &nValues);
CHECKforABORTso
}
cdf_FreeMemory (buffer1, FatalError);
cdf_FreeMemory (value2, FatalError);
if (pctLog) WriteOut (stdout, "\n");
ReportValueDifferenceTotals (recordDiffCount, valueDiffCount, varName, v);
return TRUE;
}
/******************************************************************************
* SameVarys.
******************************************************************************/
Logical SameVarys (numDims, recVary1, recVary2, dimVarys1, dimVarys2)
long numDims;
long recVary1;
long recVary2;
long dimVarys1[];
long dimVarys2[];
{
int dimNum;
if (recVary1 != recVary2) return FALSE;
for (dimNum = 0; dimNum < numDims; dimNum++) {
if (dimVarys1[dimNum] != dimVarys2[dimNum]) return FALSE;
}
return TRUE;
}
/******************************************************************************
* EquivalentDataTypes.
******************************************************************************/
Logical EquivalentDataTypes (dataType1, dataType2)
long dataType1;
long dataType2;
{
static long realDataType[] = {
0,1,2,0,3,0,0,0,0,0,
0,4,5,0,6,0,0,0,0,0,
0,7,8,0,0,0,0,0,0,0,
0,8,0,0,0,0,0,0,0,0,
0,1,0,0,7,8,0,0,0,0,
0,9,9,0,0,0,0,0,0,0
};
return (realDataType[(int)dataType1] == realDataType[(int)dataType2]);
}
/******************************************************************************
* CalcIndicesFromOffset.
******************************************************************************/
void CalcIndicesFromOffset (vOffset, rowMajor, numDims, dimSizes, dimVarys,
dimIndices)
long vOffset; /* Value offset into array (not byte offset). */
Logical rowMajor;
long numDims;
long dimSizes[];
long dimVarys[];
long dimIndices[];
{
long products[CDF_MAX_DIMS];
int dimN, dimNt;
if (rowMajor) {
for (dimN = 0; dimN < numDims; dimN++) {
products[dimN] = 1;
for (dimNt = dimN + 1; dimNt < numDims; dimNt++)
if (dimVarys[dimNt]) products[dimN] *= dimSizes[dimNt];
}
for (dimN = 0; dimN < numDims; dimN++)
if (dimVarys[dimN]) {
dimIndices[dimN] = vOffset / products[dimN];
vOffset %= products[dimN];
}
else
dimIndices[dimN] = 0;
}
else {
for (dimN = (int) (numDims - 1); dimN >= 0; dimN--) {
products[dimN] = 1;
for (dimNt = dimN - 1; dimNt >= 0; dimNt--)
if (dimVarys[dimNt]) products[dimN] *= dimSizes[dimNt];
}
for (dimN = (int) (numDims - 1); dimN >= 0; dimN--)
if (dimVarys[dimN]) {
dimIndices[dimN] = vOffset / products[dimN];
vOffset %= products[dimN];
}
else
dimIndices[dimN] = 0;
}
return;
}
/******************************************************************************
* StatusHandlerCmp.
******************************************************************************/
Logical StatusHandlerCmp (which, status)
char *which;
CDFstatus status;
{
char text[CDF_STATUSTEXT_LEN+1]; /* Explanation text. */
if (StatusERROR(status)) {
if (report[ERRORs]) {
if (pctLog) WriteOut (stdout, "\n");
CDFlib (SELECT_, CDF_STATUS_, status,
GET_, STATUS_TEXT_, text,
NULL_);
sprintf (oText, "ERROR,%s> %s", which, text);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 0);
}
return FALSE;
}
if (StatusWARN(status)) {
if (report[WARNs]) {
if (pctLog) WriteOut (stdout, "\n");
CDFlib (SELECT_, CDF_STATUS_, status,
GET_, STATUS_TEXT_, text,
NULL_);
sprintf (oText, "WARNING,%s> %s", which, text);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 0);
}
return TRUE;
}
if (StatusINFO(status)) {
if (report[INFOs]) {
if (pctLog) WriteOut (stdout, "\n");
CDFlib (SELECT_, CDF_STATUS_, status,
GET_, STATUS_TEXT_, text,
NULL_);
sprintf (oText, "INFO,%s> %s", which, text);
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 0);
}
return TRUE;
}
return TRUE; /* CDF_OK */
}
/******************************************************************************
* AtRecordIndices.
******************************************************************************/
void AtRecordIndices (hyper, valueN, rowMajor, numDims, nValuesPerRec,
nValuesPerDim, recNumber, dimIndices)
struct HyperStruct *hyper;
long valueN;
Logical rowMajor;
long numDims;
long nValuesPerRec;
long nValuesPerDim[];
long *recNumber;
long dimIndices[];
{
int dimN;
*recNumber = (valueN / nValuesPerRec) + hyper->recNumber;
valueN %= nValuesPerRec;
if (rowMajor) {
for (dimN = 0; dimN < numDims; dimN++) {
dimIndices[dimN] = hyper->dimIndices[dimN];
dimIndices[dimN] += (valueN / nValuesPerDim[dimN]);
valueN %= nValuesPerDim[dimN];
}
}
else {
for (dimN = (int) (numDims - 1); dimN >= 0; dimN--) {
dimIndices[dimN] = hyper->dimIndices[dimN];
dimIndices[dimN] += (valueN / nValuesPerDim[dimN]);
valueN %= nValuesPerDim[dimN];
}
}
return;
}
/******************************************************************************
* ReportValueDifference.
******************************************************************************/
void ReportValueDifference (recNumber, recVary, numDims, dimIndices, dimVarys,
v, varName, value1, value2, typeMsg, lastPct)
long recNumber;
long recVary;
long numDims;
long dimIndices[];
long dimVarys[];
char *v;
char *varName;
Byte *value1;
Byte *value2;
char *typeMsg;
int lastPct;
{
if (locations) {
char where[MAX_RECORD_INDICES_LEN+1];
EncodeRecordIndices (where, recNumber, recVary, numDims, dimIndices,
dimVarys);
sprintf (oText, "DIFFERENT value for %s \"%s\" at %s", v, varName, where);
if (pctLog) WriteOut (stdout, "\n");
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 6);
if (displayValue) {
WriteOut (stdout, " CDF1 value> ");
EncodeValuesFormat (varDataType1, varNumElems1, value1, oText, NULL, 0,
MAX_SCREENLINE_LEN - 21, EPOCH0_STYLE);
WriteOut (stdout, oText);
WriteOut (stdout, "\n");
WriteOut (stdout, " CDF2 value> ");
EncodeValuesFormat (varDataType2, varNumElems2, value2, oText, NULL, 0,
MAX_SCREENLINE_LEN - 21, EPOCH0_STYLE);
WriteOut (stdout, oText);
WriteOut (stdout, "\n");
}
if (pctLog) {
WriteOut (stdout, typeMsg);
WriteOut (stdout, " ");
WriteOutPct (lastPct);
}
}
return;
}
/******************************************************************************
* ReportValueDifferenceTotals.
******************************************************************************/
void ReportValueDifferenceTotals (recordDiffCount, valueDiffCount, varName, v)
long recordDiffCount;
long valueDiffCount;
char *varName;
char *v;
{
if (recordDiffCount > 0) {
diffFound = TRUE;
sprintf (oText, "DIFFERENCES in %ld record%s for %s \"%s\"",
recordDiffCount, (recordDiffCount > 1 ? "s" : ""), v, varName);
sprintf (EofS(oText), " (%ld value%s total)", valueDiffCount,
(valueDiffCount > 1 ? "s" : ""));
OutputWithMargin (stdout, oText, MAX_SCREENLINE_LEN, 4);
}
return;
}
/******************************************************************************
* ParseTolerances.
* It can be assumed that there is at least one character in `values' or QOP
* would have failed.
******************************************************************************/
Logical ParseTolerances (values, floatValueAddr, floatSet, doubleValueAddr,
doubleSet)
char *values;
float *floatValueAddr;
Logical *floatSet;
double *doubleValueAddr;
Logical *doubleSet;
{
char string[MAX_TOLERANCES_LEN+1];
int i, Ncommas;
char *ptr;
/****************************************************************************
* Strip leading and trailing white space from 1st string.
****************************************************************************/
ptr = values;
while (*ptr != NUL && Spacing(*ptr)) ptr++;
if (*ptr == NUL) return FALSE; /* Null-string. */
/****************************************************************************
* Move tolerance values to a temporary buffer and remove all spacing.
****************************************************************************/
strcpyX (string, ptr, MAX_TOLERANCES_LEN);
/****************************************************************************
* Check for (and skip) parenthesis on VMS systems.
****************************************************************************/
#if defined(vms)
if (*ptr == '(') {
char *lastChar = ptr + strlen(ptr) - 1;
if (*lastChar != ')') return FALSE;
ptr++;
*lastChar = NUL;
strcpyX (string, ptr, MAX_TOLERANCES_LEN);
}
#endif
/****************************************************************************
* Comma separated values.
****************************************************************************/
for (Ncommas = 0, i = 0; string[i] != NUL; i++) /* Count commas. */
if (string[i] == ',') Ncommas++;
ptr = string;
for (i = 0; i <= Ncommas; i++) {
if (*ptr == 'f' || *ptr == 'F') {
ptr = ptr + 2;
if ((strncmpIgCase(ptr, "default", 7) != 0) ||
(strncmpIgCase(ptr, "def", 3) != 0)) {
*floatSet = TRUE;
*floatValueAddr = (float) DEFAULT_FLOAT_TOLERANCE;
} else {
if (sscanf(ptr,"%f",(float *) floatValueAddr) != 1)
return FALSE;
else
*floatSet = TRUE;
}
} else if (*ptr == 'd' || *ptr == 'D') {
ptr = ptr + 2;
if ((strncmpIgCase(ptr, "default", 7) != 0) ||
(strncmpIgCase(ptr, "def", 3) != 0)) {
*doubleSet = TRUE;
*doubleValueAddr = (double) DEFAULT_DOUBLE_TOLERANCE;
} else {
if (sscanf(ptr,"%lf",(double *) doubleValueAddr) != 1)
return FALSE;
else
*doubleSet = TRUE;
}
} else
return FALSE;
ptr = strchr (ptr, ',') + 1; /* Garbage last time, doesn't matter. */
}
return TRUE;
}
/******************************************************************************
* ValuesCmp.
* Compare the difference between two values against the tolerance.
* It returns TRUE if outside of the tolerance, FALSE otherwise.
******************************************************************************/
Logical ValuesCmp (value1, value2, dataType, floatValue, doubleValue)
void *value1;
void *value2;
long dataType;
double floatValue;
double doubleValue;
{
if (dataType == CDF_REAL4 || dataType == CDF_FLOAT) {
/*************************************************************************
* Check the sign of tolerance.
* Use the tolerance as is to compare the difference if the tolerance is
* positive. Othwise, use the relative tolerance to compare as
* abs(value1-value2) > abs(tolerance)*max(abs(value1),abs(value2))
*************************************************************************/
if (floatValue >= 0.0) {
if (fabs(*((float *)value1) - *((float *)value2)) > floatValue)
return TRUE;
else return FALSE;
} else {
if (fabs(*((float *)value1) - *((float *)value2)) >
fabs(floatValue)*MAXIMUM(fabs(*((float *)value1)),
fabs(*((float *)value2))))
return TRUE;
else
return FALSE;
}
} else if (dataType == CDF_REAL8 || dataType == CDF_DOUBLE ||
dataType == CDF_EPOCH) {
if (doubleValue >= 0.0) {
if (fabs(*((double *)value1) - *((double *)value2)) > doubleValue)
return TRUE;
else return FALSE;
} else {
if (fabs(*((double *)value1) - *((double *)value2)) >
fabs(doubleValue)*MAXIMUM(fabs(*((double *)value1)),
fabs(*((double *)value2))))
return TRUE;
else
return FALSE;
}
} else if (dataType == CDF_EPOCH16) {
double epoch16_a[2], epoch16_b[2];
epoch16_a[0] = *((double *) value1);
epoch16_a[1] = *(((double *) value1)+1);
epoch16_b[0] = *((double *) value2);
epoch16_b[1] = *(((double *) value2)+1);
if (doubleValue >= 0.0) {
if (fabs(epoch16_a[0] - epoch16_b[0]) > doubleValue ||
fabs(epoch16_a[1] - epoch16_b[1]) > doubleValue)
return TRUE;
else return FALSE;
} else {
if ((fabs(epoch16_a[0] - epoch16_b[0]) >
fabs(doubleValue)*MAXIMUM(fabs(epoch16_a[0]),
fabs(epoch16_b[0]))) ||
(fabs(epoch16_a[1] - epoch16_b[1]) >
fabs(doubleValue)*MAXIMUM(fabs(epoch16_a[1]),
fabs(epoch16_b[1]))))
return TRUE;
else
return FALSE;
}
}
return TRUE;
}
/******************************************************************************
* ConvertQOPs.
* Returns TRUE if execution should continue.
******************************************************************************/
#if defined(mac)
Logical CompareQOPs (argC, argV)
int *argC;
char **argV[];
{
DialogPtr dialogP;
DialogRecord dRecord;
WindowPtr behind = (WindowPtr) -1;
ControlHandle controlHs[MAXIMUMin+1];
Rect iRect;
#ifdef __MWERKS__
ModalFilterUPP FilterDialogQOPsoUPP;
FileFilterUPP FilterForCDFsUPP;
UserItemUPP OutlineDefaultButtonUPP;
#endif
short itemN, iType, i;
static Logical first = TRUE;
char cancelTitle[] = "Cancel";
static Logical pageOutput = DEFAULTpageCVT;
static Logical compareAttrs = DEFAULTattrCMP;
static Logical compareVars = DEFAULTvarCMP;
static Logical compareNums = DEFAULTnumberCMP;
static Logical compareEtc = DEFAULTetcCMP;
static Logical negToPos = DEFAULT_NEGtoPOSfp0;
static Logical reportInfos = REPORTinfosDEFAULT;
static Logical reportWarns = REPORTwarningsDEFAULT;
static Logical reportErrors = REPORTerrorsDEFAULT;
static Logical logMsg = DEFAULTlogCMP;
static Logical dispPct = DEFAULTpctCMP;
static Logical dispLocs = DEFAULTlocationCMP;
static Logical dispStats = DEFAULTstatsCMP;
static Logical dispValues = DEFAULTvalueCMP;
static int zMode1 = DEFAULTzModeCMP;
static int zMode2 = DEFAULTzModeCMP;
static Str255 CDF1text = "\p";
static Str255 CDF2text = "\p";
static Str255 cacheText = "\p";
/****************************************************************************
* Create the dialog and get the control handles.
****************************************************************************/
dialogP = GetNewDialog (QOPri, &dRecord, behind);
for (itemN = 1; itemN <= MAXIMUMin; itemN++) {
GetDItem (dialogP, itemN, &iType, (Handle *) &controlHs[itemN], &iRect);
}
/****************************************************************************
* Set the control values.
****************************************************************************/
SetIText ((Handle) controlHs[CDF1TEXTin], CDF1text);
SetIText ((Handle) controlHs[CDF2TEXTin], CDF2text);
SetIText ((Handle) controlHs[CACHEin], cacheText);
if (pageOutput) SetCtlValue (controlHs[PAGEin], 1);
if (compareAttrs) SetCtlValue (controlHs[ATTRin], 1);
if (compareVars) SetCtlValue (controlHs[VARin], 1);
if (compareNums) SetCtlValue (controlHs[NUMin], 1);
if (compareEtc) SetCtlValue (controlHs[ETCin], 1);
if (negToPos) SetCtlValue (controlHs[NEGZin], 1);
if (reportInfos) SetCtlValue (controlHs[INFOin], 1);
if (reportWarns) SetCtlValue (controlHs[WARNin], 1);
if (reportErrors) SetCtlValue (controlHs[ERRORin], 1);
if (logMsg) SetCtlValue (controlHs[LOGin], 1);
if (dispPct) SetCtlValue (controlHs[PCTin], 1);
if (dispLocs) SetCtlValue (controlHs[LOCin], 1);
if (dispStats) SetCtlValue (controlHs[STATSin], 1);
if (dispValues) SetCtlValue (controlHs[VALUEin], 1);
SetCtlValue (controlHs[ZMODE1inBASE+zMode1], 1);
SetCtlValue (controlHs[ZMODE2inBASE+zMode2], 1);
#ifndef __MWERKS__
SetDItem (dialogP, (short) ODBin, (short) userItem,
(Handle) OutlineDefaultButton, &iRect);
#else
OutlineDefaultButtonUPP = NewUserItemProc (OutlineDefaultButton);
SetDItem (dialogP, (short) ODBin, (short) userItem,
(Handle) OutlineDefaultButtonUPP, &iRect);
#endif
/****************************************************************************
* Change the "Quit" button to a "Cancel" button after the first time.
****************************************************************************/
if (first)
first = FALSE;
else
SetCTitle (controlHs[CANCELin], CtoPstr(cancelTitle));
/****************************************************************************
* Display the dialog and wait for user actions.
****************************************************************************/
ShowWindow ((WindowPtr) dialogP);
SetCursor (ARROW_CURSOR);
#ifdef __MWERKS__
FilterDialogQOPsoUPP = NewModalFilterProc((ProcPtr) FilterDialogQOPso);
#endif
for (;;) {
#ifndef __MWERKS__
ModalDialog (FilterDialogQOPso, &itemN);
#else
ModalDialog (FilterDialogQOPsoUPP, &itemN);
#endif
switch (itemN) {
/************************************************************************
* Ok.
************************************************************************/
case OKin: {
int n;
char tempS3[3+1];
/**********************************************************************
* Get the value of each control.
**********************************************************************/
GetIText ((Handle) controlHs[CDF1TEXTin], CDF1text);
GetIText ((Handle) controlHs[CDF2TEXTin], CDF2text);
GetIText ((Handle) controlHs[CACHEin], cacheText);
pageOutput = GetCtlValue (controlHs[PAGEin]);
compareAttrs = GetCtlValue (controlHs[ATTRin]);
compareVars = GetCtlValue (controlHs[VARin]);
compareNums = GetCtlValue (controlHs[NUMin]);
compareEtc = GetCtlValue (controlHs[ETCin]);
negToPos = GetCtlValue (controlHs[NEGZin]);
reportInfos = GetCtlValue (controlHs[INFOin]);
reportWarns = GetCtlValue (controlHs[WARNin]);
reportErrors = GetCtlValue (controlHs[ERRORin]);
logMsg = GetCtlValue (controlHs[LOGin]);
dispPct = GetCtlValue (controlHs[PCTin]);
dispLocs = GetCtlValue (controlHs[LOCin]);
dispStats = GetCtlValue (controlHs[STATSin]);
dispValues = GetCtlValue (controlHs[VALUEin]);
for (zMode1 = 0; zMode1 < 3; zMode1++) {
if (GetCtlValue(controlHs[ZMODE1inBASE+zMode1])) break;
}
for (zMode2 = 0; zMode2 < 3; zMode2++) {
if (GetCtlValue(controlHs[ZMODE2inBASE+zMode2])) break;
}
/**********************************************************************
* Build argc/argv.
**********************************************************************/
*argC = 16 + BOO(NULpString(CDF1text),0,1) +
BOO(NULpString(CDF2text),0,1) +
BOO(NULpString(cacheText),0,2);
*argV = (char **) cdf_AllocateMemory (*argC * sizeof(char *), FatalError);
n = 0;
MAKEstrARGv (argV, n, pgmName)
if (!NULpString(CDF1text)) {
PtoCstr (CDF1text);
MAKEstrARGv (argV, n, (char *) CDF1text)
CtoPstr ((char *) CDF1text);
}
if (!NULpString(CDF2text)) {
PtoCstr (CDF2text);
MAKEstrARGv (argV, n, (char *) CDF2text)
CtoPstr ((char *) CDF2text);
}
MAKEbooARGv (argV, n, pageOutput, "-page", "-nopage")
MAKEbooARGv (argV, n, compareAttrs, "-attr", "-noattr")
MAKEbooARGv (argV, n, compareVars, "-var", "-novar")
MAKEbooARGv (argV, n, compareNums, "-number", "-nonumber")
MAKEbooARGv (argV, n, compareEtc, "-etc", "-noetc")
MAKEbooARGv (argV, n, negToPos, "-neg2posfp0", "-noneg2posfp0")
MAKEbooARGv (argV, n, logMsg, "-log", "-nolog")
MAKEbooARGv (argV, n, dispPct, "-percent", "-nopercent")
MAKEbooARGv (argV, n, dispLocs, "-location", "-nolocation")
MAKEbooARGv (argV, n, dispStats, "-statistics", "-nostatistics")
MAKEbooARGv (argV, n, dispValues, "-value", "-novalue")
MAKEstrARGv (argV, n, "-zmodes")
sprintf (tempS3, "%d,%d", zMode1, zMode2);
MAKEstrARGv (argV, n, tempS3)
MAKEstrARGv (argV, n, "-report")
MAKEstrARGv (argV, n, StatusCodeReportOptions(reportErrors,
reportWarns,
reportInfos))
if (!NULpString(cacheText)) {
MAKEstrARGv (argV, n, "-cache")
PtoCstr (cacheText);
MAKEstrARGv (argV, n, (char *) cacheText)
CtoPstr ((char *) cacheText);
}
/**********************************************************************
* Close the dialog and return.
**********************************************************************/
CloseDialog (dialogP);
#ifdef __MWERKS__
DisposeRoutineDescriptor (FilterDialogQOPsoUPP);
DisposeRoutineDescriptor (OutlineDefaultButtonUPP);
#endif
return TRUE;
}
/************************************************************************
* Help.
************************************************************************/
case HELPin: {
int n;
*argC = 1;
*argV = (char **) cdf_AllocateMemory (*argC * sizeof(char *), FatalError);
n = 0;
MAKEstrARGv (argV, n, pgmName)
#ifdef __MWERKS__
DisposeRoutineDescriptor (FilterDialogQOPsoUPP);
DisposeRoutineDescriptor (OutlineDefaultButtonUPP);
#endif
CloseDialog (dialogP);
return TRUE;
}
/************************************************************************
* Cancel.
************************************************************************/
case CANCELin:
#ifdef __MWERKS__
DisposeRoutineDescriptor (FilterDialogQOPsoUPP);
DisposeRoutineDescriptor (OutlineDefaultButtonUPP);
#endif
CloseDialog (dialogP);
return FALSE;
/************************************************************************
* Select CDF/1 specification.
************************************************************************/
case CDF1SELECTin: {
StandardFileReply reply;
char path[DU_MAX_PATH_LEN+1];
#ifndef __MWERKS__
StandardGetFile (FilterForCDFs, -1, NULL, &reply);
#else
FilterForCDFsUPP = NewFileFilterProc((ProcPtr) FilterForCDFs);
StandardGetFile (FilterForCDFsUPP, -1, NULL, &reply);
DisposeRoutineDescriptor (FilterForCDFsUPP);
#endif
if (reply.sfGood && !reply.sfIsFolder && !reply.sfIsVolume) {
BuildMacPath (&reply.sfFile, path, TRUE);
CDF1text[0] = strlen (path);
strcpyX ((char *) &CDF1text[1], path, 255);
SetIText ((Handle) controlHs[CDF1TEXTin], CDF1text);
}
break;
}
/************************************************************************
* Select CDF/2 specification.
************************************************************************/
case CDF2SELECTin: {
StandardFileReply reply;
char path[DU_MAX_PATH_LEN+1];
#ifndef __MWERKS__
StandardGetFile (FilterForCDFs, -1, NULL, &reply);
#else
FilterForCDFsUPP = NewFileFilterProc((ProcPtr) FilterForCDFs);
StandardGetFile (FilterForCDFsUPP, -1, NULL, &reply);
DisposeRoutineDescriptor (FilterForCDFsUPP);
#endif
if (reply.sfGood && !reply.sfIsFolder && !reply.sfIsVolume) {
BuildMacPath (&reply.sfFile, path, TRUE);
CDF2text[0] = strlen (path);
strcpyX ((char *) &CDF2text[1], path, 255);
SetIText ((Handle) controlHs[CDF2TEXTin], CDF2text);
}
break;
}
/************************************************************************
* Check boxes.
************************************************************************/
case PAGEin:
case ATTRin:
case VARin:
case NUMin:
case ETCin:
case NEGZin:
case INFOin:
case WARNin:
case ERRORin:
case LOGin:
case PCTin:
case LOCin:
case STATSin:
case VALUEin:
SetCtlValue (controlHs[itemN], BOO(GetCtlValue(controlHs[itemN]),0,1));
break;
/************************************************************************
* Radio buttons.
************************************************************************/
case ZMODE1inBASE+0:
case ZMODE1inBASE+1:
case ZMODE1inBASE+2:
for (i = 0; i < 3; i++) SetCtlValue (controlHs[ZMODE1inBASE+i], 0);
SetCtlValue (controlHs[itemN], 1);
break;
case ZMODE2inBASE+0:
case ZMODE2inBASE+1:
case ZMODE2inBASE+2:
for (i = 0; i < 3; i++) SetCtlValue (controlHs[ZMODE2inBASE+i], 0);
SetCtlValue (controlHs[itemN], 1);
break;
}
}
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1