Files
seta75D 2e8a93c394 Init
2021-10-11 18:20:23 -03:00

376 lines
7.1 KiB
C

#ifndef lint
static char sccsid[] = "@(#)tcov.c 1.1 92/07/30 Copyr 1984 Sun Micro";
#endif
/*
* Copyright (c) 1984 by Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <ctype.h>
enum boolean { False, True };
typedef enum boolean Boolean;
/*
* Structure for each line in the .d file
*/
struct dotd {
int lineno; /* Line where this basic block begins*/
unsigned int count; /* Count for this basic block */
int oldcount; /* Count for the previous basic block*/
} dotd;
/*
* Data structure to keep track of the most frequently executed lines
*/
struct top {
int line; /* Line num of basic block */
int cnt; /* Count for this basic block */
} *top;
static int topn; /* Keep track of the top "n" */
static int nbasic; /* Total number of basic blocks */
static int zero_basic; /* Num of basic blocks not executed */
static int executions; /* Total num basic block executions */
static int dotc_lineno; /* Current line num in .c file */
static Boolean all; /* Flag to annotate all lines */
static Boolean need_arrow; /* Print an arrow before the line */
char *cmdname;
char *rindex();
char *index();
Boolean read_dotc();
Boolean read_dotd();
main(argc, argv)
int argc;
char *argv[];
{
cmdname = argv[0];
topn = 10;
argc--;
argv++;
while (argc > 0 && argv[0][0] == '-') {
switch(argv[0][1]) {
case 'a':
all = True;
break;
default:
if (isdigit(argv[0][1])) {
topn = atoi(&argv[0][1]);
} else {
usage();
}
break;
}
argc--;
argv++;
}
if (argc < 1) {
usage();
}
init_topn();
while (argc--) {
clear_topn();
nbasic = 0;
zero_basic = 0;
executions = 0;
dotc_lineno = 0;
dotd.count = 0;
annotate(*argv++);
}
exit(0);
/* NOTREACHED */
}
/*
* annotate - annotate the source file listing with execution counts
*/
static
annotate(dotc_file)
char *dotc_file;
{
FILE *dotc_fp;
FILE *dotd_fp;
FILE *dottcov_fp;
FILE *tmp_fp;
char *tmp = "/tmp/sortd.XXXXXX";
char buff[150];
char dotd_file[500];
char dottcov_file[500];
char dotc_line[512];
char *cp;
Boolean more_dotc;
Boolean more_dotd;
strcpy(dotd_file, dotc_file);
cp = rindex(dotd_file, '.');
if(cp == NULL)
cp = index(dotd_file, '\0');
strcpy(cp, ".d");
dotd_fp = fopen(dotd_file, "r");
if (dotd_fp == NULL) {
fprintf(stderr, "%s: unable to open %s\n", cmdname, dotd_file);
exit(1);
}
dotc_fp = fopen(dotc_file, "r");
if (dotc_fp == NULL) {
fprintf(stderr, "%s: unable to open %s\n", cmdname, dotc_file);
exit(1);
}
strcpy(dottcov_file, dotc_file);
cp = rindex(dottcov_file, '.');
strcpy(cp, ".tcov");
dottcov_fp = fopen(dottcov_file, "w");
if (dottcov_fp == NULL) {
fprintf(stderr, "%s: unable to open %s\n", cmdname,
dottcov_file);
exit(1);
}
mktemp (tmp);
tmp_fp = fopen (tmp, "w");
sprintf(buff, "sort -n %s > %s", dotd_file, tmp);
system(buff);
fclose(tmp_fp);
fclose(dotd_fp);
dotd_fp = fopen (tmp, "r");
more_dotc = read_dotc(dotc_fp, dotc_line, sizeof(dotc_line));
more_dotd = read_dotd(dotd_fp, &dotd);
while (more_dotc && more_dotd) {
while (more_dotc && dotc_lineno < dotd.lineno) {
pr_count(dottcov_fp, dotc_lineno, &dotd);
pr_line(dottcov_fp, dotc_line);
more_dotc = read_dotc(dotc_fp, dotc_line,
sizeof(dotc_line));
}
if (more_dotc) {
pr_count(dottcov_fp, dotc_lineno, &dotd);
more_dotd = read_dotd(dotd_fp, &dotd);
while (more_dotd && dotc_lineno == dotd.lineno) {
another_count(dottcov_fp, &dotd);
more_dotd = read_dotd(dotd_fp, &dotd);
}
pr_line(dottcov_fp, dotc_line);
more_dotc = read_dotc(dotc_fp, dotc_line,
sizeof(dotc_line));
}
}
if (more_dotc) {
do {
pr_count(dottcov_fp, dotc_lineno, &dotd);
pr_line(dottcov_fp, dotc_line);
more_dotc = read_dotc(dotc_fp, dotc_line,
sizeof(dotc_line));
} while(more_dotc);
} else if (dotc_lineno < dotd.lineno) {
fprintf(stderr, "Premature end-of-file on %s", dotc_file);
exit(1);
}
pr_top(dottcov_fp);
pr_stats(dottcov_fp);
fclose(dotc_fp);
fclose(dotd_fp);
fclose(dottcov_fp);
unlink (tmp);
}
/*
* Read a line from the .c file
*/
static Boolean
read_dotc(fp, buf, size)
FILE *fp;
char *buf;
int size;
{
if (fgets(buf, size, fp) == NULL) {
return(False);
}
dotc_lineno++;
return(True);
}
/*
* Read a line from the .d file
*/
static Boolean
read_dotd(fp, dp)
FILE *fp;
struct dotd *dp;
{
int r;
int i, j;
dp->oldcount = dp->count;
r = fscanf(fp, "%d %d", &dp->lineno, &dp->count);
if (r != 2) {
return(False);
}
nbasic++;
if (dp->count == 0) {
zero_basic++;
}
executions += dp->count;
for (i = 0; i < topn; i++) {
if (dp->count > top[i].cnt) {
for (j = topn - 1; j > i; j--) {
top[j].line = top[j - 1].line;
top[j].cnt = top[j - 1].cnt;
}
top[i].line = dp->lineno;
top[i].cnt = dp->count;
break;
}
}
return(True);
}
/*
* pr_count - print the count field on this line
*/
static
pr_count(fp, dotc_lineno, dp)
FILE *fp;
int dotc_lineno;
struct dotd *dp;
{
if (dotc_lineno == dp->lineno) {
pcount(fp, dp->count);
need_arrow = True;
} else if (all) {
pcount(fp, dp->oldcount);
need_arrow = True;
} else {
fprintf(fp, " ");
need_arrow = False;
}
}
/*
* pcount - print the count
* Special case a zero count
*/
static
pcount(fp, count)
FILE *fp;
int count;
{
if (count > 0) {
fprintf(fp, "%7u", count);
} else {
fprintf(fp, " #####");
}
}
/*
* another_count - more than one basic block on a line
*/
static
another_count(fp, dp)
FILE *fp;
struct dotd *dp;
{
fprintf(fp, ", ");
pcount(fp, dp->count);
}
/*
* print the source line
*/
static
pr_line(fp, line)
FILE *fp;
char *line;
{
if (need_arrow) {
fprintf(fp, " -> ");
} else {
fprintf(fp, " ");
}
fprintf(fp, "%s", line);
}
/*
* init_topn - allocate space for an array to hold
* the top "n" most frequently executed lines.
*/
static
init_topn()
{
top = (struct top *) malloc(topn * sizeof(struct top));
}
/*
* clear_topn - set all the values in the top "n" list to zero
*/
static
clear_topn()
{
struct top *tp;
int i;
tp = top;
for (i = 0; i < topn; i++) {
tp->line = 0;
tp->cnt = 0;
tp++;
}
}
/*
* pr_top - print the list of most frequently executed lines
*/
static
pr_top(dottcov_fp)
FILE *dottcov_fp;
{
int i;
fprintf(dottcov_fp, "\n");
fprintf(dottcov_fp, "\n");
fprintf(dottcov_fp, "\t\t Top %d Blocks\n", topn);
fprintf(dottcov_fp, "\n");
fprintf(dottcov_fp, "\t\t Line\t Count\n");
fprintf(dottcov_fp, "\n");
for (i = 0; i < topn; i++) {
if (top[i].cnt > 0) {
fprintf(dottcov_fp, "\t\t%5d\t%8d\n",
top[i].line, top[i].cnt);
} else {
break;
}
}
}
static
pr_stats(fp)
FILE *fp;
{
float percent;
int executed;
fprintf(fp, "\n");
fprintf(fp, "\n");
executed = nbasic - zero_basic;
percent = (executed * 100)/(float) nbasic;
fprintf(fp, "\t%5d\tBasic blocks in this file\n", nbasic);
fprintf(fp, "\t%5d\tBasic blocks executed\n", executed);
fprintf(fp, "\t%5.2f\tPercent of the file executed\n", percent);
fprintf(fp, "\n");
fprintf(fp, " %8d\tTotal basic block executions\n", executions);
percent = executions/(float) nbasic;
fprintf(fp, " %8.2f\tAverage executions per basic block\n", percent);
}
static
usage()
{
fprintf(stderr, "Usage: %s [-number] [-a] files ...\n", cmdname);
exit(1);
}