/* Gcov.c: prepend line execution counts and branch probabilities to a
source file.
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998,
- 1999, 2000, 2001 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by James E. Wilson of Cygnus Support.
Mangled by Bob Manson of Cygnus Support.
#include "config.h"
#include "system.h"
#include "intl.h"
+#include "version.h"
#undef abort
+#include <getopt.h>
+
typedef HOST_WIDEST_INT gcov_type;
#include "gcov-io.h"
/* The functions in this file for creating and solution program flow graphs
are very similar to functions in the gcc source file profile.c. */
-char gcov_version_string[] = "GNU gcov version 1.5\n";
-
/* This is the size of the buffer used to read in source file lines. */
#define STRING_SIZE 200
static void read_files PARAMS ((void));
static void scan_for_source_files PARAMS ((void));
static void output_data PARAMS ((void));
-static void print_usage PARAMS ((void)) ATTRIBUTE_NORETURN;
+static void print_usage PARAMS ((int)) ATTRIBUTE_NORETURN;
+static void print_version PARAMS ((void)) ATTRIBUTE_NORETURN;
static void init_arc PARAMS ((struct adj_list *, int, int, struct bb_info *));
static struct adj_list *reverse_arcs PARAMS ((struct adj_list *));
static void create_program_flow_graph PARAMS ((struct bb_info_list *));
int argc;
char **argv;
{
-/* LC_CTYPE determines the character set used by the terminal so it has be set
- to output messages correctly. */
-
-#ifdef HAVE_LC_MESSAGES
- setlocale (LC_CTYPE, "");
- setlocale (LC_MESSAGES, "");
-#else
- setlocale (LC_ALL, "");
-#endif
-
- (void) bindtextdomain (PACKAGE, localedir);
- (void) textdomain (PACKAGE);
+ gcc_init_libintl ();
process_args (argc, argv);
exit (FATAL_EXIT_CODE);
}
\f
-/* Print a usage message and exit. */
+/* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
+ otherwise the output of --help. */
static void
-print_usage ()
+print_usage (error_p)
+ int error_p;
{
- fnotice (stderr, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
- exit (FATAL_EXIT_CODE);
+ FILE *file = error_p ? stderr : stdout;
+ int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
+ fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE\n\n");
+ fnotice (file, "Print code coverage information.\n\n");
+ fnotice (file, " -h, --help Print this help, then exit\n");
+ fnotice (file, " -v, --version Print version number, then exit\n");
+ fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
+ fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
+ rather than percentages\n");
+ fnotice (file, " -n, --no-output Do not create an output file\n");
+ fnotice (file, " -l, --long-file-names Use long output file names for included\n\
+ source files\n");
+ fnotice (file, " -f, --function-summaries Output summaries for each function\n");
+ fnotice (file, " -o, --object-directory OBJDIR Search for object files in OBJDIR\n");
+ fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
+ GCCBUGURL);
+ exit (status);
+}
+
+/* Print version information and exit. */
+
+static void
+print_version ()
+{
+ fnotice (stdout, "gcov (GCC) %s\n", version_string);
+ fnotice (stdout, "Copyright (C) 2001 Free Software Foundation, Inc.\n");
+ fnotice (stdout,
+ "This is free software; see the source for copying conditions. There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
+ exit (SUCCESS_EXIT_CODE);
}
+static const struct option options[] =
+{
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'v' },
+ { "branch-probabilities", no_argument, NULL, 'b' },
+ { "branch-counts", no_argument, NULL, 'c' },
+ { "no-output", no_argument, NULL, 'n' },
+ { "long-file-names", no_argument, NULL, 'l' },
+ { "function-summaries", no_argument, NULL, 'f' },
+ { "object-directory", required_argument, NULL, 'o' }
+};
+
/* Parse the command line. */
static void
int argc;
char **argv;
{
- int i;
+ int opt;
- for (i = 1; i < argc; i++)
+ while ((opt = getopt_long (argc, argv, "hvbclnfo:", options, NULL)) != -1)
{
- if (argv[i][0] == '-')
+ switch (opt)
{
- if (argv[i][1] == 'b')
- output_branch_probs = 1;
- else if (argv[i][1] == 'c')
- output_branch_counts = 1;
- else if (argv[i][1] == 'v')
- fputs (gcov_version_string, stderr);
- else if (argv[i][1] == 'n')
- output_gcov_file = 0;
- else if (argv[i][1] == 'l')
- output_long_names = 1;
- else if (argv[i][1] == 'f')
- output_function_summary = 1;
- else if (argv[i][1] == 'o' && argv[i][2] == '\0')
- object_directory = argv[++i];
- else
- print_usage ();
+ case 'h':
+ print_usage (false);
+ /* print_usage will exit. */
+ case 'v':
+ print_version ();
+ /* print_version will exit. */
+ case 'b':
+ output_branch_probs = 1;
+ break;
+ case 'c':
+ output_branch_counts = 1;
+ break;
+ case 'n':
+ output_gcov_file = 0;
+ break;
+ case 'l':
+ output_long_names = 1;
+ break;
+ case 'f':
+ output_function_summary = 1;
+ break;
+ case 'o':
+ object_directory = optarg;
+ break;
+ default:
+ print_usage (true);
+ /* print_usage will exit. */
}
- else if (! input_file_name)
- input_file_name = argv[i];
- else
- print_usage ();
}
- if (! input_file_name)
- print_usage ();
+ if (optind != argc - 1)
+ print_usage (true);
+
+ input_file_name = argv[optind];
}
}
-/* Reverse the arcs on a arc list. */
+/* Reverse the arcs on an arc list. */
static struct adj_list *
reverse_arcs (arcptr)
{
gcov_type tmp_count = 0;
if (da_file && __read_gcov_type (&tmp_count, da_file, 8))
- abort();
+ abort ();
arcptr->arc_count = tmp_count;
arcptr->count_valid = 1;
/* Read and ignore the first word of the .da file, which is the count of
how many numbers follow. */
if (da_file && __read_long (&total, da_file, 8))
- abort();
+ abort ();
while (! feof (bbg_file))
{
else if (line_num < 0)
{
/* Don't know what this is, but it's garbage. */
- abort();
+ abort ();
}
}
}
{
/* If this is a relative file name, and an object directory has been
specified, then make it relative to the object directory name. */
- if (! (*s_ptr->name == '/' || *s_ptr->name == DIR_SEPARATOR
- /* Check for disk name on MS-DOS-based systems. */
- || (DIR_SEPARATOR == '\\'
- && s_ptr->name[1] == ':'
- && (s_ptr->name[2] == DIR_SEPARATOR
- || s_ptr->name[2] == '/')))
+ if (! IS_ABSOLUTE_PATHNAME (s_ptr->name)
&& object_directory != 0
&& *object_directory != '\0')
{