File: cccc_opt.cc

package info (click to toggle)
cccc 3.pre81-2
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 3,820 kB
  • ctags: 4,972
  • sloc: ansic: 33,244; cpp: 10,691; java: 618; makefile: 165; sh: 11
file content (406 lines) | stat: -rw-r--r-- 11,644 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
// 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
};