#include <stdio.h>
#include <memory.h>

#define ck_fread fread
#define ck_malloc malloc

/* gmon header */
struct gm_header {
    void		*low;		/* low pc  */
    void		*high;		/* hi  pc  */
    unsigned long	nbytes;		/* bytes in header + histo size */
};

typedef unsigned short CHUNK; /* type of each histogram entry */

struct gm_call {	/* gm call record */
    void	*from;	/* the caller 				*/
    void	*to;	/* the called function (callee)		*/
    unsigned long ncalls; /* # of calls from FROM to  TO	*/
};

#define	GMON_FILE	"gmon.out"	/* name of GMON file */

main(argc, argv)
int argc;
char **argv;
{
    char *file;
    FILE *fp;
    struct gm_header head;
    struct gm_call   arc;
    unsigned short h;
    unsigned long hist_size;
    unsigned short *hist;
    long i;

    if(argc > 1)
	file = *++argv;
    else
	file = GMON_FILE;
    
    if((fp = fopen(file, "rb")) == NULL)
    {
	perror(file);
	exit(1);
    }
    ck_fread(&head, sizeof(head), 1L, fp);
    printf("lowpc %ld   hipc %ld hist size %ld tot %ld\n", head.low,
	    head.high, (hist_size = head.nbytes - sizeof(head)), head.nbytes);
    hist = (unsigned short *)ck_malloc(hist_size);
    ck_fread(hist, hist_size, 1L, fp);
    printf("\nHistogram:\n");
    for(i = 0; i < hist_size/sizeof(short); i++)
	printf("%ld:\t%d\n", i, (int)hist[i]);

    i = 0;
    printf("\nCall Graph:\n");
    while(fread(&arc, sizeof(arc), 1L, fp) == 1L)
	printf("%ld:\t from %ld\tto %ld\tcalls %ld\n", i++, arc.from, arc.to,
		arc.ncalls);
    fclose(fp);
}

    