synchronizing at version 2
[unix-history] / usr / src / usr.bin / pascal / pxp / pmon.c
CommitLineData
ebd61f12 1static char *sccsid = "@(#)pmon.c 2.1 (Berkeley) %G%";
6812412e
PK
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 */
28STATIC struct pxcnt px;
29
30/*
31 * Table to record info
32 * for procedure/function summary
33 */
34STATIC struct pftab {
35 long pfcnt;
36 short pfline;
37 char *pfname;
38 short pflev;
39} *zpf;
40
41/*
42 * Global variables
43 */
44STATIC long *zbuf; /* Count buffer */
45STATIC short zcnt; /* Number of counts */
46STATIC short zpfcnt; /* Number of proc/funcs's */
47STATIC short gcountr; /* Unique name generator */
48STATIC short zfil; /* I/o unit for count data reads */
49STATIC short lastpf; /* Total # of procs and funcs for consistency chk */
50
51getit(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 */
65getpmon(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
f4e01610 84STATIC char nospcm[] = "Not enough memory for count buffers\n";
6812412e
PK
85
86pmnospac()
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 */
97STATIC 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 */
107STATIC struct pxps {
108 char *buf;
109 short cnt;
110} pxp;
111
112getcore(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;
150format:
151 Perror(fp, "Not a Pascal system core file");
152 exit(1);
153*/
154}
155
156pmread()
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);
f4e01610 181 if (read(zfil, zbuf + (sizeof(zmagic) / sizeof(*zbuf)), i) != i)
6812412e
PK
182 return (-1);
183 zbuf++;
184 return (0);
185}
186
187cnttab(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
205prttab()
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
231nowcntr()
232{
233
234 return (px.counter);
235}
236
237long nowcnt()
238{
239
240 return (px.ntimes);
241}
242
243long cntof(pxc)
244 struct pxcnt *pxc;
245{
246
247 if (profile == 0 && table == 0)
248 return;
249 return (pxc->ntimes);
250}
251
252setcnt(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
264savecnt(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
276rescnt(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
289getcnt()
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
303unprint()
304{
305
306 px.printed = 0;
307}
308
309/*
310 * Control printing of '|'
311 * when profiling.
312 */
313STATIC char nobar;
314
315baroff()
316{
317
318 nobar = 1;
319}
320
321baron()
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 */
333shudpcnt()
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
f4e01610 345STATIC char mism[] = "Program and counter data do not correspond\n";
6812412e
PK
346
347cPANIC()
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}