V10/cmd/lcomp/lprint.c

Compare this file to the similar file:
Show the results in this format:

#include "stdio.h"
#include "ctype.h"
typedef unsigned long ul;
typedef struct {
	char *fname;
	int len;	/* how many counts have been seen */
	int quot;	/* how much has been allocated for cnt */
	int flag;
	unsigned long *cnt;	/* the basic block counts */
	int *instrcnt;		/* instrs per basic block, from .sL */
	int *lastline;		/* last source line containing instr from bb */
} stab;
stab *tab;
int ntab, ltab;
unsigned long N, B, L, V;	/* for summary */
double A, U;
FILE *fd, *sfd, *cfd;
extern FILE *popen();
char fname[512] = "/";	/* not checked for overflow */
char buf[256];
char curfunc[256];
extern char *malloc();
char flg[128];
unsigned long val;
char prcmd[128] = "pr -h %s ";	/* space for extra args */

main(argc, argv)
char **argv;
{	int i, j, seenpart = 0;
	if((fd = fopen("prof.out", "r")) == 0) {
		perror("prof.out");
		exit(1);
	}
	readall();
	fclose(fd);
	for(i = 1; i < argc; i++)
		if(argv[i][0] != '-') {
			seenpart++;
			okfile(argv[i]);
		}
		else for(j = 1; argv[i][j]; j++)
			switch(argv[i][j]) {
			default:	/* assume whole thing is for pr */
				strcat(prcmd, argv[i]);
				strcat(prcmd, " ");
				break;
			case 'b':	/* each bb */
				flg['b']++;
				break;
			case 'a':	/* intermediate everything */
				flg['a']++;
				break;
			case 'i':	/* count machine instrs */
				flg['i']++;
				break;
			case 'f':	/* counts by function */
				flg['f']++;
				flg['s']++;
				break;
			case 'p':	/* print, in addition */
				flg['p']++;
				break;
			case 's':	/* bb summary */
				flg['s']++;
				break;
			case 'c':	/* compress prof.out */
				flg['c']++;
				break;
			}
	if(argc <= seenpart + 1)
		flg['p']++;
	if(!seenpart)
		for(i = 0; i < ntab; i++)
			tab[i].flag = 1;
	if(flg['f']) {
		for(i = 0; i < ntab; i++)
			fsum(tab + i);
	}
	if(flg['s']) {
		for(i = 0; i < ntab; i++)
			summary(tab + i);
		if(ntab > 1)
			printf("%.0fie %ui %uin %.0fbbe %ubb %ubbne total\n",
				A, N, B, U, L, V);
	}
	if(flg['c']) {
		fd = fopen("prof.out", "w");
		if(fd == 0) {
			perror("rewriting prof.out");
			exit(1);
		}
		for(i = 0; i < ntab; i++) {
			fprintf(fd, "%s\n", tab[i].fname);
			for(j = 0; j < tab[i].len; j++)
				fprintf(fd, "%u\n", tab[i].cnt[j]);
		}
		fclose(fd);
	}
	if(flg['p'] || flg['i'] || flg['a'] || flg['b'])
		giantprint();
	exit(0);
}

okfile(s)
char *s;
{	int i, j, k;
	j = strlen(s);
	for(i = 0; i < ntab; i++) {
		k = strlen(tab[i].fname);
		if(strcmp(s, tab[i].fname + k - j) == 0) {
			tab[i].flag = 1;
			return;
		}
	}
	fprintf(stderr, "argument %s not a source file\n", s);
	exit(1);
}

