xref: /original-bsd/usr.bin/pascal/pxp/pmon.c (revision 0b685140)
1 static	char *sccsid = "@(#)pmon.c	1.2 (Berkeley) 03/07/81";
2 /* Copyright (c) 1979 Regents of the University of California */
3 #
4 /*
5  * pxp - Pascal execution profiler
6  *
7  * Bill Joy UCB
8  * Version 1.2 January 1979
9  */
10 
11 #include "0.h"
12 
13 /*
14  * Profile counter processing cluster
15  *
16  * This file contains all routines which do the hard work in profiling.
17  *
18  * The first group of routines (getit, getpmon, getcore, and pmread)
19  * deal with extracting data from the pmon.out and (with more difficulty)
20  * core files.
21  *
22  * The routines cnttab and prttab collect counters for
23  * and print the summary table respectively.
24  *
25  * The routines "*cnt*" deal with manipulation of counters,
26  * especially the "current" counter px.
27  */
28 STATIC	struct pxcnt px;
29 
30 /*
31  * Table to record info
32  * for procedure/function summary
33  */
34 STATIC	struct pftab {
35 	long	pfcnt;
36 	short	pfline;
37 	char	*pfname;
38 	short	pflev;
39 } *zpf;
40 
41 /*
42  * Global variables
43  */
44 STATIC	long *zbuf; 	/* Count buffer */
45 STATIC	short zcnt;	/* Number of counts */
46 STATIC	short zpfcnt;	/* Number of proc/funcs's */
47 STATIC	short gcountr;	/* Unique name generator */
48 STATIC	short zfil;	/* I/o unit for count data reads */
49 STATIC	short lastpf;	/* Total # of procs and funcs for consistency chk */
50 
51 getit(fp)
52 	register char *fp;
53 {
54 
55 	if (core)
56 		getcore(fp);
57 	else
58 		getpmon(fp);
59 }
60 
61 /*
62  * Setup monitor data buffer from pmon.out
63  * style file whose name is fp.
64  */
65 getpmon(fp)
66 	char *fp;
67 {
68 	register char *cp;
69 	short garbage;
70 
71 	zfil = open(fp, 0);
72 	if (zfil < 0) {
73 		perror(fp);
74 		pexit(NOSTART);
75 	}
76 	if (pmread() < 0 || read(zfil, &garbage, 1) == 1) {
77 		Perror(fp, "Bad format for pmon.out style file");
78 		exit(1);
79 	}
80 	close(zfil);
81 	return;
82 }
83 
84 STATIC	char nospcm[]	= "Not enough memory for count buffers\n";
85 
86 pmnospac()
87 {
88 
89 	write(2, nospcm, sizeof nospcm);
90 	pexit(NOSTART);
91 }
92 
93 /*
94  * Structure of the first few
95  * items of a px core dump.
96  */
97 STATIC	struct info {
98 	char	*off;		/* Self-reference for pure text */
99 	short	type;		/* 0 = non-pure text, 1 = pure text */
100 	char	*bp;		/* Core address of pxps struct */
101 } inf;
102 
103 /*
104  * First few words of the px
105  * information structure.
106  */
107 STATIC	struct pxps {
108 	char	*buf;
109 	short	cnt;
110 } pxp;
111 
112 getcore(fp)
113 	char *fp;
114 {
115 
116 	write(2, "-c: option not supported\n", sizeof("-c: option not supported\n"));
117 	pexit(ERRS);
118 /*
119 	short pm;
120 
121 	zfil = open(fp, 0);
122 	if (zfil < 0) {
123 		perror(fp);
124 		pexit(NOSTART);
125 	}
126 	if (lseek(zfil, 02000, 0) < 0)
127 		goto format;
128 	if (read(zfil, &inf, sizeof inf) < 0)
129 		goto format;
130 	if (inf.type != 0 && inf.type != 1)
131 		goto format;
132 	if (inf.type)
133 		inf.bp =- inf.off;
134 	if (lseek(zfil, inf.bp + 02000, 0) < 0)
135 		goto format;
136 	if (read(zfil, &pxp, sizeof pxp) != sizeof pxp)
137 		goto format;
138 	if (pxp.buf == NIL) {
139 		Perror(fp, "No profile data in file");
140 		exit(1);
141 	}
142 	if (inf.type)
143 		pxp.buf =- inf.off;
144 	if (lseek(zfil, pxp.buf + 02000, 0) < 0)
145 		goto format;
146 	if (pmread() < 0)
147 		goto format;
148 	close(zfil);
149 	return;
150 format:
151 	Perror(fp, "Not a Pascal system core file");
152 	exit(1);
153 */
154 }
155 
156 pmread()
157 {
158 	register i;
159 	register char *cp;
160 	struct {
161 		long	no;
162 		long	tim;
163 		long	cntrs;
164 		long	rtns;
165 	} zmagic;
166 
167 	if (read(zfil, &zmagic, sizeof zmagic) != sizeof zmagic)
168 		return (-1);
169 	if (zmagic.no != 0426)
170 		return (-1);
171 	ptvec = zmagic.tim;
172 	zcnt = zmagic.cntrs;
173 	zpfcnt = zmagic.rtns;
174 	cp = zbuf = alloc(i = (zcnt + 1) * sizeof *zbuf);
175 	if (cp == -1)
176 		pmnospac();
177 	cp = zpf = alloc(zpfcnt * sizeof *zpf);
178 	if (cp == -1)
179 		pmnospac();
180 	i -= sizeof(zmagic);
181 	if (read(zfil, zbuf + (sizeof(zmagic) / sizeof(*zbuf)), i) != i)
182 		return (-1);
183 	zbuf++;
184 	return (0);
185 }
186 
187 cnttab(s, no)
188 	char *s;
189 	short no;
190 {
191 	register struct pftab *pp;
192 
193 	lastpf++;
194 	if (table == 0)
195 		return;
196 	if (no == zpfcnt)
197 		cPANIC();
198 	pp = &zpf[no];
199 	pp->pfname = s;
200 	pp->pfline = line;
201 	pp->pfcnt = nowcnt();
202 	pp->pflev = cbn;
203 }
204 
205 prttab()
206 {
207 	register i, j;
208 	register struct pftab *zpfp;
209 
210 	if (profile == 0 && table == 0)
211 		return;
212 	if (cnts != zcnt || lastpf != zpfcnt)
213 		cPANIC();
214 	if (table == 0)
215 		return;
216 	if (profile)
217 		printf("\f\n");
218 	header();
219 	printf("\n\tLine\t   Count\n\n");
220 	zpfp = zpf;
221 	for (i = 0; i < zpfcnt; i++) {
222 		printf("\t%4d\t%8ld\t", zpfp->pfline, zpfp->pfcnt);
223 		if (!justify)
224 			for (j = zpfp->pflev * unit; j > 1; j--)
225 				putchar(' ');
226 		printf("%s\n", zpfp->pfname);
227 		zpfp++;
228 	}
229 }
230 
231 nowcntr()
232 {
233 
234 	return (px.counter);
235 }
236 
237 long nowcnt()
238 {
239 
240 	return (px.ntimes);
241 }
242 
243 long cntof(pxc)
244 	struct pxcnt *pxc;
245 {
246 
247 	if (profile == 0 && table == 0)
248 		return;
249 	return (pxc->ntimes);
250 }
251 
252 setcnt(l)
253 	long l;
254 {
255 
256 	if (profile == 0 && table == 0)
257 		return;
258 	px.counter = --gcountr;
259 	px.ntimes = l;
260 	px.gos = gocnt;
261 	px.printed = 0;
262 }
263 
264 savecnt(pxc)
265 	register struct pxcnt *pxc;
266 {
267 
268 	if (profile == 0 && table == 0)
269 		return;
270 	pxc->ntimes = px.ntimes;
271 	pxc->counter = px.counter;
272 	pxc->gos = px.gos;
273 	pxc->printed = 1;
274 }
275 
276 rescnt(pxc)
277 	register struct pxcnt *pxc;
278 {
279 
280 	if (profile == 0 && table == 0)
281 		return;
282 	px.ntimes = pxc->ntimes;
283 	px.counter = pxc->counter;
284 	px.gos = gocnt;
285 	px.printed = pxc->printed;
286 	return (gocnt != pxc->gos);
287 }
288 
289 getcnt()
290 {
291 
292 	if (profile == 0 && table == 0)
293 		return;
294 	if (cnts == zcnt)
295 		cPANIC();
296 	px.counter = cnts;
297 	px.ntimes = zbuf[cnts];
298 	px.gos = gocnt;
299 	px.printed = 0;
300 	++cnts;
301 }
302 
303 unprint()
304 {
305 
306 	px.printed = 0;
307 }
308 
309 /*
310  * Control printing of '|'
311  * when profiling.
312  */
313 STATIC	char	nobar;
314 
315 baroff()
316 {
317 
318 	nobar = 1;
319 }
320 
321 baron()
322 {
323 
324 	nobar = 0;
325 }
326 
327 /*
328  * Do we want cnt and/or '|' on this line ?
329  *	1 = count and '|'
330  *	0 = only '|'
331  *     -1 = spaces only
332  */
333 shudpcnt()
334 {
335 
336 	register i;
337 
338 	if (nobar)
339 		return (-1);
340 	i = px.printed;
341 	px.printed = 1;
342 	return (i == 0);
343 }
344 
345 STATIC	char mism[]	= "Program and counter data do not correspond\n";
346 
347 cPANIC()
348 {
349 
350 	printf("cnts %d zcnt %d, lastpf %d zpfcnt %d\n",
351 		cnts, zcnt, lastpf, zpfcnt);
352 	flush();
353 	write(2, mism, sizeof mism);
354 	pexit(ERRS);
355 }
356