Logo Search packages:      
Sourcecode: cccc version File versions

cccc_opt.cc

// cccc_opt.cc
#include "cccc.h"
#include <fstream>

#include "cccc_opt.h"
#include "cccc_utl.h"
#include "cccc_met.h"

#include <map>

typedef std::map<string,string> file_extension_language_map_t;
typedef std::map<string,Metric_Treatment*> metric_treatment_map_t;
typedef std::pair<string,string> dialect_keyword_t;
typedef std::map<dialect_keyword_t,string> dialect_keyword_map_t;

static file_extension_language_map_t extension_map;
static metric_treatment_map_t treatment_map;
static dialect_keyword_map_t dialect_keyword_map;

// these are declared extern so that it can be defined later in the file
extern char *default_fileext_options[];
extern char *default_treatment_options[];
extern char *default_dialect_options[];

static void add_file_extension(CCCC_Item& fileext_line)
{
      string ext, lang;
      if(
            fileext_line.Extract(ext) &&
            fileext_line.Extract(lang)
            )
    {
            file_extension_language_map_t::value_type extension_pair(ext,lang);
            extension_map.insert(extension_pair);
    }
}

void add_treatment(CCCC_Item& treatment_line)
{
      Metric_Treatment *new_treatment=new Metric_Treatment(treatment_line);
      metric_treatment_map_t::iterator iter=
            treatment_map.find(new_treatment->code);
      
      if(iter!=treatment_map.end())
    {
            delete (*iter).second;
            (*iter).second=new_treatment;
    }
      else
    {
            metric_treatment_map_t::value_type 
                  treatment_pair(new_treatment->code,new_treatment);
            treatment_map.insert(treatment_pair);
    }
}

static void add_dialect_keyword(CCCC_Item& dialect_keyword_line)
{
      string dialect, keyword, policy;
      if(
            dialect_keyword_line.Extract(dialect) &&
            dialect_keyword_line.Extract(keyword) &&
            dialect_keyword_line.Extract(policy) 
            )
    {
            dialect_keyword_map_t::key_type kt(dialect,keyword);
            dialect_keyword_map_t::value_type vt(kt,policy);
            dialect_keyword_map.insert(vt);
    }
}

void CCCC_Options::Add_Option(CCCC_Item& option)
{
      string first_token;
      bool retval=option.Extract(first_token);
      
      if(retval==false)
    {
            // do nothing
    }
      else if(first_token=="CCCC_FileExt")
    {
            add_file_extension(option);
    }
      else if(first_token=="CCCC_MetTmnt")
    {
            add_treatment(option);
    }
      else if(first_token=="CCCC_Dialect")
    {
            add_dialect_keyword(option);
    }
      else
    {
            retval=false;
    }
}


void CCCC_Options::Save_Options(const string& filename)
{
      ofstream optstr(filename.c_str());
      file_extension_language_map_t::iterator felIter;
      for(felIter=extension_map.begin();
      felIter!=extension_map.end();
      ++felIter)
    {
            CCCC_Item extLine;
            extLine.Insert("CCCC_FileExt");
            extLine.Insert((*felIter).first.c_str());
            extLine.Insert((*felIter).second.c_str());
            extLine.ToFile(optstr);
    }
      
      metric_treatment_map_t::iterator tIter;
      for(tIter=treatment_map.begin();
      tIter!=treatment_map.end();
      ++tIter)
    {
            CCCC_Item tmtLine;
            tmtLine.Insert("CCCC_MetTmnt");
            tmtLine.Insert((*tIter).second->code); 
            tmtLine.Insert((*tIter).second->lower_threshold);
            tmtLine.Insert((*tIter).second->upper_threshold);
            tmtLine.Insert((*tIter).second->numerator_threshold);
            tmtLine.Insert((*tIter).second->width);     
            tmtLine.Insert((*tIter).second->precision);
            tmtLine.Insert((*tIter).second->name);
            tmtLine.ToFile(optstr);
    }
      
      dialect_keyword_map_t::iterator dkIter;
      for(dkIter=dialect_keyword_map.begin();
      dkIter!=dialect_keyword_map.end();
      ++dkIter)
    {
            CCCC_Item dkLine;
            dkLine.Insert("CCCC_Dialect");
            dkLine.Insert((*dkIter).first.first);
            dkLine.Insert((*dkIter).first.second);
            dkLine.Insert((*dkIter).second);
            dkLine.ToFile(optstr);
    }
}

void CCCC_Options::Load_Options(const string& filename)
{
      ifstream optstr(filename.c_str());
      
      while(optstr.good())
    {
            CCCC_Item option_line;
            if(optstr.good() &&
                  option_line.FromFile(optstr)
                  )
            {
                  Add_Option(option_line);
            }
    }
      
}

