📄 metrules.c
字号:
total_statements = tot_stat(&module.function.stmnts) + mod.decl + mod.pp; function_points = total_statements / STMNT_TO_FP_DIVISOR + ROUND; /* If function(s) and supposed to, adjust function points based on average complexity. */ if (mod.functions != 0 && adjust_function_points) { function_points /= fp_adjustment_factor( avg_stat(&module.function.decisions) + 1); } if (print_metric(fnp)) out(csv ? ",%u" : " Function Points: %u\n", (unsigned)function_points); if (print_metric(idc)) out(csv ? ",%lu" : " Identifiers: %lu\n", tim_stat(&module.idents)); if (print_metric(idl)) out(csv ? ",%lu,%lu,%lu" : " Length: <%lu >%lu ~%lu\n", tim_stat(&module.idents) == 0 ? 0 : min_stat(&module.idents), tim_stat(&module.idents) == 0 ? 0 : max_stat(&module.idents), tim_stat(&module.idents) == 0 ? 0 : avg_stat(&module.idents)); if (print_metric(fnc)) out(csv ? ",%u" : " Functions: %u\n", mod.functions); } out(csv ? "\n" : "");}/* Update module-level statistics. */static void update_module_stats(BOOLEAN do_halstead, unsigned volume, float level, long unsigned effort, long unsigned length, unsigned vocabulary, unsigned intelligence, float lang_level){ record_stat(&module.function.decisions, fcn.decisions); record_stat(&module.function.conditions, fcn.conditions); if (do_halstead) { record_stat(&module.function.length, length); record_stat(&module.function.vocabulary, vocabulary); record_stat(&module.function.volume, volume); /* In order to maintain precision to the third decimal place while holding in an unsigned long, multiply by 1000. Will be divided by 1000 when extracted. */ record_stat(&module.function.level, (unsigned long)(level * 1000.0 + ROUND)); record_stat(&module.function.effort, effort); record_stat(&module.function.intelligence, intelligence); record_stat(&module.function.lang_level, (unsigned long)(lang_level * 100.0 + ROUND)); } record_stat(&module.function.lines, fcn.lines.total); record_stat(&module.function.code_lines, fcn.lines.code); record_stat(&module.function.comment_lines, fcn.lines.com); record_stat(&module.function.white_lines, fcn.lines.white); record_stat(&module.function.max_depth, max_stat(&function.max_depth)); record_stat(&module.function.decls, fcn.decl); record_stat(&module.function.stmnts, executable_function_statements());}/* Initialize function-level statistics. */static void init_function_stats(void){ init_stat(&function.idents); init_stat(&function.max_depth); function.comp = 0; function.empty_expr = 0; function.label = 0; function.gotos = 0; function.continues = 0; function.returns = 0; function.operand_length = 0; function.operator_length = 0;}/* Print function summary. */static void print_function_summary(BOOLEAN csv, BOOLEAN do_halstead, unsigned volume, float level, long unsigned effort, long unsigned length, unsigned vocabulary, unsigned intelligence, float lang_level){ if (csv) out("fcn,%s,%s", mod_name(), fcn_name()); else out("\n %s()\n", fcn_name()); if (print_metric(cyc)) out(csv ? ",%u" : " Cyclomatic: %u\n", fcn.decisions + 1); if (print_metric(exc)) out(csv ? ",%u" : " Extended: %u\n", fcn.conditions + 1); if (do_halstead) { if (print_metric(pln)) out(csv ? ",%lu" : " Halstead Length: %lu\n", length); if (print_metric(pvc)) out(csv ? ",%u" : " Vocabulary: %u\n", vocabulary); if (print_metric(pvl)) out(csv ? ",%u" : " Volume: %u\n", volume); if (print_metric(plv)) out(csv ? ",%.3f" : " Level: %.3f\n", level); if (print_metric(pef)) out(csv ? ",%lu" : " Effort: %lu\n", effort); if (print_metric(inc)) out(csv ? ",%u" : " Intelligence: %u\n", intelligence); if (print_metric(ptm)) out(csv ? ",%.1f" : " Time (hours): %.1f\n", effort / moments_per_hour); if (print_metric(llv)) out(csv ? ",%.2f" : " Lang Level: %.2f\n", lang_level); } if (print_metric(scl)) out(csv ? ",%u" : " Lines: %u\n", fcn.lines.total); if (print_metric(cdl)) out(csv ? ",%u" : " Code: %u\n", fcn.lines.code); if (print_metric(cml)) out(csv ? ",%u" : " Comment: %u\n", fcn.lines.com); if (print_metric(bll)) out(csv ? ",%u" : " Blank: %u\n", fcn.lines.white); if (print_metric(exs)) out(csv ? ",%u" : " Exec Statements: %u\n", executable_function_statements()); if (print_metric(dcs)) out(csv ? ",%u" : " Decl Statements: %u\n", fcn.decl); if (print_metric(mcd)) out(csv ? ",%lu" : " Max Depth: %lu\n", max_stat(&function.max_depth)); if (print_metric(idc)) out(csv ? ",%lu" : " Identifiers: %lu\n", tim_stat(&function.idents)); if (print_metric(idl)) out(csv ? ",%lu,%lu,%lu" : " Length: <%lu >%lu ~%lu\n", tim_stat(&function.idents) == 0 ? 0 : min_stat(&function.idents), tim_stat(&function.idents) == 0 ? 0 : max_stat(&function.idents), tim_stat(&function.idents) == 0 ? 0 : avg_stat(&function.idents)); out(csv ? "\n" : "");}/* Return factor that adjusts an initial function-point estimate based on the average functional complexity of a program. This results in a more accurate assessment of backfired function points. Divide the initial function-point estimate by the returned factor to arrive at the adjusted function-point estimate. Cyclomatic complexity is passed into this function. This function uses a table that is similar to the one in Capers Jones book, _Applied Software Measurement_. Capers' table bases the adjustment on the sum of these three subjective bounded complexity metrics: program, data, and code complexity. The table in this function bases the adjustment on McCabe's objective unbounded cyclomatic complexity metric. I adapted ideas from Capers' book to come up with this table but have no idea how well founded it is.*/static float fp_adjustment_factor(unsigned long cyclo){ static struct { unsigned long min; float factor; } table[] = { { 0, 0.70 }, /* 1 */ { 1, 0.80 }, /* 2 */ { 2, 0.85 }, /* 3 */ { 3, 0.90 }, /* 4-5 */ { 5, 0.95 }, /* 6-8 */ { 8, 1.00 }, /* 9-11 */ { 11, 1.05 }, /* 12-16 */ { 16, 1.10 }, /* 17-21 */ { 21, 1.15 }, /* 22-27 */ { 27, 1.20 }, /* 28-36 */ { 36, 1.25 }, /* 37-53 */ { 53, 1.30 }, /* 54- */ }; unsigned i; if (cyclo == 0) fatal(F_BAD_CYCLO); for (i = 0; i < DIM_OF(table) && cyclo > table[i].min; ++i) ; return table[i - 1].factor;}/* Return the total number of executable statements in the current function. */static unsigned executable_function_statements(void){ /* Subtract out compound statements from the total in fcn.high, then add 1 back in for the outer-most compound statement that contains the function itself. */ return (fcn.low - function.empty_expr) + (fcn.high - function.comp + 1) + function.label;}/* Common printf-like output function. */static int out(const char *format, ...){ va_list args; int chars_written; va_start(args, format); chars_written = vfprintf(out_fp, format, args); va_end(args); return chars_written;}/* The following *_stat() functions are accessor functions for STAT structures.*//* Initialize statistic. */static void init_stat(STAT *stat){ stat->times = 0; stat->total = 0; TYPE_MAX(stat->min); stat->max = 0;}/* Record a value for this statistic. */static void record_stat(STAT *stat, unsigned long value){ if (value > stat->max) stat->max = value; if (value < stat->min) stat->min = value; ++stat->times; stat->total += value;}/* Absorb source statistic into destination statistic. */static void absorb_stat(STAT *stat_to, STAT *stat_from){ if (stat_from->max > stat_to->max) stat_to->max = stat_from->max; if (stat_from->min < stat_to->min) stat_to->min = stat_from->min; stat_to->times += stat_from->times; stat_to->total += stat_from->total;}/* Return minimum value ever recorded for this statistic. */static unsigned long min_stat(STAT *stat){ unsigned long min; if (stat->times == 0) min = 0; else min = stat->min; return min;}/* Return maximum value ever recorded for this statistic. */static unsigned long max_stat(STAT *stat){ return stat->max;}/* Return sum of all values ever recorded for this statistic. */static unsigned long tot_stat(STAT *stat){ return stat->total;}/* Return number of times a value was recorded for this statistic. */static unsigned long tim_stat(STAT *stat){ return stat->times;}/* Return the average value of this statistic, rounding to the nearest integer.*/static unsigned long avg_stat(STAT *stat){ unsigned long avg; if (stat->times == 0) avg = 0; else avg = (unsigned long)((float)tot_stat(stat) / stat->times + ROUND); return avg;}/* The following functions (clear_vocab(), add_term(), lookup_term(), and remove_term()) manipulate the linked list whos head is pointed to by the vocabulary. These functions are used for the Halstead metrics.*//* Remove all vocabulary-table entries and return the number of entries. */static unsigned clear_vocab(TERM **vocabulary){ TERM *term = *vocabulary; unsigned entries = 0; while (term != NULL) { TERM *next_term; free(term->string); next_term = term->next; free(term); term = next_term; ++entries; } *vocabulary = NULL; return entries;}/* Add string to vocabulary table. */static void add_term(TERM **vocabulary, char *string){ TERM *term; /* If term not found, add a copy of it to the front of the vocabulary. */ if ((term = lookup_term(*vocabulary, string)) == NULL) { term = (TERM *)malloc(sizeof *term); if (term == NULL) fatal(F_MEMORY); term->next = *vocabulary; *vocabulary = term; term->string = (char *)malloc(strlen(string) + 1); if (term->string == NULL) fatal(F_MEMORY); strcpy(term->string, string); term->count = 0; } ++term->count;}/* Lookup term in vocabulary table. Return pointer to TERM entry or NULL if not found.*/static TERM *lookup_term(TERM *vocabulary, char *string){ TERM *term; /* Search through vocabulary for this term. */ for (term = vocabulary; term != NULL && strcmp(term->string, string) != 0; term = term->next) ; return term;}/* Remove term from vocabulary table. */static void remove_term(TERM **vocabulary, char *string){ TERM *term, *prev_term; /* Search through vocabulary for this term. */ for (prev_term = NULL, term = *vocabulary; term != NULL && strcmp(term->string, string) != 0; prev_term = term, term = term->next) ; if (term != NULL) { /* If prev_term is NULL, this is the first entry in the linked list. */ if (prev_term == NULL) *vocabulary = term->next; else prev_term->next = term->next; free(term->string); free(term); } /* (Else if term was not found, do not do anything. */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -