CCCC - C and C++ Code Counter  9999-git
CCCC Development version (post-3.1.4)
cccc_opt.cc
Go to the documentation of this file.
1 /*
2  CCCC - C and C++ Code Counter
3  Copyright (C) 1994-2005 Tim Littlefair (tim_littlefair@hotmail.com)
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19 // cccc_opt.cc
20 #include "cccc.h"
21 #include <fstream>
22 
23 #include "cccc_opt.h"
24 #include "cccc_utl.h"
25 #include "cccc_met.h"
26 
27 #include <map>
28 
29 typedef std::map<string,string> file_extension_language_map_t;
30 typedef std::map<string,Metric_Treatment*> metric_treatment_map_t;
31 typedef std::pair<string,string> dialect_keyword_t;
32 typedef std::map<dialect_keyword_t,string> dialect_keyword_map_t;
33 
37 
38 // these are declared extern so that it can be defined later in the file
39 extern const char *default_fileext_options[];
40 extern const char *default_treatment_options[];
41 extern const char *default_dialect_options[];
42 
43 static void add_file_extension(CCCC_Item& fileext_line)
44 {
45  string ext, lang;
46  if(
47  fileext_line.Extract(ext) &&
48  fileext_line.Extract(lang)
49  )
50  {
51  file_extension_language_map_t::value_type extension_pair(ext,lang);
52  extension_map.insert(extension_pair);
53  }
54 }
55 
56 void add_treatment(CCCC_Item& treatment_line)
57 {
58  Metric_Treatment *new_treatment=new Metric_Treatment(treatment_line);
59  metric_treatment_map_t::iterator iter=
60  treatment_map.find(new_treatment->code);
61 
62  if(iter!=treatment_map.end())
63  {
64  delete (*iter).second;
65  (*iter).second=new_treatment;
66  }
67  else
68  {
69  metric_treatment_map_t::value_type
70  treatment_pair(new_treatment->code,new_treatment);
71  treatment_map.insert(treatment_pair);
72  }
73 }
74 
75 static void add_dialect_keyword(CCCC_Item& dialect_keyword_line)
76 {
77  string dialect, keyword, policy;
78  if(
79  dialect_keyword_line.Extract(dialect) &&
80  dialect_keyword_line.Extract(keyword) &&
81  dialect_keyword_line.Extract(policy)
82  )
83  {
84  dialect_keyword_map_t::key_type kt(dialect,keyword);
85  dialect_keyword_map_t::value_type vt(kt,policy);
86  dialect_keyword_map.insert(vt);
87  }
88 }
89 
91 {
92  string first_token;
93  bool retval=option.Extract(first_token);
94 
95  if(retval==false)
96  {
97  // do nothing
98  }
99  else if(first_token=="CCCC_FileExt")
100  {
101  add_file_extension(option);
102  }
103  else if(first_token=="CCCC_MetTmnt")
104  {
105  add_treatment(option);
106  }
107  else if(first_token=="CCCC_Dialect")
108  {
109  add_dialect_keyword(option);
110  }
111  else
112  {
113  retval=false;
114  }
115 }
116 
117 
118 void CCCC_Options::Save_Options(const string& filename)
119 {
120  ofstream optstr(filename.c_str());
121  file_extension_language_map_t::iterator felIter;
122  for(felIter=extension_map.begin();
123  felIter!=extension_map.end();
124  ++felIter)
125  {
126  CCCC_Item extLine;
127  extLine.Insert("CCCC_FileExt");
128  extLine.Insert((*felIter).first.c_str());
129  extLine.Insert((*felIter).second.c_str());
130  extLine.ToFile(optstr);
131  }
132 
133  metric_treatment_map_t::iterator tIter;
134  for(tIter=treatment_map.begin();
135  tIter!=treatment_map.end();
136  ++tIter)
137  {
138  CCCC_Item tmtLine;
139  tmtLine.Insert("CCCC_MetTmnt");
140  tmtLine.Insert((*tIter).second->code);
141  tmtLine.Insert((*tIter).second->lower_threshold);
142  tmtLine.Insert((*tIter).second->upper_threshold);
143  tmtLine.Insert((*tIter).second->numerator_threshold);
144  tmtLine.Insert((*tIter).second->width);
145  tmtLine.Insert((*tIter).second->precision);
146  tmtLine.Insert((*tIter).second->name);
147  tmtLine.ToFile(optstr);
148  }
149 
150  dialect_keyword_map_t::iterator dkIter;
151  for(dkIter=dialect_keyword_map.begin();
152  dkIter!=dialect_keyword_map.end();
153  ++dkIter)
154  {
155  CCCC_Item dkLine;
156  dkLine.Insert("CCCC_Dialect");
157  dkLine.Insert((*dkIter).first.first);
158  dkLine.Insert((*dkIter).first.second);
159  dkLine.Insert((*dkIter).second);
160  dkLine.ToFile(optstr);
161  }
162 }
163 
164 void CCCC_Options::Load_Options(const string& filename)
165 {
166  ifstream optstr(filename.c_str());
167 
168  while(optstr.good())
169  {
170  CCCC_Item option_line;
171  if(optstr.good() &&
172  option_line.FromFile(optstr)
173  )
174  {
175  Add_Option(option_line);
176  }
177  }
178 
179 }
180 
181 // initialise using hard-coded defaults
183 {
184  int i=0;
185 
186  const char **option_ptr;
187 
188  option_ptr=default_fileext_options;
189  while( (*option_ptr)!=NULL)
190  {
191  string option_string="CCCC_FileExt@";
192  option_string+=(*option_ptr);
193  CCCC_Item option_line(option_string);
194  Add_Option(option_line);
195  option_ptr++;
196  }
197 
198  option_ptr=default_treatment_options;
199  while( (*option_ptr)!=NULL)
200  {
201  string option_string="CCCC_MetTmnt@";
202  option_string+=(*option_ptr);
203  CCCC_Item option_line(option_string);
204  Add_Option(option_line);
205  option_ptr++;
206  }
207 
208  option_ptr=default_dialect_options;
209  while( (*option_ptr)!=NULL)
210  {
211  string option_string="CCCC_Dialect@";
212  option_string+=(*option_ptr);
213  CCCC_Item option_line(option_string);
214  Add_Option(option_line);
215  option_ptr++;
216  }
217 }
218 
219 // map a filename to a language
220 string CCCC_Options::getFileLanguage(const string& filename)
221 {
222  string retval;
223  string extension;
224  file_extension_language_map_t::iterator iter;
225 
226  unsigned int extpos=filename.rfind(".");
227  if(extpos!=string::npos)
228  {
229  extension=filename.substr(extpos);
230  iter=extension_map.find(extension);
231  if(iter!=extension_map.end())
232  {
233  retval=(*iter).second;
234  }
235  }
236  if(retval.size()==0)
237  {
238  iter=extension_map.find("");
239  if(iter!=extension_map.end())
240  {
241  retval=(*iter).second;
242  }
243  else
244  {
245  // could not find language for extension
246  cerr << "No language found for extension " << extension.c_str() << endl;
247  }
248  }
249  return retval;
250 }
251 
252 // map a metric name to a Metric_Treatment object
254 {
255  Metric_Treatment *retval=NULL;
256  metric_treatment_map_t::iterator iter=treatment_map.find(metric_tag);
257  if(iter!=treatment_map.end())
258  {
259  retval=(*iter).second;
260  }
261  return retval;
262 }
263 
264 string CCCC_Options::dialectKeywordPolicy(const string& lang, const string& kw)
265 {
266  string retval;
267  dialect_keyword_map_t::key_type kt(lang,kw);
268  dialect_keyword_map_t::const_iterator iter=dialect_keyword_map.find(kt);
269  if(iter!=dialect_keyword_map.end())
270  {
271  retval=(*iter).second;
272  }
273  return retval;
274 }
275 
276 
278 {
279  // file extensions
280  ".c@c.ansi@",
281 
282  ".h@c++.ansi@",
283  ".cc@c++.ansi@",
284  ".cpp@c++.ansi@",
285  ".cxx@c++.ansi@",
286  ".c++@c++.ansi@",
287  ".C@c++.ansi@",
288  ".CC@c++.ansi@",
289  ".CPP@c++.ansi@",
290  ".CXX@c++.ansi@",
291  ".hh@c++.ansi@",
292  ".hpp@c++.ansi@",
293  ".hxx@c++.ansi@",
294  ".h++@c++.ansi@",
295  ".H@c++.ansi@",
296  ".HH@c++.ansi@",
297  ".HPP@c++.ansi@",
298  ".HXX@c++.ansi@",
299  ".H++@c++.ansi@",
300 
301  ".j@java@",
302  ".jav@java@",
303  ".java@java@",
304  ".J@java@",
305  ".JAV@java@",
306  ".JAVA@java@",
307 
308  ".ada@ada.95@",
309  ".ads@ada.95@",
310  ".adb@ada.95@",
311 
312  ".ADA@ada.95@",
313  ".ADS@ada.95@",
314  ".ADB@ada.95@",
315 
316  // The language associated with the empty file extension would be used as a default
317  // if defined.
318  // This is presently disabled so that we don't process files in
319  // MSVC projects like .rc, .odl which are not in C++.
320  // "@c++.ansi@",
321 
322  NULL
323 };
324 
326 {
327  // metric treatments
328  // all metric values are displayed using the class CCCC_Metric, which may be
329  // viewed as ratio of two integers associated with a character string tag
330  // the denominator of the ratio defaults to 1, allowing simple counts to
331  // be handled by the same code as is used for ratios
332  //
333  // the tag associated with a metric is used as a key to lookup a record
334  // describing a policy for its display (class Metric_Treatment)
335  //
336  // the fields of each treatment record are as follows:
337  // TAG the short string of characters used as the lookup key.
338  // T1, T2 two numeric thresholds which are the lower bounds for the ratio of
339  // the metric's numerator and denominator beyond which the
340  // value is treated as high or extreme by the analyser
341  // these will be displayed in emphasized fonts, and if the browser
342  // supports the BGCOLOR attribute, extreme values will have a red
343  // background, while high values will have a yellow background.
344  // The intent is that high values should be treated as suspicious but
345  // tolerable in moderation, whereas extreme values should almost
346  // always be regarded as defects (not necessarily that you will fix
347  // them).
348  // NT a third threshold which supresses calculation of ratios where
349  // the numerator is lower than NT.
350  // The principal reason for doing this is to prevent ratios like L_C
351  // being shown as *** (infinity) and displayed as extreme when the
352  // denominator is 0, providing the numerator is sufficiently low.
353  // Suitable values are probably similar to those for T1.
354  // W the width of the metric (total number of digits).
355  // P the precision of the metric (digits after the decimal point).
356  // Comment a free form field extending to the end of the line.
357 
358  // TAG T1 T2 NT W P Comment
359  "LOCf@ 30@ 100@ 0@ 6@ 0@Lines of code/function@",
360  "LOCm@ 500@ 2000@ 0@ 6@ 0@Lines of code/single module@",
361  "LOCper@ 500@ 2000@ 0@ 6@ 3@Lines of code/average module@",
362  "LOCp@ 999999@ 999999@ 0@ 6@ 0@Lines of code/project@",
363  "MVGf@ 10@ 30@ 0@ 6@ 0@Cyclomatic complexity/function@",
364  "MVGm@ 200@ 1000@ 0@ 6@ 0@Cyclomatic complexity/single module@",
365  "MVGper@ 200@ 1000@ 0@ 6@ 3@Cyclomatic complexity/average module@",
366  "MVGp@ 999999@ 999999@ 0@ 6@ 0@Cyclomatic complexity/project@",
367  "COM@ 999999@ 999999@ 0@ 6@ 0@Comment lines@",
368  "COMper@999999@ 999999@ 0@ 6@ 3@Comment lines (averaged)@",
369  "M_C@ 5@ 10@ 5@ 6@ 3@MVG/COM McCabe/comment line@",
370  "L_C@ 7@ 30@ 20@ 6@ 3@LOC/COM Lines of code/comment line@",
371  "FI@ 12@ 20@ 0@ 6@ 0@Fan in (overall)@",
372  "FIv@ 6@ 12@ 0@ 6@ 0@Fan in (visible uses only)@",
373  "FIc@ 6@ 12@ 0@ 6@ 0@Fan in (concrete uses only)@",
374  "FO@ 12@ 20@ 0@ 6@ 0@Fan out (overall)@",
375  "FOv@ 6@ 12@ 0@ 6@ 0@Fan out (visible uses only)@",
376  "FOc@ 6@ 12@ 0@ 6@ 0@Fan out (concrete uses only)@",
377  "IF4@ 100@ 1000@ 0@ 6@ 0@Henry-Kafura/Shepperd measure (overall)@",
378  "IF4v@ 30@ 100@ 0@ 6@ 0@Henry-Kafura/Shepperd measure (visible)@",
379  "IF4c@ 30@ 100@ 0@ 6@ 0@Henry-Kafura/Shepperd measure (concrete)@",
380  // WMC stands for weighted methods per class,
381  // the suffix distinguishes the weighting function
382  "WMC1@ 30@ 100@ 0@ 6@ 0@Weighting function=1 unit per method@",
383  "WMCv@ 10@ 30@ 0@ 6@ 0@Weighting function=1 unit per visible method@",
384  "DIT@ 3@ 6@ 0@ 6@ 0@Depth of Inheritance Tree@",
385  "NOC@ 4@ 15@ 0@ 6@ 0@Number of children@",
386  "CBO@ 12@ 30@ 0@ 6@ 0@Coupling between objects@",
387  "8.3@ 999999@ 999999@ 0@ 8@ 3@General format for fixed precision 3 d.p.@",
388  NULL
389 };
390 
391 const char *default_dialect_options[] =
392 {
393  // This configuration item allows the description of
394  // dialects in which C/C++ identifiers get treated
395  // as supplementary keyword. The rules specified
396  // here (or in the runtime option file, if specified)
397  // allow the parser to make the call
398  // CCCC_Options::dialect_keyword_policy(lang,kw) which
399  // returns a string. If nothing is known about the
400  // pair <lang,kw>, an empty string is returned. If
401  // an entry is specified here the associated string is
402  // returned, which is called the policy, which the
403  // parser uses to guide its actions. The most common
404  // policy is to ignore, but any string can be
405  // specified, providing the person implementing
406  // the parser can think of an intelligent way to
407  // proceed.
408  "c++.mfc@BEGIN_MESSAGE_MAP@start_skipping@",
409  "c++.mfc@END_MESSAGE_MAP@stop_skipping@",
410  "c++.stl@__STL_BEGIN_NAMESPACE@ignore@",
411  "c++.stl@__STL_END_NAMESPACE@ignore@",
412  NULL
413 };
414 
415 
416 
417 
418 
419 
420 
421 
422 
423 
424 
static void Save_Options(const string &filename)
Definition: cccc_opt.cc:118
const char * default_treatment_options[]
Definition: cccc_opt.cc:325
static void add_file_extension(CCCC_Item &fileext_line)
Definition: cccc_opt.cc:43
bool Insert(const string &s)
Definition: cccc_itm.cc:31
static file_extension_language_map_t extension_map
Definition: cccc_opt.cc:34
void add_treatment(CCCC_Item &treatment_line)
Definition: cccc_opt.cc:56
const char * default_dialect_options[]
Definition: cccc_opt.cc:391
std::map< string, string > file_extension_language_map_t
Definition: cccc_opt.cc:29
std::pair< string, string > dialect_keyword_t
Definition: cccc_opt.cc:31
static void add_dialect_keyword(CCCC_Item &dialect_keyword_line)
Definition: cccc_opt.cc:75
static void Load_Options()
Definition: cccc_opt.cc:182
bool Extract(string &s)
Definition: cccc_itm.cc:47
static string dialectKeywordPolicy(const string &lang, const string &kw)
Definition: cccc_opt.cc:264
static dialect_keyword_map_t dialect_keyword_map
Definition: cccc_opt.cc:36
bool FromFile(ifstream &ifstr)
Definition: cccc_itm.cc:119
static metric_treatment_map_t treatment_map
Definition: cccc_opt.cc:35
static string getFileLanguage(const string &filename)
Definition: cccc_opt.cc:220
static Metric_Treatment * getMetricTreatment(const string &metric_tag)
Definition: cccc_opt.cc:253
std::map< dialect_keyword_t, string > dialect_keyword_map_t
Definition: cccc_opt.cc:32
std::map< string, Metric_Treatment * > metric_treatment_map_t
Definition: cccc_opt.cc:30
static void Add_Option(CCCC_Item &option_line)
Definition: cccc_opt.cc:90
const char * default_fileext_options[]
Definition: cccc_opt.cc:277
bool ToFile(ofstream &ofstr)
Definition: cccc_itm.cc:112