// initialise using hard-coded defaults
void CCCC_Options::Load_Options()
{  
      int i=0;
      
      char **option_ptr;
      
      option_ptr=default_fileext_options;
      while( (*option_ptr)!=NULL)
    {
            string option_string="CCCC_FileExt@";
            option_string+=(*option_ptr);
            CCCC_Item option_line(option_string);
            Add_Option(option_line);
            option_ptr++;
    }
      
      option_ptr=default_treatment_options;
      while( (*option_ptr)!=NULL)
    {
            string option_string="CCCC_MetTmnt@";
            option_string+=(*option_ptr);
            CCCC_Item option_line(option_string);
            Add_Option(option_line);
            option_ptr++;
    }
      
      option_ptr=default_dialect_options;
      while( (*option_ptr)!=NULL)
    {
            string option_string="CCCC_Dialect@";
            option_string+=(*option_ptr);
            CCCC_Item option_line(option_string);
            Add_Option(option_line);
            option_ptr++;
    }
}

// map a filename to a language
string CCCC_Options::getFileLanguage(const string& filename)
{
      string retval;
      string extension;
      file_extension_language_map_t::iterator iter;
      
      unsigned int extpos=filename.rfind(".");
      if(extpos!=string::npos)
    {
            extension=filename.substr(extpos);
            iter=extension_map.find(extension);
            if(iter!=extension_map.end())
            {
                  retval=(*iter).second;
            }
    }
      if(retval.size()==0)
    {
            iter=extension_map.find("");
            if(iter!=extension_map.end())
            {
                  retval=(*iter).second;
            }
            else
            {
                  // could not find language for extension
                  cerr << "No language found for extension " << extension.c_str() << endl;
            }
    }
      return retval;
}

// map a metric name to a Metric_Treatment object
Metric_Treatment *CCCC_Options::getMetricTreatment(const string& metric_tag)
{
      Metric_Treatment *retval=NULL;
      metric_treatment_map_t::iterator iter=treatment_map.find(metric_tag);
      if(iter!=treatment_map.end())
    {
            retval=(*iter).second;
    }
      return retval;
}

string CCCC_Options::dialectKeywordPolicy(const string& lang, const string& kw)
{
      string retval;
      dialect_keyword_map_t::key_type kt(lang,kw);
      dialect_keyword_map_t::const_iterator iter=dialect_keyword_map.find(kt);
      if(iter!=dialect_keyword_map.end())
    {
            retval=(*iter).second;
    }
      return retval;
}


char *default_fileext_options[]=
{
      // file extensions
      ".c@c.ansi@",
            
            ".h@c++.ansi@",
            ".cc@c++.ansi@",
            ".cpp@c++.ansi@",
            ".cxx@c++.ansi@",
            ".c++@c++.ansi@",
            ".C@c++.ansi@",
            ".CC@c++.ansi@",
            ".CPP@c++.ansi@",
            ".CXX@c++.ansi@",
            ".hh@c++.ansi@",
            ".hpp@c++.ansi@",
            ".hxx@c++.ansi@",
            ".h++@c++.ansi@",
            ".H@c++.ansi@",
            ".HH@c++.ansi@",
            ".HPP@c++.ansi@",
            ".HXX@c++.ansi@",
            ".H++@c++.ansi@",
            
            ".j@java@",
            ".jav@java@",
            ".java@java@",
            ".J@java@",
            ".JAV@java@",
            ".JAVA@java@",
            
            ".ada@ada.95@",
            ".ads@ada.95@",
            ".adb@ada.95@",
            
            ".ADA@ada.95@",
            ".ADS@ada.95@",
            ".ADB@ada.95@",
            
            // The language associated with the empty file extension would be used as a default
            // if defined.
            // This is presently disabled so that we don't process files in 
            // MSVC projects like .rc, .odl which are not in C++.
            // "@c++.ansi@",
            
            NULL
};

