diff options
Diffstat (limited to 'gcc/gcov.c')
-rw-r--r-- | gcc/gcov.c | 550 |
1 files changed, 311 insertions, 239 deletions
diff --git a/gcc/gcov.c b/gcc/gcov.c index c56bac20278..48bcdc0d4c3 100644 --- a/gcc/gcov.c +++ b/gcc/gcov.c @@ -33,6 +33,7 @@ along with Gcov; see the file COPYING3. If not see #include "config.h" #define INCLUDE_ALGORITHM #define INCLUDE_VECTOR +#define INCLUDE_STRING #include "system.h" #include "coretypes.h" #include "tm.h" @@ -40,6 +41,7 @@ along with Gcov; see the file COPYING3. If not see #include "diagnostic.h" #include "version.h" #include "demangle.h" +#include "color-macros.h" #include <getopt.h> @@ -106,9 +108,6 @@ typedef struct arc_info /* Loop making arc. */ unsigned int cycle : 1; - /* Next branch on line. */ - struct arc_info *line_next; - /* Links to next arc on src and dst lists. */ struct arc_info *succ_next; struct arc_info *pred_next; @@ -243,67 +242,109 @@ typedef struct coverage_info /* Describes a single line of source. Contains a chain of basic blocks with code on it. */ -typedef struct line_info +struct line_info { + /* Default constructor. */ + line_info (); + /* Return true when NEEDLE is one of basic blocks the line belongs to. */ bool has_block (block_t *needle); - gcov_type count; /* execution count */ - arc_t *branches; /* branches from blocks that end on this line. */ - block_t *blocks; /* blocks which start on this line. - Used in all-blocks mode. */ + /* Execution count. */ + gcov_type count; + + /* Branches from blocks that end on this line. */ + vector<arc_t *> branches; + + /* blocks which start on this line. Used in all-blocks mode. */ + vector<block_t *> blocks; + unsigned exists : 1; unsigned unexceptional : 1; -} line_t; + unsigned has_unexecuted_block : 1; +}; -bool -line_t::has_block (block_t *needle) +line_info::line_info (): count (0), branches (), blocks (), exists (false), + unexceptional (0), has_unexecuted_block (0) { - for (block_t *n = blocks; n; n = n->chain) - if (n == needle) - return true; +} - return false; +bool +line_info::has_block (block_t *needle) +{ + return std::find (blocks.begin (), blocks.end (), needle) != blocks.end (); } /* Describes a file mentioned in the block graph. Contains an array of line info. */ -typedef struct source_info +struct source_info { + /* Default constructor. */ + source_info (); + /* Canonical name of source file. */ char *name; time_t file_time; - /* Array of line information. */ - line_t *lines; - unsigned num_lines; + /* Vector of line information. */ + vector<line_info> lines; coverage_t coverage; /* Functions in this source file. These are in ascending line number order. */ function_t *functions; -} source_t; +}; + +source_info::source_info (): name (NULL), file_time (), lines (), + coverage (), functions (NULL) +{ +} -typedef struct name_map +class name_map { - char *name; /* Source file name */ +public: + name_map () + { + } + + name_map (char *_name, unsigned _src): name (_name), src (_src) + { + } + + bool operator== (const name_map &rhs) const + { +#if HAVE_DOS_BASED_FILE_SYSTEM + return strcasecmp (this->name, rhs.name) == 0; +#else + return strcmp (this->name, rhs.name) == 0; +#endif + } + + bool operator< (const name_map &rhs) const + { +#if HAVE_DOS_BASED_FILE_SYSTEM + return strcasecmp (this->name, rhs.name) < 0; +#else + return strcmp (this->name, rhs.name) < 0; +#endif + } + + const char *name; /* Source file name */ unsigned src; /* Source file */ -} name_map_t; +}; /* Holds a list of function basic block graphs. */ static function_t *functions; static function_t **fn_end = &functions; -static source_t *sources; /* Array of source files */ -static unsigned n_sources; /* Number of sources */ -static unsigned a_sources; /* Allocated sources */ +/* Vector of source files. */ +static vector<source_info> sources; -static name_map_t *names; /* Mapping of file names to sources */ -static unsigned n_names; /* Number of names */ -static unsigned a_names; /* Allocated names */ +/* Mapping of file names to sources */ +static vector<name_map> names; /* This holds data summary information. */ @@ -381,11 +422,19 @@ static int flag_hash_filenames = 0; static int flag_verbose = 0; +/* Print colored output. */ + +static int flag_use_colors = 0; + /* Output count information for every basic block, not merely those that contain line number information. */ static int flag_all_blocks = 0; +/* Output human readable numbers. */ + +static int flag_human_readable_numbers = 0; + /* Output summary info for each function. */ static int flag_function_summary = 0; @@ -424,8 +473,6 @@ static void print_version (void) ATTRIBUTE_NORETURN; static void process_file (const char *); static void generate_results (const char *); static void create_file_names (const char *); -static int name_search (const void *, const void *); -static int name_sort (const void *, const void *); static char *canonicalize_name (const char *); static unsigned find_source (const char *); static function_t *read_graph_file (void); @@ -437,10 +484,10 @@ static void add_line_counts (coverage_t *, function_t *); static void executed_summary (unsigned, unsigned); static void function_summary (const coverage_t *, const char *); static const char *format_gcov (gcov_type, gcov_type, int); -static void accumulate_line_counts (source_t *); -static void output_gcov_file (const char *, source_t *); +static void accumulate_line_counts (source_info *); +static void output_gcov_file (const char *, source_info *); static int output_branch_count (FILE *, int, const arc_t *); -static void output_lines (FILE *, const source_t *); +static void output_lines (FILE *, const source_info *); static char *make_gcov_file_name (const char *, const char *); static char *mangle_name (const char *, char *); static void release_structures (void); @@ -556,7 +603,7 @@ unblock (const block_t *u, block_vector_t &blocked, static loop_type circuit (block_t *v, arc_vector_t &path, block_t *start, block_vector_t &blocked, vector<block_vector_t> &block_lists, - line_t &linfo, int64_t &count) + line_info &linfo, int64_t &count) { loop_type result = NO_LOOP; @@ -605,7 +652,7 @@ circuit (block_t *v, arc_vector_t &path, block_t *start, contains a negative loop, then perform the same function once again. */ static gcov_type -get_cycles_count (line_t &linfo, bool handle_negative_cycles = true) +get_cycles_count (line_info &linfo, bool handle_negative_cycles = true) { /* Note that this algorithm works even if blocks aren't in sorted order. Each iteration of the circuit detection is completely independent @@ -615,12 +662,13 @@ get_cycles_count (line_t &linfo, bool handle_negative_cycles = true) loop_type result = NO_LOOP; gcov_type count = 0; - for (block_t *block = linfo.blocks; block; block = block->chain) + for (vector<block_t *>::iterator it = linfo.blocks.begin (); + it != linfo.blocks.end (); it++) { arc_vector_t path; block_vector_t blocked; vector<block_vector_t > block_lists; - result |= circuit (block, path, block, blocked, block_lists, linfo, + result |= circuit (*it, path, *it, blocked, block_lists, linfo, count); } @@ -655,11 +703,6 @@ main (int argc, char **argv) /* Handle response files. */ expandargv (&argc, &argv); - a_names = 10; - names = XNEWVEC (name_map_t, a_names); - a_sources = 10; - sources = XNEWVEC (source_t, a_sources); - argno = process_args (argc, argv); if (optind == argc) print_usage (true); @@ -703,6 +746,8 @@ print_usage (int error_p) fnotice (file, " -f, --function-summaries Output summaries for each function\n"); fnotice (file, " -h, --help Print this help, then exit\n"); fnotice (file, " -i, --intermediate-format Output .gcov file in intermediate text format\n"); + fnotice (file, " -j, --human-readable Output human readable numbers\n"); + fnotice (file, " -k, --use-colors Emit colored output\n"); fnotice (file, " -l, --long-file-names Use long output file names for included\n\ source files\n"); fnotice (file, " -m, --demangled-names Output demangled function names\n"); @@ -744,6 +789,7 @@ static const struct option options[] = { "branch-probabilities", no_argument, NULL, 'b' }, { "branch-counts", no_argument, NULL, 'c' }, { "intermediate-format", no_argument, NULL, 'i' }, + { "human-readable", no_argument, NULL, 'j' }, { "no-output", no_argument, NULL, 'n' }, { "long-file-names", no_argument, NULL, 'l' }, { "function-summaries", no_argument, NULL, 'f' }, @@ -756,6 +802,7 @@ static const struct option options[] = { "unconditional-branches", no_argument, NULL, 'u' }, { "display-progress", no_argument, NULL, 'd' }, { "hash-filenames", no_argument, NULL, 'x' }, + { "use-colors", no_argument, NULL, 'k' }, { 0, 0, 0, 0 } }; @@ -766,7 +813,7 @@ process_args (int argc, char **argv) { int opt; - const char *opts = "abcdfhilmno:prs:uvwx"; + const char *opts = "abcdfhijklmno:prs:uvwx"; while ((opt = getopt_long (argc, argv, opts, options, NULL)) != -1) { switch (opt) @@ -789,6 +836,12 @@ process_args (int argc, char **argv) case 'l': flag_long_names = 1; break; + case 'j': + flag_human_readable_numbers = 1; + break; + case 'k': + flag_use_colors = 1; + break; case 'm': flag_demangled_names = 1; break; @@ -839,28 +892,7 @@ process_args (int argc, char **argv) /* Output the result in intermediate format used by 'lcov'. The intermediate format contains a single file named 'foo.cc.gcov', -with no source code included. A sample output is - -file:foo.cc -function:5,1,_Z3foov -function:13,1,main -function:19,1,_GLOBAL__sub_I__Z3foov -function:19,1,_Z41__static_initialization_and_destruction_0ii -lcount:5,1 -lcount:7,9 -lcount:9,8 -lcount:11,1 -file:/.../iostream -lcount:74,1 -file:/.../basic_ios.h -file:/.../ostream -file:/.../ios_base.h -function:157,0,_ZStorSt12_Ios_IostateS_ -lcount:157,0 -file:/.../char_traits.h -function:258,0,_ZNSt11char_traitsIcE6lengthEPKc -lcount:258,0 -... +with no source code included. The default gcov outputs multiple files: 'foo.cc.gcov', 'iostream.gcov', 'ios_base.h.gcov', etc. with source code @@ -868,10 +900,10 @@ included. Instead the intermediate format here outputs only a single file 'foo.cc.gcov' similar to the above example. */ static void -output_intermediate_file (FILE *gcov_file, source_t *src) +output_intermediate_file (FILE *gcov_file, source_info *src) { unsigned line_num; /* current line number. */ - const line_t *line; /* current line info ptr. */ + const line_info *line; /* current line info ptr. */ function_t *fn; /* current function info ptr. */ fprintf (gcov_file, "file:%s\n", src->name); /* source file name */ @@ -885,32 +917,32 @@ output_intermediate_file (FILE *gcov_file, source_t *src) } for (line_num = 1, line = &src->lines[line_num]; - line_num < src->num_lines; + line_num < src->lines.size (); line_num++, line++) { - arc_t *arc; if (line->exists) - fprintf (gcov_file, "lcount:%u,%s\n", line_num, - format_gcov (line->count, 0, -1)); + fprintf (gcov_file, "lcount:%u,%s,%d\n", line_num, + format_gcov (line->count, 0, -1), line->has_unexecuted_block); if (flag_branches) - for (arc = line->branches; arc; arc = arc->line_next) - { - if (!arc->is_unconditional && !arc->is_call_non_return) - { - const char *branch_type; - /* branch:<line_num>,<branch_coverage_type> - branch_coverage_type - : notexec (Branch not executed) - : taken (Branch executed and taken) - : nottaken (Branch executed, but not taken) - */ - if (arc->src->count) - branch_type = (arc->count > 0) ? "taken" : "nottaken"; - else - branch_type = "notexec"; - fprintf (gcov_file, "branch:%d,%s\n", line_num, branch_type); - } - } + for (vector<arc_t *>::const_iterator it = line->branches.begin (); + it != line->branches.end (); it++) + { + if (!(*it)->is_unconditional && !(*it)->is_call_non_return) + { + const char *branch_type; + /* branch:<line_num>,<branch_coverage_type> + branch_coverage_type + : notexec (Branch not executed) + : taken (Branch executed and taken) + : nottaken (Branch executed, but not taken) + */ + if ((*it)->src->count) + branch_type = ((*it)->count > 0) ? "taken" : "nottaken"; + else + branch_type = "notexec"; + fprintf (gcov_file, "branch:%d,%s\n", line_num, branch_type); + } + } } } @@ -939,7 +971,7 @@ process_file (const char *file_name) unsigned line = fn->line; unsigned block_no; function_t *probe, **prev; - + /* Now insert it into the source file's list of functions. Normally functions will be encountered in ascending order, so a simple scan is quick. Note we're @@ -967,8 +999,8 @@ process_file (const char *file_name) { unsigned last_line = block->locations[i].lines.back () + 1; - if (last_line > sources[s].num_lines) - sources[s].num_lines = last_line; + if (last_line > sources[s].lines.size ()) + sources[s].lines.resize (last_line); } } } @@ -987,7 +1019,7 @@ process_file (const char *file_name) } static void -output_gcov_file (const char *file_name, source_t *src) +output_gcov_file (const char *file_name, source_info *src) { char *gcov_file_name = make_gcov_file_name (file_name, src->coverage.name); @@ -1020,14 +1052,8 @@ output_gcov_file (const char *file_name, source_t *src) static void generate_results (const char *file_name) { - unsigned ix; - source_t *src; function_t *fn; - for (ix = n_sources, src = sources; ix--; src++) - if (src->num_lines) - src->lines = XCNEWVEC (line_t, src->num_lines); - for (fn = functions; fn; fn = fn->next) { coverage_t coverage; @@ -1042,18 +1068,23 @@ generate_results (const char *file_name) } } + name_map needle; + if (file_name) { - name_map_t *name_map = (name_map_t *)bsearch - (file_name, names, n_names, sizeof (*names), name_search); - if (name_map) - file_name = sources[name_map->src].coverage.name; + needle.name = file_name; + vector<name_map>::iterator it = std::find (names.begin (), names.end (), + needle); + if (it != names.end ()) + file_name = sources[it->src].coverage.name; else file_name = canonicalize_name (file_name); } - for (ix = n_sources, src = sources; ix--; src++) + for (vector<source_info>::iterator it = sources.begin (); + it != sources.end (); it++) { + source_info *src = &(*it); if (flag_relative_only) { /* Ignore this source, if it is an absolute path (after @@ -1088,17 +1119,8 @@ generate_results (const char *file_name) static void release_structures (void) { - unsigned ix; function_t *fn; - for (ix = n_sources; ix--;) - free (sources[ix].lines); - free (sources); - - for (ix = n_names; ix--;) - free (names[ix].name); - free (names); - while ((fn = functions)) { functions = fn->next; @@ -1174,90 +1196,45 @@ create_file_names (const char *file_name) return; } -/* A is a string and B is a pointer to name_map_t. Compare for file - name orderability. */ - -static int -name_search (const void *a_, const void *b_) -{ - const char *a = (const char *)a_; - const name_map_t *b = (const name_map_t *)b_; - -#if HAVE_DOS_BASED_FILE_SYSTEM - return strcasecmp (a, b->name); -#else - return strcmp (a, b->name); -#endif -} - -/* A and B are a pointer to name_map_t. Compare for file name - orderability. */ - -static int -name_sort (const void *a_, const void *b_) -{ - const name_map_t *a = (const name_map_t *)a_; - return name_search (a->name, b_); -} - /* Find or create a source file structure for FILE_NAME. Copies FILE_NAME on creation */ static unsigned find_source (const char *file_name) { - name_map_t *name_map; char *canon; unsigned idx; struct stat status; if (!file_name) file_name = "<unknown>"; - name_map = (name_map_t *)bsearch - (file_name, names, n_names, sizeof (*names), name_search); - if (name_map) - { - idx = name_map->src; - goto check_date; - } - if (n_names + 2 > a_names) + name_map needle; + needle.name = file_name; + + vector<name_map>::iterator it = std::find (names.begin (), names.end (), + needle); + if (it != names.end ()) { - /* Extend the name map array -- we'll be inserting one or two - entries. */ - a_names *= 2; - name_map = XNEWVEC (name_map_t, a_names); - memcpy (name_map, names, n_names * sizeof (*names)); - free (names); - names = name_map; + idx = it->src; + goto check_date; } /* Not found, try the canonical name. */ canon = canonicalize_name (file_name); - name_map = (name_map_t *) bsearch (canon, names, n_names, sizeof (*names), - name_search); - if (!name_map) + needle.name = canon; + it = std::find (names.begin (), names.end (), needle); + if (it == names.end ()) { /* Not found with canonical name, create a new source. */ - source_t *src; - - if (n_sources == a_sources) - { - a_sources *= 2; - src = XNEWVEC (source_t, a_sources); - memcpy (src, sources, n_sources * sizeof (*sources)); - free (sources); - sources = src; - } - - idx = n_sources; + source_info *src; - name_map = &names[n_names++]; - name_map->name = canon; - name_map->src = idx; + idx = sources.size (); + needle = name_map (canon, idx); + names.push_back (needle); - src = &sources[n_sources++]; - memset (src, 0, sizeof (*src)); + sources.push_back (source_info ()); + src = &sources.back (); src->name = canon; src->coverage.name = src->name; if (source_length @@ -1274,18 +1251,17 @@ find_source (const char *file_name) src->file_time = status.st_mtime; } else - idx = name_map->src; + idx = it->src; - if (name_search (file_name, name_map)) + needle.name = file_name; + if (std::find (names.begin (), names.end (), needle) == names.end ()) { /* Append the non-canonical name. */ - name_map = &names[n_names++]; - name_map->name = xstrdup (file_name); - name_map->src = idx; + names.push_back (name_map (xstrdup (file_name), idx)); } /* Resort the name map. */ - qsort (names, n_names, sizeof (*names), name_sort); + std::sort (names.begin (), names.end ()); check_date: if (sources[idx].file_time > bbg_file_time) @@ -1947,6 +1923,33 @@ add_branch_counts (coverage_t *coverage, const arc_t *arc) } } +/* Format COUNT, if flag_human_readable_numbers is set, return it human + readable format. */ + +static char const * +format_count (gcov_type count) +{ + static char buffer[64]; + const char *units = " kMGTPEZY"; + + if (count < 1000 || !flag_human_readable_numbers) + { + sprintf (buffer, "%" PRId64, count); + return buffer; + } + + unsigned i; + gcov_type divisor = 1; + for (i = 0; units[i+1]; i++, divisor *= 1000) + { + if (count + divisor / 2 < 1000 * divisor) + break; + } + gcov_type r = (count + divisor / 2) / divisor; + sprintf (buffer, "%" PRId64 "%c", r, units[i]); + return buffer; +} + /* Format a GCOV_TYPE integer as either a percent ratio, or absolute count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places. If DP is zero, no decimal point is printed. Only print 100% when @@ -1994,7 +1997,7 @@ format_gcov (gcov_type top, gcov_type bottom, int dp) } } else - sprintf (buffer, "%" PRId64, (int64_t)top); + return format_count (top); return buffer; } @@ -2257,13 +2260,13 @@ add_line_counts (coverage_t *coverage, function_t *fn) /* Scan each basic block. */ for (unsigned ix = 0; ix != fn->blocks.size (); ix++) { - line_t *line = NULL; + line_info *line = NULL; block_t *block = &fn->blocks[ix]; if (block->count && ix && ix + 1 != fn->blocks.size ()) fn->blocks_executed++; for (unsigned i = 0; i < block->locations.size (); i++) { - const source_t *src = &sources[block->locations[i].source_file_idx]; + source_info *src = &sources[block->locations[i].source_file_idx]; vector<unsigned> &lines = block->locations[i].lines; for (unsigned j = 0; j < lines.size (); j++) @@ -2278,7 +2281,11 @@ add_line_counts (coverage_t *coverage, function_t *fn) } line->exists = 1; if (!block->exceptional) - line->unexceptional = 1; + { + line->unexceptional = 1; + if (block->count == 0) + line->has_unexecuted_block = 1; + } line->count += block->count; } } @@ -2290,8 +2297,7 @@ add_line_counts (coverage_t *coverage, function_t *fn) /* Entry or exit block */; else if (line != NULL) { - block->chain = line->blocks; - line->blocks = block; + line->blocks.push_back (block); if (flag_branches) { @@ -2299,8 +2305,7 @@ add_line_counts (coverage_t *coverage, function_t *fn) for (arc = block->succ; arc; arc = arc->succ_next) { - arc->line_next = line->branches; - line->branches = arc; + line->branches.push_back (arc); if (coverage && !arc->is_unconditional) add_branch_counts (coverage, arc); } @@ -2315,11 +2320,10 @@ add_line_counts (coverage_t *coverage, function_t *fn) /* Accumulate the line counts of a file. */ static void -accumulate_line_counts (source_t *src) +accumulate_line_counts (source_info *src) { - line_t *line; function_t *fn, *fn_p, *fn_n; - unsigned ix; + unsigned ix = 0; /* Reverse the function order. */ for (fn = src->functions, fn_p = NULL; fn; fn_p = fn, fn = fn_n) @@ -2329,9 +2333,11 @@ accumulate_line_counts (source_t *src) } src->functions = fn_p; - for (ix = src->num_lines, line = src->lines; ix--; line++) + for (vector<line_info>::reverse_iterator it = src->lines.rbegin (); + it != src->lines.rend (); it++) { - if (line->blocks) + line_info *line = &(*it); + if (!line->blocks.empty ()) { /* The user expects the line count to be the number of times a line has been executed. Simply summing the block count @@ -2339,36 +2345,27 @@ accumulate_line_counts (source_t *src) is to sum the entry counts to the graph of blocks on this line, then find the elementary cycles of the local graph and add the transition counts of those cycles. */ - block_t *block, *block_p, *block_n; gcov_type count = 0; - /* Reverse the block information. */ - for (block = line->blocks, block_p = NULL; block; - block_p = block, block = block_n) - { - block_n = block->chain; - block->chain = block_p; - block->cycle.ident = ix; - } - line->blocks = block_p; - /* Sum the entry arcs. */ - for (block = line->blocks; block; block = block->chain) + for (vector<block_t *>::iterator it = line->blocks.begin (); + it != line->blocks.end (); it++) { arc_t *arc; - for (arc = block->pred; arc; arc = arc->pred_next) + for (arc = (*it)->pred; arc; arc = arc->pred_next) if (flag_branches) add_branch_counts (&src->coverage, arc); } /* Cycle detection. */ - for (block = line->blocks; block; block = block->chain) + for (vector<block_t *>::iterator it = line->blocks.begin (); + it != line->blocks.end (); it++) { - for (arc_t *arc = block->pred; arc; arc = arc->pred_next) + for (arc_t *arc = (*it)->pred; arc; arc = arc->pred_next) if (!line->has_block (arc->src)) count += arc->count; - for (arc_t *arc = block->succ; arc; arc = arc->succ_next) + for (arc_t *arc = (*it)->succ; arc; arc = arc->succ_next) arc->cs_count = arc->count; } @@ -2383,6 +2380,8 @@ accumulate_line_counts (source_t *src) if (line->count) src->coverage.lines_executed++; } + + ix++; } } @@ -2468,28 +2467,101 @@ read_line (FILE *file) return pos ? string : NULL; } +/* Pad string S with spaces from left to have total width equal to 9. */ + +static void +pad_count_string (string &s) +{ + if (s.size () < 9) + s.insert (0, 9 - s.size (), ' '); +} + +/* Print GCOV line beginning to F stream. If EXISTS is set to true, the + line exists in source file. UNEXCEPTIONAL indicated that it's not in + an exceptional statement. The output is printed for LINE_NUM of given + COUNT of executions. EXCEPTIONAL_STRING and UNEXCEPTIONAL_STRING are + used to indicate non-executed blocks. */ + +static void +output_line_beginning (FILE *f, bool exists, bool unexceptional, + bool has_unexecuted_block, + gcov_type count, unsigned line_num, + const char *exceptional_string, + const char *unexceptional_string) +{ + string s; + if (exists) + { + if (count > 0) + { + s = format_gcov (count, 0, -1); + if (has_unexecuted_block) + { + if (flag_use_colors) + { + pad_count_string (s); + s = SGR_SEQ (COLOR_BG_MAGENTA COLOR_SEPARATOR COLOR_FG_WHITE); + s += SGR_RESET; + } + else + s += "*"; + } + pad_count_string (s); + } + else + { + if (flag_use_colors) + { + s = "0"; + pad_count_string (s); + if (unexceptional) + s.insert (0, SGR_SEQ (COLOR_BG_RED + COLOR_SEPARATOR COLOR_FG_WHITE)); + else + s.insert (0, SGR_SEQ (COLOR_BG_CYAN + COLOR_SEPARATOR COLOR_FG_WHITE)); + s += SGR_RESET; + } + else + { + s = unexceptional ? unexceptional_string : exceptional_string; + pad_count_string (s); + } + } + } + else + { + s = "-"; + pad_count_string (s); + } + + fprintf (f, "%s:%5u", s.c_str (), line_num); +} + /* Read in the source file one line at a time, and output that line to the gcov file preceded by its execution count and other information. */ static void -output_lines (FILE *gcov_file, const source_t *src) +output_lines (FILE *gcov_file, const source_info *src) { +#define DEFAULT_LINE_START " -: 0:" + FILE *source_file; unsigned line_num; /* current line number. */ - const line_t *line; /* current line info ptr. */ + const line_info *line; /* current line info ptr. */ const char *retval = ""; /* status of source file reading. */ function_t *fn = NULL; - fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->coverage.name); + fprintf (gcov_file, DEFAULT_LINE_START "Source:%s\n", src->coverage.name); if (!multiple_files) { - fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name); - fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0, + fprintf (gcov_file, DEFAULT_LINE_START "Graph:%s\n", bbg_file_name); + fprintf (gcov_file, DEFAULT_LINE_START "Data:%s\n", no_data_file ? "-" : da_file_name); - fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0, object_runs); + fprintf (gcov_file, DEFAULT_LINE_START "Runs:%u\n", object_runs); } - fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count); + fprintf (gcov_file, DEFAULT_LINE_START "Programs:%u\n", program_count); source_file = fopen (src->name, "r"); if (!source_file) @@ -2498,13 +2570,13 @@ output_lines (FILE *gcov_file, const source_t *src) retval = NULL; } else if (src->file_time == 0) - fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n", "-", 0); + fprintf (gcov_file, DEFAULT_LINE_START "Source is newer than graph\n"); if (flag_branches) fn = src->functions; for (line_num = 1, line = &src->lines[line_num]; - line_num < src->num_lines; line_num++, line++) + line_num < src->lines.size (); line_num++, line++) { for (; fn && fn->line == line_num; fn = fn->next_file_fn) { @@ -2537,44 +2609,44 @@ output_lines (FILE *gcov_file, const source_t *src) Otherwise, print the execution count before the source line. There are 16 spaces of indentation added before the source line so that tabs won't be messed up. */ - fprintf (gcov_file, "%9s:%5u:%s\n", - !line->exists ? "-" : line->count - ? format_gcov (line->count, 0, -1) - : line->unexceptional ? "#####" : "=====", line_num, - retval ? retval : "/*EOF*/"); + output_line_beginning (gcov_file, line->exists, line->unexceptional, + line->has_unexecuted_block, line->count, line_num, + "=====", "#####"); + fprintf (gcov_file, ":%s\n", retval ? retval : "/*EOF*/"); if (flag_all_blocks) { - block_t *block; arc_t *arc; int ix, jx; - for (ix = jx = 0, block = line->blocks; block; - block = block->chain) + ix = jx = 0; + for (vector<block_t *>::const_iterator it = line->blocks.begin (); + it != line->blocks.end (); it++) { - if (!block->is_call_return) + if (!(*it)->is_call_return) { - fprintf (gcov_file, "%9s:%5u-block %2d", - !line->exists ? "-" : block->count - ? format_gcov (block->count, 0, -1) - : block->exceptional ? "%%%%%" : "$$$$$", - line_num, ix++); + output_line_beginning (gcov_file, line->exists, + (*it)->exceptional, false, + (*it)->count, line_num, + "%%%%%", "$$$$$"); + fprintf (gcov_file, "-block %2d", ix++); if (flag_verbose) - fprintf (gcov_file, " (BB %u)", block->id); + fprintf (gcov_file, " (BB %u)", (*it)->id); fprintf (gcov_file, "\n"); } if (flag_branches) - for (arc = block->succ; arc; arc = arc->succ_next) + for (arc = (*it)->succ; arc; arc = arc->succ_next) jx += output_branch_count (gcov_file, jx, arc); } } else if (flag_branches) { int ix; - arc_t *arc; - for (ix = 0, arc = line->branches; arc; arc = arc->line_next) - ix += output_branch_count (gcov_file, ix, arc); + ix = 0; + for (vector<arc_t *>::const_iterator it = line->branches.begin (); + it != line->branches.end (); it++) + ix += output_branch_count (gcov_file, ix, (*it)); } } |