readall()
{	int c, i, index;
	stab *curtab = 0;
sawnl:
	if((c = getc(fd)) == EOF)
		return;
	if(c == '\n')
		goto sawnl;
	if(c == '/') {
		fscanf(fd, "%s", fname+1);
		for(i = 0; i < ntab; i++)
			if(strcmp(fname, tab[i].fname) == 0)
				break;
		if(i >= ntab) {	/* new file */
			if(ltab == 0) {
				tab = (stab *)malloc(20 * sizeof(stab));
				ltab = 20;
			}
			else if(ntab >= ltab)
				tab = (stab *)realloc((char *)tab,
					(ltab += 20) * sizeof(stab));
			tab[ntab].fname = malloc(sizeof(fname) + 1);
			strcpy(tab[ntab].fname, fname);
			tab[ntab].flag = tab[ntab].len = tab[ntab].quot = 0;
			ntab++;
		}
		curtab = tab + i;
		index = 0;
	}
	else if(c < '0' || c > '9') {
		fprintf(stderr, "prof.out has weird format\n");
		abort();
	}
	else {
		ungetc(c, fd);
		fscanf(fd, "%d", &val);
		if(curtab->len <= index) {
			if(curtab->quot == 0) {
				curtab->cnt = (ul *)malloc(100*sizeof(long));
				curtab->quot = 100;
				for(i = 0; i < 100; i++)
					curtab->cnt[i] = 0;
			}
			else if(curtab->len >= curtab->quot) {
				curtab->cnt = (ul *)realloc((char *)curtab->cnt,
					(curtab->quot += 200) * sizeof(long));
				for(i = curtab->quot-200; i < curtab->quot; i++)
					curtab->cnt[i] = 0;
			}
			curtab->len++;
		}
		curtab->cnt[index++] += val;
	}
	goto sawnl;
}

summary(x)
stab *x;
{	unsigned long i, v, n, b;
	double a, u;
	for(i = u = v = 0; i < x->len; i++)
		if(x->cnt[i])
			u += x->cnt[i];
		else
			v++;
	n = strlen(x->fname);
	strcpy(buf, x->fname);
	strcpy(buf + n - 2, ".sL");
	if((fd = fopen(buf, "r")) == 0) {
		perror(buf);
		printf("%s %u bbs %.0f execs %u untouched\n",
			x->fname, x->len, u, v);
		return;
	}
	for(n = a = b = 0; ;) {
		(void) fgets(buf, sizeof(buf), fd);
		if(feof(fd))
			break;
		if(hascolon(buf))
			continue;
		n++;
		i = atoi(buf)/4 - 3;
		if(x->cnt[i])
			a += x->cnt[i];
		else
			b++;
	}
	printf("%.0fie %ui %uine %.0fbbe %ubb %ubbne %s\n", a, n, b, u, x->len,
		v, x->fname);
	fclose(fd);
	A += a; N += n; B += b; U += u; L += x->len; V += v;
}

fsum(x)
stab *x;
{	unsigned i, v, n, b, cnt;
	double a, u;
	char *p;
	strcpy(buf, x->fname);
	n = strlen(x->fname);
	strcpy(buf + n - 2, ".sL");
	if((fd = fopen(buf, "r")) == 0) {
		perror(buf);
		return;
	}
	curfunc[0] = 0;
	for(cnt = v = n = b = a = u = 0;;) {
		(void) fgets(buf, sizeof(buf), fd);
		if(feof(fd))
			break;
		if(hascolon(buf)) {
			/* 24 foo.c: 456	or
			 * 24 foo.c: _funcjunk */
			for(p = buf; *p != ':'; p++)
				;
			while(isspace(*++p))
				;
			if(isdigit(*p))
				continue;
			if(curfunc[0] != 0)
				printf("%.0fie %dcalls %ui %uine %s\n",
					a, v, n, b, curfunc);
			for(i = 0; *p && *p != '\n'; i++)
				curfunc[i] = *p++;
			curfunc[i] = 0;
			a = n = b = 0;
			i = atoi(buf)/4 - 3;
			v = x->cnt[i];
			continue;
		}
		n++;
		i = atoi(buf)/4 - 3;
		if(x->cnt[i])
			a += x->cnt[i];
		else
			b++;
	}
	if(n > 0)
		printf("%.0fie %dcalls %ui %uine %s\n", a, v, n, b, curfunc);
	fclose(fd);
}

giantprint()
{	int i, n;
	for(i = 0; i < ntab; i++) {
		if(tab[i].flag == 0)
			continue;
	/* the fname file is the source, there should be a corresponding
	 * .sL file for correlation between basic blocks and source.
	 * If fname is a .s file, the .sL file is all there is */
		n = strlen(tab[i].fname);
		if(strcmp(".s", tab[i].fname + n - 2) == 0) {
			sfile(tab + i);
			continue;
		}
		sfd = fopen(tab[i].fname, "r");
		if(sfd == 0 && !flg['a']) {
			perror(tab[i].fname);
			return;
		}
		strcpy(buf, tab[i].fname);
		strcpy(buf + n - 1, "sL");
		if((cfd = fopen(buf, "r")) == 0) {
			fprintf(stderr, "no intermediate listing file ");
			perror(buf);
			fclose(sfd);
			return;
		}
		sprintf(buf, prcmd, tab[i].fname);
		if(!flg['a'])
			fd = popen(buf, "w");
		if(!flg['a'])
			xlistit(tab + i);
		else
			listit(tab + i);
		if(fd)
			pclose(fd);
		if(sfd)
			fclose(sfd);
		fclose(cfd);
	}
}