char *default_treatment_options[] = 
{
      // metric treatments
      // all metric values are displayed using the class CCCC_Metric, which may be
      // viewed as ratio of two integers associated with a character string tag
      // the denominator of the ratio defaults to 1, allowing simple counts to
      // be handled by the same code as is used for ratios
      //
      // the tag associated with a metric is used as a key to lookup a record
      // describing a policy for its display (class Metric_Treatment)
      //
      // the fields of each treatment record are as follows:
      // TAG     the short string of characters used as the lookup key. 
      // T1, T2  two numeric thresholds which are the lower bounds for the ratio of
      // the metric's numerator and denominator beyond which the 
      //  value is treated as high or extreme by the analyser
      //  these will be displayed in emphasized fonts, and if the browser
      //  supports the BGCOLOR attribute, extreme values will have a red
      //  background, while high values will have a yellow background.
      //  The intent is that high values should be treated as suspicious but
      //  tolerable in moderation, whereas extreme values should almost 
      //  always be regarded as defects (not necessarily that you will fix 
      //  them).
      // NT  a third threshold which supresses calculation of ratios where
      //     the numerator is lower than NT.
      //     The principal reason for doing this is to prevent ratios like L_C
      //  being shown as *** (infinity) and displayed as extreme when the 
      //  denominator is 0, providing the numerator is sufficiently low.
      //  Suitable values are probably similar to those for T1.
      // W       the width of the metric (total number of digits).
      // P       the precision of the metric (digits after the decimal point).
      // Comment a free form field extending to the end of the line.
      
      // TAG      T1      T2   NT  W  P Comment
      "LOCf@      30@    100@   0@ 6@ 0@Lines of code/function@",
      "LOCm@     500@   2000@   0@ 6@ 0@Lines of code/single module@", 
      "LOCper@   500@   2000@   0@ 6@ 3@Lines of code/average module@", 
      "LOCp@  999999@ 999999@   0@ 6@ 0@Lines of code/project@", 
      "MVGf@      10@     30@   0@ 6@ 0@Cyclomatic complexity/function@",
      "MVGm@     200@   1000@   0@ 6@ 0@Cyclomatic complexity/single module@",
      "MVGper@   200@   1000@   0@ 6@ 3@Cyclomatic complexity/average module@",
      "MVGp@  999999@ 999999@   0@ 6@ 0@Cyclomatic complexity/project@",
      "COM@   999999@ 999999@   0@ 6@ 0@Comment lines@",
      "COMper@999999@ 999999@   0@ 6@ 3@Comment lines (averaged)@",
      "M_C@        5@     10@   5@ 6@ 3@MVG/COM McCabe/comment line@",
      "L_C@        7@     30@  20@ 6@ 3@LOC/COM Lines of code/comment line@",
      "FI@        12@     20@   0@ 6@ 0@Fan in (overall)@",
      "FIv@        6@     12@   0@ 6@ 0@Fan in (visible uses only)@",
      "FIc@        6@     12@   0@ 6@ 0@Fan in (concrete uses only)@",
      "FO@        12@     20@   0@ 6@ 0@Fan out (overall)@",
      "FOv@        6@     12@   0@ 6@ 0@Fan out (visible uses only)@",
      "FOc@        6@     12@   0@ 6@ 0@Fan out (concrete uses only)@",
      "IF4@      100@   1000@   0@ 6@ 0@Henry-Kafura/Shepperd measure (overall)@",
      "IF4v@      30@    100@   0@ 6@ 0@Henry-Kafura/Shepperd measure (visible)@",
      "IF4c@      30@    100@   0@ 6@ 0@Henry-Kafura/Shepperd measure (concrete)@",
       // WMC stands for weighted methods per class, 
       // the suffix distinguishes the weighting function
       "WMC1@      30@    100@   0@ 6@ 0@Weighting function=1 unit per method@",
       "WMCv@      10@     30@   0@ 6@ 0@Weighting function=1 unit per visible method@",
       "DIT@             3@      6@   0@ 6@ 0@Depth of Inheritance Tree@",
       "NOC@             4@     15@   0@ 6@ 0@Number of children@",
       "CBO@            12@     30@   0@ 6@ 0@Coupling between objects@",
       "8.3@    999999@ 999999@   0@ 8@ 3@General format for fixed precision 3 d.p.@",
       NULL
};

char *default_dialect_options[] = 
{
      // This configuration item allows the description of 
      // dialects in which C/C++ identifiers get treated
      // as supplementary keyword.  The rules specified
      // here (or in the runtime option file, if specified)
      // allow the parser to make the call 
      // CCCC_Options::dialect_keyword_policy(lang,kw) which
      // returns a string.  If nothing is known about the 
      // pair <lang,kw>, an empty string is returned.  If
      // an entry is specified here the associated string is 
      // returned, which is called the policy, which the
      // parser uses to guide its actions.  The most common
      // policy is to ignore, but any string can be 
      // specified, providing the person implementing
      // the parser can think of an intelligent way to 
      // proceed.
      "c++.mfc@BEGIN_MESSAGE_MAP@start_skipping@",
            "c++.mfc@END_MESSAGE_MAP@stop_skipping@",
            "c++.stl@__STL_BEGIN_NAMESPACE@ignore@",
            "c++.stl@__STL_END_NAMESPACE@ignore@",
            NULL
};












Generated by  Doxygen 1.6.0   Back to index