/*! @file Explanations.cc
* @brief Explanations Implementation
*
* This file contains the implementation of the functions
* which provide a base level of functionality of a Explanations.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <rld.h>
#include "Explanations.h"
#include "app_common.h"
namespace Coverage {
Explanations::Explanations()
{
}
Explanations::~Explanations()
{
}
void Explanations::load(
const char* const explanations
)
{
#define MAX_LINE_LENGTH 512
FILE *explain;
char *cStatus;
Explanation *e;
int line = 1;
if (!explanations)
return;
explain = ::fopen( explanations, "r" );
if (!explain) {
std::ostringstream what;
what << "Unable to open " << explanations;
throw rld::error( what, "Explanations::load" );
}
while ( 1 ) {
e = new Explanation;
// Read the starting line of this explanation and
// skip blank lines between
do {
inputBuffer[0] = '\0';
cStatus = fgets( inputBuffer, MAX_LINE_LENGTH, explain );
if (cStatus == NULL) {
goto done;
}
inputBuffer[ strlen(inputBuffer) - 1] = '\0';
line++;
} while ( inputBuffer[0] == '\0' );
// Have we already seen this one?
if (set.find( inputBuffer ) != set.end()) {
std::ostringstream what;
what << "line " << line
<< "contains a duplicate explanation ("
<< inputBuffer << ")";
throw rld::error( what, "Explanations::load" );
}
// Add the starting line and file
e->startingPoint = std::string(inputBuffer);
e->found = false;
// Get the classification
cStatus = fgets( inputBuffer, MAX_LINE_LENGTH, explain );
if (cStatus == NULL) {
std::ostringstream what;
what << "line " << line
<< "out of sync at the classification";
throw rld::error( what, "Explanations::load" );
}
inputBuffer[ strlen(inputBuffer) - 1] = '\0';
e->classification = inputBuffer;
line++;
// Get the explanation
while (1) {
cStatus = fgets( inputBuffer, MAX_LINE_LENGTH, explain );
// fprintf( stderr, "%d - %s\n", line, inputBuffer );
if (cStatus == NULL) {
std::ostringstream what;
what << "line " << line
<< "out of sync at the explanation";
throw rld::error( what, "Explanations::load" );
}
inputBuffer[ strlen(inputBuffer) - 1] = '\0';
line++;
const char delimiter[4] = "+++";
if (!strncmp( inputBuffer, delimiter, 3 )) {
break;
}
// XXX only taking last line. Needs to be a vector
e->explanation.push_back( inputBuffer );
}
// Add this to the set of Explanations
set[ e->startingPoint ] = *e;
}
done:
;
#undef MAX_LINE_LENGTH
}
const Explanation *Explanations::lookupExplanation(
std::string& start
)
{
if (set.find( start ) == set.end()) {
#if 0
std::cerr << "Warning: Unable to find explanation for "
<< start << std::endl;
#endif
return NULL;
}
set[ start ].found = true;
return &set[ start ];
}
void Explanations::writeNotFound(
const char* const fileName
)
{
FILE* notFoundFile;
bool notFoundOccurred = false;
if (!fileName)
return;
notFoundFile = fopen( fileName, "w" );
if (!fileName) {
std::ostringstream what;
what << "Unable to open " << fileName
<< "out of sync at the explanation";
throw rld::error( what, "Explanations::writeNotFound" );
}
for (std::map<std::string, Explanation>::iterator itr = set.begin();
itr != set.end();
itr++) {
Explanation e = (*itr).second;
std::string key = (*itr).first;
if (!e.found) {
notFoundOccurred = true;
fprintf(
notFoundFile,
"%s\n",
e.startingPoint.c_str()
);
}
}
fclose( notFoundFile );
if (!notFoundOccurred) {
if (!unlink( fileName )) {
std::cerr << "Warning: Unable to unlink " << fileName
<< std::endl
<< std::endl;
}
}
}
}