/*! * Counts file language complexity based on specified language keywords/characters. * * \param fmap list of processed file lines * \param result counter results * * \return method status */ int CPythonCounter::CountComplexity(filemap* fmap, results* result) { if (classtype == UNKNOWN || classtype == DATAFILE) return 0; filemap::iterator fit; size_t idx; unsigned int cnt, ret, cyclomatic_cnt = 0, ignore_cyclomatic_cnt = 0, main_cyclomatic_cnt = 1, function_count = 0, cyclomatic_logic_cnt = 0, main_cyclomatic_logic_cnt = 1; bool isMainExisted = false; string line, needIndentation = "", file_ext, function_name = ""; vector<int> indenStack; indenStack.push_back(0); int numWS; string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$"; StringVector function_stack; stack<unsigned int> cyclomatic_stack; stack<unsigned int> cyclomatic_logic_stack; bool process_cyclomatic_complexity = false; // check whether to process cyclomatic complexity if (cmplx_cyclomatic_list.size() > 0) { process_cyclomatic_complexity = true; if (skip_cmplx_cyclomatic_file_extension_list.size() > 0) { idx = result->file_name.find_last_of("."); if (idx != string::npos) { file_ext = result->file_name.substr(idx); file_ext = CUtil::ToLower(file_ext); if (find(skip_cmplx_cyclomatic_file_extension_list.begin(), skip_cmplx_cyclomatic_file_extension_list.end(), file_ext) != skip_cmplx_cyclomatic_file_extension_list.end()) process_cyclomatic_complexity = false; } } } // process each line bool notEndFile = true; for (fit = fmap->begin(); notEndFile; fit++) { if (fit == fmap->end()) { notEndFile = false; } if (!notEndFile) { line = " endofmain"; //to handle last line of a file belongs to one function: // return(1) --> end of function. }else{ line = fit->line; if (CUtil::CheckBlank(line)) continue; line = " " + line; } //cout << line << "meiyige"; // mathematical functions cnt = 0; CUtil::CountTally(line, math_func_list, cnt, 1, exclude, "", "", &result->math_func_count, casesensitive); result->cmplx_math_lines += cnt; // trigonometric functions cnt = 0; CUtil::CountTally(line, trig_func_list, cnt, 1, exclude, "", "", &result->trig_func_count, casesensitive); result->cmplx_trig_lines += cnt; // logarithmic functions cnt = 0; CUtil::CountTally(line, log_func_list, cnt, 1, exclude, "", "", &result->log_func_count, casesensitive); result->cmplx_logarithm_lines += cnt; // calculations cnt = 0; CUtil::CountTally(line, cmplx_calc_list, cnt, 1, exclude, "", "", &result->cmplx_calc_count, casesensitive); result->cmplx_calc_lines += cnt; // conditionals cnt = 0; CUtil::CountTally(line, cmplx_cond_list, cnt, 1, exclude, "", "", &result->cmplx_cond_count, casesensitive); result->cmplx_cond_lines += cnt; // logical operators cnt = 0; CUtil::CountTally(line, cmplx_logic_list, cnt, 1, exclude, "", "", &result->cmplx_logic_count, casesensitive); result->cmplx_logic_lines += cnt; // preprocessor directives cnt = 0; CUtil::CountTally(line, cmplx_preproc_list, cnt, 1, exclude, "", "", &result->cmplx_preproc_count, casesensitive); result->cmplx_preproc_lines += cnt; // assignments cnt = 0; CUtil::CountTally(line, cmplx_assign_list, cnt, 1, exclude, "", "", &result->cmplx_assign_count, casesensitive); result->cmplx_assign_lines += cnt; // pointers cnt = 0; CUtil::CountTally(line, cmplx_pointer_list, cnt, 1, exclude, "", "", &result->cmplx_pointer_count, casesensitive); result->cmplx_pointer_lines += cnt; // cyclomatic complexity if (process_cyclomatic_complexity) { // search for cyclomatic complexity keywords CUtil::CountTally(line, cmplx_cyclomatic_list, cyclomatic_cnt, 1, exclude, "", "", 0, casesensitive); // search for keywords to exclude if (ignore_cmplx_cyclomatic_list.size() > 0) CUtil::CountTally(line, ignore_cmplx_cyclomatic_list, ignore_cyclomatic_cnt, 1, exclude, "", "", 0, casesensitive); // search for cyclomatic complexity logical keywords if (cmplx_cyclomatic_logic_list.size() > 0) CUtil::CountTally(line, cmplx_cyclomatic_logic_list, cyclomatic_logic_cnt, 1, exclude, "", "", 0, casesensitive); // parse function name if found ret = ParseFunctionName(line, needIndentation, function_stack, function_name, indenStack, numWS); if (ret != 1 && !cyclomatic_stack.empty() && cyclomatic_stack.size() == function_stack.size()-1) { // remove count stack entry for non-function names cyclomatic_cnt += cyclomatic_stack.top(); ignore_cyclomatic_cnt = 0; cyclomatic_stack.pop(); } if (ret != 1 && !cyclomatic_logic_stack.empty() && cyclomatic_logic_stack.size() == function_stack.size()-1) { // remove count stack entry for non-function names cyclomatic_logic_cnt += cyclomatic_logic_stack.top(); cyclomatic_logic_stack.pop(); } // modify the condition when comes to function_stack.size() [add 1] if (ret == 1) // and modify this part { //this line is not in the current function, handle it later int remember = cyclomatic_cnt - ignore_cyclomatic_cnt + 1; int remember2 = remember + cyclomatic_logic_cnt; cyclomatic_cnt = 0; ignore_cyclomatic_cnt = 0; cyclomatic_logic_cnt = 0; CUtil::CountTally(line, cmplx_cyclomatic_list, cyclomatic_cnt, 1, exclude, "", "", 0, casesensitive); // get this line's complexity if (ignore_cmplx_cyclomatic_list.size() > 0) CUtil::CountTally(line, ignore_cmplx_cyclomatic_list, ignore_cyclomatic_cnt, 1, exclude, "", "", 0, casesensitive); if (cmplx_cyclomatic_logic_list.size() > 0) CUtil::CountTally(line, cmplx_cyclomatic_logic_list, cyclomatic_logic_cnt, 1, exclude, "", "", 0, casesensitive); //substrack the current line's complexity remember -= cyclomatic_cnt - ignore_cyclomatic_cnt; remember2 -= cyclomatic_cnt - ignore_cyclomatic_cnt + cyclomatic_logic_cnt; // capture count at end of function lineElement element(remember, function_name); result->cmplx_cycfunct_count.push_back(element); lineElement n_element(remember2, function_name); result->cmplx_cycfunct_CC2_count.push_back(n_element); function_name = ""; if (function_stack.size() > 1) { // grab previous function from stack to continue if (!cyclomatic_stack.empty()) { int flag = 0; //both the stacks' first element is redundant so " ** > 1 " while (indenStack.size() > 1 && function_stack.size() > 1) { if (flag == 1) { indenStack.pop_back(); function_stack.pop_back(); } if (numWS >= indenStack.back()) { //the current line belongs to one of the functions in the function_stack break; } int temp = cyclomatic_stack.top() + 1; cyclomatic_stack.pop(); int temp2 = cyclomatic_logic_stack.top(); cyclomatic_logic_stack.pop(); string str = function_stack.back(); size_t idx = str.find("("); if (idx != string::npos) { function_name = CUtil::ClearRedundantSpaces(str.substr(0, idx)); } lineElement element(temp, function_name); result->cmplx_cycfunct_count.push_back(element); lineElement n_element(temp + temp2, function_name); result->cmplx_cycfunct_CC2_count.push_back(n_element); function_name = ""; flag = 1; } if (indenStack.size() > 1) { //the current line belongs to one of the functions in the function_stack cyclomatic_cnt += cyclomatic_stack.top() - ignore_cyclomatic_cnt; cyclomatic_stack.pop(); cyclomatic_logic_cnt += cyclomatic_logic_stack.top(); cyclomatic_logic_stack.pop(); }else{ //the current line not belongs to any of the functions in the function_stack, so it should belong to main if (line != " endofmain") { main_cyclomatic_cnt += cyclomatic_cnt - ignore_cyclomatic_cnt; main_cyclomatic_logic_cnt += cyclomatic_cnt - ignore_cyclomatic_cnt + cyclomatic_logic_cnt; isMainExisted = true; } cyclomatic_cnt = cyclomatic_logic_cnt = 0; } } } else{ if (line != " endofmain") { main_cyclomatic_cnt += cyclomatic_cnt - ignore_cyclomatic_cnt; main_cyclomatic_logic_cnt += cyclomatic_cnt - ignore_cyclomatic_cnt + cyclomatic_logic_cnt; isMainExisted = true; } cyclomatic_cnt = cyclomatic_logic_cnt = 0; } ignore_cyclomatic_cnt = 0; } else if (ret == 2) { // some code doesn't belong to any function if (line != " endofmain") { main_cyclomatic_cnt += cyclomatic_cnt - ignore_cyclomatic_cnt; main_cyclomatic_logic_cnt += cyclomatic_cnt - ignore_cyclomatic_cnt + cyclomatic_logic_cnt; isMainExisted = true; } cyclomatic_cnt = ignore_cyclomatic_cnt = cyclomatic_logic_cnt = 0; } else { if (function_stack.size() > 1 && (function_stack.size() - 1 > cyclomatic_stack.size() + 1 || (cyclomatic_stack.empty() && function_stack.size() - 1 > 1))) { // capture previous complexity count from open function cyclomatic_stack.push(cyclomatic_cnt - ignore_cyclomatic_cnt); cyclomatic_cnt = ignore_cyclomatic_cnt = 0; } if (function_stack.size() > 1 && (function_stack.size() - 1 > cyclomatic_logic_stack.size() + 1 || (cyclomatic_logic_stack.empty() && function_stack.size() - 1 > 1))) { // capture previous complexity count from open function cyclomatic_logic_stack.push(cyclomatic_logic_cnt); cyclomatic_logic_cnt = 0; } } } } // done with a file, if has "main" code add it if (isMainExisted) { lineElement element(main_cyclomatic_cnt, "main"); lineElement n_element(main_cyclomatic_logic_cnt, "main"); result->cmplx_cycfunct_count.push_back(element); result->cmplx_cycfunct_CC2_count.push_back(n_element); } return 1; }
/*! * Counts file language complexity based on specified language keywords/characters. * * \param fmap list of processed file lines * \param result counter results * * \return method status */ int CCshCounter::CountComplexity(filemap* fmap, results* result) { if (classtype == UNKNOWN || classtype == DATAFILE) return 0; filemap::iterator fit; size_t idx; unsigned int cnt, ret, cyclomatic_cnt = 0, ignore_cyclomatic_cnt = 0, main_cyclomatic_cnt = 0, function_count = 0, cyclomatic_logic_cnt = 0, main_cyclomatic_logic_cnt = 1, cyclomatic_case_cnt = 0, main_cyclomatic_case_cnt = 1, cyclomatic_default_cnt = 0, cyclomatic_switch_cnt = 0; string line, lastline, file_ext, function_name = ""; string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$"; filemap function_stack; stack<unsigned int> cyclomatic_stack; stack<unsigned int> cyclomatic_logic_stack; stack<unsigned int> cyclomatic_case_stack; map<unsigned int, lineElement> function_map; map<unsigned int, lineElement> logical_map; map<unsigned int, lineElement> case_map; bool process_cyclomatic_complexity = false; // check whether to process cyclomatic complexity if (cmplx_cyclomatic_list.size() > 0) { process_cyclomatic_complexity = true; if (skip_cmplx_cyclomatic_file_extension_list.size() > 0) { idx = result->file_name.find_last_of("."); if (idx != string::npos) { file_ext = result->file_name.substr(idx); file_ext = CUtil::ToLower(file_ext); if (find(skip_cmplx_cyclomatic_file_extension_list.begin(), skip_cmplx_cyclomatic_file_extension_list.end(), file_ext) != skip_cmplx_cyclomatic_file_extension_list.end()) process_cyclomatic_complexity = false; } } } // process each line for (fit = fmap->begin(); fit != fmap->end(); fit++) { line = fit->line; if (CUtil::CheckBlank(line)) continue; line = echoHelper(line); line = " " + line; // mathematical functions cnt = 0; CUtil::CountTally(line, math_func_list, cnt, 1, exclude, "", "", &result->math_func_count, casesensitive); result->cmplx_math_lines += cnt; // trigonometric functions cnt = 0; CUtil::CountTally(line, trig_func_list, cnt, 1, exclude, "", "", &result->trig_func_count, casesensitive); result->cmplx_trig_lines += cnt; // logarithmic functions cnt = 0; CUtil::CountTally(line, log_func_list, cnt, 1, exclude, "", "", &result->log_func_count, casesensitive); result->cmplx_logarithm_lines += cnt; // calculations cnt = 0; CUtil::CountTally(line, cmplx_calc_list, cnt, 1, exclude, "", "", &result->cmplx_calc_count, casesensitive); result->cmplx_calc_lines += cnt; // conditionals cnt = 0; CUtil::CountTally(line, cmplx_cond_list, cnt, 1, exclude, "", "", &result->cmplx_cond_count, casesensitive); result->cmplx_cond_lines += cnt; // logical operators cnt = 0; CUtil::CountTally(line, cmplx_logic_list, cnt, 1, exclude, "", "", &result->cmplx_logic_count, casesensitive); result->cmplx_logic_lines += cnt; // preprocessor directives cnt = 0; CUtil::CountTally(line, cmplx_preproc_list, cnt, 1, exclude, "", "", &result->cmplx_preproc_count, casesensitive); result->cmplx_preproc_lines += cnt; // assignments cnt = 0; CUtil::CountTally(line, cmplx_assign_list, cnt, 1, exclude, "", "", &result->cmplx_assign_count, casesensitive); result->cmplx_assign_lines += cnt; // pointers cnt = 0; CUtil::CountTally(line, cmplx_pointer_list, cnt, 1, exclude, "", "", &result->cmplx_pointer_count, casesensitive); result->cmplx_pointer_lines += cnt; // cyclomatic complexity if (process_cyclomatic_complexity) { // search for cyclomatic complexity keywords CUtil::CountTally(line, cmplx_cyclomatic_list, cyclomatic_cnt, 1, exclude, "", "", 0, casesensitive); CUtil::CountTally(line, cmplx_cyclomatic_switch_list, cyclomatic_switch_cnt, 1, exclude, "", "", 0, casesensitive); // search for keywords to exclude if (ignore_cmplx_cyclomatic_list.size() > 0) CUtil::CountTally(line, ignore_cmplx_cyclomatic_list, ignore_cyclomatic_cnt, 1, exclude, "", "", 0, casesensitive); // search for cyclomatic complexity logical keywords if (cmplx_cyclomatic_logic_list.size() > 0) CUtil::CountTally(line, cmplx_cyclomatic_logic_list, cyclomatic_logic_cnt, 1, exclude, "", "", 0, casesensitive); // search for cyclomatic complexity logical keywords if (cmplx_cyclomatic_case_list.size() > 0) CUtil::CountTally(line, cmplx_cyclomatic_case_list, cyclomatic_case_cnt, 1, exclude, "", "", 0, casesensitive); // search for cyclomatic complexity case default keywords if (cmplx_cyclomatic_default_list.size() > 0) CUtil::CountTally(line, cmplx_cyclomatic_default_list, cyclomatic_default_cnt, 1, exclude, "", "", 0, casesensitive); if(cyclomatic_default_cnt > 0) { cyclomatic_cnt -= cyclomatic_default_cnt; cyclomatic_case_cnt -= cyclomatic_default_cnt; cyclomatic_default_cnt = 0; } // parse function name if found ret = ParseFunctionName(line, lastline, function_stack, function_name); if (ret != 1 && !cyclomatic_stack.empty() && cyclomatic_stack.size() == function_stack.size()) { // remove count stack entry for non-function names cyclomatic_cnt += cyclomatic_stack.top(); ignore_cyclomatic_cnt = 0; cyclomatic_stack.pop(); } if (ret != 1 && !cyclomatic_logic_stack.empty() && cyclomatic_logic_stack.size() == function_stack.size()) { // remove count stack entry for non-function names cyclomatic_logic_cnt += cyclomatic_logic_stack.top(); cyclomatic_logic_stack.pop(); } if (ret != 1 && !cyclomatic_case_stack.empty() && cyclomatic_case_stack.size() == function_stack.size()) { // remove count stack entry for non-function names cyclomatic_case_cnt += cyclomatic_case_stack.top(); cyclomatic_case_stack.pop(); } if (ret == 1) { // capture count at end of function lineElement element(cyclomatic_cnt - ignore_cyclomatic_cnt + 1, function_name); function_map[function_count] = element; lineElement n_element(cyclomatic_cnt - ignore_cyclomatic_cnt + cyclomatic_logic_cnt + 1, function_name); logical_map[function_count] = n_element; if (cyclomatic_case_cnt > 0) { lineElement c_element(cyclomatic_cnt - ignore_cyclomatic_cnt - cyclomatic_case_cnt + cyclomatic_switch_cnt + 1, function_name); case_map[function_count] = c_element; } else case_map[function_count] = element; if (!function_stack.empty()) { // grab previous function from stack to continue if (!cyclomatic_stack.empty()) { cyclomatic_cnt = cyclomatic_stack.top(); cyclomatic_stack.pop(); } if (!cyclomatic_logic_stack.empty()) { cyclomatic_logic_cnt = cyclomatic_logic_stack.top(); cyclomatic_logic_stack.pop(); } if (!cyclomatic_case_stack.empty()) { cyclomatic_case_cnt = cyclomatic_case_stack.top(); cyclomatic_case_stack.pop(); } } else { cyclomatic_cnt = 0; cyclomatic_logic_cnt = 0; cyclomatic_case_cnt = 0; } function_name = ""; ignore_cyclomatic_cnt = 0; cyclomatic_switch_cnt = 0; } else if (ret == 2) { if (main_cyclomatic_cnt < 1) main_cyclomatic_cnt = 1; // add 1 for main function here in case no other decision points are found in main // some code doesn't belong to any function main_cyclomatic_cnt += cyclomatic_cnt - ignore_cyclomatic_cnt; main_cyclomatic_logic_cnt += cyclomatic_cnt - ignore_cyclomatic_cnt + cyclomatic_logic_cnt; main_cyclomatic_case_cnt += cyclomatic_cnt - ignore_cyclomatic_cnt - cyclomatic_case_cnt + cyclomatic_switch_cnt; cyclomatic_cnt = ignore_cyclomatic_cnt = cyclomatic_logic_cnt = cyclomatic_case_cnt = cyclomatic_switch_cnt = 0; } else { if (!function_stack.empty() && (function_stack.size() > cyclomatic_stack.size() + 1 || (cyclomatic_stack.empty() && function_stack.size() > 1))) { // capture previous complexity count from open function cyclomatic_stack.push(cyclomatic_cnt - ignore_cyclomatic_cnt); cyclomatic_cnt = ignore_cyclomatic_cnt = 0; } if (!function_stack.empty() && (function_stack.size() > cyclomatic_logic_stack.size() + 1 || (cyclomatic_logic_stack.empty() && function_stack.size() > 1))) { // capture previous complexity count from open function cyclomatic_logic_stack.push(cyclomatic_logic_cnt); cyclomatic_logic_cnt = 0; } if (!function_stack.empty() && (function_stack.size() > cyclomatic_case_stack.size() + 1 || (cyclomatic_case_stack.empty() && function_stack.size() > 1))) { // capture previous complexity count from open function cyclomatic_case_stack.push(cyclomatic_case_cnt - cyclomatic_switch_cnt); cyclomatic_case_cnt = 0; cyclomatic_switch_cnt = 0; } } } } // done with a file if (main_cyclomatic_cnt > 0) { // add "main" code lineElement element(main_cyclomatic_cnt, "main"); lineElement n_element(main_cyclomatic_logic_cnt, "main"); lineElement c_element(main_cyclomatic_case_cnt, "main"); function_map[0] = element; logical_map[0] = n_element; case_map[0] = c_element; } else { // finish the first function if not closed while (!function_stack.empty()) { function_name = function_stack.back().line; function_count = function_stack.back().lineNumber; function_stack.pop_back(); if (!function_stack.empty()) { // grab previous function from stack to continue if (!cyclomatic_stack.empty()) { cyclomatic_cnt = cyclomatic_stack.top(); cyclomatic_stack.pop(); } } else { // capture count at end of function lineElement element(cyclomatic_cnt - ignore_cyclomatic_cnt + 1, function_name); lineElement n_element(cyclomatic_cnt - ignore_cyclomatic_cnt + cyclomatic_logic_cnt + 1, function_name); lineElement c_element(cyclomatic_cnt - ignore_cyclomatic_cnt - cyclomatic_case_cnt + cyclomatic_switch_cnt + 1, function_name); function_map[function_count] = element; logical_map[function_count] = n_element; case_map[function_count] = c_element; } } } // process ordered functions for (map<unsigned int, lineElement>::iterator it = function_map.begin(); it != function_map.end(); ++it) result->cmplx_cycfunct_count.push_back(it->second); if(cmplx_cyclomatic_logic_list.size() > 0) { for (map<unsigned int, lineElement>::iterator it = logical_map.begin(); it != logical_map.end(); ++it) result->cmplx_cycfunct_CC2_count.push_back(it->second); } if(cmplx_cyclomatic_case_list.size() > 0) { for (map<unsigned int, lineElement>::iterator it = case_map.begin(); it != case_map.end(); ++it) result->cmplx_cycfunct_CC3_count.push_back(it->second); } return 1; }
int CVerilogCounter::CountComplexity(filemap* fmap, results* result) { if (classtype == UNKNOWN || classtype == DATAFILE) return 0; filemap::iterator fit; filemap fitBak; filemap::iterator fitForw, fitBack;//used to check prior an later lines for semicolons //unsigned int cnt; //string line, line2; string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$><=:"; tokLocVect conditionalVector; tokLocVect::reverse_iterator r_tlvIter; //StringVector::iterator strIter = this->cmplx_cond_list.begin(); warning fix string buf; // have a buffer string stringstream ss; // insert the string into a stream tokenLocation tl; int count; bool whenCont; size_t idx; unsigned int cnt, ret, cyclomatic_cnt = 0, ignore_cyclomatic_cnt = 0, main_cyclomatic_cnt = 0, /*function_count = 0, */cyclomatic_logic_cnt = 0, main_cyclomatic_logic_cnt = 1, cyclomatic_case_cnt = 0, main_cyclomatic_case_cnt = 1; // warning fix string line, lastline, file_ext, function_name = ""; StringVector function_stack; stack<unsigned int> cyclomatic_stack; stack<unsigned int> cyclomatic_logic_stack; stack<unsigned int> cyclomatic_case_stack; bool process_cyclomatic_complexity = false; bool first_line_in_main = true; StringVector switch_case_key_list; StringVector switch_case_stack; switch_case_key_list.push_back(":"); // check whether to process cyclomatic complexity if (cmplx_cyclomatic_list.size() > 0) { process_cyclomatic_complexity = true; if (skip_cmplx_cyclomatic_file_extension_list.size() > 0) { idx = result->file_name.find_last_of("."); if (idx != string::npos) { file_ext = result->file_name.substr(idx); file_ext = CUtil::ToLower(file_ext); if (find(skip_cmplx_cyclomatic_file_extension_list.begin(), skip_cmplx_cyclomatic_file_extension_list.end(), file_ext) != skip_cmplx_cyclomatic_file_extension_list.end()) process_cyclomatic_complexity = false; } } } for (fit = fmap->begin(); fit != fmap->end(); fit++) { line = fit->line; if (CUtil::CheckBlank(line)) continue; line = " " + line; // mathematical functions cnt = 0; CUtil::CountTally(line, math_func_list, cnt, 1, exclude, "", "", &result->math_func_count, casesensitive); result->cmplx_math_lines += cnt; // trigonometric functions cnt = 0; CUtil::CountTally(line, trig_func_list, cnt, 1, exclude, "", "", &result->trig_func_count, casesensitive); result->cmplx_trig_lines += cnt; // logarithmic functions cnt = 0; CUtil::CountTally(line, log_func_list, cnt, 1, exclude, "", "", &result->log_func_count, casesensitive); result->cmplx_logarithm_lines += cnt; // calculations cnt = 0; CUtil::CountTally(line, cmplx_calc_list, cnt, 1, exclude, "", "", &result->cmplx_calc_count, casesensitive); result->cmplx_calc_lines += cnt; // conditionals cnt = 0; CUtil::CountTally(line, cmplx_cond_list, cnt, 1, exclude, "", "", &result->cmplx_cond_count, casesensitive); result->cmplx_cond_lines += cnt; // logical operators cnt = 0; StringVector tmpList = cmplx_logic_list;//making a temporary list with the '<=' operator removed from the list; counting it on another pass; tmpList.pop_back(); CUtil::CountTally(line, tmpList, cnt, 1, exclude, "", "", &result->cmplx_logic_count, casesensitive); result->cmplx_logic_lines += cnt; // preprocessor directives cnt = 0; CUtil::CountTally(line, cmplx_preproc_list, cnt, 1, exclude, "", "", &result->cmplx_preproc_count, casesensitive); result->cmplx_preproc_lines += cnt; // assignments cnt = 0; tmpList.clear(); tmpList = cmplx_assign_list;//making a temporary list with the '<=' operator removed from the list; counting it on another pass; tmpList.pop_back(); CUtil::CountTally(line, tmpList, cnt, 1, exclude, "", "", &result->cmplx_assign_count, casesensitive); result->cmplx_assign_lines += cnt; /* No pointer for Verilog // pointers cnt = 0; // Pointers are embedded syntax so there is NO exclude string or include strings CUtil::CountTally(line, cmplx_pointer_list, cnt, 1, "", "", "", &result->cmplx_pointer_count, casesensitive); result->cmplx_pointer_lines += cnt; */ // cyclomatic complexity if (process_cyclomatic_complexity) { // search for cyclomatic complexity keywords unsigned int temp = 0; CUtil::CountTally(line, cmplx_cyclomatic_list, temp, 1, exclude, "", "", 0, casesensitive); cyclomatic_cnt += temp; // search for keywords to exclude if (ignore_cmplx_cyclomatic_list.size() > 0) CUtil::CountTally(line, ignore_cmplx_cyclomatic_list, ignore_cyclomatic_cnt, 1, exclude, "", "", 0, casesensitive); // search for cyclomatic complexity case keywords if (cmplx_cyclomatic_case_list.size() > 0) CUtil::CountTally(line, cmplx_cyclomatic_case_list, cyclomatic_case_cnt, 1, exclude, "", "", 0, casesensitive); cyclomatic_case_cnt += temp; //search for keyword "case" size_t idx_case = CUtil::FindKeyword(line, "case"); if (idx_case != string::npos) { switch_case_stack.push_back("case"); } //search for keyword "case" idx_case = CUtil::FindKeyword(line, "casez"); if (idx_case != string::npos) { switch_case_stack.push_back("case"); } //search for keyword "case" idx_case = CUtil::FindKeyword(line, "casex"); if (idx_case != string::npos) { switch_case_stack.push_back("case"); } //only if switch_case_stack is not empty, we will search keyword ":" and "[" and "?" if(!switch_case_stack.empty()){ size_t idx = CUtil::FindKeyword(line, ":"); size_t idx_1 = CUtil::FindKeyword(line, "["); size_t idx_2 = CUtil::FindKeyword(line, "?"); size_t idx_3 = CUtil::FindKeyword(line, "default"); if ((idx != string::npos) && ((idx_1 == string::npos) || (idx < idx_1)) && ((idx_2 == string::npos) || (idx < idx_2)) && (idx_3 == string::npos)) { cyclomatic_cnt++; } //search for keyword "endcase" idx = CUtil::FindKeyword(line, "endcase"); if (idx != string::npos) { switch_case_stack.pop_back(); } } // search for cyclomatic complexity logical keywords if (cmplx_cyclomatic_logic_list.size() > 0) CUtil::CountTally(line, cmplx_cyclomatic_logic_list, cyclomatic_logic_cnt, 1, exclude, "", "", 0, casesensitive); // parse function name if found ret = (unsigned)ParseFunctionName(line, lastline, function_stack, function_name); if (ret != 1 && !cyclomatic_stack.empty() && cyclomatic_stack.size() == function_stack.size()) { // remove count stack entry for non-function names cyclomatic_cnt += cyclomatic_stack.top(); ignore_cyclomatic_cnt = 0; cyclomatic_stack.pop(); } if (ret != 1 && !cyclomatic_logic_stack.empty() && cyclomatic_logic_stack.size() == function_stack.size()-1) { // remove count stack entry for non-function names cyclomatic_logic_cnt += cyclomatic_logic_stack.top(); cyclomatic_logic_stack.pop(); } if (ret != 1 && !cyclomatic_case_stack.empty() && cyclomatic_case_stack.size() == function_stack.size()-1) { // remove count stack entry for non-function names cyclomatic_case_cnt += cyclomatic_case_stack.top(); cyclomatic_case_stack.pop(); } if (ret == 1) { // capture count at end of function lineElement element(cyclomatic_cnt - ignore_cyclomatic_cnt + 1, function_name); result->cmplx_cycfunct_count.push_back(element); lineElement n_element(cyclomatic_cnt - ignore_cyclomatic_cnt + cyclomatic_logic_cnt + 1, function_name); result->cmplx_cycfunct_CC2_count.push_back(n_element); lineElement c_element(cyclomatic_case_cnt - ignore_cyclomatic_cnt + 1, function_name); result->cmplx_cycfunct_CC3_count.push_back(c_element); if (!function_stack.empty()) { // grab previous function from stack to continue if (!cyclomatic_stack.empty()) { cyclomatic_cnt = cyclomatic_stack.top(); cyclomatic_stack.pop(); } if (!cyclomatic_logic_stack.empty()) { cyclomatic_logic_cnt = cyclomatic_logic_stack.top(); cyclomatic_logic_stack.pop(); } if (!cyclomatic_case_stack.empty()) { cyclomatic_case_cnt = cyclomatic_case_stack.top(); cyclomatic_case_stack.pop(); } } else { cyclomatic_cnt = 0; cyclomatic_logic_cnt = 0; cyclomatic_case_cnt = 0; } function_name = ""; ignore_cyclomatic_cnt = 0; } else if (ret == 2) { if (first_line_in_main) { main_cyclomatic_cnt = 1; first_line_in_main = false; } if (main_cyclomatic_cnt < 1) main_cyclomatic_cnt = 1; // add 1 for main function here in case no other decision points are found in main // some code doesn't belong to any function main_cyclomatic_cnt += cyclomatic_cnt - ignore_cyclomatic_cnt; main_cyclomatic_logic_cnt += cyclomatic_cnt - ignore_cyclomatic_cnt + cyclomatic_logic_cnt; main_cyclomatic_case_cnt += cyclomatic_case_cnt - ignore_cyclomatic_cnt; cyclomatic_cnt = ignore_cyclomatic_cnt = cyclomatic_logic_cnt = cyclomatic_case_cnt = 0; } else { if (!function_stack.empty() && (function_stack.size() > cyclomatic_stack.size() + 1 || (cyclomatic_stack.empty() && function_stack.size() > 1))) { // capture previous complexity count from open function cyclomatic_stack.push(cyclomatic_cnt - ignore_cyclomatic_cnt); cyclomatic_cnt = ignore_cyclomatic_cnt = 0; } if (!function_stack.empty() && (function_stack.size() > cyclomatic_logic_stack.size() + 1 || (cyclomatic_logic_stack.empty() && function_stack.size() > 1))) { // capture previous complexity count from open function cyclomatic_logic_stack.push(cyclomatic_logic_cnt); cyclomatic_logic_cnt = 0; } if (!function_stack.empty() && (function_stack.size() > cyclomatic_case_stack.size() + 1 || (cyclomatic_case_stack.empty() && function_stack.size() > 1))) { // capture previous complexity count from open function cyclomatic_case_stack.push(cyclomatic_case_cnt); cyclomatic_case_cnt = 0; } } } } // do a single pass to mark and replace logical operator lessThan or equal "<=" // these appear only in conditional statements // the remaining are signal assignment operators for (fit = fmap->begin(); fit != fmap->end(); fit++) { line = fit->line; line = CUtil::ToLower(line); if (CUtil::CheckBlank(line)) continue; ss.clear(); ss.str(""); ss << line; count = -1; while (ss >> buf) { ++count; if (!buf.compare("if")) { tl.lineNumber = fit->lineNumber; tl.position = count; tl.token = buf; buf.clear(); conditionalVector.push_back(tl); continue; } // No wait in Verilog // No until")) // No assert")) if (!buf.compare("while")) { tl.lineNumber = fit->lineNumber; tl.position = count; tl.token = buf; buf.clear(); conditionalVector.push_back(tl); continue; } // No loop")) // No next")) // No when")) // No exit")) if (!buf.compare("return")) { tl.lineNumber = fit->lineNumber; tl.position = count; tl.token = buf; buf.clear(); conditionalVector.push_back(tl); continue; } if (!buf.compare("case")) { tl.lineNumber = fit->lineNumber; tl.position = count; tl.token = buf; buf.clear(); conditionalVector.push_back(tl); continue; } if (!buf.compare("casex")) { tl.lineNumber = fit->lineNumber; tl.position = count; tl.token = buf; buf.clear(); conditionalVector.push_back(tl); continue; } if (!buf.compare("casez")) { tl.lineNumber = fit->lineNumber; tl.position = count; tl.token = buf; buf.clear(); conditionalVector.push_back(tl); continue; } if (buf.find_last_of(";") != string::npos) { tl.lineNumber = fit->lineNumber; tl.position = count; tl.token = ";"; buf.clear(); conditionalVector.push_back(tl); continue; } if (buf.find("<=") != string::npos) { whenCont = false; // iterate up the vector an look for the first conditional statement r_tlvIter = conditionalVector.rbegin(); while (r_tlvIter != conditionalVector.rend()) { if (!r_tlvIter->token.compare(";")) { result->cmplx_assign_count.back()++; result->cmplx_assign_lines++; tl.token = "assign"; break; } else { if ((!r_tlvIter->token.compare("if") || !r_tlvIter->token.compare("elsif") || !r_tlvIter->token.compare("assert") || !r_tlvIter->token.compare("while") || !r_tlvIter->token.compare("return") || !r_tlvIter->token.compare("until") ) && !whenCont) { result->cmplx_logic_count.back()++; result->cmplx_logic_lines++; tl.token = "lte"; break; } if (!r_tlvIter->token.compare("when")) { whenCont = true; r_tlvIter++; continue; } if (!r_tlvIter->token.compare("case") || !r_tlvIter->token.compare("next") || !r_tlvIter->token.compare("exit")) { result->cmplx_assign_count.back()++; result->cmplx_assign_lines++; tl.token = "assign"; whenCont = false; break; } result->cmplx_assign_count.back()++; result->cmplx_assign_lines++; tl.token = "assign"; break; } // r_tlvIter++; MS VC++ warning C4702 unreachable code TODO: Review ! ! ! } tl.lineNumber = fit->lineNumber; tl.position = count; buf.clear(); conditionalVector.push_back(tl); continue; } } } // done with a file, if has "main" code add it if (main_cyclomatic_cnt > 0) { lineElement element(main_cyclomatic_cnt, "main"); lineElement n_element(main_cyclomatic_logic_cnt, "main"); lineElement c_element(main_cyclomatic_case_cnt, "main"); result->cmplx_cycfunct_count.push_back(element); result->cmplx_cycfunct_CC2_count.push_back(n_element); result->cmplx_cycfunct_CC3_count.push_back(c_element); } return 1; }