4.4BSD/usr/src/usr.bin/pascal/pxp/pmon.c

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

/*-
 * Copyright (c) 1980, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef lint
static char sccsid[] = "@(#)pmon.c	8.1 (Berkeley) 6/6/93";
#endif /* not lint */

/*
 * pxp - Pascal execution profiler
 *
 * Bill Joy UCB
 * Version 1.2 January 1979
 */

#include "0.h"

/*
 * Profile counter processing cluster
 *
 * This file contains all routines which do the hard work in profiling.
 *
 * The first group of routines (getit, getpmon, getcore, and pmread)
 * deal with extracting data from the pmon.out and (with more difficulty)
 * core files.
 *
 * The routines cnttab and prttab collect counters for
 * and print the summary table respectively.
 *
 * The routines "*cnt*" deal with manipulation of counters,
 * especially the "current" counter px.
 */
STATIC	struct pxcnt px;

/*
 * Table to record info
 * for procedure/function summary
 */
STATIC	struct pftab {
	long	pfcnt;
	short	pfline;
	char	*pfname;
	short	pflev;
} *zpf;

/*
 * Global variables
 */
STATIC	long *zbuf; 	/* Count buffer */
STATIC	short zcnt;	/* Number of counts */
STATIC	short zpfcnt;	/* Number of proc/funcs's */
STATIC	short gcountr;	/* Unique name generator */
STATIC	short zfil;	/* I/o unit for count data reads */
STATIC	short lastpf;	/* Total # of procs and funcs for consistency chk */

getit(fp)
	register char *fp;
{

	if (core)
		getcore(fp);
	else
		getpmon(fp);
}

/*
 * Setup monitor data buffer from pmon.out
 * style file whose name is fp.
 */
getpmon(fp)
	char *fp;
{
	register char *cp;
	short garbage;

	zfil = open(fp, 0);
	if (zfil < 0) {
		perror(fp);
		pexit(NOSTART);
	}
	if (pmread() < 0 || read(zfil, &garbage, 1) == 1) {
		Perror(fp, "Bad format for pmon.out style file");
		exit(1);
	}
	close(zfil);
	return;
}

STATIC	char nospcm[]	= "Not enough memory for count buffers\n";

pmnospac()
{

	write(2, nospcm, sizeof nospcm);
	pexit(NOSTART);
}

/*
 * Structure of the first few
 * items of a px core dump.
 */
STATIC	struct info {
	char	*off;		/* Self-reference for pure text */
	short	type;		/* 0 = non-pure text, 1 = pure text */
	char	*bp;		/* Core address of pxps struct */
} inf;

/*
 * First few words of the px
 * information structure.
 */
STATIC	struct pxps {
	char	*buf;
	short	cnt;
} pxp;

getcore(fp)
	char *fp;
{

	write(2, "-c: option not supported\n", sizeof("-c: option not supported\n"));
	pexit(ERRS);
/*
	short pm;

	zfil = open(fp, 0);
	if (zfil < 0) {
		perror(fp);
		pexit(NOSTART);
	}
	if (lseek(zfil, 02000, 0) < 0)
		goto format;
	if (read(zfil, &inf, sizeof inf) < 0)
		goto format;
	if (inf.type != 0 && inf.type != 1)
		goto format;
	if (inf.type)
		inf.bp -= inf.off;
	if (lseek(zfil, inf.bp + 02000, 0) < 0)
		goto format;
	if (read(zfil, &pxp, sizeof pxp) != sizeof pxp)
		goto format;
	if (pxp.buf == NIL) {
		Perror(fp, "No profile data in file");
		exit(1);
	}
	if (inf.type)
		pxp.buf -= inf.off;
	if (lseek(zfil, pxp.buf + 02000, 0) < 0)
		goto format;
	if (pmread() < 0)
		goto format;
	close(zfil);
	return;
format:
	Perror(fp, "Not a Pascal system core file");
	exit(1);
*/
}

