⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 metrules.c

📁 这是一个C程序分析工具
💻 C
📖 第 1 页 / 共 4 页
字号:
/*************************************************************   Copyright (c) 1993-1995 by Paul Long  All rights reserved.**************************************************************//*************************************************************   metrules.c  This source file contains a set of rules for               the METRE metrics tool.**************************************************************/#include <stdarg.h>#include <stdio.h>#include <limits.h>#include <stdlib.h>#include <math.h>#include <string.h>#include "metre.h"/* Manifest constants. *//* Do Halstead metrics. Do not normally because slows things down. */#define HALSTEAD_OPT_CHAR     'H'/* Adjust function points. (Nonstandard adjustment calculation.) */#define ADJUST_FP_OPT_CHAR    'a'/* Just print the summaries (no function-specific info)? */#define SUMMARY_OPT_CHAR      's'/*   Value for the "Stroud number" in Halstead's Programming Time metric.   18 is the default.*/#define STROUD_OPT_CHAR       'T'/* Produce comma-separated-value, machine-readable output. */#define CSV_OPT_CHAR          'c'/* Print a particluar metric, e.g., -p=fnp. Can be repeated. */#define SELECT_METRIC_OPT_CHAR   'm'/* Defines for diagnostics that are generated by the rules, not the parser. */#define F_MEMORY              0, "Out of memory"#define F_BAD_CYCLO           1, "Cyclomatic complexity of 0"#define W_GOTO                0, "Goto statement used (%u time%s)"#define W_CONTINUE            1, "Continue statement used (%u time%s)"#define W_RETURNS             2, "Multiple return statements (%u)"#define W_TAB_SPACE_INDENT    3, "Tab & space used on same line for indention"#define W_MULT_STATEMENTS     4, "Multiple statements (%u) per line"#define W_NONSTANDARD         5, "Non-standard character (0x%x) encountered"#define W_BAD_METRIC          6, "Invalid metric identifier (%s)"/* Nicety to evaluate as "s" if argument is greater than one; otherwise, "". */#define NUMBER(x)       ((x) > 1 ? "s" : "")/* Evaluate to stringified x and value of x. */#define STRX_X(x) #x,x/* Assign max value to integer argument regardless of type, e.g., long int. */#define TYPE_MAX(x) ((x = ~0) < 0 ? x = ~(1 << ((sizeof x * CHAR_BIT) - 1)) : x)/* Halstead requires log2(). This macro uses log10() to calculate log2(). */#define log2(x)         (log10(x) / log10_to_2_divisor)/*   Function points are backfired by dividing the number of statements by   this factor.*/#define STMNT_TO_FP_DIVISOR   (128.0)/* Default Stroud number used in calculating Halstead Programming Time. */#define DEFAULT_STROUD_NUMBER (18)/* Conversion factor from seconds to hours. */#define SECONDS_TO_HOURS_FACTOR  (60.0 * 60.0)/*   Since C truncates when converting float to integral, force rounding   by adding 0.5 before conversion. This manifest constant provides the   proper addend which is to be added to the float value before converting   to an integral type.*/#define ROUND  (0.5)/* Number of columns on output device. */#define OUTPUT_WIDTH 80/* General-purpose statistics structure. */typedef struct {   unsigned long times; /* Number of times stat recorded. */   unsigned long total; /* Summation of stat being measured. */   unsigned long min;   /* Minimum and maximum value of stat. */   unsigned long max;} STAT;/*   The following structures are for statistics that are maintained at   the function, module, and project level.*//* Function-level statistics. */static struct {   STAT idents;               /* Identifiers. */   STAT max_depth;            /* Nesting level. */   unsigned comp;             /* How many compound statements. */   unsigned empty_expr;       /* How many empty expression statements. */   unsigned label;            /* How many (goto) labels. */   unsigned gotos;            /* How many gotos. */   unsigned continues;        /* How many continues. */   unsigned returns;          /* How many returns. */   /* For Halstead's Software Science metric. */   unsigned long operator_length;   unsigned long operand_length;} function;/* Module-level statistics. */static struct {   /* ...across all functions in a module. */   struct {      STAT decisions,         /* Binary decision points. */         conditions,          /* How many conditions, not just decisions. */         /* Halstead's Software Science metrics. */         length, vocabulary, volume, level, effort, intelligence, lang_level,         /* Various LOC metrics. */         lines, code_lines, comment_lines, white_lines,         decls,               /* Number of declaration statements. */         stmnts,              /* Number of executable statements. */         max_depth;           /* Maximum control depth. */   } function;   STAT idents;               /* Identifiers. */   /* Various LOC metrics. */   unsigned lines, code_lines, comment_lines, white_lines;} module;/* Project-level statistics. */static struct {   /* ...across all functions in a module. */   struct {      STAT decisions,         /* Binary decision points. */         conditions,          /* How many conditions, not just decisions. */         /* Halstead's Software Science metrics. */         length, vocabulary, volume, level, effort, intelligence, lang_level,         /* Various LOC metrics. */         lines, code_lines, comment_lines, white_lines,         decls,               /* Number of declaration statements. */         stmnts,              /* Number of executable statements. */         max_depth;           /* Maximum control depth. */   } function;   /* ...across all modules in a module. */   struct {      /* Various LOC metrics. */      STAT lines, code_lines, comment_lines, white_lines,         decls,               /* Number of declaration statements. */         stmnts,              /* Number of executable statements. */         pp,                  /* Number of preprocessor statements. */         funcs;               /* Number of functions. */   } module;   STAT idents;               /* Identifiers. */   unsigned long modules;     /* Number of modules. */} project;/* Used by Halstead metrics to record each term in a vocabulary. */typedef struct term {   struct term *next;   /* Next term in the linked list. */   char *string;        /* Lexeme */   unsigned count;      /* Number of occurences. */} TERM;/* Vocabularies as table of string terms.*/static TERM *operator_vocabulary = NULL;static TERM *operand_vocabulary = NULL;/* Conversion divisor from 1og 10 to 2.*/static double log10_to_2_divisor;/* Moments per hour. */static float moments_per_hour;/* Types of metrics. */enum metric_type {   bll,  /* Blank lines. */   cyc,  /* Cyclomatic complexity. */   cdl,  /* Code lines. */   cml,  /* Comment lines. */   dcs,  /* Declaration statements. */   exc,  /* Extended complexity. */   exs,  /* Executable statements. */   fnc,  /* Function count. */   fnp,  /* Function points. */   inc,  /* Intelligence content. */   idc,  /* Identifier count. */   idl,  /* Identifier length. */   llv,  /* Language level. */   mdc,  /* Module count. */   mcd,  /* Maximum control depth. */   pef,  /* Programming effort. */   pln,  /* Program length. */   plv,  /* Program level. */   pps,  /* Preprocessor statements. */   ptm,  /* Programming time. */   pvl,  /* Program volume. */   pvc,  /* Program vocabulary. */   scl   /* Source lines. */};static struct {   char *name;             /* Abbreviated name of metric (same as enum id). */   enum metric_type type;  /* Type of metric. */   BOOLEAN print;          /* Whether to print this metric. */   /* Whether this metric is part of a particular section in the output. */   BOOLEAN fcn,            /* Function metrics. */         mod_fcn,          /* Function-related module metrics. */         mod,              /* Module-related module metrics. */         prj_fcn,          /* Function-related project metrics. */         prj_mod,          /* Module-related project metrics. */         prj;              /* Project-related projecrt metrics. */} metric[] = {   /* name type   print    fcn      mod-fcn  mod      prj-fcn  prj-mod  prj */   { STRX_X(bll), FALSE,   TRUE,    TRUE,    FALSE,   TRUE,    FALSE,   FALSE },   { STRX_X(cyc), FALSE,   TRUE,    TRUE,    FALSE,   TRUE,    FALSE,   FALSE },   { STRX_X(cdl), FALSE,   TRUE,    TRUE,    TRUE,    TRUE,    TRUE,    TRUE  },   { STRX_X(cml), FALSE,   TRUE,    TRUE,    TRUE,    TRUE,    TRUE,    TRUE  },   { STRX_X(dcs), FALSE,   TRUE,    TRUE,    TRUE,    TRUE,    TRUE,    TRUE  },   { STRX_X(exc), FALSE,   TRUE,    TRUE,    FALSE,   TRUE,    FALSE,   FALSE },   { STRX_X(exs), FALSE,   TRUE,    TRUE,    TRUE,    TRUE,    TRUE,    TRUE  },   { STRX_X(fnc), FALSE,   FALSE,   FALSE,   TRUE,    FALSE,   TRUE,    TRUE  },   { STRX_X(fnp), FALSE,   FALSE,   FALSE,   TRUE,    FALSE,   FALSE,   TRUE  },   { STRX_X(inc), FALSE,   TRUE,    TRUE,    FALSE,   TRUE,    FALSE,   FALSE },   { STRX_X(idc), FALSE,   TRUE,    FALSE,   TRUE,    FALSE,   FALSE,   TRUE  },   { STRX_X(idl), FALSE,   TRUE,    FALSE,   TRUE,    FALSE,   FALSE,   TRUE  },   { STRX_X(llv), FALSE,   TRUE,    TRUE,    FALSE,   TRUE,    FALSE,   FALSE },   { STRX_X(mdc), FALSE,   FALSE,   FALSE,   FALSE,   FALSE,   FALSE,   TRUE  },   { STRX_X(mcd), FALSE,   TRUE,    TRUE,    FALSE,   TRUE,    FALSE,   FALSE },   { STRX_X(pef), FALSE,   TRUE,    TRUE,    FALSE,   TRUE,    FALSE,   FALSE },   { STRX_X(pln), FALSE,   TRUE,    TRUE,    FALSE,   TRUE,    FALSE,   FALSE },   { STRX_X(plv), FALSE,   TRUE,    TRUE,    FALSE,   TRUE,    FALSE,   FALSE },   { STRX_X(pps), FALSE,   FALSE,   FALSE,   TRUE,    FALSE,   TRUE,    TRUE  },   { STRX_X(ptm), FALSE,   TRUE,    TRUE,    FALSE,   TRUE,    FALSE,   FALSE },   { STRX_X(pvl), FALSE,   TRUE,    TRUE,    FALSE,   TRUE,    FALSE,   FALSE },   { STRX_X(pvc), FALSE,   TRUE,    TRUE,    FALSE,   TRUE,    FALSE,   FALSE },   { STRX_X(scl), FALSE,   TRUE,    TRUE,    TRUE,    TRUE,    TRUE,    TRUE  },};/* Local-function prototypes. */static void print_help(void);static BOOLEAN mark_metrics_to_print(void);static void mark_sections_to_print(BOOLEAN *, BOOLEAN *, BOOLEAN *, BOOLEAN *,      BOOLEAN *, BOOLEAN *);static BOOLEAN print_metric(enum metric_type);static void print_project_summary(BOOLEAN, BOOLEAN, BOOLEAN, BOOLEAN, BOOLEAN,      BOOLEAN);static void print_module_summary(BOOLEAN, BOOLEAN, BOOLEAN, BOOLEAN, BOOLEAN);static void print_function_summary(BOOLEAN, BOOLEAN, unsigned, float,      long unsigned, long unsigned, unsigned, unsigned, float);static void init_function_stats(void);static void init_module_stats(BOOLEAN);static void init_project_stats(BOOLEAN);static void update_project_stats(BOOLEAN);static void update_module_stats(BOOLEAN, unsigned, float, long unsigned,      long unsigned, unsigned, unsigned, float);static float fp_adjustment_factor(unsigned long);static unsigned executable_function_statements(void);static int out(const char *, ...);static void init_stat(STAT *);static void record_stat(STAT *, unsigned long);static void absorb_stat(STAT *, STAT *);static unsigned long min_stat(STAT *);static unsigned long max_stat(STAT *);static unsigned long tim_stat(STAT *);static unsigned long avg_stat(STAT *);static unsigned long tot_stat(STAT *);static unsigned clear_vocab(TERM **);static void add_term(TERM **, char *);static TERM *lookup_term(TERM *, char *);static void remove_term(TERM **, char *);void rules(void){   /* Whether spaces & tabs in indent. */   static BOOLEAN mixed_indent_lines;   /* Whether within logic, as opposed to a declaration. */   static BOOLEAN is_logic = FALSE;   /* Whether we are within a function definition. */   static BOOLEAN is_within_function = FALSE;   /* Adjust function points with non-standard algorithm? */   static BOOLEAN adjust_function_points = FALSE;   /* Whether to calculate the Halsetad metrics. */   static BOOLEAN do_halstead = FALSE;   /* Just print the summaries? */   static BOOLEAN summaries_only = FALSE;   /* Whether to generate output in Comma-Separated-Value format. */   static BOOLEAN csv;   /* Whether whole sections are printed. */   static BOOLEAN         print_fcn,     /* Function metrics. */         print_mod_fcn, /* Function-related module metrics. */         print_mod,     /* Module-related module metrics. */         print_prj_fcn, /* Function-related project metrics. */         print_prj_mod, /* Module-related project metrics. */         print_prj;     /* Project-related project metrics. */   /* Addendum to main help info when -h is specified. */   if (prj.help)      print_help();   if (prj.begin)   {      unsigned stroud_number;      /* Save log10-to-log2 factor so do not have to recalculate. */      log10_to_2_divisor = log10(2);      stroud_number = option(STROUD_OPT_CHAR);      if (stroud_number == 0)         stroud_number = DEFAULT_STROUD_NUMBER;      moments_per_hour = stroud_number * SECONDS_TO_HOURS_FACTOR;      do_halstead = option(HALSTEAD_OPT_CHAR);      adjust_function_points = option(ADJUST_FP_OPT_CHAR);      summaries_only = option(SUMMARY_OPT_CHAR);      csv = option(CSV_OPT_CHAR);      /* Mark which metrics should be printed. */      if (mark_metrics_to_print())         /*            If at least one of the Halstead metrics has been selected to be            printed, calculate the root Halstead metrics. Same as if the user            had used the -H command-line option.         */         if (print_metric(pln) || print_metric(pvc) || print_metric(pvl) ||               print_metric(plv) || print_metric(pef) || print_metric(inc) ||               print_metric(ptm) || print_metric(llv))            do_halstead = TRUE;      /* Determine which entire sections are to be printed. */      mark_sections_to_print(&print_fcn, &print_mod_fcn, &print_mod,         &print_prj_fcn, &print_prj_mod, &print_prj);      init_project_stats(do_halstead);   }   /*      At the end of the project, print a project summary if multiple      modules and at least one function-, module-, or project-related      project metric has been selected.   */   if (prj.end && project.modules > 1 &&         (print_prj_fcn || print_prj_mod || print_prj))      print_project_summary(csv, print_prj_fcn, print_prj_mod, print_prj,            do_halstead, adjust_function_points);   if (mod.begin)   {      if (!csv) {         out("\n****************************************************");         out("\n\n%s:\n", mod_name());      }      mixed_indent_lines = FALSE;      init_module_stats(do_halstead);   }   /*      At the end of each module, update project statistics and print a      module summary.   */   if (mod.end)   {      update_project_stats(do_halstead);      /*         Only print module metrics if at least one function- or         module-related module metric has been selected.      */      if (print_mod || print_mod_fcn)         print_module_summary(csv, print_mod, print_mod_fcn,               do_halstead, adjust_function_points);      if (mixed_indent_lines)         warn(W_TAB_SPACE_INDENT);   }   if (fcn.begin)   {      init_function_stats();      is_within_function = TRUE;   }   /*      At the end of each function, update module statistics and print      function statistics.   */   if (fcn.end)   {      unsigned unique_operators, unique_operands, volume;      float level;      long unsigned effort;      long unsigned length;      unsigned vocabulary;      unsigned intelligence;      float lang_level;      if (do_halstead) {         unsigned unique_terms;         unique_operators = clear_vocab(&operator_vocabulary);         unique_operands = clear_vocab(&operand_vocabulary);         unique_terms = unique_operators + unique_operands;         /*            Program Length                  N = N1 + N2            Program Vocabulary              n = n1 + n2            Program Volume                  V = N * log2(n)            Program Level                   L^ = (2 / n1) * (n2 / N2)            Programming Effort              E = V / L^            Programming Time (in hours)     T^ = E / (f * S)            Intelligence Content            I = L^ * V            Language Level                  L' = L^ * I         */         /* Detect log2(0) before it happens. */         if (unique_terms == 0)            volume = 0;         else            volume = (function.operator_length + function.operand_length) *                  log2(unique_terms) + ROUND;         if (unique_operators == 0 || function.operand_length == 0)            level = 0.0;         else            level = (2.0 / unique_operators) *                  ((float)unique_operands / function.operand_length);         if (level == 0.0)            effort = 0;         else            effort = (long unsigned)(volume / level + ROUND);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -