void Program::Compile() { if (compiled_) { ERROR_WARNING("Program is already compiled."); return; } if (vertexShader_ == NULL || fragmentShader_ == NULL) { ERROR_REPORT("Could not compile program."); } glLinkProgram(program_); int status; glGetProgramiv(program_, GL_LINK_STATUS, &status); if (status != GL_TRUE) { char* log; GLint logLength; glGetProgramiv(program_, GL_INFO_LOG_LENGTH, &logLength); log = new char[logLength + 1]; glGetProgramInfoLog(program_, logLength, NULL, log); ERROR_REPORT(log); delete[] log; } glDetachShader(program_, *vertexShader_); glDetachShader(program_, *fragmentShader_); compiled_ = true; }
int tmstats(Options* inOptions) /* ** As quick as possible, load the input file and report stats. */ { int retval = 0; tmreader* tmr = NULL; TMStats stats; memset(&stats, 0, sizeof(stats)); stats.mOptions = inOptions; stats.uMinTicks = 0xFFFFFFFFU; /* ** Need a tmreader. */ tmr = tmreader_new(inOptions->mProgramName, &stats); if(NULL != tmr) { int tmResult = 0; tmResult = tmreader_eventloop(tmr, inOptions->mInputName, tmEventHandler); if(0 == tmResult) { retval = __LINE__; ERROR_REPORT(retval, inOptions->mInputName, "Problem reading trace-malloc data."); } tmreader_destroy(tmr); tmr = NULL; if(0 == retval) { retval = report_stats(inOptions, &stats); } } else { retval = __LINE__; ERROR_REPORT(retval, inOptions->mProgramName, "Unable to obtain tmreader."); } return retval; }
Shader::Shader(const char* filename, GLenum type) : shader_(0) { const char* source = readFile(filename); if (source == NULL) { ERROR_REPORT("Could not read shader file."); } shader_ = glCreateShader(type); if (shader_ == 0) { ERROR_REPORT("Could not create shader."); } glShaderSource(shader_, 1, &source, NULL); glCompileShader(shader_); // check if shader compiled correctly GLint status; glGetShaderiv(shader_, GL_COMPILE_STATUS, &status); if (status == GL_FALSE) { GLint infoLogLength; glGetShaderiv(shader_, GL_INFO_LOG_LENGTH, &infoLogLength); GLchar *infoLog = new GLchar[infoLogLength + 1]; glGetShaderInfoLog(shader_, infoLogLength, NULL, infoLog); std::stringstream message; message << "Could not compile shader for: " << filename << std::endl; message << infoLog << std::endl; delete[] infoLog; ERROR_REPORT(message.str().c_str()); } delete[] source; }
int initOptions(Options* outOptions, int inArgc, char** inArgv) /* ** returns int 0 if successful. */ { int retval = 0; int loop = 0; int switchLoop = 0; int match = 0; const int switchCount = sizeof(gSwitches) / sizeof(gSwitches[0]); Switch* current = NULL; /* ** Set any defaults. */ memset(outOptions, 0, sizeof(Options)); outOptions->mProgramName = inArgv[0]; outOptions->mInput = stdin; outOptions->mInputName = strdup("stdin"); outOptions->mOutput = stdout; outOptions->mOutputName = strdup("stdout"); if(NULL == outOptions->mOutputName || NULL == outOptions->mInputName) { retval = __LINE__; ERROR_REPORT(retval, "stdin/stdout", "Unable to strdup."); } /* ** Go through and attempt to do the right thing. */ for(loop = 1; loop < inArgc && 0 == retval; loop++) { match = 0; current = NULL; for(switchLoop = 0; switchLoop < switchCount && 0 == retval; switchLoop++) { if(0 == strcmp(gSwitches[switchLoop]->mLongName, inArgv[loop])) { match = __LINE__; } else if(0 == strcmp(gSwitches[switchLoop]->mShortName, inArgv[loop])) { match = __LINE__; } if(match) { if(gSwitches[switchLoop]->mHasValue) { /* ** Attempt to absorb next option to fullfill value. */ if(loop + 1 < inArgc) { loop++; current = gSwitches[switchLoop]; current->mValue = inArgv[loop]; } } else { current = gSwitches[switchLoop]; } break; } } if(0 == match) { outOptions->mHelp = __LINE__; retval = __LINE__; ERROR_REPORT(retval, inArgv[loop], "Unknown command line switch."); } else if(NULL == current) { outOptions->mHelp = __LINE__; retval = __LINE__; ERROR_REPORT(retval, inArgv[loop], "Command line switch requires a value."); } else { /* ** Do something based on address/swtich. */ if(current == &gInputSwitch) { CLEANUP(outOptions->mInputName); if(NULL != outOptions->mInput && stdin != outOptions->mInput) { fclose(outOptions->mInput); outOptions->mInput = NULL; } outOptions->mInput = fopen(current->mValue, "r"); if(NULL == outOptions->mInput) { retval = __LINE__; ERROR_REPORT(retval, current->mValue, "Unable to open input file."); } else { outOptions->mInputName = strdup(current->mValue); if(NULL == outOptions->mInputName) { retval = __LINE__; ERROR_REPORT(retval, current->mValue, "Unable to strdup."); } } } else if(current == &gOutputSwitch) { CLEANUP(outOptions->mOutputName); if(NULL != outOptions->mOutput && stdout != outOptions->mOutput) { fclose(outOptions->mOutput); outOptions->mOutput = NULL; } outOptions->mOutput = fopen(current->mValue, "a"); if(NULL == outOptions->mOutput) { retval = __LINE__; ERROR_REPORT(retval, current->mValue, "Unable to open output file."); } else { outOptions->mOutputName = strdup(current->mValue); if(NULL == outOptions->mOutputName) { retval = __LINE__; ERROR_REPORT(retval, current->mValue, "Unable to strdup."); } } } else if(current == &gHelpSwitch) { outOptions->mHelp = __LINE__; } else { retval = __LINE__; ERROR_REPORT(retval, current->mLongName, "No hanlder for command line switch."); } } } return retval; }
int nm2tsv(Options* inOptions) /* ** Read all input. ** Output tab seperated value data. ** ** We expect our data to be in a particular format. ** nm --format=bsd --size-sort --print-file-name --demangle */ { int retval = 0; char lineBuffer[4096]; /* yes, the are some very large symbols */ char* module = NULL; char* size = NULL; char* type = NULL; char* symbol = NULL; /* ** Read in the nm file. */ while(0 == retval && NULL != fgets(lineBuffer, sizeof(lineBuffer), inOptions->mInput)) { trimWhite(lineBuffer); /* ** Find the various pieces of information we'll be looking for. */ size = strchr(lineBuffer, ':'); if(NULL != size) { *size = '\0'; size++; module = strrchr(lineBuffer, '/'); if(NULL == module) { module = lineBuffer; } else { *module = '\0'; module++; } type = scanWhite(size); *type = '\0'; type++; symbol = type + 1; *symbol = '\0'; symbol++; /* ** Skip certain types. */ switch(*type) { case '-': continue; break; default: break; } /* ** Simply output the data with a little more interpretation. ** First is size. */ fprintf(inOptions->mOutput, "%s\t", size); /* ** Type, CODE or DATA */ switch(toupper(*type)) { case 'T': /* text (code) */ case 'W': /* weak symbol ??? */ fprintf(inOptions->mOutput, "CODE\t"); break; default: fprintf(inOptions->mOutput, "DATA\t"); break; } /* ** Scope, PUBLIC, STATIC, or UNDEF */ if(islower(*type)) { fprintf(inOptions->mOutput, "STATIC\t"); } else { switch(*type) { case '?': fprintf(inOptions->mOutput, "UNDEF\t"); break; default: fprintf(inOptions->mOutput, "PUBLIC\t"); break; } } /* ** Module name, segment. */ fprintf(inOptions->mOutput, "%s\t", module); fprintf(inOptions->mOutput, "%c\t", toupper(*type)); /* ** Origin */ fprintf(inOptions->mOutput, "UNDEF:%s:%c\t", module, toupper(*type)); /* ** Symbol is last. */ fprintf(inOptions->mOutput, "%s\n", symbol); } else { retval = __LINE__; ERROR_REPORT(retval, lineBuffer, "Malformed input line."); } } if(0 == retval && 0 != ferror(inOptions->mInput)) { retval = __LINE__; ERROR_REPORT(retval, inOptions->mInputName, "Unable to read file."); } return retval; }
int initOptions(Options* outOptions, int inArgc, char** inArgv) /* ** returns int 0 if successful. */ { int retval = 0; int loop = 0; int switchLoop = 0; int match = 0; const int switchCount = sizeof(gSwitches) / sizeof(gSwitches[0]); Switch* current = NULL; /* ** Set any defaults. */ memset(outOptions, 0, sizeof(Options)); outOptions->mProgramName = inArgv[0]; outOptions->mInput = stdin; outOptions->mInputName = strdup("stdin"); outOptions->mOutput = stdout; outOptions->mOutputName = strdup("stdout"); outOptions->mMaxSize = 0xFFFFFFFFU; if(NULL == outOptions->mOutputName || NULL == outOptions->mInputName) { retval = __LINE__; ERROR_REPORT(retval, "stdin/stdout", "Unable to strdup."); } /* ** Go through and attempt to do the right thing. */ for(loop = 1; loop < inArgc && 0 == retval; loop++) { match = 0; current = NULL; for(switchLoop = 0; switchLoop < switchCount && 0 == retval; switchLoop++) { if(0 == strcmp(gSwitches[switchLoop]->mLongName, inArgv[loop])) { match = __LINE__; } else if(0 == strcmp(gSwitches[switchLoop]->mShortName, inArgv[loop])) { match = __LINE__; } if(match) { if(gSwitches[switchLoop]->mHasValue) { /* ** Attempt to absorb next option to fulfill value. */ if(loop + 1 < inArgc) { loop++; current = gSwitches[switchLoop]; current->mValue = inArgv[loop]; } } else { current = gSwitches[switchLoop]; } break; } } if(0 == match) { outOptions->mHelp = __LINE__; retval = __LINE__; ERROR_REPORT(retval, inArgv[loop], "Unknown command line switch."); } else if(NULL == current) { outOptions->mHelp = __LINE__; retval = __LINE__; ERROR_REPORT(retval, inArgv[loop], "Command line switch requires a value."); } else { /* ** Do something based on address/swtich. */ if(current == &gInputSwitch) { CLEANUP(outOptions->mInputName); if(NULL != outOptions->mInput && stdin != outOptions->mInput) { fclose(outOptions->mInput); outOptions->mInput = NULL; } outOptions->mInput = fopen(current->mValue, "r"); if(NULL == outOptions->mInput) { retval = __LINE__; ERROR_REPORT(retval, current->mValue, "Unable to open input file."); } else { outOptions->mInputName = strdup(current->mValue); if(NULL == outOptions->mInputName) { retval = __LINE__; ERROR_REPORT(retval, current->mValue, "Unable to strdup."); } } } else if(current == &gOutputSwitch) { CLEANUP(outOptions->mOutputName); if(NULL != outOptions->mOutput && stdout != outOptions->mOutput) { fclose(outOptions->mOutput); outOptions->mOutput = NULL; } outOptions->mOutput = fopen(current->mValue, "a"); if(NULL == outOptions->mOutput) { retval = __LINE__; ERROR_REPORT(retval, current->mValue, "Unable to open output file."); } else { outOptions->mOutputName = strdup(current->mValue); if(NULL == outOptions->mOutputName) { retval = __LINE__; ERROR_REPORT(retval, current->mValue, "Unable to strdup."); } } } else if(current == &gHelpSwitch) { outOptions->mHelp = __LINE__; } else if(current == &gModuleSwitch) { outOptions->mModules = __LINE__; } else if(current == &gTotalSwitch) { outOptions->mTotalOnly = __LINE__; } else if(current == &gMinSize) { unsigned long arg = 0; char* endScan = NULL; errno = 0; arg = strtoul(current->mValue, &endScan, 0); if(0 == errno && endScan != current->mValue) { outOptions->mMinSize = arg; } else { retval = __LINE__; ERROR_REPORT(retval, current->mValue, "Unable to convert to a number."); } } else if(current == &gMaxSize) { unsigned long arg = 0; char* endScan = NULL; errno = 0; arg = strtoul(current->mValue, &endScan, 0); if(0 == errno && endScan != current->mValue) { outOptions->mMaxSize = arg; } else { retval = __LINE__; ERROR_REPORT(retval, current->mValue, "Unable to convert to a number."); } } else if(current == &gMatchClass) { char* dupMatch = NULL; dupMatch = strdup(current->mValue); if(NULL != dupMatch) { void* moved = NULL; moved = realloc(outOptions->mMatchClasses, sizeof(char*) * (outOptions->mMatchClassCount + 1)); if(NULL != moved) { outOptions->mMatchClasses = (char**)moved; outOptions->mMatchClasses[outOptions->mMatchClassCount] = dupMatch; outOptions->mMatchClassCount++; } else { retval = __LINE__; ERROR_REPORT(retval, current->mLongName, "Unable to expand array."); } } else { retval = __LINE__; ERROR_REPORT(retval, current->mValue, "Unable to duplicate string."); } } else if(current == &gMatchScope) { char* dupMatch = NULL; dupMatch = strdup(current->mValue); if(NULL != dupMatch) { void* moved = NULL; moved = realloc(outOptions->mMatchScopes, sizeof(char*) * (outOptions->mMatchScopeCount + 1)); if(NULL != moved) { outOptions->mMatchScopes = (char**)moved; outOptions->mMatchScopes[outOptions->mMatchScopeCount] = dupMatch; outOptions->mMatchScopeCount++; } else { retval = __LINE__; ERROR_REPORT(retval, current->mLongName, "Unable to expand array."); } } else { retval = __LINE__; ERROR_REPORT(retval, current->mValue, "Unable to duplicate string."); } } else if(current == &gMatchModule) { char* dupMatch = NULL; dupMatch = strdup(current->mValue); if(NULL != dupMatch) { void* moved = NULL; moved = realloc(outOptions->mMatchModules, sizeof(char*) * (outOptions->mMatchModuleCount + 1)); if(NULL != moved) { outOptions->mMatchModules = (char**)moved; outOptions->mMatchModules[outOptions->mMatchModuleCount] = dupMatch; outOptions->mMatchModuleCount++; } else { retval = __LINE__; ERROR_REPORT(retval, current->mLongName, "Unable to expand array."); } } else { retval = __LINE__; ERROR_REPORT(retval, current->mValue, "Unable to duplicate string."); } } else if(current == &gMatchSection) { char* dupMatch = NULL; dupMatch = strdup(current->mValue); if(NULL != dupMatch) { void* moved = NULL; moved = realloc(outOptions->mMatchSections, sizeof(char*) * (outOptions->mMatchSectionCount + 1)); if(NULL != moved) { outOptions->mMatchSections = (char**)moved; outOptions->mMatchSections[outOptions->mMatchSectionCount] = dupMatch; outOptions->mMatchSectionCount++; } else { retval = __LINE__; ERROR_REPORT(retval, current->mLongName, "Unable to expand array."); } } else { retval = __LINE__; ERROR_REPORT(retval, current->mValue, "Unable to duplicate string."); } } else if(current == &gMatchObject) { char* dupMatch = NULL; dupMatch = strdup(current->mValue); if(NULL != dupMatch) { void* moved = NULL; moved = realloc(outOptions->mMatchObjects, sizeof(char*) * (outOptions->mMatchObjectCount + 1)); if(NULL != moved) { outOptions->mMatchObjects = (char**)moved; outOptions->mMatchObjects[outOptions->mMatchObjectCount] = dupMatch; outOptions->mMatchObjectCount++; } else { retval = __LINE__; ERROR_REPORT(retval, current->mLongName, "Unable to expand array."); } } else { retval = __LINE__; ERROR_REPORT(retval, current->mValue, "Unable to duplicate string."); } } else if(current == &gMatchSymbol) { char* dupMatch = NULL; dupMatch = strdup(current->mValue); if(NULL != dupMatch) { void* moved = NULL; moved = realloc(outOptions->mMatchSymbols, sizeof(char*) * (outOptions->mMatchSymbolCount + 1)); if(NULL != moved) { outOptions->mMatchSymbols = (char**)moved; outOptions->mMatchSymbols[outOptions->mMatchSymbolCount] = dupMatch; outOptions->mMatchSymbolCount++; } else { retval = __LINE__; ERROR_REPORT(retval, current->mLongName, "Unable to expand array."); } } else { retval = __LINE__; ERROR_REPORT(retval, current->mValue, "Unable to duplicate string."); } } else { retval = __LINE__; ERROR_REPORT(retval, current->mLongName, "No handler for command line switch."); } } } return retval; }
int codesighs(Options* inOptions) /* ** Output a simplistic report based on our options. */ { int retval = 0; char lineBuffer[0x1000]; int scanRes = 0; unsigned long size; #define SEGCLASS_CHARS 15 char segClass[SEGCLASS_CHARS + 1]; #define SCOPE_CHARS 15 char scope[SCOPE_CHARS + 1]; #define MODULE_CHARS 255 char module[MODULE_CHARS + 1]; #define SEGMENT_CHARS 63 char segment[SEGMENT_CHARS + 1]; #define OBJECT_CHARS 255 char object[OBJECT_CHARS + 1]; char* symbol; SizeStats overall; ModuleStats* modules = NULL; unsigned moduleCount = 0; memset(&overall, 0, sizeof(overall)); /* ** Read the file line by line, regardless of number of fields. ** We assume tab separated value formatting, at least 7 lead values: ** size class scope module segment object symbol .... */ while(0 == retval && NULL != fgets(lineBuffer, sizeof(lineBuffer), inOptions->mInput)) { trimWhite(lineBuffer); #define STRINGIFY(s_) STRINGIFY2(s_) #define STRINGIFY2(s_) #s_ scanRes = sscanf(lineBuffer, "%x\t%" STRINGIFY(SEGCLASS_CHARS) "s\t%" STRINGIFY(SCOPE_CHARS) "s\t%" STRINGIFY(MODULE_CHARS) "s\t%" STRINGIFY(SEGMENT_CHARS) "s\t%" STRINGIFY(OBJECT_CHARS) "s\t", (unsigned*)&size, segClass, scope, module, segment, object); if(6 == scanRes) { SegmentClass segmentClass = CODE; symbol = strchr(lineBuffer, '\t') + 1; /* ** Qualify the segment class. */ if(0 == strcmp(segClass, "DATA")) { segmentClass = DATA; } else if(0 == strcmp(segClass, "CODE")) { segmentClass = CODE; } else { retval = __LINE__; ERROR_REPORT(retval, segClass, "Unable to determine segment class."); } if(0 == retval) { /* ** Match any options required before continuing. ** This is where you would want to add more restrictive totalling. */ /* ** Match size. */ if(size < inOptions->mMinSize) { continue; } if(size > inOptions->mMaxSize) { continue; } /* ** Match class. */ if(0 != inOptions->mMatchClassCount) { unsigned loop = 0; for(loop = 0; loop < inOptions->mMatchClassCount; loop++) { if(NULL != strstr(segClass, inOptions->mMatchClasses[loop])) { break; } } /* ** If there was no match, we skip the line. */ if(loop == inOptions->mMatchClassCount) { continue; } } /* ** Match scope. */ if(0 != inOptions->mMatchScopeCount) { unsigned loop = 0; for(loop = 0; loop < inOptions->mMatchScopeCount; loop++) { if(NULL != strstr(scope, inOptions->mMatchScopes[loop])) { break; } } /* ** If there was no match, we skip the line. */ if(loop == inOptions->mMatchScopeCount) { continue; } } /* ** Match modules. */ if(0 != inOptions->mMatchModuleCount) { unsigned loop = 0; for(loop = 0; loop < inOptions->mMatchModuleCount; loop++) { if(NULL != strstr(module, inOptions->mMatchModules[loop])) { break; } } /* ** If there was no match, we skip the line. */ if(loop == inOptions->mMatchModuleCount) { continue; } } /* ** Match sections. */ if(0 != inOptions->mMatchSectionCount) { unsigned loop = 0; for(loop = 0; loop < inOptions->mMatchSectionCount; loop++) { if(NULL != strstr(segment, inOptions->mMatchSections[loop])) { break; } } /* ** If there was no match, we skip the line. */ if(loop == inOptions->mMatchSectionCount) { continue; } } /* ** Match object. */ if(0 != inOptions->mMatchObjectCount) { unsigned loop = 0; for(loop = 0; loop < inOptions->mMatchObjectCount; loop++) { if(NULL != strstr(object, inOptions->mMatchObjects[loop])) { break; } } /* ** If there was no match, we skip the line. */ if(loop == inOptions->mMatchObjectCount) { continue; } } /* ** Match symbols. */ if(0 != inOptions->mMatchSymbolCount) { unsigned loop = 0; for(loop = 0; loop < inOptions->mMatchSymbolCount; loop++) { if(NULL != strstr(symbol, inOptions->mMatchSymbols[loop])) { break; } } /* ** If there was no match, we skip the line. */ if(loop == inOptions->mMatchSymbolCount) { continue; } } /* ** Update overall totals. */ if(CODE == segmentClass) { overall.mCode += size; } else if(DATA == segmentClass) { overall.mData += size; } /* ** See what else we should be tracking. */ if(0 == inOptions->mTotalOnly) { if(inOptions->mModules) { unsigned index = 0; /* ** Find the module to modify. */ for(index = 0; index < moduleCount; index++) { if(0 == strcmp(modules[index].mModule, module)) { break; } } /* ** If the index is the same as the count, we need to ** add a new module. */ if(index == moduleCount) { void* moved = NULL; moved = realloc(modules, sizeof(ModuleStats) * (moduleCount + 1)); if(NULL != moved) { modules = (ModuleStats*)moved; moduleCount++; memset(modules + index, 0, sizeof(ModuleStats)); modules[index].mModule = strdup(module); if(NULL == modules[index].mModule) { retval = __LINE__; ERROR_REPORT(retval, module, "Unable to duplicate string."); } } else { retval = __LINE__; ERROR_REPORT(retval, inOptions->mProgramName, "Unable to allocate module memory."); } } if(0 == retval) { if(CODE == segmentClass) { modules[index].mSize.mCode += size; } else if(DATA == segmentClass) { modules[index].mSize.mData += size; } } } } } } else { retval = __LINE__; ERROR_REPORT(retval, inOptions->mInputName, "Problem extracting values from file."); } } if(0 == retval && 0 != ferror(inOptions->mInput)) { retval = __LINE__; ERROR_REPORT(retval, inOptions->mInputName, "Unable to read file."); } /* ** If all went well, time to report. */ if(0 == retval) { if(inOptions->mTotalOnly) { fprintf(inOptions->mOutput, "%u\n", (unsigned)(overall.mCode + overall.mData)); } else { fprintf(inOptions->mOutput, "Overall Size\n"); fprintf(inOptions->mOutput, "\tTotal:\t%10u\n", (unsigned)(overall.mCode + overall.mData)); fprintf(inOptions->mOutput, "\tCode:\t%10u\n", (unsigned)overall.mCode); fprintf(inOptions->mOutput, "\tData:\t%10u\n", (unsigned)overall.mData); } /* ** Check options to see what else we should output. */ if(inOptions->mModules && moduleCount) { unsigned loop = 0; /* ** Sort the modules by their size. */ qsort(modules, (size_t)moduleCount, sizeof(ModuleStats), moduleCompare); /* ** Output each one. ** Might as well clean up while we go too. */ for(loop = 0; loop < moduleCount; loop++) { fprintf(inOptions->mOutput, "\n"); fprintf(inOptions->mOutput, "%s\n", modules[loop].mModule); fprintf(inOptions->mOutput, "\tTotal:\t%10u\n", (unsigned)(modules[loop].mSize.mCode + modules[loop].mSize.mData)); fprintf(inOptions->mOutput, "\tCode:\t%10u\n", (unsigned)modules[loop].mSize.mCode); fprintf(inOptions->mOutput, "\tData:\t%10u\n", (unsigned)modules[loop].mSize.mData); CLEANUP(modules[loop].mModule); } /* ** Done with modules. */ CLEANUP(modules); moduleCount = 0; } } return retval; }
int difftool(Options* inOptions) /* ** Read a diff file and spit out relevant information. */ { int retval = 0; char lineBuffer[0x500]; SizeStats overall; ModuleStats* modules = NULL; unsigned moduleCount = 0; unsigned moduleLoop = 0; ModuleStats* theModule = NULL; unsigned segmentLoop = 0; SegmentStats* theSegment = NULL; unsigned objectLoop = 0; ObjectStats* theObject = NULL; unsigned symbolLoop = 0; SymbolStats* theSymbol = NULL; unsigned allSymbolCount = 0; memset(&overall, 0, sizeof(overall)); /* ** Read the entire diff file. ** We're only interested in lines beginning with < or > */ while(0 == retval && NULL != fgets(lineBuffer, sizeof(lineBuffer), inOptions->mInput)) { trimWhite(lineBuffer); if(('<' == lineBuffer[0] || '>' == lineBuffer[0]) && ' ' == lineBuffer[1]) { int additive = 0; char* theLine = &lineBuffer[2]; int scanRes = 0; int size; #define SEGCLASS_CHARS 15 char segClass[SEGCLASS_CHARS + 1]; #define SCOPE_CHARS 15 char scope[SCOPE_CHARS + 1]; #define MODULE_CHARS 255 char module[MODULE_CHARS + 1]; #define SEGMENT_CHARS 63 char segment[SEGMENT_CHARS + 1]; #define OBJECT_CHARS 255 char object[OBJECT_CHARS + 1]; char* symbol = NULL; /* ** Figure out if the line adds or subtracts from something. */ if('>' == lineBuffer[0]) { additive = __LINE__; } /* ** Scan the line for information. */ #define STRINGIFY(s_) STRINGIFY2(s_) #define STRINGIFY2(s_) #s_ scanRes = sscanf(theLine, "%x\t%" STRINGIFY(SEGCLASS_CHARS) "s\t%" STRINGIFY(SCOPE_CHARS) "s\t%" STRINGIFY(MODULE_CHARS) "s\t%" STRINGIFY(SEGMENT_CHARS) "s\t%" STRINGIFY(OBJECT_CHARS) "s\t", (unsigned*)&size, segClass, scope, module, segment, object); if(6 == scanRes) { SegmentClass segmentClass = DATA; symbol = strrchr(theLine, '\t') + 1; if(0 == strcmp(segClass, "CODE")) { segmentClass = CODE; } else if(0 == strcmp(segClass, "DATA")) { segmentClass = DATA; } else { retval = __LINE__; ERROR_REPORT(retval, segClass, "Unable to determine segment class."); } if(0 == retval) { unsigned moduleIndex = 0; /* ** Find, in succession, the following things: ** the module ** the segment ** the object ** the symbol ** Failure to find any one of these means to create it. */ for(moduleIndex = 0; moduleIndex < moduleCount; moduleIndex++) { if(0 == strcmp(modules[moduleIndex].mModule, module)) { break; } } if(moduleIndex == moduleCount) { void* moved = NULL; moved = realloc(modules, sizeof(ModuleStats) * (1 + moduleCount)); if(NULL != moved) { modules = (ModuleStats*)moved; moduleCount++; memset(modules + moduleIndex, 0, sizeof(ModuleStats)); modules[moduleIndex].mModule = strdup(module); if(NULL == modules[moduleIndex].mModule) { retval = __LINE__; ERROR_REPORT(retval, module, "Unable to duplicate string."); } } else { retval = __LINE__; ERROR_REPORT(retval, inOptions->mProgramName, "Unable to increase module array."); } } if(0 == retval) { unsigned segmentIndex = 0; theModule = (modules + moduleIndex); for(segmentIndex = 0; segmentIndex < theModule->mSegmentCount; segmentIndex++) { if(0 == strcmp(segment, theModule->mSegments[segmentIndex].mSegment)) { break; } } if(segmentIndex == theModule->mSegmentCount) { void* moved = NULL; moved = realloc(theModule->mSegments, sizeof(SegmentStats) * (theModule->mSegmentCount + 1)); if(NULL != moved) { theModule->mSegments = (SegmentStats*)moved; theModule->mSegmentCount++; memset(theModule->mSegments + segmentIndex, 0, sizeof(SegmentStats)); theModule->mSegments[segmentIndex].mClass = segmentClass; theModule->mSegments[segmentIndex].mSegment = strdup(segment); if(NULL == theModule->mSegments[segmentIndex].mSegment) { retval = __LINE__; ERROR_REPORT(retval, segment, "Unable to duplicate string."); } } else { retval = __LINE__; ERROR_REPORT(retval, inOptions->mProgramName, "Unable to increase segment array."); } } if(0 == retval) { unsigned objectIndex = 0; theSegment = (theModule->mSegments + segmentIndex); for(objectIndex = 0; objectIndex < theSegment->mObjectCount; objectIndex++) { if(0 == strcmp(object, theSegment->mObjects[objectIndex].mObject)) { break; } } if(objectIndex == theSegment->mObjectCount) { void* moved = NULL; moved = realloc(theSegment->mObjects, sizeof(ObjectStats) * (1 + theSegment->mObjectCount)); if(NULL != moved) { theSegment->mObjects = (ObjectStats*)moved; theSegment->mObjectCount++; memset(theSegment->mObjects + objectIndex, 0, sizeof(ObjectStats)); theSegment->mObjects[objectIndex].mObject = strdup(object); if(NULL == theSegment->mObjects[objectIndex].mObject) { retval = __LINE__; ERROR_REPORT(retval, object, "Unable to duplicate string."); } } else { retval = __LINE__; ERROR_REPORT(retval, inOptions->mProgramName, "Unable to increase object array."); } } if(0 == retval) { unsigned symbolIndex = 0; theObject = (theSegment->mObjects + objectIndex); for(symbolIndex = 0; symbolIndex < theObject->mSymbolCount; symbolIndex++) { if(0 == strcmp(symbol, theObject->mSymbols[symbolIndex].mSymbol)) { break; } } if(symbolIndex == theObject->mSymbolCount) { void* moved = NULL; moved = realloc(theObject->mSymbols, sizeof(SymbolStats) * (1 + theObject->mSymbolCount)); if(NULL != moved) { theObject->mSymbols = (SymbolStats*)moved; theObject->mSymbolCount++; allSymbolCount++; memset(theObject->mSymbols + symbolIndex, 0, sizeof(SymbolStats)); theObject->mSymbols[symbolIndex].mSymbol = strdup(symbol); if(NULL == theObject->mSymbols[symbolIndex].mSymbol) { retval = __LINE__; ERROR_REPORT(retval, symbol, "Unable to duplicate string."); } } else { retval = __LINE__; ERROR_REPORT(retval, inOptions->mProgramName, "Unable to increase symbol array."); } } if(0 == retval) { theSymbol = (theObject->mSymbols + symbolIndex); /* ** Update our various totals. */ if(additive) { if(CODE == segmentClass) { overall.mCode += size; theModule->mSize.mCode += size; } else if(DATA == segmentClass) { overall.mData += size; theModule->mSize.mData += size; } theSegment->mSize += size; theObject->mSize += size; theSymbol->mSize += size; } else { if(CODE == segmentClass) { overall.mCode -= size; theModule->mSize.mCode -= size; } else if(DATA == segmentClass) { overall.mData -= size; theModule->mSize.mData -= size; } theSegment->mSize -= size; theObject->mSize -= size; theSymbol->mSize -= size; } } } } } } } else { retval = __LINE__; ERROR_REPORT(retval, inOptions->mInputName, "Unable to scan line data."); } } } if(0 == retval && 0 != ferror(inOptions->mInput)) { retval = __LINE__; ERROR_REPORT(retval, inOptions->mInputName, "Unable to read file."); } /* ** Next, it is time to perform revisionist history of sorts. ** If the negation switch is in play, we perfrom the following ** aggressive steps: ** ** For each section, find size changes which have an equal and ** opposite change, and set them both to zero. ** However, you can only do this if the number of negating changes ** is even, as if it is odd, then any one of the many could be ** at fault for the actual change. ** ** This originally exists to make the win32 codesighs reports more ** readable/meaningful. */ if(0 == retval && 0 != inOptions->mNegation) { ObjectStats** objArray = NULL; SymbolStats** symArray = NULL; /* ** Create arrays big enough to hold all symbols. ** As well as an array to keep the owning object at the same index. ** We will keep the object around as we may need to modify the size. */ objArray = (ObjectStats**)malloc(allSymbolCount * sizeof(ObjectStats*)); symArray = (SymbolStats**)malloc(allSymbolCount * sizeof(SymbolStats*)); if(NULL == objArray || NULL == symArray) { retval = __LINE__; ERROR_REPORT(retval, inOptions->mProgramName, "Unable to allocate negation array memory."); } else { unsigned arrayCount = 0; unsigned arrayLoop = 0; /* ** Go through and perform the steps on each section/segment. */ for(moduleLoop = 0; moduleLoop < moduleCount; moduleLoop++) { theModule = modules + moduleLoop; for(segmentLoop = 0; segmentLoop < theModule->mSegmentCount; segmentLoop++) { theSegment = theModule->mSegments + segmentLoop; /* ** Collect all symbols under this section. ** The symbols are spread out between all the objects, ** so keep track of both independently at the ** same index. */ arrayCount = 0; for(objectLoop = 0; objectLoop < theSegment->mObjectCount; objectLoop++) { theObject = theSegment->mObjects + objectLoop; for(symbolLoop = 0; symbolLoop < theObject->mSymbolCount; symbolLoop++) { theSymbol = theObject->mSymbols + symbolLoop; objArray[arrayCount] = theObject; symArray[arrayCount] = theSymbol; arrayCount++; } } /* ** Now that we have a list of symbols, go through each ** and see if there is a chance of negation. */ for(arrayLoop = 0; arrayLoop < arrayCount; arrayLoop++) { /* ** If the item is NULL, it was already negated. ** Don't do this for items with a zero size. */ if(NULL != symArray[arrayLoop] && 0 != symArray[arrayLoop]->mSize) { unsigned identicalValues = 0; unsigned oppositeValues = 0; unsigned lookLoop = 0; const int lookingFor = symArray[arrayLoop]->mSize; /* ** Count the number of items with this value. ** Count the number of items with the opposite equal value. ** If they are equal, go through and negate all sizes. */ for(lookLoop = arrayLoop; lookLoop < arrayCount; lookLoop++) { /* ** Skip negated items. ** Skip zero length items. */ if(NULL == symArray[lookLoop] || 0 == symArray[lookLoop]->mSize) { continue; } if(lookingFor == symArray[lookLoop]->mSize) { identicalValues++; } else if((-1 * lookingFor) == symArray[lookLoop]->mSize) { oppositeValues++; } } if(0 != identicalValues && identicalValues == oppositeValues) { unsigned negationLoop = 0; for(negationLoop = arrayLoop; 0 != identicalValues || 0 != oppositeValues; negationLoop++) { /* ** Skip negated items. ** Skip zero length items. */ if(NULL == symArray[negationLoop] || 0 == symArray[negationLoop]->mSize) { continue; } /* ** Negate any size matches. ** Reflect the change in the object as well. ** Clear the symbol. */ if(lookingFor == symArray[negationLoop]->mSize) { objArray[negationLoop]->mSize -= lookingFor; symArray[negationLoop]->mSize = 0; symArray[negationLoop] = NULL; identicalValues--; } else if((-1 * lookingFor) == symArray[negationLoop]->mSize) { objArray[negationLoop]->mSize += lookingFor; symArray[negationLoop]->mSize = 0; symArray[negationLoop] = NULL; oppositeValues--; } } } } } } } } CLEANUP(objArray); CLEANUP(symArray); } /* ** If all went well, time to report. */ if(0 == retval) { /* ** Loop through our data once more, so that the symbols can ** propigate their changes upwards in a positive/negative ** fashion. ** This will help give the composite change more meaning. */ for(moduleLoop = 0; moduleLoop < moduleCount; moduleLoop++) { theModule = modules + moduleLoop; /* ** Skip if there is zero drift, or no net change. */ if(0 == inOptions->mZeroDrift && 0 == (theModule->mSize.mCode + theModule->mSize.mData)) { continue; } for(segmentLoop = 0; segmentLoop < theModule->mSegmentCount; segmentLoop++) { theSegment = theModule->mSegments + segmentLoop; /* ** Skip if there is zero drift, or no net change. */ if(0 == inOptions->mZeroDrift && 0 == theSegment->mSize) { continue; } for(objectLoop = 0; objectLoop < theSegment->mObjectCount; objectLoop++) { theObject = theSegment->mObjects + objectLoop; /* ** Skip if there is zero drift, or no net change. */ if(0 == inOptions->mZeroDrift && 0 == theObject->mSize) { continue; } for(symbolLoop = 0; symbolLoop < theObject->mSymbolCount; symbolLoop++) { theSymbol = theObject->mSymbols + symbolLoop; /* ** Propagate the composition all the way to the top. ** Sizes of zero change are skipped. */ if(0 < theSymbol->mSize) { theObject->mComposition.mPositive += theSymbol->mSize; theSegment->mComposition.mPositive += theSymbol->mSize; if(CODE == theSegment->mClass) { overall.mCodeComposition.mPositive += theSymbol->mSize; theModule->mSize.mCodeComposition.mPositive += theSymbol->mSize; } else if(DATA == theSegment->mClass) { overall.mDataComposition.mPositive += theSymbol->mSize; theModule->mSize.mDataComposition.mPositive += theSymbol->mSize; } } else if(0 > theSymbol->mSize) { theObject->mComposition.mNegative += theSymbol->mSize; theSegment->mComposition.mNegative += theSymbol->mSize; if(CODE == theSegment->mClass) { overall.mCodeComposition.mNegative += theSymbol->mSize; theModule->mSize.mCodeComposition.mNegative += theSymbol->mSize; } else if(DATA == theSegment->mClass) { overall.mDataComposition.mNegative += theSymbol->mSize; theModule->mSize.mDataComposition.mNegative += theSymbol->mSize; } } } } } } if(inOptions->mSummaryOnly) { fprintf(inOptions->mOutput, "%+d (%+d/%+d)\n", overall.mCode + overall.mData, overall.mCodeComposition.mPositive + overall.mDataComposition.mPositive, overall.mCodeComposition.mNegative + overall.mDataComposition.mNegative); } else { fprintf(inOptions->mOutput, "Overall Change in Size\n"); fprintf(inOptions->mOutput, "\tTotal:\t%+11d (%+d/%+d)\n", overall.mCode + overall.mData, overall.mCodeComposition.mPositive + overall.mDataComposition.mPositive, overall.mCodeComposition.mNegative + overall.mDataComposition.mNegative); fprintf(inOptions->mOutput, "\tCode:\t%+11d (%+d/%+d)\n", overall.mCode, overall.mCodeComposition.mPositive, overall.mCodeComposition.mNegative); fprintf(inOptions->mOutput, "\tData:\t%+11d (%+d/%+d)\n", overall.mData, overall.mDataComposition.mPositive, overall.mDataComposition.mNegative); } /* ** Check what else we should output. */ if(0 == inOptions->mSummaryOnly && NULL != modules && moduleCount) { const char* segmentType = NULL; /* ** We're going to sort everything. */ qsort(modules, moduleCount, sizeof(ModuleStats), moduleCompare); for(moduleLoop = 0; moduleLoop < moduleCount; moduleLoop++) { theModule = modules + moduleLoop; qsort(theModule->mSegments, theModule->mSegmentCount, sizeof(SegmentStats), segmentCompare); for(segmentLoop = 0; segmentLoop < theModule->mSegmentCount; segmentLoop++) { theSegment = theModule->mSegments + segmentLoop; qsort(theSegment->mObjects, theSegment->mObjectCount, sizeof(ObjectStats), objectCompare); for(objectLoop = 0; objectLoop < theSegment->mObjectCount; objectLoop++) { theObject = theSegment->mObjects + objectLoop; qsort(theObject->mSymbols, theObject->mSymbolCount, sizeof(SymbolStats), symbolCompare); } } } /* ** Loop through for output. */ for(moduleLoop = 0; moduleLoop < moduleCount; moduleLoop++) { theModule = modules + moduleLoop; /* ** Skip if there is zero drift, or no net change. */ if(0 == inOptions->mZeroDrift && 0 == (theModule->mSize.mCode + theModule->mSize.mData)) { continue; } fprintf(inOptions->mOutput, "\n"); fprintf(inOptions->mOutput, "%s\n", theModule->mModule); fprintf(inOptions->mOutput, "\tTotal:\t%+11d (%+d/%+d)\n", theModule->mSize.mCode + theModule->mSize.mData, theModule->mSize.mCodeComposition.mPositive + theModule->mSize.mDataComposition.mPositive, theModule->mSize.mCodeComposition.mNegative + theModule->mSize.mDataComposition.mNegative); fprintf(inOptions->mOutput, "\tCode:\t%+11d (%+d/%+d)\n", theModule->mSize.mCode, theModule->mSize.mCodeComposition.mPositive, theModule->mSize.mCodeComposition.mNegative); fprintf(inOptions->mOutput, "\tData:\t%+11d (%+d/%+d)\n", theModule->mSize.mData, theModule->mSize.mDataComposition.mPositive, theModule->mSize.mDataComposition.mNegative); for(segmentLoop = 0; segmentLoop < theModule->mSegmentCount; segmentLoop++) { theSegment = theModule->mSegments + segmentLoop; /* ** Skip if there is zero drift, or no net change. */ if(0 == inOptions->mZeroDrift && 0 == theSegment->mSize) { continue; } if(CODE == theSegment->mClass) { segmentType = "CODE"; } else if(DATA == theSegment->mClass) { segmentType = "DATA"; } fprintf(inOptions->mOutput, "\t%+11d (%+d/%+d)\t%s (%s)\n", theSegment->mSize, theSegment->mComposition.mPositive, theSegment->mComposition.mNegative, theSegment->mSegment, segmentType); for(objectLoop = 0; objectLoop < theSegment->mObjectCount; objectLoop++) { theObject = theSegment->mObjects + objectLoop; /* ** Skip if there is zero drift, or no net change. */ if(0 == inOptions->mZeroDrift && 0 == theObject->mSize) { continue; } fprintf(inOptions->mOutput, "\t\t%+11d (%+d/%+d)\t%s\n", theObject->mSize, theObject->mComposition.mPositive, theObject->mComposition.mNegative, theObject->mObject); for(symbolLoop = 0; symbolLoop < theObject->mSymbolCount; symbolLoop++) { theSymbol = theObject->mSymbols + symbolLoop; /* ** Skip if there is zero drift, or no net change. */ if(0 == inOptions->mZeroDrift && 0 == theSymbol->mSize) { continue; } fprintf(inOptions->mOutput, "\t\t\t%+11d\t%s\n", theSymbol->mSize, theSymbol->mSymbol); } } } } } } /* ** Cleanup time. */ for(moduleLoop = 0; moduleLoop < moduleCount; moduleLoop++) { theModule = modules + moduleLoop; for(segmentLoop = 0; segmentLoop < theModule->mSegmentCount; segmentLoop++) { theSegment = theModule->mSegments + segmentLoop; for(objectLoop = 0; objectLoop < theSegment->mObjectCount; objectLoop++) { theObject = theSegment->mObjects + objectLoop; for(symbolLoop = 0; symbolLoop < theObject->mSymbolCount; symbolLoop++) { theSymbol = theObject->mSymbols + symbolLoop; CLEANUP(theSymbol->mSymbol); } CLEANUP(theObject->mSymbols); CLEANUP(theObject->mObject); } CLEANUP(theSegment->mObjects); CLEANUP(theSegment->mSegment); } CLEANUP(theModule->mSegments); CLEANUP(theModule->mModule); } CLEANUP(modules); return retval; }