pmread()
{
	register i;
	register char *cp;
	struct {
		long	no;
		long	tim;
		long	cntrs;
		long	rtns;
	} zmagic;

	if (read(zfil, &zmagic, sizeof zmagic) != sizeof zmagic)
		return (-1);
	if (zmagic.no != 0426)
		return (-1);
	ptvec = zmagic.tim;
	zcnt = zmagic.cntrs;
	zpfcnt = zmagic.rtns;
	cp = zbuf = pcalloc(i = (zcnt + 1) * sizeof *zbuf, 1);
	if (cp == NULL)
		pmnospac();
	cp = zpf = pcalloc(zpfcnt * sizeof *zpf, 1);
	if (cp == NULL)
		pmnospac();
	i -= sizeof(zmagic);
	if (read(zfil, zbuf + (sizeof(zmagic) / sizeof(*zbuf)), i) != i)
		return (-1);
	zbuf++;
	return (0);
}

cnttab(s, no)
	char *s;
	short no;
{
	register struct pftab *pp;

	lastpf++;
	if (table == 0)
		return;
	if (no == zpfcnt)
		cPANIC();
	pp = &zpf[no];
	pp->pfname = s;
	pp->pfline = line;
	pp->pfcnt = nowcnt();
	pp->pflev = cbn;
}

prttab()
{
	register i, j;
	register struct pftab *zpfp;

	if (profile == 0 && table == 0)
		return;
	if (cnts != zcnt || lastpf != zpfcnt)
		cPANIC();
	if (table == 0)
		return;
	if (profile)
		printf("\f\n");
	header();
	printf("\n\tLine\t   Count\n\n");
	zpfp = zpf;
	for (i = 0; i < zpfcnt; i++) {
		printf("\t%4d\t%8ld\t", zpfp->pfline, zpfp->pfcnt);
		if (!justify)
			for (j = zpfp->pflev * unit; j > 1; j--)
				putchar(' ');
		printf("%s\n", zpfp->pfname);
		zpfp++;
	}
}

nowcntr()
{

	return (px.counter);
}

long nowcnt()
{

	return (px.ntimes);
}

long cntof(pxc)
	struct pxcnt *pxc;
{

	if (profile == 0 && table == 0)
		return;
	return (pxc->ntimes);
}

setcnt(l)
	long l;
{

	if (profile == 0 && table == 0)
		return;
	px.counter = --gcountr;
	px.ntimes = l;
	px.gos = gocnt;
	px.printed = 0;
}

savecnt(pxc)
	register struct pxcnt *pxc;
{

	if (profile == 0 && table == 0)
		return;
	pxc->ntimes = px.ntimes;
	pxc->counter = px.counter;
	pxc->gos = px.gos;
	pxc->printed = 1;
}

rescnt(pxc)
	register struct pxcnt *pxc;
{

	if (profile == 0 && table == 0)
		return;
	px.ntimes = pxc->ntimes;
	px.counter = pxc->counter;
	px.gos = gocnt;
	px.printed = pxc->printed;
	return (gocnt != pxc->gos);
}

getcnt()
{

	if (profile == 0 && table == 0)
		return;
	if (cnts == zcnt)
		cPANIC();
	px.counter = cnts;
	px.ntimes = zbuf[cnts];
	px.gos = gocnt;
	px.printed = 0;
	++cnts;
}

unprint()
{

	px.printed = 0;
}

/*
 * Control printing of '|'
 * when profiling.
 */
STATIC	char	nobar;

baroff()
{

	nobar = 1;
}

baron()
{

	nobar = 0;
}

/*
 * Do we want cnt and/or '|' on this line ?
 *	1 = count and '|'
 *	0 = only '|'
 *     -1 = spaces only
 */
shudpcnt()
{

	register i;

	if (nobar)
		return (-1);
	i = px.printed;
	px.printed = 1;
	return (i == 0);
}

STATIC	char mism[]	= "Program and counter data do not correspond\n";

cPANIC()
{

	printf("cnts %d zcnt %d, lastpf %d zpfcnt %d\n",
		cnts, zcnt, lastpf, zpfcnt);
	flush();
	write(2, mism, sizeof mism);
	pexit(ERRS);
}