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