sfile(x)
stab *x;
{	int i;
	char *p;
	strcpy(buf, x->fname);
	strcat(buf, "L");
	sfd = fopen(buf, "r");
	if(sfd == 0) {
		perror(buf);
		return;
	}
	sprintf(buf, "pr -h %s", x->fname);
	fd = popen(buf, "w");
	if(fd == 0) {
		perror(buf);
		fclose(sfd);
		return;
	}
	for(;;) {
		(void) fgets(buf, sizeof(buf), sfd);
		if(feof(sfd)) {
			pclose(fd);
			fclose(sfd);
			return;
		}
		for(i = 0, p = buf; *p >= '0' && *p <= '9'; p++)
			i = 10 * i + *p - '0';
		i = i/4 - 3;
		fprintf(fd, "%u\t%s", x->cnt[i], p);
	}
}

/* function added, so name (stripnum) is now misleading */
char *
stripnum(s)
char *s;
{	char *p;
	while(*s && (isdigit(*s) || isspace(*s)))
		s++;
	for(p = s; *p && *p != '\n'; p++)
		;
	if(*p == '\n')
		*p = ' ';
	return(s);
}

listit(x)
stab *x;
{	int i;
	char *p;
	for(;;) {
		(void) fgets(buf, sizeof(buf), cfd);
		if(feof(cfd))
			break;
		for(p = buf; *p && *p != ':' ; p++)
			;
		if(*p++ != ':') {	/* these are instructions */
			i = x->cnt[atoi(buf)/4 - 3];
			printf("%d\t%s\n", i, stripnum(buf));
			continue;
		}
		else {
			printf("%s", stripnum(buf));
			if(atoi(p) == 0) {	/* foo.c: _main */
				putchar('\n');
				continue;
			}
			(void) fgets(buf, sizeof(buf), sfd);
			printf("%s", buf);
			continue;
		}
	}
}

xlistit(x)
stab *x;
{	int lnum, i, icnt, bcnt;
	char *p;
	x->instrcnt = (int *) malloc(x->len * sizeof(int));
	x->lastline = (int *) malloc(x->len * sizeof(int));
	if(!x->instrcnt || !x->lastline) {
		fprintf(stderr, "out of memory\n");
		return;
	}
	for(i = 0; i < x->len; i++)
		x->instrcnt[i] = x->lastline[i] = 0;
	for(;;) {
		(void) fgets(buf, sizeof(buf), cfd);
		if(feof(cfd))
			break;
		for(p = buf; *p && *p != ':'; p++)
			;
		if(*p++ != ':') {	/* instruction */
			x->instrcnt[atoi(buf)/4 - 3]++;
			continue;
		}
		lnum = atoi(p);		/* hmm (atoi (" x..") is zero?)*/
		if(lnum <= 0)
			continue;
		i = atoi(buf)/4 - 3;
		x->lastline[i] = lnum;
	}
	/* now read all the source lines and print out appropriate stuff */
	for(lnum = 1, i = 0;; lnum++) {
		(void) fgets(buf, sizeof(buf), sfd);
		if(feof(sfd))
			return;
		icnt = bcnt = 0;
		for(; i < x->len && x->lastline[i] <= lnum; i++) {
			if(flg['b'] && flg['i'])
				fprintf(fd, "%u,%ui ", x->cnt[i],
					x->cnt[i] * x->instrcnt[i]);
			else if(flg['b'])
				fprintf(fd, "%u ", x->cnt[i]);
			else {
				icnt += x->cnt[i] * x->instrcnt[i];
				bcnt += x->cnt[i];
			}
		}
		if(!flg['b'] && flg['p'] && bcnt)
			fprintf(fd, "%u ", bcnt);
		if(!flg['b'] && flg['i'] && icnt)
			fprintf(fd, "%ui ", icnt);
		fprintf(fd, "\t%s", buf);
	}
}

hascolon(s)
register char *s;
{
	for(; *s && *s != ':'; s++)
		;
	if(*s == ':')
		return(1);
	else
		return(0);
}