xref: /inferno-os/appl/lib/profile.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsythimplement Profile;
2*37da2899SCharles.Forsyth
3*37da2899SCharles.Forsythinclude "sys.m";
4*37da2899SCharles.Forsyth	sys: Sys;
5*37da2899SCharles.Forsythinclude "draw.m";
6*37da2899SCharles.Forsythinclude "bufio.m";
7*37da2899SCharles.Forsyth	bufio: Bufio;
8*37da2899SCharles.Forsyth	Iobuf: import bufio;
9*37da2899SCharles.Forsythinclude "workdir.m";
10*37da2899SCharles.Forsyth	workdir: Workdir;
11*37da2899SCharles.Forsythinclude "debug.m";
12*37da2899SCharles.Forsyth	debug: Debug;
13*37da2899SCharles.Forsyth	Sym: import debug;
14*37da2899SCharles.Forsythinclude "dis.m";
15*37da2899SCharles.Forsyth	dism: Dis;
16*37da2899SCharles.Forsythinclude "profile.m";
17*37da2899SCharles.Forsyth
18*37da2899SCharles.Forsyth# merge common code
19*37da2899SCharles.Forsyth
20*37da2899SCharles.ForsythPROF: con "/prof";
21*37da2899SCharles.ForsythCTL: con "ctl";
22*37da2899SCharles.ForsythNAME: con "name";
23*37da2899SCharles.ForsythMPATH: con "path";
24*37da2899SCharles.ForsythHISTOGRAM: con "histogram";
25*37da2899SCharles.Forsyth
26*37da2899SCharles.Forsythinited: int;
27*37da2899SCharles.Forsythmodl: string;
28*37da2899SCharles.Forsythlasterr: string;
29*37da2899SCharles.Forsyth
30*37da2899SCharles.Forsythbspath := array[] of
31*37da2899SCharles.Forsyth{
32*37da2899SCharles.Forsyth	("/dis/",		"/appl/cmd/"),
33*37da2899SCharles.Forsyth	("/dis/",		"/appl/"),
34*37da2899SCharles.Forsyth};
35*37da2899SCharles.Forsyth
36*37da2899SCharles.Forsytherror(s: string)
37*37da2899SCharles.Forsyth{
38*37da2899SCharles.Forsyth	lasterr = sys->sprint("%s: %r", s);
39*37da2899SCharles.Forsyth}
40*37da2899SCharles.Forsyth
41*37da2899SCharles.Forsytherror0(s: string)
42*37da2899SCharles.Forsyth{
43*37da2899SCharles.Forsyth	lasterr = s;
44*37da2899SCharles.Forsyth}
45*37da2899SCharles.Forsyth
46*37da2899SCharles.Forsythcleare()
47*37da2899SCharles.Forsyth{
48*37da2899SCharles.Forsyth	lasterr = nil;
49*37da2899SCharles.Forsyth}
50*37da2899SCharles.Forsyth
51*37da2899SCharles.Forsythlasterror(): string
52*37da2899SCharles.Forsyth{
53*37da2899SCharles.Forsyth	return lasterr;
54*37da2899SCharles.Forsyth}
55*37da2899SCharles.Forsyth
56*37da2899SCharles.Forsythinit(): int
57*37da2899SCharles.Forsyth{
58*37da2899SCharles.Forsyth	cleare();
59*37da2899SCharles.Forsyth	sys = load Sys Sys->PATH;
60*37da2899SCharles.Forsyth	bufio = load Bufio Bufio->PATH;
61*37da2899SCharles.Forsyth	debug = load Debug Debug->PATH;
62*37da2899SCharles.Forsyth	if(debug == nil){
63*37da2899SCharles.Forsyth		error("cannot load Debug module");
64*37da2899SCharles.Forsyth		return -1;
65*37da2899SCharles.Forsyth	}
66*37da2899SCharles.Forsyth	debug->init();
67*37da2899SCharles.Forsyth	(ok, nil) := sys->stat(PROF + "/ctl");
68*37da2899SCharles.Forsyth	if (ok == -1) {
69*37da2899SCharles.Forsyth		if(sys->bind("#P", PROF, Sys->MREPL|Sys->MCREATE) < 0){
70*37da2899SCharles.Forsyth			error(sys->sprint("cannot bind prof device to /prof"));
71*37da2899SCharles.Forsyth			return -1;
72*37da2899SCharles.Forsyth		}
73*37da2899SCharles.Forsyth	}
74*37da2899SCharles.Forsyth	inited = 1;
75*37da2899SCharles.Forsyth	return 0;
76*37da2899SCharles.Forsyth}
77*37da2899SCharles.Forsyth
78*37da2899SCharles.Forsythend(): int
79*37da2899SCharles.Forsyth{
80*37da2899SCharles.Forsyth	cleare();
81*37da2899SCharles.Forsyth	inited = 0;
82*37da2899SCharles.Forsyth	modl = nil;
83*37da2899SCharles.Forsyth	if(write(mkpath(PROF, CTL), "end") < 0)
84*37da2899SCharles.Forsyth		return -1;
85*37da2899SCharles.Forsyth	return 0;
86*37da2899SCharles.Forsyth}
87*37da2899SCharles.Forsyth
88*37da2899SCharles.Forsythstart(): int
89*37da2899SCharles.Forsyth{
90*37da2899SCharles.Forsyth	cleare();
91*37da2899SCharles.Forsyth	if(!inited && init() < 0)
92*37da2899SCharles.Forsyth		return -1;
93*37da2899SCharles.Forsyth	if(write(mkpath(PROF, CTL), "module " + modl) < 0)
94*37da2899SCharles.Forsyth		return -1;
95*37da2899SCharles.Forsyth	if(write(mkpath(PROF, CTL), "start") < 0)
96*37da2899SCharles.Forsyth		return -1;
97*37da2899SCharles.Forsyth	return 0;
98*37da2899SCharles.Forsyth}
99*37da2899SCharles.Forsyth
100*37da2899SCharles.Forsythcpstart(pid: int): int
101*37da2899SCharles.Forsyth{
102*37da2899SCharles.Forsyth	cleare();
103*37da2899SCharles.Forsyth	if(!inited && init() < 0)
104*37da2899SCharles.Forsyth		return -1;
105*37da2899SCharles.Forsyth	if(write(mkpath(PROF, CTL), "module " + modl) < 0)
106*37da2899SCharles.Forsyth		return -1;
107*37da2899SCharles.Forsyth	if(write(mkpath(PROF, CTL), "startcp " + string pid) < 0)
108*37da2899SCharles.Forsyth		return -1;
109*37da2899SCharles.Forsyth	return 0;
110*37da2899SCharles.Forsyth}
111*37da2899SCharles.Forsyth
112*37da2899SCharles.Forsythmemstart(m: int): int
113*37da2899SCharles.Forsyth{
114*37da2899SCharles.Forsyth	cleare();
115*37da2899SCharles.Forsyth	if(!inited && init() < 0)
116*37da2899SCharles.Forsyth		return -1;
117*37da2899SCharles.Forsyth	if(modl != nil && write(mkpath(PROF, CTL), "module " + modl) < 0)
118*37da2899SCharles.Forsyth		return -1;
119*37da2899SCharles.Forsyth	start := "startmp";
120*37da2899SCharles.Forsyth	if(m == 0)
121*37da2899SCharles.Forsyth		m = MAIN|HEAP|IMAGE;
122*37da2899SCharles.Forsyth	if(m&MAIN)
123*37da2899SCharles.Forsyth		start += "1";
124*37da2899SCharles.Forsyth	if(m&HEAP)
125*37da2899SCharles.Forsyth		start += "2";
126*37da2899SCharles.Forsyth	if(m&IMAGE)
127*37da2899SCharles.Forsyth		start += "3";
128*37da2899SCharles.Forsyth	if(write(mkpath(PROF, CTL), start) < 0)
129*37da2899SCharles.Forsyth		return -1;
130*37da2899SCharles.Forsyth	return 0;
131*37da2899SCharles.Forsyth}
132*37da2899SCharles.Forsyth
133*37da2899SCharles.Forsythstop(): int
134*37da2899SCharles.Forsyth{
135*37da2899SCharles.Forsyth	cleare();
136*37da2899SCharles.Forsyth	if(!inited && init() < 0)
137*37da2899SCharles.Forsyth		return -1;
138*37da2899SCharles.Forsyth	if(write(mkpath(PROF, CTL), "stop") < 0)
139*37da2899SCharles.Forsyth		return -1;
140*37da2899SCharles.Forsyth	return 0;
141*37da2899SCharles.Forsyth}
142*37da2899SCharles.Forsyth
143*37da2899SCharles.Forsythsample(i: int): int
144*37da2899SCharles.Forsyth{
145*37da2899SCharles.Forsyth	cleare();
146*37da2899SCharles.Forsyth	if(i <= 0){
147*37da2899SCharles.Forsyth		error0(sys->sprint("bad sample rate %d", i));
148*37da2899SCharles.Forsyth		return -1;
149*37da2899SCharles.Forsyth	}
150*37da2899SCharles.Forsyth	if(write(mkpath(PROF, CTL), "interval " + string i) < 0)
151*37da2899SCharles.Forsyth		return -1;
152*37da2899SCharles.Forsyth	return 0;
153*37da2899SCharles.Forsyth}
154*37da2899SCharles.Forsyth
155*37da2899SCharles.Forsythprofile(m: string): int
156*37da2899SCharles.Forsyth{
157*37da2899SCharles.Forsyth	cleare();
158*37da2899SCharles.Forsyth	modl = m + " " + modl;
159*37da2899SCharles.Forsyth	return 0;
160*37da2899SCharles.Forsyth}
161*37da2899SCharles.Forsyth
162*37da2899SCharles.Forsythstats(): Prof
163*37da2899SCharles.Forsyth{
164*37da2899SCharles.Forsyth	mp: Modprof;
165*37da2899SCharles.Forsyth	p: Prof;
166*37da2899SCharles.Forsyth	mpl: list of Modprof;
167*37da2899SCharles.Forsyth
168*37da2899SCharles.Forsyth	cleare();
169*37da2899SCharles.Forsyth	fd := sys->open(PROF, Sys->OREAD);
170*37da2899SCharles.Forsyth	if(fd == nil){
171*37da2899SCharles.Forsyth		error(sys->sprint("cannot open %s for reading", PROF));
172*37da2899SCharles.Forsyth		return (nil, 0, nil);
173*37da2899SCharles.Forsyth	}
174*37da2899SCharles.Forsyth	total := 0;
175*37da2899SCharles.Forsyth	for(;;){
176*37da2899SCharles.Forsyth		(nr, d) := sys->dirread(fd);
177*37da2899SCharles.Forsyth		if(nr <= 0)
178*37da2899SCharles.Forsyth			break;
179*37da2899SCharles.Forsyth		for(i := 0; i < nr; i++){
180*37da2899SCharles.Forsyth			if(d[i].name == CTL)
181*37da2899SCharles.Forsyth				continue;
182*37da2899SCharles.Forsyth			dn := mkpath(PROF, d[i].name);
183*37da2899SCharles.Forsyth			mp.name = read(mkpath(dn, NAME));
184*37da2899SCharles.Forsyth			mp.path = read(mkpath(dn, MPATH));
185*37da2899SCharles.Forsyth			fdh := sys->open(mkpath(dn, HISTOGRAM), Sys->OREAD);
186*37da2899SCharles.Forsyth			if(fdh == nil)
187*37da2899SCharles.Forsyth				continue;
188*37da2899SCharles.Forsyth			(mp.srcpath, mp.linetab, mp.funtab, mp.total) = tprofile(fdh, mp.path);
189*37da2899SCharles.Forsyth			if((sp := getb(mp.path)) != nil)
190*37da2899SCharles.Forsyth				mp.srcpath = sp;
191*37da2899SCharles.Forsyth			if(mp.total != 0){
192*37da2899SCharles.Forsyth				mpl = mp :: mpl;
193*37da2899SCharles.Forsyth				total += mp.total;
194*37da2899SCharles.Forsyth			}
195*37da2899SCharles.Forsyth		}
196*37da2899SCharles.Forsyth	}
197*37da2899SCharles.Forsyth	p.mods = mpl;
198*37da2899SCharles.Forsyth	p.total = total;
199*37da2899SCharles.Forsyth	return p;
200*37da2899SCharles.Forsyth}
201*37da2899SCharles.Forsyth
202*37da2899SCharles.Forsythcpstats(rec: int, v: int): Prof
203*37da2899SCharles.Forsyth{
204*37da2899SCharles.Forsyth	m: string;
205*37da2899SCharles.Forsyth	mp: Modprof;
206*37da2899SCharles.Forsyth	p: Prof;
207*37da2899SCharles.Forsyth	mpl: list of Modprof;
208*37da2899SCharles.Forsyth
209*37da2899SCharles.Forsyth	cleare();
210*37da2899SCharles.Forsyth	fd := sys->open(PROF, Sys->OREAD);
211*37da2899SCharles.Forsyth	if(fd == nil){
212*37da2899SCharles.Forsyth		error(sys->sprint("cannot open %s for reading", PROF));
213*37da2899SCharles.Forsyth		return (nil, 0, nil);
214*37da2899SCharles.Forsyth	}
215*37da2899SCharles.Forsyth	total := 0;
216*37da2899SCharles.Forsyth	for(;;){
217*37da2899SCharles.Forsyth		(nr, d) := sys->dirread(fd);
218*37da2899SCharles.Forsyth		if(nr <= 0)
219*37da2899SCharles.Forsyth			break;
220*37da2899SCharles.Forsyth		for(i:=0; i<nr; i++){
221*37da2899SCharles.Forsyth			if(d[i].name == CTL)
222*37da2899SCharles.Forsyth				continue;
223*37da2899SCharles.Forsyth			dn := mkpath(PROF, d[i].name);
224*37da2899SCharles.Forsyth			mp.name = read(mkpath(dn, NAME));
225*37da2899SCharles.Forsyth			mp.path = read(mkpath(dn, MPATH));
226*37da2899SCharles.Forsyth			fdh := sys->open(mkpath(dn, HISTOGRAM), Sys->OREAD);
227*37da2899SCharles.Forsyth			if(fdh == nil)
228*37da2899SCharles.Forsyth				continue;
229*37da2899SCharles.Forsyth			(m, mp.srcpath, mp.rawtab, mp.linetab, mp.rngtab, mp.total, mp.coverage) = cprofile(fdh, mp.path, rec, v);
230*37da2899SCharles.Forsyth			if(mp.name == nil)
231*37da2899SCharles.Forsyth				mp.name = m;
232*37da2899SCharles.Forsyth			if((sp := getb(mp.path)) != nil)
233*37da2899SCharles.Forsyth				mp.srcpath = sp;
234*37da2899SCharles.Forsyth			if(len mp.rawtab > 0){
235*37da2899SCharles.Forsyth				mpl = mp :: mpl;
236*37da2899SCharles.Forsyth				total += mp.total;
237*37da2899SCharles.Forsyth			}
238*37da2899SCharles.Forsyth		}
239*37da2899SCharles.Forsyth	}
240*37da2899SCharles.Forsyth	p.mods = mpl;
241*37da2899SCharles.Forsyth	p.total = total;
242*37da2899SCharles.Forsyth	return p;
243*37da2899SCharles.Forsyth}
244*37da2899SCharles.Forsyth
245*37da2899SCharles.Forsythcpfstats(v: int): Prof
246*37da2899SCharles.Forsyth{
247*37da2899SCharles.Forsyth	mp: Modprof;
248*37da2899SCharles.Forsyth	p: Prof;
249*37da2899SCharles.Forsyth	mpl: list of Modprof;
250*37da2899SCharles.Forsyth
251*37da2899SCharles.Forsyth	cleare();
252*37da2899SCharles.Forsyth	total := 0;
253*37da2899SCharles.Forsyth	(nil, l) := sys->tokenize(modl, " ");
254*37da2899SCharles.Forsyth	for( ; l != nil; l = tl l){
255*37da2899SCharles.Forsyth		s := hd l;
256*37da2899SCharles.Forsyth		suf := suff(s);
257*37da2899SCharles.Forsyth		if(suf == nil)
258*37da2899SCharles.Forsyth			s += ".dis";
259*37da2899SCharles.Forsyth		else
260*37da2899SCharles.Forsyth			s = repsuff(s, "."+suf, ".dis");
261*37da2899SCharles.Forsyth		if(!exists(s) && s[0] != '/' && s[0:2] != "./")
262*37da2899SCharles.Forsyth			s = "/dis/"+s;
263*37da2899SCharles.Forsyth		mp.path = s;
264*37da2899SCharles.Forsyth		(mp.name, mp.srcpath, mp.rawtab, mp.linetab, mp.rngtab, mp.total, mp.coverage) = cprofile(nil, mp.path, 1, v);
265*37da2899SCharles.Forsyth		if((sp := getb(mp.path)) != nil)
266*37da2899SCharles.Forsyth			mp.srcpath = sp;
267*37da2899SCharles.Forsyth		if(len mp.rawtab > 0){
268*37da2899SCharles.Forsyth			mpl = mp :: mpl;
269*37da2899SCharles.Forsyth			total += mp.total;
270*37da2899SCharles.Forsyth		}
271*37da2899SCharles.Forsyth	}
272*37da2899SCharles.Forsyth	p.mods = mpl;
273*37da2899SCharles.Forsyth	p.total = total;
274*37da2899SCharles.Forsyth	return p;
275*37da2899SCharles.Forsyth}
276*37da2899SCharles.Forsyth
277*37da2899SCharles.Forsythmemstats(): Prof
278*37da2899SCharles.Forsyth{
279*37da2899SCharles.Forsyth	mp: Modprof;
280*37da2899SCharles.Forsyth	p: Prof;
281*37da2899SCharles.Forsyth	mpl: list of Modprof;
282*37da2899SCharles.Forsyth
283*37da2899SCharles.Forsyth	cleare();
284*37da2899SCharles.Forsyth	fd := sys->open(PROF, Sys->OREAD);
285*37da2899SCharles.Forsyth	if(fd == nil){
286*37da2899SCharles.Forsyth		error(sys->sprint("cannot open %s for reading", PROF));
287*37da2899SCharles.Forsyth		return (nil, 0, nil);
288*37da2899SCharles.Forsyth	}
289*37da2899SCharles.Forsyth	total := totale := 0;
290*37da2899SCharles.Forsyth	for(;;){
291*37da2899SCharles.Forsyth		(nr, d) := sys->dirread(fd);
292*37da2899SCharles.Forsyth		if(nr <= 0)
293*37da2899SCharles.Forsyth			break;
294*37da2899SCharles.Forsyth		for(i:=0; i<nr; i++){
295*37da2899SCharles.Forsyth			if(d[i].name == CTL)
296*37da2899SCharles.Forsyth				continue;
297*37da2899SCharles.Forsyth			dn := mkpath(PROF, d[i].name);
298*37da2899SCharles.Forsyth			mp.name = read(mkpath(dn, NAME));
299*37da2899SCharles.Forsyth			mp.path = read(mkpath(dn, MPATH));
300*37da2899SCharles.Forsyth			fdh := sys->open(mkpath(dn, HISTOGRAM), Sys->OREAD);
301*37da2899SCharles.Forsyth			if(fdh == nil)
302*37da2899SCharles.Forsyth				continue;
303*37da2899SCharles.Forsyth			mp.totals = array[1] of int;
304*37da2899SCharles.Forsyth			(mp.srcpath, mp.linetab, mp.funtab, mp.total, mp.totals[0]) = mprofile(fdh, mp.path);
305*37da2899SCharles.Forsyth			if((sp := getb(mp.path)) != nil)
306*37da2899SCharles.Forsyth				mp.srcpath = sp;
307*37da2899SCharles.Forsyth			if(mp.total != 0 || mp.totals[0] != 0){
308*37da2899SCharles.Forsyth				mpl = mp :: mpl;
309*37da2899SCharles.Forsyth				total += mp.total;
310*37da2899SCharles.Forsyth				totale += mp.totals[0];
311*37da2899SCharles.Forsyth			}
312*37da2899SCharles.Forsyth		}
313*37da2899SCharles.Forsyth	}
314*37da2899SCharles.Forsyth	p.mods = mpl;
315*37da2899SCharles.Forsyth	p.total = total;
316*37da2899SCharles.Forsyth	p.totals = array[1] of int;
317*37da2899SCharles.Forsyth	p.totals[0] = totale;
318*37da2899SCharles.Forsyth	return p;
319*37da2899SCharles.Forsyth}
320*37da2899SCharles.Forsyth
321*37da2899SCharles.Forsythtprofile(fd: ref Sys->FD, dis: string): (string, array of int, array of Funprof, int)
322*37da2899SCharles.Forsyth{
323*37da2899SCharles.Forsyth	sbl := findsbl(dis);
324*37da2899SCharles.Forsyth	if(sbl == nil){
325*37da2899SCharles.Forsyth		error0(sys->sprint("cannot locate symbol table file for %s", dis));
326*37da2899SCharles.Forsyth		return (nil, nil, nil, 0);
327*37da2899SCharles.Forsyth	}
328*37da2899SCharles.Forsyth	(sym, err) := debug->sym(sbl);
329*37da2899SCharles.Forsyth	if(sym == nil){
330*37da2899SCharles.Forsyth		error0(sys->sprint("bad symbol table file: %s", err));
331*37da2899SCharles.Forsyth		return (nil, nil, nil, 0);
332*37da2899SCharles.Forsyth	}
333*37da2899SCharles.Forsyth	nlines := 0;
334*37da2899SCharles.Forsyth	nl := len sym.src;
335*37da2899SCharles.Forsyth	for(i := 0; i < nl; i++){
336*37da2899SCharles.Forsyth		if((l := sym.src[i].stop.line) > nlines)
337*37da2899SCharles.Forsyth			nlines = l;
338*37da2899SCharles.Forsyth	}
339*37da2899SCharles.Forsyth	name := sym.src[0].start.file;
340*37da2899SCharles.Forsyth	line := array[nlines+1] of int;
341*37da2899SCharles.Forsyth	for(i = 0; i <= nlines; i++)
342*37da2899SCharles.Forsyth		line[i] = 0;
343*37da2899SCharles.Forsyth	nf := len sym.fns;
344*37da2899SCharles.Forsyth	fun := array[nf] of Funprof;
345*37da2899SCharles.Forsyth	for(i = 0; i < nf; i++){
346*37da2899SCharles.Forsyth		fun[i].name = sym.fns[i].name;
347*37da2899SCharles.Forsyth		# src seems to be always nil
348*37da2899SCharles.Forsyth		# fun[i].file = sym.fns[i].src.start.file;
349*37da2899SCharles.Forsyth		# fun[i].line = (sym.fns[i].src.start.line+sym.fns[i].src.stop.line)/2;
350*37da2899SCharles.Forsyth		src := sym.pctosrc(sym.fns[i].offset);
351*37da2899SCharles.Forsyth		if(src != nil)
352*37da2899SCharles.Forsyth			fun[i].line = src.start.line;
353*37da2899SCharles.Forsyth		else
354*37da2899SCharles.Forsyth			fun[i].line = 0;
355*37da2899SCharles.Forsyth		fun[i].count = 0;
356*37da2899SCharles.Forsyth	}
357*37da2899SCharles.Forsyth	buf := array[32] of byte;
358*37da2899SCharles.Forsyth	# pc := 0;
359*37da2899SCharles.Forsyth	tot := 0;
360*37da2899SCharles.Forsyth	fi := 0;
361*37da2899SCharles.Forsyth# for(i=0; i < nl; i++) sys->print("%d -> %d\n", i, sym.pctosrc(i).start.line);
362*37da2899SCharles.Forsyth	while((m := sys->read(fd, buf, len buf)) > 0){
363*37da2899SCharles.Forsyth		(nw, lw) := sys->tokenize(string buf[0:m], " ");
364*37da2899SCharles.Forsyth		if(nw != 2){
365*37da2899SCharles.Forsyth			error0("bad histogram data");
366*37da2899SCharles.Forsyth			return  (nil, nil, nil, 0);
367*37da2899SCharles.Forsyth		}
368*37da2899SCharles.Forsyth		pc := int hd lw;
369*37da2899SCharles.Forsyth		f := int hd tl lw;
370*37da2899SCharles.Forsyth		rpc := pc-1;
371*37da2899SCharles.Forsyth		src := sym.pctosrc(rpc);
372*37da2899SCharles.Forsyth		if(src == nil)
373*37da2899SCharles.Forsyth			continue;
374*37da2899SCharles.Forsyth		l1 := src.start.line;
375*37da2899SCharles.Forsyth		l2 := src.stop.line;
376*37da2899SCharles.Forsyth		if(l1 == 0 || l2 == 0)
377*37da2899SCharles.Forsyth			continue;
378*37da2899SCharles.Forsyth		if((nl = l2-l1+1) == 1)
379*37da2899SCharles.Forsyth			line[l1] += f;
380*37da2899SCharles.Forsyth		else{
381*37da2899SCharles.Forsyth			q := f/nl;
382*37da2899SCharles.Forsyth			r := f-q*nl;
383*37da2899SCharles.Forsyth			for(i = l1; i <= l2; i++)
384*37da2899SCharles.Forsyth				line[i] += q+(r-->0);
385*37da2899SCharles.Forsyth		}
386*37da2899SCharles.Forsyth		if(fi < nf){
387*37da2899SCharles.Forsyth			if(rpc >= sym.fns[fi].offset && rpc < sym.fns[fi].stoppc)
388*37da2899SCharles.Forsyth				fun[fi].count += f;
389*37da2899SCharles.Forsyth			else{
390*37da2899SCharles.Forsyth				while(fi < nf && rpc >= sym.fns[fi].stoppc)
391*37da2899SCharles.Forsyth					fi++;
392*37da2899SCharles.Forsyth				# fi++;
393*37da2899SCharles.Forsyth				if(fi >= nf && f != 0)
394*37da2899SCharles.Forsyth					error0(sys->sprint("bad fn index"));
395*37da2899SCharles.Forsyth				if(fi < nf)
396*37da2899SCharles.Forsyth					fun[fi].count += f;
397*37da2899SCharles.Forsyth			}
398*37da2899SCharles.Forsyth		}
399*37da2899SCharles.Forsyth		tot += f;
400*37da2899SCharles.Forsyth# sys->print("pc %d count %d l1 %d l2 %d\n", rpc, f, l1, l2);
401*37da2899SCharles.Forsyth	}
402*37da2899SCharles.Forsyth	return (name, line, fun, tot);
403*37da2899SCharles.Forsyth}
404*37da2899SCharles.Forsyth
405*37da2899SCharles.Forsythcprofile(fd: ref Sys->FD, dis: string, rec: int, v: int): (string, string, array of (int, int), array of int, array of ref Range, int, int)
406*37da2899SCharles.Forsyth{
407*37da2899SCharles.Forsyth	freq := v&FREQUENCY;
408*37da2899SCharles.Forsyth	sbl := findsbl(dis);
409*37da2899SCharles.Forsyth	if(sbl == nil){
410*37da2899SCharles.Forsyth		error0(sys->sprint("cannot locate symbol table file for %s", dis));
411*37da2899SCharles.Forsyth		return (nil, nil, nil, nil, nil, 0, 0);
412*37da2899SCharles.Forsyth	}
413*37da2899SCharles.Forsyth	(sym, err) := debug->sym(sbl);
414*37da2899SCharles.Forsyth	if(sym == nil){
415*37da2899SCharles.Forsyth		error0(sys->sprint("bad symbol table file: %s", err));
416*37da2899SCharles.Forsyth		return (nil, nil, nil, nil, nil, 0, 0);
417*37da2899SCharles.Forsyth	}
418*37da2899SCharles.Forsyth	nlines := 0;
419*37da2899SCharles.Forsyth	nl := len sym.src;
420*37da2899SCharles.Forsyth	for(i := 0; i < nl; i++){
421*37da2899SCharles.Forsyth		if((l := sym.src[i].start.line) > nlines)
422*37da2899SCharles.Forsyth			nlines = l;
423*37da2899SCharles.Forsyth		if((l = sym.src[i].stop.line) > nlines)
424*37da2899SCharles.Forsyth			nlines = l;
425*37da2899SCharles.Forsyth	}
426*37da2899SCharles.Forsyth	name := sym.src[0].start.file;
427*37da2899SCharles.Forsyth	line := array[nlines+1] of int;
428*37da2899SCharles.Forsyth	for(i = 0; i <= nlines; i++){
429*37da2899SCharles.Forsyth		if(freq)
430*37da2899SCharles.Forsyth			line[i] = -1;
431*37da2899SCharles.Forsyth		else
432*37da2899SCharles.Forsyth			line[i] = 0;
433*37da2899SCharles.Forsyth	}
434*37da2899SCharles.Forsyth	rng := array[nlines+1] of ref Range;
435*37da2899SCharles.Forsyth	for(i = 0; i < nl; i++)
436*37da2899SCharles.Forsyth		cover(i, -1, sym, line, rng, freq);
437*37da2899SCharles.Forsyth	buf := array[32] of byte;
438*37da2899SCharles.Forsyth	nr := 0;
439*37da2899SCharles.Forsyth	r := array[1024] of (int, int);
440*37da2899SCharles.Forsyth	while((m := sys->read(fd, buf, len buf)) > 0){
441*37da2899SCharles.Forsyth		(nw, lw) := sys->tokenize(string buf[0:m], " ");
442*37da2899SCharles.Forsyth		if(nw != 2){
443*37da2899SCharles.Forsyth			error0("bad histogram data");
444*37da2899SCharles.Forsyth			return  (nil, nil, nil, nil, nil, 0, 0);
445*37da2899SCharles.Forsyth		}
446*37da2899SCharles.Forsyth		(r, nr) = add(r, nr, int hd lw, int hd tl lw);
447*37da2899SCharles.Forsyth	}
448*37da2899SCharles.Forsyth	r = clip(r, nr);
449*37da2899SCharles.Forsyth	if(rec){
450*37da2899SCharles.Forsyth		wt := nr > 0;
451*37da2899SCharles.Forsyth		prf := repsuff(sbl, ".sbl", ".prf");
452*37da2899SCharles.Forsyth		if(exists(prf)){
453*37da2899SCharles.Forsyth			if(stamp(sbl) > stamp(prf)){
454*37da2899SCharles.Forsyth				error0(sys->sprint("%s later than %s", sbl, prf));
455*37da2899SCharles.Forsyth				return (nil, nil, nil, nil, nil, 0, 0);
456*37da2899SCharles.Forsyth			}
457*37da2899SCharles.Forsyth			r = mergeprof(r, readprof(prf));
458*37da2899SCharles.Forsyth			nr = len r;
459*37da2899SCharles.Forsyth		}
460*37da2899SCharles.Forsyth		if(wt && writeprof(prf, r) < 0){
461*37da2899SCharles.Forsyth			error0(sys->sprint("cannot write profile file %s", prf));
462*37da2899SCharles.Forsyth			return (nil, nil, nil, nil, nil, 0, 0);
463*37da2899SCharles.Forsyth		}
464*37da2899SCharles.Forsyth	}
465*37da2899SCharles.Forsyth	tot := 0;
466*37da2899SCharles.Forsyth	lpc := 0;
467*37da2899SCharles.Forsyth	dise := dist := 0;
468*37da2899SCharles.Forsyth	for(i = 0; i < nr; i++){
469*37da2899SCharles.Forsyth		(pc, f) := r[i];
470*37da2899SCharles.Forsyth		for( ; lpc < pc; lpc++){
471*37da2899SCharles.Forsyth			cover(lpc, 0, sym, line, rng, freq);
472*37da2899SCharles.Forsyth			dist++;
473*37da2899SCharles.Forsyth		}
474*37da2899SCharles.Forsyth		cover(pc, f, sym, line, rng, freq);
475*37da2899SCharles.Forsyth		dist++;
476*37da2899SCharles.Forsyth		if(f != 0)
477*37da2899SCharles.Forsyth			dise++;
478*37da2899SCharles.Forsyth		tot += f;
479*37da2899SCharles.Forsyth		lpc = pc+1;
480*37da2899SCharles.Forsyth	}
481*37da2899SCharles.Forsyth	for( ; lpc < nl; lpc++){
482*37da2899SCharles.Forsyth		cover(lpc, 0, sym, line, rng, freq);
483*37da2899SCharles.Forsyth		dist++;
484*37da2899SCharles.Forsyth	}
485*37da2899SCharles.Forsyth	if(dist == 0)
486*37da2899SCharles.Forsyth		dist = 1;
487*37da2899SCharles.Forsyth	return (sym.name, name, r, line, rng, tot, (100*dise)/dist);
488*37da2899SCharles.Forsyth}
489*37da2899SCharles.Forsyth
490*37da2899SCharles.Forsythshow(p: Prof, v: int): int
491*37da2899SCharles.Forsyth{
492*37da2899SCharles.Forsyth	i: int;
493*37da2899SCharles.Forsyth
494*37da2899SCharles.Forsyth	cleare();
495*37da2899SCharles.Forsyth	tot := p.total;
496*37da2899SCharles.Forsyth	if(tot == 0)
497*37da2899SCharles.Forsyth		return 0;
498*37da2899SCharles.Forsyth	verbose := v&VERBOSE;
499*37da2899SCharles.Forsyth	fullhdr := v&FULLHDR;
500*37da2899SCharles.Forsyth	for(ml := p.mods; ml != nil; ml = tl ml){
501*37da2899SCharles.Forsyth		mp := hd ml;
502*37da2899SCharles.Forsyth		if(mp.total == 0)
503*37da2899SCharles.Forsyth			continue;
504*37da2899SCharles.Forsyth		if((b := getb(mp.path)) == nil)
505*37da2899SCharles.Forsyth			continue;
506*37da2899SCharles.Forsyth		sys->print("\nModule: %s(%s)\n\n", mp.name, mp.path);
507*37da2899SCharles.Forsyth		line := mp.linetab;
508*37da2899SCharles.Forsyth		if(v&FUNCTION){
509*37da2899SCharles.Forsyth			fun := mp.funtab;
510*37da2899SCharles.Forsyth			nf := len fun;
511*37da2899SCharles.Forsyth			for(i = 0; i < nf; i++)
512*37da2899SCharles.Forsyth				if(verbose || fun[i].count != 0){
513*37da2899SCharles.Forsyth					if(fullhdr)
514*37da2899SCharles.Forsyth						sys->print("%s:", b);
515*37da2899SCharles.Forsyth					sys->print("%d\t%.2f\t%s()\n", fun[i].line, 100.0*(real fun[i].count)/(real tot), fun[i].name);
516*37da2899SCharles.Forsyth			}
517*37da2899SCharles.Forsyth			sys->print("\n**** module sampling points %d ****\n\n", mp.total);
518*37da2899SCharles.Forsyth			if(v&LINE)
519*37da2899SCharles.Forsyth				sys->print("\n");
520*37da2899SCharles.Forsyth		}
521*37da2899SCharles.Forsyth		if(v&LINE){
522*37da2899SCharles.Forsyth			bio := bufio->open(b, Bufio->OREAD);
523*37da2899SCharles.Forsyth			if(bio == nil){
524*37da2899SCharles.Forsyth				error(sys->sprint("cannot open %s for reading", b));
525*37da2899SCharles.Forsyth				continue;
526*37da2899SCharles.Forsyth			}
527*37da2899SCharles.Forsyth			i = 1;
528*37da2899SCharles.Forsyth			ll := len line;
529*37da2899SCharles.Forsyth			while((s := bio.gets('\n')) != nil){
530*37da2899SCharles.Forsyth				f := 0;
531*37da2899SCharles.Forsyth				if(i < ll)
532*37da2899SCharles.Forsyth					f = line[i];
533*37da2899SCharles.Forsyth				if(verbose || f != 0){
534*37da2899SCharles.Forsyth					if(fullhdr)
535*37da2899SCharles.Forsyth						sys->print("%s:", b);
536*37da2899SCharles.Forsyth					sys->print("%d\t%.2f\t%s", i, 100.0*(real f)/(real tot), s);
537*37da2899SCharles.Forsyth				}
538*37da2899SCharles.Forsyth				i++;
539*37da2899SCharles.Forsyth			}
540*37da2899SCharles.Forsyth			sys->print("\n**** module sampling points %d ****\n\n", mp.total);
541*37da2899SCharles.Forsyth		}
542*37da2899SCharles.Forsyth	}
543*37da2899SCharles.Forsyth	if(p.mods != nil && tl p.mods != nil)
544*37da2899SCharles.Forsyth		sys->print("\n**** total sampling points %d ****\n\n", p.total);
545*37da2899SCharles.Forsyth	return 0;
546*37da2899SCharles.Forsyth}
547*37da2899SCharles.Forsyth
548*37da2899SCharles.Forsythcpshow(p: Prof, v: int): int
549*37da2899SCharles.Forsyth{
550*37da2899SCharles.Forsyth	i: int;
551*37da2899SCharles.Forsyth
552*37da2899SCharles.Forsyth	cleare();
553*37da2899SCharles.Forsyth	tot := p.total;
554*37da2899SCharles.Forsyth	fullhdr := v&FULLHDR;
555*37da2899SCharles.Forsyth	freq := v&FREQUENCY;
556*37da2899SCharles.Forsyth	for(ml := p.mods; ml != nil; ml = tl ml){
557*37da2899SCharles.Forsyth		mp := hd ml;
558*37da2899SCharles.Forsyth		if((b := getb(mp.path)) == nil)
559*37da2899SCharles.Forsyth			continue;
560*37da2899SCharles.Forsyth		sys->print("\nModule: %s(%s)", mp.name, mp.path);
561*37da2899SCharles.Forsyth		sys->print("\t%d%% coverage\n\n", mp.coverage);
562*37da2899SCharles.Forsyth		if(mp.coverage == 100 && !freq)
563*37da2899SCharles.Forsyth			continue;
564*37da2899SCharles.Forsyth		line := mp.linetab;
565*37da2899SCharles.Forsyth		rng := mp.rngtab;
566*37da2899SCharles.Forsyth		bio := bufio->open(b, Bufio->OREAD);
567*37da2899SCharles.Forsyth		if(bio == nil){
568*37da2899SCharles.Forsyth			error(sys->sprint("cannot open %s for reading", b));
569*37da2899SCharles.Forsyth			continue;
570*37da2899SCharles.Forsyth		}
571*37da2899SCharles.Forsyth		i = 1;
572*37da2899SCharles.Forsyth		ll := len line;
573*37da2899SCharles.Forsyth		while((s := bio.gets('\n')) != nil){
574*37da2899SCharles.Forsyth			f := 0;
575*37da2899SCharles.Forsyth			if(i < ll)
576*37da2899SCharles.Forsyth				f = line[i];
577*37da2899SCharles.Forsyth			if(fullhdr)
578*37da2899SCharles.Forsyth				sys->print("%s:", b);
579*37da2899SCharles.Forsyth			sys->print("%d\t", i);
580*37da2899SCharles.Forsyth			if(rng != nil && i < ll && (r := rng[i]) != nil && multirng(r)){
581*37da2899SCharles.Forsyth				for( ; r != nil; r = r.n){
582*37da2899SCharles.Forsyth					sys->print("%s", trans(r.f, freq));
583*37da2899SCharles.Forsyth					if(r.n != nil)
584*37da2899SCharles.Forsyth						sys->print("|");
585*37da2899SCharles.Forsyth				}
586*37da2899SCharles.Forsyth			}
587*37da2899SCharles.Forsyth			else
588*37da2899SCharles.Forsyth				sys->print("%s", trans(f, freq));
589*37da2899SCharles.Forsyth			sys->print("\t%s", s);
590*37da2899SCharles.Forsyth			i++;
591*37da2899SCharles.Forsyth		}
592*37da2899SCharles.Forsyth		sys->print("\n**** module dis instructions %d ****\n\n", mp.total);
593*37da2899SCharles.Forsyth	}
594*37da2899SCharles.Forsyth	if(p.mods != nil && tl p.mods != nil)
595*37da2899SCharles.Forsyth		sys->print("\n**** total number dis instructions %d ****\n\n", p.total);
596*37da2899SCharles.Forsyth	return 0;
597*37da2899SCharles.Forsyth}
598*37da2899SCharles.Forsyth
599*37da2899SCharles.Forsythcoverage(p: Prof, v: int): Coverage
600*37da2899SCharles.Forsyth{
601*37da2899SCharles.Forsyth	i: int;
602*37da2899SCharles.Forsyth	clist: Coverage;
603*37da2899SCharles.Forsyth
604*37da2899SCharles.Forsyth	cleare();
605*37da2899SCharles.Forsyth	freq := v&FREQUENCY;
606*37da2899SCharles.Forsyth	for(ml := p.mods; ml != nil; ml = tl ml){
607*37da2899SCharles.Forsyth		mp := hd ml;
608*37da2899SCharles.Forsyth		if((b := getb(mp.path)) == nil)
609*37da2899SCharles.Forsyth			continue;
610*37da2899SCharles.Forsyth		line := mp.linetab;
611*37da2899SCharles.Forsyth		rng := mp.rngtab;
612*37da2899SCharles.Forsyth		bio := bufio->open(b, Bufio->OREAD);
613*37da2899SCharles.Forsyth		if(bio == nil){
614*37da2899SCharles.Forsyth			error(sys->sprint("cannot open %s for reading", b));
615*37da2899SCharles.Forsyth			continue;
616*37da2899SCharles.Forsyth		}
617*37da2899SCharles.Forsyth		i = 1;
618*37da2899SCharles.Forsyth		ll := len line;
619*37da2899SCharles.Forsyth		llist: list of (list of (int, int, int), string);
620*37da2899SCharles.Forsyth		while((s := bio.gets('\n')) != nil){
621*37da2899SCharles.Forsyth			f := 0;
622*37da2899SCharles.Forsyth			if(i < ll)
623*37da2899SCharles.Forsyth				f = line[i];
624*37da2899SCharles.Forsyth			rlist: list of (int, int, int);
625*37da2899SCharles.Forsyth			if(rng != nil && i < ll && (r := rng[i]) != nil){
626*37da2899SCharles.Forsyth				for( ; r != nil; r = r.n){
627*37da2899SCharles.Forsyth					if(r.u == ∞)
628*37da2899SCharles.Forsyth						r.u = len s - 1;
629*37da2899SCharles.Forsyth					if(freq){
630*37da2899SCharles.Forsyth						if(r.f > 0)
631*37da2899SCharles.Forsyth							rlist = (r.l, r.u, r.f) :: rlist;
632*37da2899SCharles.Forsyth					}
633*37da2899SCharles.Forsyth					else{
634*37da2899SCharles.Forsyth						if(r.f&NEX)
635*37da2899SCharles.Forsyth							rlist = (r.l, r.u, (r.f&EXE)==EXE) :: rlist;
636*37da2899SCharles.Forsyth					}
637*37da2899SCharles.Forsyth				}
638*37da2899SCharles.Forsyth			}
639*37da2899SCharles.Forsyth			else{
640*37da2899SCharles.Forsyth				if(freq){
641*37da2899SCharles.Forsyth					if(f > 0)
642*37da2899SCharles.Forsyth						rlist = (0, len s - 1, f) :: rlist;
643*37da2899SCharles.Forsyth				}
644*37da2899SCharles.Forsyth				else{
645*37da2899SCharles.Forsyth					if(f&NEX)
646*37da2899SCharles.Forsyth						rlist = (0, len s - 1, (f&EXE)==EXE) :: nil;
647*37da2899SCharles.Forsyth				}
648*37da2899SCharles.Forsyth			}
649*37da2899SCharles.Forsyth			llist = (rlist, s) :: llist;
650*37da2899SCharles.Forsyth			i++;
651*37da2899SCharles.Forsyth		}
652*37da2899SCharles.Forsyth		if(freq)
653*37da2899SCharles.Forsyth			n := mp.total;
654*37da2899SCharles.Forsyth		else
655*37da2899SCharles.Forsyth			n = mp.coverage;
656*37da2899SCharles.Forsyth		clist = (b, n, rev(llist)) :: clist;
657*37da2899SCharles.Forsyth	}
658*37da2899SCharles.Forsyth	return clist;
659*37da2899SCharles.Forsyth}
660*37da2899SCharles.Forsyth
661*37da2899SCharles.Forsyth∞: con 1<<30;
662*37da2899SCharles.Forsyth
663*37da2899SCharles.ForsythDIS: con 1;
664*37da2899SCharles.ForsythEXE: con 2;
665*37da2899SCharles.ForsythNEX: con 4;
666*37da2899SCharles.Forsyth
667*37da2899SCharles.Forsythcover(pc: int, f: int, sym: ref Debug->Sym, line: array of int, rng: array of ref Range, freq: int)
668*37da2899SCharles.Forsyth{
669*37da2899SCharles.Forsyth	v: int;
670*37da2899SCharles.Forsyth
671*37da2899SCharles.Forsyth	src := sym.pctosrc(pc);
672*37da2899SCharles.Forsyth	if(src == nil)
673*37da2899SCharles.Forsyth		return;
674*37da2899SCharles.Forsyth	l1 := src.start.line;
675*37da2899SCharles.Forsyth	l2 := src.stop.line;
676*37da2899SCharles.Forsyth	if(l1 == 0 || l2 == 0)
677*37da2899SCharles.Forsyth		return;
678*37da2899SCharles.Forsyth	c1 := src.start.pos;
679*37da2899SCharles.Forsyth	c2 := src.stop.pos;
680*37da2899SCharles.Forsyth	if(freq){
681*37da2899SCharles.Forsyth		v = 0;
682*37da2899SCharles.Forsyth		if(f > 0)
683*37da2899SCharles.Forsyth			v = f;
684*37da2899SCharles.Forsyth	}
685*37da2899SCharles.Forsyth	else{
686*37da2899SCharles.Forsyth		v = DIS;
687*37da2899SCharles.Forsyth		if(f > 0)
688*37da2899SCharles.Forsyth			v = EXE;
689*37da2899SCharles.Forsyth		else if(f == 0)
690*37da2899SCharles.Forsyth			v = NEX;
691*37da2899SCharles.Forsyth	}
692*37da2899SCharles.Forsyth	for(i := l1; i <= l2; i++){
693*37da2899SCharles.Forsyth		r1 := 0;
694*37da2899SCharles.Forsyth		r2 := ∞;
695*37da2899SCharles.Forsyth		if(i == l1)
696*37da2899SCharles.Forsyth			r1 = c1;
697*37da2899SCharles.Forsyth		if(i == l2)
698*37da2899SCharles.Forsyth			r2 = c2;
699*37da2899SCharles.Forsyth		if(rng != nil)
700*37da2899SCharles.Forsyth			rng[i] = mrgrng(addrng(rng[i], r1, r2, v, freq));
701*37da2899SCharles.Forsyth		if(freq){
702*37da2899SCharles.Forsyth			if(v > line[i])
703*37da2899SCharles.Forsyth				line[i] = v;
704*37da2899SCharles.Forsyth		}
705*37da2899SCharles.Forsyth		else
706*37da2899SCharles.Forsyth			line[i] |= v;
707*37da2899SCharles.Forsyth		# if(i==123) sys->print("%d %d-%d %d %d\n", i, r1, r2, v, pc);
708*37da2899SCharles.Forsyth	}
709*37da2899SCharles.Forsyth}
710*37da2899SCharles.Forsyth
711*37da2899SCharles.Forsytharng(c1: int, c2: int, f: int, tr: ref Range, lr: ref Range, r: ref Range): ref Range
712*37da2899SCharles.Forsyth{
713*37da2899SCharles.Forsyth	nr := ref Range(c1, c2, f, tr);
714*37da2899SCharles.Forsyth	if(lr == nil)
715*37da2899SCharles.Forsyth		r = nr;
716*37da2899SCharles.Forsyth	else
717*37da2899SCharles.Forsyth		lr.n = nr;
718*37da2899SCharles.Forsyth	return r;
719*37da2899SCharles.Forsyth}
720*37da2899SCharles.Forsyth
721*37da2899SCharles.Forsythaddrng(r: ref Range, c1: int, c2: int, f: int, freq: int): ref Range
722*37da2899SCharles.Forsyth{
723*37da2899SCharles.Forsyth	lr: ref Range;
724*37da2899SCharles.Forsyth
725*37da2899SCharles.Forsyth	if(c1 > c2)
726*37da2899SCharles.Forsyth		return r;
727*37da2899SCharles.Forsyth	for(tr := r; tr != nil; tr = tr.n){
728*37da2899SCharles.Forsyth		r1 := tr.l;
729*37da2899SCharles.Forsyth		r2 := tr.u;
730*37da2899SCharles.Forsyth		if(c1 < r1){
731*37da2899SCharles.Forsyth			if(c2 < r1)
732*37da2899SCharles.Forsyth				return arng(c1, c2, f, tr, lr, r);
733*37da2899SCharles.Forsyth			else if(c2 <= r2){
734*37da2899SCharles.Forsyth				r = addrng(r, c1, r1-1, f, freq);
735*37da2899SCharles.Forsyth				return addrng(r, r1, c2, f, freq);
736*37da2899SCharles.Forsyth			}
737*37da2899SCharles.Forsyth			else{
738*37da2899SCharles.Forsyth				r = addrng(r, c1, r1-1, f, freq);
739*37da2899SCharles.Forsyth				r = addrng(r, r1, r2, f, freq);
740*37da2899SCharles.Forsyth				return addrng(r, r2+1, c2, f, freq);
741*37da2899SCharles.Forsyth			}
742*37da2899SCharles.Forsyth		}
743*37da2899SCharles.Forsyth		else if(c1 <= r2){
744*37da2899SCharles.Forsyth			if(c2 <= r2){
745*37da2899SCharles.Forsyth				v := tr.f;
746*37da2899SCharles.Forsyth				tr.l = c1;
747*37da2899SCharles.Forsyth				tr.u = c2;
748*37da2899SCharles.Forsyth				if(freq){
749*37da2899SCharles.Forsyth					if(f > tr.f)
750*37da2899SCharles.Forsyth						tr.f = f;
751*37da2899SCharles.Forsyth				}
752*37da2899SCharles.Forsyth				else
753*37da2899SCharles.Forsyth					tr.f |= f;
754*37da2899SCharles.Forsyth				r = addrng(r, r1, c1-1, v, freq);
755*37da2899SCharles.Forsyth				return addrng(r, c2+1, r2, v, freq);
756*37da2899SCharles.Forsyth			}
757*37da2899SCharles.Forsyth			else{
758*37da2899SCharles.Forsyth				r = addrng(r, c1, r2, f, freq);
759*37da2899SCharles.Forsyth				return addrng(r, r2+1, c2, f, freq);
760*37da2899SCharles.Forsyth			}
761*37da2899SCharles.Forsyth		}
762*37da2899SCharles.Forsyth		lr = tr;
763*37da2899SCharles.Forsyth	}
764*37da2899SCharles.Forsyth	return arng(c1, c2, f, nil, lr, r);
765*37da2899SCharles.Forsyth}
766*37da2899SCharles.Forsyth
767*37da2899SCharles.Forsythmrgrng(r: ref Range): ref Range
768*37da2899SCharles.Forsyth{
769*37da2899SCharles.Forsyth	lr: ref Range;
770*37da2899SCharles.Forsyth
771*37da2899SCharles.Forsyth	for(tr := r; tr != nil; tr = tr.n){
772*37da2899SCharles.Forsyth		if(lr != nil && lr.u >= tr.l)
773*37da2899SCharles.Forsyth			sys->print("ERROR %d %d\n", lr.u, tr.l);
774*37da2899SCharles.Forsyth		if(lr != nil && lr.f == tr.f && lr.u+1 == tr.l){
775*37da2899SCharles.Forsyth			lr.u = tr.u;
776*37da2899SCharles.Forsyth			lr.n = tr.n;
777*37da2899SCharles.Forsyth		}
778*37da2899SCharles.Forsyth		else
779*37da2899SCharles.Forsyth			lr = tr;
780*37da2899SCharles.Forsyth	}
781*37da2899SCharles.Forsyth	return r;
782*37da2899SCharles.Forsyth}
783*37da2899SCharles.Forsyth
784*37da2899SCharles.Forsythmultirng(r: ref Range): int
785*37da2899SCharles.Forsyth{
786*37da2899SCharles.Forsyth	f := r.f;
787*37da2899SCharles.Forsyth	for(tr := r; tr != nil; tr = tr.n)
788*37da2899SCharles.Forsyth		if(tr.f != f)
789*37da2899SCharles.Forsyth			return 1;
790*37da2899SCharles.Forsyth	return 0;
791*37da2899SCharles.Forsyth}
792*37da2899SCharles.Forsyth
793*37da2899SCharles.Forsythadd(r: array of (int, int), nr: int, pc: int, f: int): (array of (int, int), int)
794*37da2899SCharles.Forsyth{
795*37da2899SCharles.Forsyth	l := len r;
796*37da2899SCharles.Forsyth	if(nr == l){
797*37da2899SCharles.Forsyth		s := array[2*l] of (int, int);
798*37da2899SCharles.Forsyth		s[0:] = r[0: nr];
799*37da2899SCharles.Forsyth		r = s;
800*37da2899SCharles.Forsyth	}
801*37da2899SCharles.Forsyth	r[nr++] = (pc, f);
802*37da2899SCharles.Forsyth	return (r, nr);
803*37da2899SCharles.Forsyth}
804*37da2899SCharles.Forsyth
805*37da2899SCharles.Forsythclip(r: array of (int, int), nr: int): array of (int, int)
806*37da2899SCharles.Forsyth{
807*37da2899SCharles.Forsyth	l := len r;
808*37da2899SCharles.Forsyth	if(nr < l){
809*37da2899SCharles.Forsyth		s := array[nr] of (int, int);
810*37da2899SCharles.Forsyth		s[0:] = r[0: nr];
811*37da2899SCharles.Forsyth		r = s;
812*37da2899SCharles.Forsyth	}
813*37da2899SCharles.Forsyth	return r;
814*37da2899SCharles.Forsyth}
815*37da2899SCharles.Forsyth
816*37da2899SCharles.Forsythreadprof(f: string): array of (int, int)
817*37da2899SCharles.Forsyth{
818*37da2899SCharles.Forsyth	b := bufio->open(f, Bufio->OREAD);
819*37da2899SCharles.Forsyth	if(b == nil)
820*37da2899SCharles.Forsyth		return nil;
821*37da2899SCharles.Forsyth	nr := 0;
822*37da2899SCharles.Forsyth	r := array[1024] of (int, int);
823*37da2899SCharles.Forsyth	while((buf := b.gets('\n')) != nil){
824*37da2899SCharles.Forsyth		(nw, lw) := sys->tokenize(buf, " ");
825*37da2899SCharles.Forsyth		if(nw != 2){
826*37da2899SCharles.Forsyth			error0("bad raw data");
827*37da2899SCharles.Forsyth			return  nil;
828*37da2899SCharles.Forsyth		}
829*37da2899SCharles.Forsyth		(r, nr) = add(r, nr, int hd lw, int hd tl lw);
830*37da2899SCharles.Forsyth	}
831*37da2899SCharles.Forsyth	r = clip(r, nr);
832*37da2899SCharles.Forsyth	return r;
833*37da2899SCharles.Forsyth}
834*37da2899SCharles.Forsyth
835*37da2899SCharles.Forsythmergeprof(r1, r2: array of (int, int)): array of (int, int)
836*37da2899SCharles.Forsyth{
837*37da2899SCharles.Forsyth	nr := 0;
838*37da2899SCharles.Forsyth	r := array[1024] of (int, int);
839*37da2899SCharles.Forsyth	l1 := len r1;
840*37da2899SCharles.Forsyth	l2 := len r2;
841*37da2899SCharles.Forsyth	for((i, j) := (0, 0); i < l1 || j < l2; ){
842*37da2899SCharles.Forsyth		if(i < l1)
843*37da2899SCharles.Forsyth			(pc1, f1) := r1[i];
844*37da2899SCharles.Forsyth		else
845*37da2899SCharles.Forsyth			pc1 = ∞;
846*37da2899SCharles.Forsyth		if(j < l2)
847*37da2899SCharles.Forsyth			(pc2, f2) := r2[j];
848*37da2899SCharles.Forsyth		else
849*37da2899SCharles.Forsyth			pc2 = ∞;
850*37da2899SCharles.Forsyth		if(pc1 < pc2){
851*37da2899SCharles.Forsyth			(r, nr) = add(r, nr, pc1, f1);
852*37da2899SCharles.Forsyth			i++;
853*37da2899SCharles.Forsyth		}
854*37da2899SCharles.Forsyth		else if(pc1 > pc2){
855*37da2899SCharles.Forsyth			(r, nr) = add(r, nr, pc2, f2);
856*37da2899SCharles.Forsyth			j++;
857*37da2899SCharles.Forsyth		}
858*37da2899SCharles.Forsyth		else{
859*37da2899SCharles.Forsyth			(r, nr) = add(r, nr, pc1, f1+f2);
860*37da2899SCharles.Forsyth			i++;
861*37da2899SCharles.Forsyth			j++;
862*37da2899SCharles.Forsyth		}
863*37da2899SCharles.Forsyth	}
864*37da2899SCharles.Forsyth	r = clip(r, nr);
865*37da2899SCharles.Forsyth	return r;
866*37da2899SCharles.Forsyth}
867*37da2899SCharles.Forsyth
868*37da2899SCharles.Forsythwriteprof(f: string, r: array of (int, int)): int
869*37da2899SCharles.Forsyth{
870*37da2899SCharles.Forsyth	fd := sys->create(f, Sys->OWRITE, 8r664);
871*37da2899SCharles.Forsyth	if(fd == nil)
872*37da2899SCharles.Forsyth		return -1;
873*37da2899SCharles.Forsyth	l := len r;
874*37da2899SCharles.Forsyth	for(i := 0; i < l; i++){
875*37da2899SCharles.Forsyth		(pc, fr) := r[i];
876*37da2899SCharles.Forsyth		sys->fprint(fd, "%d %d\n", pc, fr);
877*37da2899SCharles.Forsyth	}
878*37da2899SCharles.Forsyth	return 0;
879*37da2899SCharles.Forsyth}
880*37da2899SCharles.Forsyth
881*37da2899SCharles.Forsythtrans(f: int, freq: int): string
882*37da2899SCharles.Forsyth{
883*37da2899SCharles.Forsyth	if(freq)
884*37da2899SCharles.Forsyth		return transf(f);
885*37da2899SCharles.Forsyth	else
886*37da2899SCharles.Forsyth		return transc(f);
887*37da2899SCharles.Forsyth}
888*37da2899SCharles.Forsyth
889*37da2899SCharles.Forsythtransf(f: int): string
890*37da2899SCharles.Forsyth{
891*37da2899SCharles.Forsyth	if(f < 0)
892*37da2899SCharles.Forsyth		return " ";
893*37da2899SCharles.Forsyth	return string f;
894*37da2899SCharles.Forsyth}
895*37da2899SCharles.Forsyth
896*37da2899SCharles.Forsythtransc(f: int): string
897*37da2899SCharles.Forsyth{
898*37da2899SCharles.Forsyth	c := "";
899*37da2899SCharles.Forsyth	case(f){
900*37da2899SCharles.Forsyth		0 => c = " ";
901*37da2899SCharles.Forsyth		DIS|EXE => c = "+";
902*37da2899SCharles.Forsyth		DIS|NEX => c = "-";
903*37da2899SCharles.Forsyth		DIS|EXE|NEX => c = "?";
904*37da2899SCharles.Forsyth		* =>
905*37da2899SCharles.Forsyth			error(sys->sprint("bad code %d\n", f));
906*37da2899SCharles.Forsyth	}
907*37da2899SCharles.Forsyth	return c;
908*37da2899SCharles.Forsyth}
909*37da2899SCharles.Forsyth
910*37da2899SCharles.Forsythgetb(dis: string): string
911*37da2899SCharles.Forsyth{
912*37da2899SCharles.Forsyth	b := findb(dis);
913*37da2899SCharles.Forsyth	if(b == nil){
914*37da2899SCharles.Forsyth		error0(sys->sprint("cannot locate source file for %s\n", dis));
915*37da2899SCharles.Forsyth		return nil;
916*37da2899SCharles.Forsyth	}
917*37da2899SCharles.Forsyth	if(stamp(b) > stamp(dis)){
918*37da2899SCharles.Forsyth		error0(sys->sprint("%s later than %s", b, dis));
919*37da2899SCharles.Forsyth		return nil;
920*37da2899SCharles.Forsyth	}
921*37da2899SCharles.Forsyth	return b;
922*37da2899SCharles.Forsyth}
923*37da2899SCharles.Forsyth
924*37da2899SCharles.Forsythmkpath(d: string, f: string): string
925*37da2899SCharles.Forsyth{
926*37da2899SCharles.Forsyth	return d+"/"+f;
927*37da2899SCharles.Forsyth}
928*37da2899SCharles.Forsyth
929*37da2899SCharles.Forsythsuff(s: string): string
930*37da2899SCharles.Forsyth{
931*37da2899SCharles.Forsyth	(n, l) := sys->tokenize(s, ".");
932*37da2899SCharles.Forsyth	if(n > 1){
933*37da2899SCharles.Forsyth		while(tl l != nil)
934*37da2899SCharles.Forsyth			l = tl l;
935*37da2899SCharles.Forsyth		return hd l;
936*37da2899SCharles.Forsyth	}
937*37da2899SCharles.Forsyth	return nil;
938*37da2899SCharles.Forsyth}
939*37da2899SCharles.Forsyth
940*37da2899SCharles.Forsythrepsuff(s: string, old: string, new: string): string
941*37da2899SCharles.Forsyth{
942*37da2899SCharles.Forsyth	lo := len old;
943*37da2899SCharles.Forsyth	ls := len s;
944*37da2899SCharles.Forsyth	if(lo <= ls && s[ls-lo:ls] == old)
945*37da2899SCharles.Forsyth		return s[0:ls-lo]+new;
946*37da2899SCharles.Forsyth	return s;
947*37da2899SCharles.Forsyth}
948*37da2899SCharles.Forsyth
949*37da2899SCharles.Forsythread(f: string): string
950*37da2899SCharles.Forsyth{
951*37da2899SCharles.Forsyth	if((fd := sys->open(f, Sys->OREAD)) == nil){
952*37da2899SCharles.Forsyth		error(sys->sprint("cannot open %s for reading", f));
953*37da2899SCharles.Forsyth		return nil;
954*37da2899SCharles.Forsyth	}
955*37da2899SCharles.Forsyth	buf := array[128] of byte;
956*37da2899SCharles.Forsyth	n := sys->read(fd, buf, len buf);
957*37da2899SCharles.Forsyth	return string buf[0:n];
958*37da2899SCharles.Forsyth}
959*37da2899SCharles.Forsyth
960*37da2899SCharles.Forsythwrite(f: string, s: string): int
961*37da2899SCharles.Forsyth{
962*37da2899SCharles.Forsyth	if((fd := sys->open(f, Sys->OWRITE)) == nil){
963*37da2899SCharles.Forsyth		error(sys->sprint("cannot open %s for writing", f));
964*37da2899SCharles.Forsyth		return -1;
965*37da2899SCharles.Forsyth	}
966*37da2899SCharles.Forsyth	b := array of byte s;
967*37da2899SCharles.Forsyth	if((n := sys->write(fd, b, len b)) != len b){
968*37da2899SCharles.Forsyth		error(sys->sprint("cannot write %s to file %s", s, f));
969*37da2899SCharles.Forsyth		return -1;
970*37da2899SCharles.Forsyth	}
971*37da2899SCharles.Forsyth	return 0;
972*37da2899SCharles.Forsyth}
973*37da2899SCharles.Forsyth
974*37da2899SCharles.Forsythexists(f: string): int
975*37da2899SCharles.Forsyth{
976*37da2899SCharles.Forsyth	return sys->open(f, Sys->OREAD) != nil;
977*37da2899SCharles.Forsyth}
978*37da2899SCharles.Forsyth
979*37da2899SCharles.Forsythstamp(f: string): int
980*37da2899SCharles.Forsyth{
981*37da2899SCharles.Forsyth	(ok, d) := sys->stat(f);
982*37da2899SCharles.Forsyth	if(ok < 0)
983*37da2899SCharles.Forsyth		return 0;
984*37da2899SCharles.Forsyth	return d.mtime;
985*37da2899SCharles.Forsyth}
986*37da2899SCharles.Forsyth
987*37da2899SCharles.Forsythfindb(dis: string): string
988*37da2899SCharles.Forsyth{
989*37da2899SCharles.Forsyth	if(dism == nil){
990*37da2899SCharles.Forsyth		dism = load Dis Dis->PATH;
991*37da2899SCharles.Forsyth		if(dism != nil)
992*37da2899SCharles.Forsyth			dism->init();
993*37da2899SCharles.Forsyth	}
994*37da2899SCharles.Forsyth	if(dism != nil && (b := dism->src(dis)) != nil && exists(b))
995*37da2899SCharles.Forsyth		return b;
996*37da2899SCharles.Forsyth	return findfile(repsuff(dis, ".dis", ".b"));
997*37da2899SCharles.Forsyth}
998*37da2899SCharles.Forsyth
999*37da2899SCharles.Forsythfindsbl(dis: string): string
1000*37da2899SCharles.Forsyth{
1001*37da2899SCharles.Forsyth	b := findb(dis);
1002*37da2899SCharles.Forsyth	if(b != nil){
1003*37da2899SCharles.Forsyth		sbl := repsuff(b, ".b", ".sbl");
1004*37da2899SCharles.Forsyth		if(exists(sbl))
1005*37da2899SCharles.Forsyth			return sbl;
1006*37da2899SCharles.Forsyth		return findfile(sbl);
1007*37da2899SCharles.Forsyth	}
1008*37da2899SCharles.Forsyth	return findfile(repsuff(dis, ".dis", ".sbl"));
1009*37da2899SCharles.Forsyth}
1010*37da2899SCharles.Forsyth
1011*37da2899SCharles.Forsythfindfile(s: string): string
1012*37da2899SCharles.Forsyth{
1013*37da2899SCharles.Forsyth	if(exists(s))
1014*37da2899SCharles.Forsyth		return s;
1015*37da2899SCharles.Forsyth	if(s != nil && s[0] != '/'){
1016*37da2899SCharles.Forsyth		if(workdir == nil)
1017*37da2899SCharles.Forsyth			workdir = load Workdir Workdir->PATH;
1018*37da2899SCharles.Forsyth		if(workdir == nil){
1019*37da2899SCharles.Forsyth			error("cannot load Workdir module");
1020*37da2899SCharles.Forsyth			return nil;
1021*37da2899SCharles.Forsyth		}
1022*37da2899SCharles.Forsyth		s = workdir->init() + "/" + s;
1023*37da2899SCharles.Forsyth	}
1024*37da2899SCharles.Forsyth	(d, f) := split(s, '/');
1025*37da2899SCharles.Forsyth	(fp, nil) := split(f, '.');
1026*37da2899SCharles.Forsyth	if(fp != nil)
1027*37da2899SCharles.Forsyth		fp = fp[0: len fp - 1];
1028*37da2899SCharles.Forsyth	for(k := 0; k < 2; k++){
1029*37da2899SCharles.Forsyth		if(k == 0)
1030*37da2899SCharles.Forsyth			str := s;
1031*37da2899SCharles.Forsyth		else
1032*37da2899SCharles.Forsyth			str = d;
1033*37da2899SCharles.Forsyth		ls := len str;
1034*37da2899SCharles.Forsyth		for(i := 0; i < len bspath; i++){
1035*37da2899SCharles.Forsyth			(dis, src) := bspath[i];
1036*37da2899SCharles.Forsyth			ld := len dis;
1037*37da2899SCharles.Forsyth			if(ls >= ld && str[:ld] == dis){
1038*37da2899SCharles.Forsyth				if(k == 0)
1039*37da2899SCharles.Forsyth					ns := src + str[ld:];
1040*37da2899SCharles.Forsyth				else
1041*37da2899SCharles.Forsyth					ns = src + str[ld:] + fp + "/" + f;
1042*37da2899SCharles.Forsyth				if(exists(ns))
1043*37da2899SCharles.Forsyth					return ns;
1044*37da2899SCharles.Forsyth			}
1045*37da2899SCharles.Forsyth		}
1046*37da2899SCharles.Forsyth	}
1047*37da2899SCharles.Forsyth	return nil;
1048*37da2899SCharles.Forsyth}
1049*37da2899SCharles.Forsyth
1050*37da2899SCharles.Forsythsplit(s: string, c: int): (string, string)
1051*37da2899SCharles.Forsyth{
1052*37da2899SCharles.Forsyth	for(i := len s - 1; i >= 0; --i)
1053*37da2899SCharles.Forsyth		if(s[i] == c)
1054*37da2899SCharles.Forsyth			break;
1055*37da2899SCharles.Forsyth	return (s[0:i+1], s[i+1:]);
1056*37da2899SCharles.Forsyth}
1057*37da2899SCharles.Forsyth
1058*37da2899SCharles.Forsythrev(llist: list of (list of (int, int, int), string)): list of (list of (int, int, int), string)
1059*37da2899SCharles.Forsyth{
1060*37da2899SCharles.Forsyth	r: list of (list of (int, int, int), string);
1061*37da2899SCharles.Forsyth
1062*37da2899SCharles.Forsyth	for(l := llist; l != nil; l = tl l)
1063*37da2899SCharles.Forsyth		r = hd l :: r;
1064*37da2899SCharles.Forsyth	return r;
1065*37da2899SCharles.Forsyth}
1066*37da2899SCharles.Forsyth
1067*37da2899SCharles.Forsythmprofile(fd: ref Sys->FD, dis: string): (string, array of int, array of Funprof, int, int)
1068*37da2899SCharles.Forsyth{
1069*37da2899SCharles.Forsyth	sbl := findsbl(dis);
1070*37da2899SCharles.Forsyth	if(sbl == nil){
1071*37da2899SCharles.Forsyth		error0(sys->sprint("cannot locate symbol table file for %s", dis));
1072*37da2899SCharles.Forsyth		return (nil, nil, nil, 0, 0);
1073*37da2899SCharles.Forsyth	}
1074*37da2899SCharles.Forsyth	(sym, err) := debug->sym(sbl);
1075*37da2899SCharles.Forsyth	if(sym == nil){
1076*37da2899SCharles.Forsyth		error0(sys->sprint("bad symbol table file: %s", err));
1077*37da2899SCharles.Forsyth		return (nil, nil, nil, 0, 0);
1078*37da2899SCharles.Forsyth	}
1079*37da2899SCharles.Forsyth	nlines := 0;
1080*37da2899SCharles.Forsyth	nl := len sym.src;
1081*37da2899SCharles.Forsyth	for(i := 0; i < nl; i++){
1082*37da2899SCharles.Forsyth		if((l := sym.src[i].stop.line) > nlines)
1083*37da2899SCharles.Forsyth			nlines = l;
1084*37da2899SCharles.Forsyth	}
1085*37da2899SCharles.Forsyth	name := sym.src[0].start.file;
1086*37da2899SCharles.Forsyth	nl0 := 2*(nlines+1);
1087*37da2899SCharles.Forsyth	line := array[nl0] of int;
1088*37da2899SCharles.Forsyth	for(i = 0; i < nl0; i++)
1089*37da2899SCharles.Forsyth		line[i] = 0;
1090*37da2899SCharles.Forsyth	nf := len sym.fns;
1091*37da2899SCharles.Forsyth	fun := array[nf] of Funprof;
1092*37da2899SCharles.Forsyth	for(i = 0; i < nf; i++){
1093*37da2899SCharles.Forsyth		fun[i].name = sym.fns[i].name;
1094*37da2899SCharles.Forsyth		# src seems to be always nil
1095*37da2899SCharles.Forsyth		# fun[i].file = sym.fns[i].src.start.file;
1096*37da2899SCharles.Forsyth		# fun[i].line = (sym.fns[i].src.start.line+sym.fns[i].src.stop.line)/2;
1097*37da2899SCharles.Forsyth		src := sym.pctosrc(sym.fns[i].offset);
1098*37da2899SCharles.Forsyth		if(src != nil)
1099*37da2899SCharles.Forsyth			fun[i].line = src.start.line;
1100*37da2899SCharles.Forsyth		else
1101*37da2899SCharles.Forsyth			fun[i].line = 0;
1102*37da2899SCharles.Forsyth		fun[i].count = fun[i].counte = 0;
1103*37da2899SCharles.Forsyth	}
1104*37da2899SCharles.Forsyth	buf := array[32] of byte;
1105*37da2899SCharles.Forsyth	# pc := 0;
1106*37da2899SCharles.Forsyth	ktot := ktot1 := 0;
1107*37da2899SCharles.Forsyth	fi := 0;
1108*37da2899SCharles.Forsyth# for(i=0; i < nl; i++) sys->print("%d -> %d\n", i, sym.pctosrc(i).start.line);
1109*37da2899SCharles.Forsyth	while((m := sys->read(fd, buf, len buf)) > 0){
1110*37da2899SCharles.Forsyth		(nw, lw) := sys->tokenize(string buf[0:m], " ");
1111*37da2899SCharles.Forsyth		if(nw != 2){
1112*37da2899SCharles.Forsyth			error0("bad histogram data");
1113*37da2899SCharles.Forsyth			return  (nil, nil, nil, 0, 0);
1114*37da2899SCharles.Forsyth		}
1115*37da2899SCharles.Forsyth		pc := int hd lw;
1116*37da2899SCharles.Forsyth		f := int hd tl lw;
1117*37da2899SCharles.Forsyth		if(pc == 0){
1118*37da2899SCharles.Forsyth			ktot = f;
1119*37da2899SCharles.Forsyth			continue;
1120*37da2899SCharles.Forsyth		}
1121*37da2899SCharles.Forsyth		if(pc == 1){
1122*37da2899SCharles.Forsyth			ktot1 = f;
1123*37da2899SCharles.Forsyth			continue;
1124*37da2899SCharles.Forsyth		}
1125*37da2899SCharles.Forsyth		pc -= 2;
1126*37da2899SCharles.Forsyth		t := pc&1;
1127*37da2899SCharles.Forsyth		pc /= 2;
1128*37da2899SCharles.Forsyth		rpc := pc-1;
1129*37da2899SCharles.Forsyth		src := sym.pctosrc(rpc);
1130*37da2899SCharles.Forsyth		if(src == nil)
1131*37da2899SCharles.Forsyth			continue;
1132*37da2899SCharles.Forsyth		l1 := src.start.line;
1133*37da2899SCharles.Forsyth		l2 := src.stop.line;
1134*37da2899SCharles.Forsyth		if(l1 == 0 || l2 == 0)
1135*37da2899SCharles.Forsyth			continue;
1136*37da2899SCharles.Forsyth		if((nl = l2-l1+1) == 1)
1137*37da2899SCharles.Forsyth			line[2*l1+t] += f;
1138*37da2899SCharles.Forsyth		else{
1139*37da2899SCharles.Forsyth			q := f/nl;
1140*37da2899SCharles.Forsyth			r := f-q*nl;
1141*37da2899SCharles.Forsyth			for(i = l1; i <= l2; i++)
1142*37da2899SCharles.Forsyth				line[2*i+t] += q+(r-->0);
1143*37da2899SCharles.Forsyth		}
1144*37da2899SCharles.Forsyth		if(fi < nf){
1145*37da2899SCharles.Forsyth			if(rpc >= sym.fns[fi].offset && rpc < sym.fns[fi].stoppc){
1146*37da2899SCharles.Forsyth				if(t)
1147*37da2899SCharles.Forsyth					fun[fi].counte += f;
1148*37da2899SCharles.Forsyth				else
1149*37da2899SCharles.Forsyth					fun[fi].count += f;
1150*37da2899SCharles.Forsyth			}
1151*37da2899SCharles.Forsyth			else{
1152*37da2899SCharles.Forsyth				while(fi < nf && rpc >= sym.fns[fi].stoppc)
1153*37da2899SCharles.Forsyth					fi++;
1154*37da2899SCharles.Forsyth				# fi++;
1155*37da2899SCharles.Forsyth				if(fi >= nf && f != 0)
1156*37da2899SCharles.Forsyth					error0(sys->sprint("bad fn index"));
1157*37da2899SCharles.Forsyth				if(fi < nf){
1158*37da2899SCharles.Forsyth					if(t)
1159*37da2899SCharles.Forsyth						fun[fi].counte += f;
1160*37da2899SCharles.Forsyth					else
1161*37da2899SCharles.Forsyth						fun[fi].count += f;
1162*37da2899SCharles.Forsyth				}
1163*37da2899SCharles.Forsyth			}
1164*37da2899SCharles.Forsyth		}
1165*37da2899SCharles.Forsyth# sys->print("pc %d count %d l1 %d l2 %d\n", rpc, f, l1, l2);
1166*37da2899SCharles.Forsyth	}
1167*37da2899SCharles.Forsyth	return (name, line, fun, ktot, ktot1);
1168*37da2899SCharles.Forsyth}
1169*37da2899SCharles.Forsyth
1170*37da2899SCharles.Forsythmemshow(p: Prof, v: int): int
1171*37da2899SCharles.Forsyth{
1172*37da2899SCharles.Forsyth	i: int;
1173*37da2899SCharles.Forsyth
1174*37da2899SCharles.Forsyth	cleare();
1175*37da2899SCharles.Forsyth	tot := p.total;
1176*37da2899SCharles.Forsyth	if(p.total == 0 && p.totals[0] == 0)
1177*37da2899SCharles.Forsyth		return 0;
1178*37da2899SCharles.Forsyth	verbose := v&VERBOSE;
1179*37da2899SCharles.Forsyth	fullhdr := v&FULLHDR;
1180*37da2899SCharles.Forsyth	for(ml := p.mods; ml != nil; ml = tl ml){
1181*37da2899SCharles.Forsyth		mp := hd ml;
1182*37da2899SCharles.Forsyth		if(mp.total == 0 && mp.totals[0] == 0)
1183*37da2899SCharles.Forsyth			continue;
1184*37da2899SCharles.Forsyth		if((b := getb(mp.path)) == nil)
1185*37da2899SCharles.Forsyth			continue;
1186*37da2899SCharles.Forsyth		sys->print("\nModule: %s(%s)\n\n", mp.name, mp.path);
1187*37da2899SCharles.Forsyth		line := mp.linetab;
1188*37da2899SCharles.Forsyth		if(v&LINE){
1189*37da2899SCharles.Forsyth			bio := bufio->open(b, Bufio->OREAD);
1190*37da2899SCharles.Forsyth			if(bio == nil){
1191*37da2899SCharles.Forsyth				error(sys->sprint("cannot open %s for reading", b));
1192*37da2899SCharles.Forsyth				continue;
1193*37da2899SCharles.Forsyth			}
1194*37da2899SCharles.Forsyth			i = 1;
1195*37da2899SCharles.Forsyth			ll := len line/2;
1196*37da2899SCharles.Forsyth			while((s := bio.gets('\n')) != nil){
1197*37da2899SCharles.Forsyth				f := g := 0;
1198*37da2899SCharles.Forsyth				if(i < ll){
1199*37da2899SCharles.Forsyth					f = line[2*i];
1200*37da2899SCharles.Forsyth					g = line[2*i+1];
1201*37da2899SCharles.Forsyth				}
1202*37da2899SCharles.Forsyth				if(verbose || f != 0 || g != 0){
1203*37da2899SCharles.Forsyth					if(fullhdr)
1204*37da2899SCharles.Forsyth						sys->print("%s:", b);
1205*37da2899SCharles.Forsyth					sys->print("%d\t%d\t%d\t%s", i, f, g, s);
1206*37da2899SCharles.Forsyth				}
1207*37da2899SCharles.Forsyth				i++;
1208*37da2899SCharles.Forsyth			}
1209*37da2899SCharles.Forsyth			if(v&(FUNCTION|MODULE))
1210*37da2899SCharles.Forsyth				sys->print("\n");
1211*37da2899SCharles.Forsyth		}
1212*37da2899SCharles.Forsyth		if(v&FUNCTION){
1213*37da2899SCharles.Forsyth			fun := mp.funtab;
1214*37da2899SCharles.Forsyth			nf := len fun;
1215*37da2899SCharles.Forsyth			for(i = 0; i < nf; i++)
1216*37da2899SCharles.Forsyth				if(verbose || fun[i].count != 0 || fun[i].counte != 0){
1217*37da2899SCharles.Forsyth					if(fullhdr)
1218*37da2899SCharles.Forsyth						sys->print("%s:", b);
1219*37da2899SCharles.Forsyth					sys->print("%d\t%d\t%d\t%s()\n", fun[i].line, fun[i].count, fun[i].counte, fun[i].name);
1220*37da2899SCharles.Forsyth			}
1221*37da2899SCharles.Forsyth			if(v&MODULE)
1222*37da2899SCharles.Forsyth				sys->print("\n");
1223*37da2899SCharles.Forsyth		}
1224*37da2899SCharles.Forsyth		if(v&MODULE)
1225*37da2899SCharles.Forsyth			sys->print("Module totals\t%d\t%d\n\n", mp.total, mp.totals[0]);
1226*37da2899SCharles.Forsyth	}
1227*37da2899SCharles.Forsyth	if(p.mods != nil && tl p.mods != nil)
1228*37da2899SCharles.Forsyth		sys->print("Grand totals\t%d\t%d\n\n", p.total, p.totals[0]);
1229*37da2899SCharles.Forsyth	return 0;
1230*37da2899SCharles.Forsyth}
1231