xref: /onnv-gate/usr/src/cmd/sgs/gprof/common/printgprof.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright (c) 1990-1998 by Sun Microsystems, Inc.
24*0Sstevel@tonic-gate  * All rights reserved.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <ctype.h>
30*0Sstevel@tonic-gate #include <string.h>
31*0Sstevel@tonic-gate #include <sys/param.h>
32*0Sstevel@tonic-gate #include <stdlib.h>
33*0Sstevel@tonic-gate #include "gprof.h"
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate extern int find_run_directory(char *, char *, char *, char **, char *);
36*0Sstevel@tonic-gate void print_demangled_name(int, nltype *);
37*0Sstevel@tonic-gate void striped_name(char *, nltype **);
38*0Sstevel@tonic-gate 
39*0Sstevel@tonic-gate 
40*0Sstevel@tonic-gate extern char *demangle();
41*0Sstevel@tonic-gate char *strstr();
42*0Sstevel@tonic-gate char *parsename();
43*0Sstevel@tonic-gate char name_buffer[512];
44*0Sstevel@tonic-gate extern long hz;
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate /*
47*0Sstevel@tonic-gate  * Symbols that must never be printed, no matter what.
48*0Sstevel@tonic-gate  */
49*0Sstevel@tonic-gate char *splsym[] = {
50*0Sstevel@tonic-gate 	PRF_ETEXT,
51*0Sstevel@tonic-gate 	PRF_EXTSYM,
52*0Sstevel@tonic-gate 	PRF_MEMTERM,
53*0Sstevel@tonic-gate 	0
54*0Sstevel@tonic-gate };
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate char *
57*0Sstevel@tonic-gate demangled_name(nltype *selfp)
58*0Sstevel@tonic-gate {
59*0Sstevel@tonic-gate 	char *name;
60*0Sstevel@tonic-gate 	if (!Cflag)
61*0Sstevel@tonic-gate 		return (selfp->name);
62*0Sstevel@tonic-gate 
63*0Sstevel@tonic-gate 	name = (char *) sgs_demangle(selfp->name);
64*0Sstevel@tonic-gate 	return (name);
65*0Sstevel@tonic-gate }
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate void
68*0Sstevel@tonic-gate printprof()
69*0Sstevel@tonic-gate {
70*0Sstevel@tonic-gate 	nltype	*np;
71*0Sstevel@tonic-gate 	nltype	**sortednlp;
72*0Sstevel@tonic-gate 	int	i, index;
73*0Sstevel@tonic-gate 	int 	print_count = number_funcs_toprint;
74*0Sstevel@tonic-gate 	bool	print_flag = TRUE;
75*0Sstevel@tonic-gate 	mod_info_t	*mi;
76*0Sstevel@tonic-gate 
77*0Sstevel@tonic-gate 	actime = 0.0;
78*0Sstevel@tonic-gate 	printf("\f\n");
79*0Sstevel@tonic-gate 	flatprofheader();
80*0Sstevel@tonic-gate 
81*0Sstevel@tonic-gate 	/*
82*0Sstevel@tonic-gate 	 *	Sort the symbol table in by time
83*0Sstevel@tonic-gate 	 */
84*0Sstevel@tonic-gate 	sortednlp = (nltype **) calloc(total_names, sizeof (nltype *));
85*0Sstevel@tonic-gate 	if (sortednlp == (nltype **) 0) {
86*0Sstevel@tonic-gate 		fprintf(stderr,
87*0Sstevel@tonic-gate 		    "[printprof] ran out of memory for time sorting\n");
88*0Sstevel@tonic-gate 	}
89*0Sstevel@tonic-gate 
90*0Sstevel@tonic-gate 	index = 0;
91*0Sstevel@tonic-gate 	for (mi = &modules; mi; mi = mi->next) {
92*0Sstevel@tonic-gate 		for (i = 0; i < mi->nname; i++)
93*0Sstevel@tonic-gate 			sortednlp[index++] = &(mi->nl[i]);
94*0Sstevel@tonic-gate 	}
95*0Sstevel@tonic-gate 
96*0Sstevel@tonic-gate 	qsort(sortednlp, total_names, sizeof (nltype *),
97*0Sstevel@tonic-gate 		(int(*)(const void *, const void *))timecmp);
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate 	for (index = 0; (index < total_names) && print_flag; index += 1) {
100*0Sstevel@tonic-gate 		np = sortednlp[index];
101*0Sstevel@tonic-gate 		flatprofline(np);
102*0Sstevel@tonic-gate 		if (nflag) {
103*0Sstevel@tonic-gate 			if (--print_count == 0)
104*0Sstevel@tonic-gate 				print_flag = FALSE;
105*0Sstevel@tonic-gate 		}
106*0Sstevel@tonic-gate 	}
107*0Sstevel@tonic-gate 	actime = 0.0;
108*0Sstevel@tonic-gate 	free(sortednlp);
109*0Sstevel@tonic-gate }
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate int
112*0Sstevel@tonic-gate timecmp(nltype **npp1, nltype **npp2)
113*0Sstevel@tonic-gate {
114*0Sstevel@tonic-gate 	double	timediff;
115*0Sstevel@tonic-gate 	long	calldiff;
116*0Sstevel@tonic-gate 
117*0Sstevel@tonic-gate 	timediff = (*npp2)->time - (*npp1)->time;
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate 	if (timediff > 0.0)
120*0Sstevel@tonic-gate 		return (1);
121*0Sstevel@tonic-gate 
122*0Sstevel@tonic-gate 	if (timediff < 0.0)
123*0Sstevel@tonic-gate 		return (-1);
124*0Sstevel@tonic-gate 
125*0Sstevel@tonic-gate 	calldiff = (*npp2)->ncall - (*npp1)->ncall;
126*0Sstevel@tonic-gate 
127*0Sstevel@tonic-gate 	if (calldiff > 0)
128*0Sstevel@tonic-gate 		return (1);
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 	if (calldiff < 0)
131*0Sstevel@tonic-gate 		return (-1);
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate 	return (strcmp((*npp1)->name, (*npp2)->name));
134*0Sstevel@tonic-gate }
135*0Sstevel@tonic-gate 
136*0Sstevel@tonic-gate /*
137*0Sstevel@tonic-gate  *	header for flatprofline
138*0Sstevel@tonic-gate  */
139*0Sstevel@tonic-gate void
140*0Sstevel@tonic-gate flatprofheader()
141*0Sstevel@tonic-gate {
142*0Sstevel@tonic-gate 
143*0Sstevel@tonic-gate 	if (bflag)
144*0Sstevel@tonic-gate 		printblurb(FLAT_BLURB);
145*0Sstevel@tonic-gate 
146*0Sstevel@tonic-gate 	if (old_style) {
147*0Sstevel@tonic-gate 		printf("\ngranularity: each sample hit covers %d byte(s)",
148*0Sstevel@tonic-gate 					    (long)scale * sizeof (UNIT));
149*0Sstevel@tonic-gate 		if (totime > 0.0) {
150*0Sstevel@tonic-gate 			printf(" for %.2f%% of %.2f seconds\n\n",
151*0Sstevel@tonic-gate 			    100.0/totime, totime / hz);
152*0Sstevel@tonic-gate 		} else {
153*0Sstevel@tonic-gate 			printf(" no time accumulated\n\n");
154*0Sstevel@tonic-gate 			/*
155*0Sstevel@tonic-gate 			 * this doesn't hurt since all the numerators will
156*0Sstevel@tonic-gate 			 * be zero.
157*0Sstevel@tonic-gate 			 */
158*0Sstevel@tonic-gate 			totime = 1.0;
159*0Sstevel@tonic-gate 		}
160*0Sstevel@tonic-gate 	}
161*0Sstevel@tonic-gate 
162*0Sstevel@tonic-gate 	printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
163*0Sstevel@tonic-gate 	    "% ", "cumulative", "self ", "", "self ", "total ", "");
164*0Sstevel@tonic-gate 	printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
165*0Sstevel@tonic-gate 	    "time", "seconds ", "seconds", "calls",
166*0Sstevel@tonic-gate 	    "ms/call", "ms/call", "name");
167*0Sstevel@tonic-gate }
168*0Sstevel@tonic-gate 
169*0Sstevel@tonic-gate void
170*0Sstevel@tonic-gate flatprofline(nltype *np)
171*0Sstevel@tonic-gate {
172*0Sstevel@tonic-gate 	if (zflag == 0 && np->ncall == 0 && np->time == 0)
173*0Sstevel@tonic-gate 		return;
174*0Sstevel@tonic-gate 
175*0Sstevel@tonic-gate 	/*
176*0Sstevel@tonic-gate 	 * Do not print certain special symbols, like PRF_EXTSYM, etc.
177*0Sstevel@tonic-gate 	 * even if zflag was on.
178*0Sstevel@tonic-gate 	 */
179*0Sstevel@tonic-gate 	if (is_special_sym(np))
180*0Sstevel@tonic-gate 		return;
181*0Sstevel@tonic-gate 
182*0Sstevel@tonic-gate 	actime += np->time;
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate 	printf("%5.1f %10.2f %8.2f",
185*0Sstevel@tonic-gate 	    100 * np->time / totime, actime / hz, np->time / hz);
186*0Sstevel@tonic-gate 
187*0Sstevel@tonic-gate 	if (np->ncall != 0) {
188*0Sstevel@tonic-gate 		printf(" %8lld %8.2f %8.2f  ", np->ncall,
189*0Sstevel@tonic-gate 		    1000 * np->time / hz / np->ncall,
190*0Sstevel@tonic-gate 		    1000 * (np->time + np->childtime) / hz / np->ncall);
191*0Sstevel@tonic-gate 	} else {
192*0Sstevel@tonic-gate 		if (!Cflag)
193*0Sstevel@tonic-gate 			printf(" %8.8s %8.8s %8.8s ", "", "", "");
194*0Sstevel@tonic-gate 		else
195*0Sstevel@tonic-gate 			printf(" %8.8s %8.8s %8.8s  ", "", "", "");
196*0Sstevel@tonic-gate 	}
197*0Sstevel@tonic-gate 
198*0Sstevel@tonic-gate 	printname(np);
199*0Sstevel@tonic-gate 
200*0Sstevel@tonic-gate 	if (Cflag)
201*0Sstevel@tonic-gate 		print_demangled_name(55, np);
202*0Sstevel@tonic-gate 
203*0Sstevel@tonic-gate 	printf("\n");
204*0Sstevel@tonic-gate }
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate void
207*0Sstevel@tonic-gate gprofheader()
208*0Sstevel@tonic-gate {
209*0Sstevel@tonic-gate 
210*0Sstevel@tonic-gate 	if (bflag)
211*0Sstevel@tonic-gate 		printblurb(CALLG_BLURB);
212*0Sstevel@tonic-gate 
213*0Sstevel@tonic-gate 	if (old_style) {
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate 		printf("\ngranularity: each sample hit covers %d byte(s)",
216*0Sstevel@tonic-gate 						(long)scale * sizeof (UNIT));
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate 		if (printtime > 0.0) {
219*0Sstevel@tonic-gate 			printf(" for %.2f%% of %.2f seconds\n\n",
220*0Sstevel@tonic-gate 			    100.0/printtime, printtime / hz);
221*0Sstevel@tonic-gate 		} else {
222*0Sstevel@tonic-gate 			printf(" no time propagated\n\n");
223*0Sstevel@tonic-gate 			/*
224*0Sstevel@tonic-gate 			 * this doesn't hurt, since all the numerators
225*0Sstevel@tonic-gate 			 * will be 0.0
226*0Sstevel@tonic-gate 			 */
227*0Sstevel@tonic-gate 			printtime = 1.0;
228*0Sstevel@tonic-gate 		}
229*0Sstevel@tonic-gate 	} else {
230*0Sstevel@tonic-gate 		printf("\ngranularity: each pc-hit is considered 1 tick");
231*0Sstevel@tonic-gate 		if (hz != 1) {
232*0Sstevel@tonic-gate 			printf(" (@ %4.3f seconds per tick)",
233*0Sstevel@tonic-gate 							(double) 1.0 / hz);
234*0Sstevel@tonic-gate 		}
235*0Sstevel@tonic-gate 		puts("\n\n");
236*0Sstevel@tonic-gate 	}
237*0Sstevel@tonic-gate 
238*0Sstevel@tonic-gate 	printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n",
239*0Sstevel@tonic-gate 	    "", "", "", "", "called", "total", "parents");
240*0Sstevel@tonic-gate 	printf("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n",
241*0Sstevel@tonic-gate 	    "index", "%time", "self", "descendents",
242*0Sstevel@tonic-gate 	    "called", "self", "name", "index");
243*0Sstevel@tonic-gate 	printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n",
244*0Sstevel@tonic-gate 	    "", "", "", "", "called", "total", "children");
245*0Sstevel@tonic-gate 	printf("\n");
246*0Sstevel@tonic-gate }
247*0Sstevel@tonic-gate 
248*0Sstevel@tonic-gate void
249*0Sstevel@tonic-gate gprofline(nltype *np)
250*0Sstevel@tonic-gate {
251*0Sstevel@tonic-gate 	char	kirkbuffer[BUFSIZ];
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate 	sprintf(kirkbuffer, "[%d]", np->index);
254*0Sstevel@tonic-gate 	printf("%-6.6s %5.1f %7.2f %11.2f", kirkbuffer,
255*0Sstevel@tonic-gate 	    100 * (np->propself + np->propchild) / printtime,
256*0Sstevel@tonic-gate 	    np->propself / hz, np->propchild / hz);
257*0Sstevel@tonic-gate 
258*0Sstevel@tonic-gate 	if ((np->ncall + np->selfcalls) != 0) {
259*0Sstevel@tonic-gate 		printf(" %7lld", np->ncall);
260*0Sstevel@tonic-gate 
261*0Sstevel@tonic-gate 		if (np->selfcalls != 0)
262*0Sstevel@tonic-gate 			printf("+%-7lld ", np->selfcalls);
263*0Sstevel@tonic-gate 		else
264*0Sstevel@tonic-gate 			printf(" %7.7s ", "");
265*0Sstevel@tonic-gate 	} else {
266*0Sstevel@tonic-gate 		printf(" %7.7s %7.7s ", "", "");
267*0Sstevel@tonic-gate 	}
268*0Sstevel@tonic-gate 
269*0Sstevel@tonic-gate 	printname(np);
270*0Sstevel@tonic-gate 
271*0Sstevel@tonic-gate 	if (Cflag)
272*0Sstevel@tonic-gate 		print_demangled_name(50, np);
273*0Sstevel@tonic-gate 
274*0Sstevel@tonic-gate 	printf("\n");
275*0Sstevel@tonic-gate }
276*0Sstevel@tonic-gate 
277*0Sstevel@tonic-gate static bool
278*0Sstevel@tonic-gate is_special_sym(nltype *nlp)
279*0Sstevel@tonic-gate {
280*0Sstevel@tonic-gate 	int	i;
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate 	if (nlp->name == NULL)
283*0Sstevel@tonic-gate 		return (FALSE);
284*0Sstevel@tonic-gate 
285*0Sstevel@tonic-gate 	for (i = 0;  splsym[i]; i++)
286*0Sstevel@tonic-gate 		if (strcmp(splsym[i], nlp->name) == 0)
287*0Sstevel@tonic-gate 			return (TRUE);
288*0Sstevel@tonic-gate 
289*0Sstevel@tonic-gate 	return (FALSE);
290*0Sstevel@tonic-gate }
291*0Sstevel@tonic-gate 
292*0Sstevel@tonic-gate void
293*0Sstevel@tonic-gate printgprof(nltype **timesortnlp)
294*0Sstevel@tonic-gate {
295*0Sstevel@tonic-gate 	int	index;
296*0Sstevel@tonic-gate 	nltype	*parentp;
297*0Sstevel@tonic-gate 	int 	print_count = number_funcs_toprint;
298*0Sstevel@tonic-gate 	bool	count_flag = TRUE;
299*0Sstevel@tonic-gate 
300*0Sstevel@tonic-gate 	/*
301*0Sstevel@tonic-gate 	 * Print out the structured profiling list
302*0Sstevel@tonic-gate 	 */
303*0Sstevel@tonic-gate 	gprofheader();
304*0Sstevel@tonic-gate 
305*0Sstevel@tonic-gate 	for (index = 0; index < total_names + ncycle && count_flag; index++) {
306*0Sstevel@tonic-gate 		parentp = timesortnlp[index];
307*0Sstevel@tonic-gate 		if (zflag == 0 && parentp->ncall == 0 &&
308*0Sstevel@tonic-gate 		    parentp->selfcalls == 0 && parentp->propself == 0 &&
309*0Sstevel@tonic-gate 		    parentp -> propchild == 0)
310*0Sstevel@tonic-gate 			continue;
311*0Sstevel@tonic-gate 
312*0Sstevel@tonic-gate 		if (!parentp->printflag)
313*0Sstevel@tonic-gate 			continue;
314*0Sstevel@tonic-gate 
315*0Sstevel@tonic-gate 		/*
316*0Sstevel@tonic-gate 		 * Do not print certain special symbols, like PRF_EXTSYM, etc.
317*0Sstevel@tonic-gate 		 * even if zflag was on.
318*0Sstevel@tonic-gate 		 */
319*0Sstevel@tonic-gate 		if (is_special_sym(parentp))
320*0Sstevel@tonic-gate 			continue;
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate 		if (parentp->name == 0 && parentp->cycleno != 0) {
323*0Sstevel@tonic-gate 			/*
324*0Sstevel@tonic-gate 			 *	cycle header
325*0Sstevel@tonic-gate 			 */
326*0Sstevel@tonic-gate 			printcycle(parentp);
327*0Sstevel@tonic-gate 			printmembers(parentp);
328*0Sstevel@tonic-gate 		} else {
329*0Sstevel@tonic-gate 			printparents(parentp);
330*0Sstevel@tonic-gate 			gprofline(parentp);
331*0Sstevel@tonic-gate 			printchildren(parentp);
332*0Sstevel@tonic-gate 		}
333*0Sstevel@tonic-gate 
334*0Sstevel@tonic-gate 		printf("\n");
335*0Sstevel@tonic-gate 		printf("-----------------------------------------------\n");
336*0Sstevel@tonic-gate 		printf("\n");
337*0Sstevel@tonic-gate 
338*0Sstevel@tonic-gate 		if (nflag) {
339*0Sstevel@tonic-gate 			--print_count;
340*0Sstevel@tonic-gate 			if (print_count == 0)
341*0Sstevel@tonic-gate 				count_flag = FALSE;
342*0Sstevel@tonic-gate 		}
343*0Sstevel@tonic-gate 	}
344*0Sstevel@tonic-gate 	free(timesortnlp);
345*0Sstevel@tonic-gate }
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate /*
348*0Sstevel@tonic-gate  *	sort by decreasing propagated time
349*0Sstevel@tonic-gate  *	if times are equal, but one is a cycle header,
350*0Sstevel@tonic-gate  *		say that's first (e.g. less, i.e. -1).
351*0Sstevel@tonic-gate  *	if one's name doesn't have an underscore and the other does,
352*0Sstevel@tonic-gate  *		say the one is first.
353*0Sstevel@tonic-gate  *	all else being equal, sort by names.
354*0Sstevel@tonic-gate  */
355*0Sstevel@tonic-gate int
356*0Sstevel@tonic-gate totalcmp(nltype **npp1, nltype **npp2)
357*0Sstevel@tonic-gate {
358*0Sstevel@tonic-gate 	nltype	*np1 = *npp1;
359*0Sstevel@tonic-gate 	nltype	*np2 = *npp2;
360*0Sstevel@tonic-gate 	double	diff;
361*0Sstevel@tonic-gate 
362*0Sstevel@tonic-gate 	diff = (np1->propself + np1->propchild) -
363*0Sstevel@tonic-gate 	    (np2->propself + np2->propchild);
364*0Sstevel@tonic-gate 
365*0Sstevel@tonic-gate 	if (diff < 0.0)
366*0Sstevel@tonic-gate 		return (1);
367*0Sstevel@tonic-gate 	if (diff > 0.0)
368*0Sstevel@tonic-gate 		return (-1);
369*0Sstevel@tonic-gate 	if (np1->name == 0 && np1->cycleno != 0)
370*0Sstevel@tonic-gate 		return (-1);
371*0Sstevel@tonic-gate 	if (np2->name == 0 && np2->cycleno != 0)
372*0Sstevel@tonic-gate 		return (1);
373*0Sstevel@tonic-gate 	if (np1->name == 0)
374*0Sstevel@tonic-gate 		return (-1);
375*0Sstevel@tonic-gate 	if (np2->name == 0)
376*0Sstevel@tonic-gate 		return (1);
377*0Sstevel@tonic-gate 
378*0Sstevel@tonic-gate 	if (*(np1->name) != '_' && *(np2->name) == '_')
379*0Sstevel@tonic-gate 		return (-1);
380*0Sstevel@tonic-gate 	if (*(np1->name) == '_' && *(np2->name) != '_')
381*0Sstevel@tonic-gate 		return (1);
382*0Sstevel@tonic-gate 	if (np1->ncall > np2->ncall)
383*0Sstevel@tonic-gate 		return (-1);
384*0Sstevel@tonic-gate 	if (np1->ncall < np2->ncall)
385*0Sstevel@tonic-gate 		return (1);
386*0Sstevel@tonic-gate 	return (strcmp(np1->name, np2->name));
387*0Sstevel@tonic-gate }
388*0Sstevel@tonic-gate 
389*0Sstevel@tonic-gate void
390*0Sstevel@tonic-gate printparents(nltype *childp)
391*0Sstevel@tonic-gate {
392*0Sstevel@tonic-gate 	nltype	*parentp;
393*0Sstevel@tonic-gate 	arctype	*arcp;
394*0Sstevel@tonic-gate 	nltype	*cycleheadp;
395*0Sstevel@tonic-gate 
396*0Sstevel@tonic-gate 	if (childp->cyclehead != 0)
397*0Sstevel@tonic-gate 		cycleheadp = childp -> cyclehead;
398*0Sstevel@tonic-gate 	else
399*0Sstevel@tonic-gate 		cycleheadp = childp;
400*0Sstevel@tonic-gate 
401*0Sstevel@tonic-gate 	if (childp->parents == 0) {
402*0Sstevel@tonic-gate 		printf("%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s"
403*0Sstevel@tonic-gate 		    "     <spontaneous>\n", "", "", "", "", "", "");
404*0Sstevel@tonic-gate 		return;
405*0Sstevel@tonic-gate 	}
406*0Sstevel@tonic-gate 
407*0Sstevel@tonic-gate 	sortparents(childp);
408*0Sstevel@tonic-gate 
409*0Sstevel@tonic-gate 	for (arcp = childp->parents; arcp; arcp = arcp->arc_parentlist) {
410*0Sstevel@tonic-gate 		parentp = arcp -> arc_parentp;
411*0Sstevel@tonic-gate 		if (childp == parentp || (childp->cycleno != 0 &&
412*0Sstevel@tonic-gate 		    parentp->cycleno == childp->cycleno)) {
413*0Sstevel@tonic-gate 			/*
414*0Sstevel@tonic-gate 			 *	selfcall or call among siblings
415*0Sstevel@tonic-gate 			 */
416*0Sstevel@tonic-gate 			printf("%6.6s %5.5s %7.7s %11.11s %7lld %7.7s     ",
417*0Sstevel@tonic-gate 			    "", "", "", "", arcp->arc_count, "");
418*0Sstevel@tonic-gate 			printname(parentp);
419*0Sstevel@tonic-gate 
420*0Sstevel@tonic-gate 			if (Cflag)
421*0Sstevel@tonic-gate 				print_demangled_name(54, parentp);
422*0Sstevel@tonic-gate 
423*0Sstevel@tonic-gate 			printf("\n");
424*0Sstevel@tonic-gate 		} else {
425*0Sstevel@tonic-gate 			/*
426*0Sstevel@tonic-gate 			 *	regular parent of child
427*0Sstevel@tonic-gate 			 */
428*0Sstevel@tonic-gate 			printf("%6.6s %5.5s %7.2f %11.2f %7lld/%-7lld     ", "",
429*0Sstevel@tonic-gate 			    "", arcp->arc_time / hz, arcp->arc_childtime / hz,
430*0Sstevel@tonic-gate 			    arcp->arc_count, cycleheadp->ncall);
431*0Sstevel@tonic-gate 			printname(parentp);
432*0Sstevel@tonic-gate 
433*0Sstevel@tonic-gate 			if (Cflag)
434*0Sstevel@tonic-gate 				print_demangled_name(54, parentp);
435*0Sstevel@tonic-gate 
436*0Sstevel@tonic-gate 			printf("\n");
437*0Sstevel@tonic-gate 		}
438*0Sstevel@tonic-gate 	}
439*0Sstevel@tonic-gate }
440*0Sstevel@tonic-gate 
441*0Sstevel@tonic-gate void
442*0Sstevel@tonic-gate printchildren(nltype *parentp)
443*0Sstevel@tonic-gate {
444*0Sstevel@tonic-gate 	nltype	*childp;
445*0Sstevel@tonic-gate 	arctype	*arcp;
446*0Sstevel@tonic-gate 
447*0Sstevel@tonic-gate 	sortchildren(parentp);
448*0Sstevel@tonic-gate 
449*0Sstevel@tonic-gate 	for (arcp = parentp->children; arcp; arcp = arcp->arc_childlist) {
450*0Sstevel@tonic-gate 		childp = arcp->arc_childp;
451*0Sstevel@tonic-gate 		if (childp == parentp || (childp->cycleno != 0 &&
452*0Sstevel@tonic-gate 		    childp->cycleno == parentp->cycleno)) {
453*0Sstevel@tonic-gate 			/*
454*0Sstevel@tonic-gate 			 * self call or call to sibling
455*0Sstevel@tonic-gate 			 */
456*0Sstevel@tonic-gate 			printf("%6.6s %5.5s %7.7s %11.11s %7lld %7.7s     ",
457*0Sstevel@tonic-gate 			    "", "", "", "", arcp->arc_count, "");
458*0Sstevel@tonic-gate 			printname(childp);
459*0Sstevel@tonic-gate 
460*0Sstevel@tonic-gate 			if (Cflag)
461*0Sstevel@tonic-gate 				print_demangled_name(54, childp);
462*0Sstevel@tonic-gate 
463*0Sstevel@tonic-gate 			printf("\n");
464*0Sstevel@tonic-gate 		} else {
465*0Sstevel@tonic-gate 			/*
466*0Sstevel@tonic-gate 			 *	regular child of parent
467*0Sstevel@tonic-gate 			 */
468*0Sstevel@tonic-gate 			if (childp->cyclehead)
469*0Sstevel@tonic-gate 				printf("%6.6s %5.5s %7.2f %11.2f "
470*0Sstevel@tonic-gate 				    "%7lld/%-7lld     ", "", "",
471*0Sstevel@tonic-gate 				    arcp->arc_time / hz,
472*0Sstevel@tonic-gate 				    arcp->arc_childtime / hz, arcp->arc_count,
473*0Sstevel@tonic-gate 				    childp->cyclehead->ncall);
474*0Sstevel@tonic-gate 			else
475*0Sstevel@tonic-gate 				printf("%6.6s %5.5s %7.2f %11.2f "
476*0Sstevel@tonic-gate 				    "%7lld %7.7s    ",
477*0Sstevel@tonic-gate 				    "", "", arcp->arc_time / hz,
478*0Sstevel@tonic-gate 				    arcp->arc_childtime / hz, arcp->arc_count,
479*0Sstevel@tonic-gate 				    "");
480*0Sstevel@tonic-gate 
481*0Sstevel@tonic-gate 			printname(childp);
482*0Sstevel@tonic-gate 
483*0Sstevel@tonic-gate 			if (Cflag)
484*0Sstevel@tonic-gate 				print_demangled_name(54, childp);
485*0Sstevel@tonic-gate 
486*0Sstevel@tonic-gate 			printf("\n");
487*0Sstevel@tonic-gate 		}
488*0Sstevel@tonic-gate 	}
489*0Sstevel@tonic-gate }
490*0Sstevel@tonic-gate 
491*0Sstevel@tonic-gate void
492*0Sstevel@tonic-gate printname(nltype *selfp)
493*0Sstevel@tonic-gate {
494*0Sstevel@tonic-gate 	char  *c;
495*0Sstevel@tonic-gate 	c = demangled_name(selfp);
496*0Sstevel@tonic-gate 
497*0Sstevel@tonic-gate 	if (selfp->name != 0) {
498*0Sstevel@tonic-gate 		if (!Cflag)
499*0Sstevel@tonic-gate 			printf("%s", selfp->name);
500*0Sstevel@tonic-gate 		else
501*0Sstevel@tonic-gate 			printf("%s", c);
502*0Sstevel@tonic-gate 
503*0Sstevel@tonic-gate #ifdef DEBUG
504*0Sstevel@tonic-gate 		if (debug & DFNDEBUG)
505*0Sstevel@tonic-gate 			printf("{%d} ", selfp->toporder);
506*0Sstevel@tonic-gate 
507*0Sstevel@tonic-gate 		if (debug & PROPDEBUG)
508*0Sstevel@tonic-gate 			printf("%5.2f%% ", selfp->propfraction);
509*0Sstevel@tonic-gate #endif DEBUG
510*0Sstevel@tonic-gate 	}
511*0Sstevel@tonic-gate 
512*0Sstevel@tonic-gate 	if (selfp->cycleno != 0)
513*0Sstevel@tonic-gate 		printf("\t<cycle %d>", selfp->cycleno);
514*0Sstevel@tonic-gate 
515*0Sstevel@tonic-gate 	if (selfp->index != 0) {
516*0Sstevel@tonic-gate 		if (selfp->printflag)
517*0Sstevel@tonic-gate 			printf(" [%d]", selfp->index);
518*0Sstevel@tonic-gate 		else
519*0Sstevel@tonic-gate 			printf(" (%d)", selfp->index);
520*0Sstevel@tonic-gate 	}
521*0Sstevel@tonic-gate }
522*0Sstevel@tonic-gate 
523*0Sstevel@tonic-gate void
524*0Sstevel@tonic-gate print_demangled_name(int n, nltype *selfp)
525*0Sstevel@tonic-gate {
526*0Sstevel@tonic-gate 	char *c;
527*0Sstevel@tonic-gate 	int i;
528*0Sstevel@tonic-gate 
529*0Sstevel@tonic-gate 	c = selfp->name;
530*0Sstevel@tonic-gate 
531*0Sstevel@tonic-gate 	if (strcmp(c, demangled_name(selfp)) == 0)
532*0Sstevel@tonic-gate 		return;
533*0Sstevel@tonic-gate 	else {
534*0Sstevel@tonic-gate 		printf("\n");
535*0Sstevel@tonic-gate 		for (i = 1; i < n; i++)
536*0Sstevel@tonic-gate 			printf(" ");
537*0Sstevel@tonic-gate 		printf("[%s]", selfp->name);
538*0Sstevel@tonic-gate 	}
539*0Sstevel@tonic-gate }
540*0Sstevel@tonic-gate 
541*0Sstevel@tonic-gate char *exotic();
542*0Sstevel@tonic-gate 
543*0Sstevel@tonic-gate void
544*0Sstevel@tonic-gate sortchildren(nltype *parentp)
545*0Sstevel@tonic-gate {
546*0Sstevel@tonic-gate 	arctype	*arcp;
547*0Sstevel@tonic-gate 	arctype	*detachedp;
548*0Sstevel@tonic-gate 	arctype	sorted;
549*0Sstevel@tonic-gate 	arctype	*prevp;
550*0Sstevel@tonic-gate 
551*0Sstevel@tonic-gate 	/*
552*0Sstevel@tonic-gate 	 *	unlink children from parent,
553*0Sstevel@tonic-gate 	 *	then insertion sort back on to sorted's children.
554*0Sstevel@tonic-gate 	 *	    *arcp	the arc you have detached and are inserting.
555*0Sstevel@tonic-gate 	 *	    *detachedp	the rest of the arcs to be sorted.
556*0Sstevel@tonic-gate 	 *	    sorted	arc list onto which you insertion sort.
557*0Sstevel@tonic-gate 	 *	    *prevp	arc before the arc you are comparing.
558*0Sstevel@tonic-gate 	 */
559*0Sstevel@tonic-gate 	sorted.arc_childlist = 0;
560*0Sstevel@tonic-gate 
561*0Sstevel@tonic-gate 	for ((arcp = parentp->children) && (detachedp = arcp->arc_childlist);
562*0Sstevel@tonic-gate 	    arcp;
563*0Sstevel@tonic-gate 	    (arcp = detachedp) && (detachedp = detachedp->arc_childlist)) {
564*0Sstevel@tonic-gate 		/*
565*0Sstevel@tonic-gate 		 *	consider *arcp as disconnected
566*0Sstevel@tonic-gate 		 *	insert it into sorted
567*0Sstevel@tonic-gate 		 */
568*0Sstevel@tonic-gate 		for (prevp = &sorted; prevp->arc_childlist;
569*0Sstevel@tonic-gate 		    prevp = prevp->arc_childlist) {
570*0Sstevel@tonic-gate 			if (arccmp(arcp, prevp->arc_childlist) != LESSTHAN)
571*0Sstevel@tonic-gate 				break;
572*0Sstevel@tonic-gate 		}
573*0Sstevel@tonic-gate 
574*0Sstevel@tonic-gate 		arcp->arc_childlist = prevp->arc_childlist;
575*0Sstevel@tonic-gate 		prevp->arc_childlist = arcp;
576*0Sstevel@tonic-gate 	}
577*0Sstevel@tonic-gate 
578*0Sstevel@tonic-gate 	/*
579*0Sstevel@tonic-gate 	 *	reattach sorted children to parent
580*0Sstevel@tonic-gate 	 */
581*0Sstevel@tonic-gate 	parentp->children = sorted.arc_childlist;
582*0Sstevel@tonic-gate }
583*0Sstevel@tonic-gate 
584*0Sstevel@tonic-gate void
585*0Sstevel@tonic-gate sortparents(nltype *childp)
586*0Sstevel@tonic-gate {
587*0Sstevel@tonic-gate 	arctype	*arcp;
588*0Sstevel@tonic-gate 	arctype	*detachedp;
589*0Sstevel@tonic-gate 	arctype	sorted;
590*0Sstevel@tonic-gate 	arctype	*prevp;
591*0Sstevel@tonic-gate 
592*0Sstevel@tonic-gate 	/*
593*0Sstevel@tonic-gate 	 *	unlink parents from child,
594*0Sstevel@tonic-gate 	 *	then insertion sort back on to sorted's parents.
595*0Sstevel@tonic-gate 	 *	    *arcp	the arc you have detached and are inserting.
596*0Sstevel@tonic-gate 	 *	    *detachedp	the rest of the arcs to be sorted.
597*0Sstevel@tonic-gate 	 *	    sorted	arc list onto which you insertion sort.
598*0Sstevel@tonic-gate 	 *	    *prevp	arc before the arc you are comparing.
599*0Sstevel@tonic-gate 	 */
600*0Sstevel@tonic-gate 	sorted.arc_parentlist = 0;
601*0Sstevel@tonic-gate 
602*0Sstevel@tonic-gate 	for ((arcp = childp->parents) && (detachedp = arcp->arc_parentlist);
603*0Sstevel@tonic-gate 	    arcp;
604*0Sstevel@tonic-gate 	    (arcp = detachedp) && (detachedp = detachedp->arc_parentlist)) {
605*0Sstevel@tonic-gate 		/*
606*0Sstevel@tonic-gate 		 *	consider *arcp as disconnected
607*0Sstevel@tonic-gate 		 *	insert it into sorted
608*0Sstevel@tonic-gate 		 */
609*0Sstevel@tonic-gate 		for (prevp = &sorted; prevp->arc_parentlist;
610*0Sstevel@tonic-gate 		    prevp = prevp->arc_parentlist) {
611*0Sstevel@tonic-gate 			if (arccmp(arcp, prevp->arc_parentlist) != GREATERTHAN)
612*0Sstevel@tonic-gate 				break;
613*0Sstevel@tonic-gate 		}
614*0Sstevel@tonic-gate 		arcp->arc_parentlist = prevp->arc_parentlist;
615*0Sstevel@tonic-gate 		prevp->arc_parentlist = arcp;
616*0Sstevel@tonic-gate 	}
617*0Sstevel@tonic-gate 
618*0Sstevel@tonic-gate 	/*
619*0Sstevel@tonic-gate 	 *	reattach sorted arcs to child
620*0Sstevel@tonic-gate 	 */
621*0Sstevel@tonic-gate 	childp->parents = sorted.arc_parentlist;
622*0Sstevel@tonic-gate }
623*0Sstevel@tonic-gate 
624*0Sstevel@tonic-gate void
625*0Sstevel@tonic-gate printcycle(nltype *cyclep)
626*0Sstevel@tonic-gate {
627*0Sstevel@tonic-gate 	char	kirkbuffer[BUFSIZ];
628*0Sstevel@tonic-gate 
629*0Sstevel@tonic-gate 	sprintf(kirkbuffer, "[%d]", cyclep->index);
630*0Sstevel@tonic-gate 	printf("%-6.6s %5.1f %7.2f %11.2f %7lld", kirkbuffer,
631*0Sstevel@tonic-gate 	    100 * (cyclep->propself + cyclep->propchild) / printtime,
632*0Sstevel@tonic-gate 	    cyclep -> propself / hz, cyclep -> propchild / hz,
633*0Sstevel@tonic-gate 	    cyclep -> ncall);
634*0Sstevel@tonic-gate 
635*0Sstevel@tonic-gate 	if (cyclep->selfcalls != 0)
636*0Sstevel@tonic-gate 		printf("+%-7lld", cyclep->selfcalls);
637*0Sstevel@tonic-gate 	else
638*0Sstevel@tonic-gate 		printf(" %7.7s", "");
639*0Sstevel@tonic-gate 
640*0Sstevel@tonic-gate 	printf(" <cycle %d as a whole>\t[%d]\n", cyclep->cycleno,
641*0Sstevel@tonic-gate 	    cyclep->index);
642*0Sstevel@tonic-gate }
643*0Sstevel@tonic-gate 
644*0Sstevel@tonic-gate /*
645*0Sstevel@tonic-gate  *	print the members of a cycle
646*0Sstevel@tonic-gate  */
647*0Sstevel@tonic-gate void
648*0Sstevel@tonic-gate printmembers(nltype *cyclep)
649*0Sstevel@tonic-gate {
650*0Sstevel@tonic-gate 	nltype	*memberp;
651*0Sstevel@tonic-gate 
652*0Sstevel@tonic-gate 	sortmembers(cyclep);
653*0Sstevel@tonic-gate 
654*0Sstevel@tonic-gate 	for (memberp = cyclep->cnext; memberp; memberp = memberp->cnext) {
655*0Sstevel@tonic-gate 		printf("%6.6s %5.5s %7.2f %11.2f %7lld", "", "",
656*0Sstevel@tonic-gate 		    memberp->propself / hz, memberp->propchild / hz,
657*0Sstevel@tonic-gate 		    memberp->ncall);
658*0Sstevel@tonic-gate 
659*0Sstevel@tonic-gate 		if (memberp->selfcalls != 0)
660*0Sstevel@tonic-gate 			printf("+%-7lld", memberp->selfcalls);
661*0Sstevel@tonic-gate 		else
662*0Sstevel@tonic-gate 			printf(" %7.7s", "");
663*0Sstevel@tonic-gate 
664*0Sstevel@tonic-gate 		printf("     ");
665*0Sstevel@tonic-gate 		printname(memberp);
666*0Sstevel@tonic-gate 		if (Cflag)
667*0Sstevel@tonic-gate 			print_demangled_name(54, memberp);
668*0Sstevel@tonic-gate 		printf("\n");
669*0Sstevel@tonic-gate 	}
670*0Sstevel@tonic-gate }
671*0Sstevel@tonic-gate 
672*0Sstevel@tonic-gate /*
673*0Sstevel@tonic-gate  * sort members of a cycle
674*0Sstevel@tonic-gate  */
675*0Sstevel@tonic-gate void
676*0Sstevel@tonic-gate sortmembers(nltype *cyclep)
677*0Sstevel@tonic-gate {
678*0Sstevel@tonic-gate 	nltype	*todo;
679*0Sstevel@tonic-gate 	nltype	*doing;
680*0Sstevel@tonic-gate 	nltype	*prev;
681*0Sstevel@tonic-gate 
682*0Sstevel@tonic-gate 	/*
683*0Sstevel@tonic-gate 	 *	detach cycle members from cyclehead,
684*0Sstevel@tonic-gate 	 *	and insertion sort them back on.
685*0Sstevel@tonic-gate 	 */
686*0Sstevel@tonic-gate 	todo = cyclep->cnext;
687*0Sstevel@tonic-gate 	cyclep->cnext = 0;
688*0Sstevel@tonic-gate 
689*0Sstevel@tonic-gate 	for ((doing = todo) && (todo = doing->cnext);
690*0Sstevel@tonic-gate 	    doing; (doing = todo) && (todo = doing->cnext)) {
691*0Sstevel@tonic-gate 		for (prev = cyclep; prev->cnext; prev = prev->cnext) {
692*0Sstevel@tonic-gate 			if (membercmp(doing, prev->cnext) == GREATERTHAN)
693*0Sstevel@tonic-gate 				break;
694*0Sstevel@tonic-gate 		}
695*0Sstevel@tonic-gate 		doing->cnext = prev->cnext;
696*0Sstevel@tonic-gate 		prev->cnext = doing;
697*0Sstevel@tonic-gate 	}
698*0Sstevel@tonic-gate }
699*0Sstevel@tonic-gate 
700*0Sstevel@tonic-gate /*
701*0Sstevel@tonic-gate  *	major sort is on propself + propchild,
702*0Sstevel@tonic-gate  *	next is sort on ncalls + selfcalls.
703*0Sstevel@tonic-gate  */
704*0Sstevel@tonic-gate int
705*0Sstevel@tonic-gate membercmp(nltype *this, nltype *that)
706*0Sstevel@tonic-gate {
707*0Sstevel@tonic-gate 	double	thistime = this->propself + this->propchild;
708*0Sstevel@tonic-gate 	double	thattime = that->propself + that->propchild;
709*0Sstevel@tonic-gate 	actype	thiscalls = this->ncall + this->selfcalls;
710*0Sstevel@tonic-gate 	actype	thatcalls = that->ncall + that->selfcalls;
711*0Sstevel@tonic-gate 
712*0Sstevel@tonic-gate 	if (thistime > thattime)
713*0Sstevel@tonic-gate 		return (GREATERTHAN);
714*0Sstevel@tonic-gate 
715*0Sstevel@tonic-gate 	if (thistime < thattime)
716*0Sstevel@tonic-gate 		return (LESSTHAN);
717*0Sstevel@tonic-gate 
718*0Sstevel@tonic-gate 	if (thiscalls > thatcalls)
719*0Sstevel@tonic-gate 		return (GREATERTHAN);
720*0Sstevel@tonic-gate 
721*0Sstevel@tonic-gate 	if (thiscalls < thatcalls)
722*0Sstevel@tonic-gate 		return (LESSTHAN);
723*0Sstevel@tonic-gate 
724*0Sstevel@tonic-gate 	return (EQUALTO);
725*0Sstevel@tonic-gate }
726*0Sstevel@tonic-gate 
727*0Sstevel@tonic-gate /*
728*0Sstevel@tonic-gate  *	compare two arcs to/from the same child/parent.
729*0Sstevel@tonic-gate  *	- if one arc is a self arc, it's least.
730*0Sstevel@tonic-gate  *	- if one arc is within a cycle, it's less than.
731*0Sstevel@tonic-gate  *	- if both arcs are within a cycle, compare arc counts.
732*0Sstevel@tonic-gate  *	- if neither arc is within a cycle, compare with
733*0Sstevel@tonic-gate  *		arc_time + arc_childtime as major key
734*0Sstevel@tonic-gate  *		arc count as minor key
735*0Sstevel@tonic-gate  */
736*0Sstevel@tonic-gate int
737*0Sstevel@tonic-gate arccmp(arctype *thisp, arctype *thatp)
738*0Sstevel@tonic-gate {
739*0Sstevel@tonic-gate 	nltype	*thisparentp = thisp->arc_parentp;
740*0Sstevel@tonic-gate 	nltype	*thischildp = thisp->arc_childp;
741*0Sstevel@tonic-gate 	nltype	*thatparentp = thatp->arc_parentp;
742*0Sstevel@tonic-gate 	nltype	*thatchildp = thatp->arc_childp;
743*0Sstevel@tonic-gate 	double	thistime;
744*0Sstevel@tonic-gate 	double	thattime;
745*0Sstevel@tonic-gate 
746*0Sstevel@tonic-gate #ifdef DEBUG
747*0Sstevel@tonic-gate 	if (debug & TIMEDEBUG) {
748*0Sstevel@tonic-gate 		printf("[arccmp] ");
749*0Sstevel@tonic-gate 		printname(thisparentp);
750*0Sstevel@tonic-gate 		printf(" calls ");
751*0Sstevel@tonic-gate 		printname(thischildp);
752*0Sstevel@tonic-gate 		printf(" %f + %f %lld/%lld\n", thisp->arc_time,
753*0Sstevel@tonic-gate 		    thisp->arc_childtime, thisp->arc_count,
754*0Sstevel@tonic-gate 		    thischildp->ncall);
755*0Sstevel@tonic-gate 		printf("[arccmp] ");
756*0Sstevel@tonic-gate 		printname(thatparentp);
757*0Sstevel@tonic-gate 		printf(" calls ");
758*0Sstevel@tonic-gate 		printname(thatchildp);
759*0Sstevel@tonic-gate 		printf(" %f + %f %lld/%lld\n", thatp->arc_time,
760*0Sstevel@tonic-gate 		    thatp->arc_childtime, thatp->arc_count,
761*0Sstevel@tonic-gate 		    thatchildp->ncall);
762*0Sstevel@tonic-gate 		printf("\n");
763*0Sstevel@tonic-gate 	}
764*0Sstevel@tonic-gate #endif DEBUG
765*0Sstevel@tonic-gate 
766*0Sstevel@tonic-gate 	if (thisparentp == thischildp) {
767*0Sstevel@tonic-gate 		/*
768*0Sstevel@tonic-gate 		 * this is a self call
769*0Sstevel@tonic-gate 		 */
770*0Sstevel@tonic-gate 		return (LESSTHAN);
771*0Sstevel@tonic-gate 	}
772*0Sstevel@tonic-gate 
773*0Sstevel@tonic-gate 	if (thatparentp == thatchildp) {
774*0Sstevel@tonic-gate 		/*
775*0Sstevel@tonic-gate 		 * that is a self call
776*0Sstevel@tonic-gate 		 */
777*0Sstevel@tonic-gate 		return (GREATERTHAN);
778*0Sstevel@tonic-gate 	}
779*0Sstevel@tonic-gate 
780*0Sstevel@tonic-gate 	if (thisparentp->cycleno != 0 && thischildp->cycleno != 0 &&
781*0Sstevel@tonic-gate 	    thisparentp->cycleno == thischildp->cycleno) {
782*0Sstevel@tonic-gate 		/*
783*0Sstevel@tonic-gate 		 * this is a call within a cycle
784*0Sstevel@tonic-gate 		 */
785*0Sstevel@tonic-gate 		if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 &&
786*0Sstevel@tonic-gate 		    thatparentp->cycleno == thatchildp->cycleno) {
787*0Sstevel@tonic-gate 			/*
788*0Sstevel@tonic-gate 			 * that is a call within the cycle, too
789*0Sstevel@tonic-gate 			 */
790*0Sstevel@tonic-gate 			if (thisp->arc_count < thatp->arc_count)
791*0Sstevel@tonic-gate 				return (LESSTHAN);
792*0Sstevel@tonic-gate 
793*0Sstevel@tonic-gate 			if (thisp->arc_count > thatp->arc_count)
794*0Sstevel@tonic-gate 				return (GREATERTHAN);
795*0Sstevel@tonic-gate 
796*0Sstevel@tonic-gate 			return (EQUALTO);
797*0Sstevel@tonic-gate 		} else {
798*0Sstevel@tonic-gate 			/*
799*0Sstevel@tonic-gate 			 * that isn't a call within the cycle
800*0Sstevel@tonic-gate 			 */
801*0Sstevel@tonic-gate 			return (LESSTHAN);
802*0Sstevel@tonic-gate 		}
803*0Sstevel@tonic-gate 	} else {
804*0Sstevel@tonic-gate 		/*
805*0Sstevel@tonic-gate 		 * this isn't a call within a cycle
806*0Sstevel@tonic-gate 		 */
807*0Sstevel@tonic-gate 		if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 &&
808*0Sstevel@tonic-gate 		    thatparentp->cycleno == thatchildp->cycleno) {
809*0Sstevel@tonic-gate 			/*
810*0Sstevel@tonic-gate 			 * that is a call within a cycle
811*0Sstevel@tonic-gate 			 */
812*0Sstevel@tonic-gate 			return (GREATERTHAN);
813*0Sstevel@tonic-gate 		} else {
814*0Sstevel@tonic-gate 			/*
815*0Sstevel@tonic-gate 			 * neither is a call within a cycle
816*0Sstevel@tonic-gate 			 */
817*0Sstevel@tonic-gate 			thistime = thisp->arc_time + thisp->arc_childtime;
818*0Sstevel@tonic-gate 			thattime = thatp->arc_time + thatp->arc_childtime;
819*0Sstevel@tonic-gate 
820*0Sstevel@tonic-gate 			if (thistime < thattime)
821*0Sstevel@tonic-gate 				return (LESSTHAN);
822*0Sstevel@tonic-gate 
823*0Sstevel@tonic-gate 			if (thistime > thattime)
824*0Sstevel@tonic-gate 				return (GREATERTHAN);
825*0Sstevel@tonic-gate 
826*0Sstevel@tonic-gate 			if (thisp->arc_count < thatp->arc_count)
827*0Sstevel@tonic-gate 				return (LESSTHAN);
828*0Sstevel@tonic-gate 
829*0Sstevel@tonic-gate 			if (thisp->arc_count > thatp->arc_count)
830*0Sstevel@tonic-gate 				return (GREATERTHAN);
831*0Sstevel@tonic-gate 
832*0Sstevel@tonic-gate 			return (EQUALTO);
833*0Sstevel@tonic-gate 		}
834*0Sstevel@tonic-gate 	}
835*0Sstevel@tonic-gate }
836*0Sstevel@tonic-gate 
837*0Sstevel@tonic-gate void
838*0Sstevel@tonic-gate printblurb(char *blurbname)
839*0Sstevel@tonic-gate {
840*0Sstevel@tonic-gate 	FILE	*blurbfile;
841*0Sstevel@tonic-gate 	int	input;
842*0Sstevel@tonic-gate 	char	blurb_directory[MAXPATHLEN];
843*0Sstevel@tonic-gate 	char	cwd[MAXPATHLEN];
844*0Sstevel@tonic-gate 
845*0Sstevel@tonic-gate 	cwd[0] = '.';
846*0Sstevel@tonic-gate 	cwd[1] = '\0';
847*0Sstevel@tonic-gate 
848*0Sstevel@tonic-gate 	if (find_run_directory(prog_name, cwd, blurb_directory,
849*0Sstevel@tonic-gate 	    NULL, getenv("PATH")) != 0) {
850*0Sstevel@tonic-gate 		(void) fprintf(stderr, "Error in finding run directory.");
851*0Sstevel@tonic-gate 		return;
852*0Sstevel@tonic-gate 	} else {
853*0Sstevel@tonic-gate 		strcat(blurb_directory, blurbname);
854*0Sstevel@tonic-gate 	}
855*0Sstevel@tonic-gate 
856*0Sstevel@tonic-gate 	blurbfile = fopen(blurb_directory, "r");
857*0Sstevel@tonic-gate 	if (blurbfile == NULL) {
858*0Sstevel@tonic-gate 		perror(blurb_directory);
859*0Sstevel@tonic-gate 		return;
860*0Sstevel@tonic-gate 	}
861*0Sstevel@tonic-gate 
862*0Sstevel@tonic-gate 	while ((input = getc(blurbfile)) != EOF)
863*0Sstevel@tonic-gate 		putchar(input);
864*0Sstevel@tonic-gate 
865*0Sstevel@tonic-gate 	fclose(blurbfile);
866*0Sstevel@tonic-gate }
867*0Sstevel@tonic-gate 
868*0Sstevel@tonic-gate char *s1, *s2;
869*0Sstevel@tonic-gate 
870*0Sstevel@tonic-gate int
871*0Sstevel@tonic-gate namecmp(nltype **npp1, nltype **npp2)
872*0Sstevel@tonic-gate {
873*0Sstevel@tonic-gate 	if (!Cflag)
874*0Sstevel@tonic-gate 		return (strcmp((*npp1)->name, (*npp2)->name));
875*0Sstevel@tonic-gate 	else {
876*0Sstevel@tonic-gate 		striped_name(s1, npp1);
877*0Sstevel@tonic-gate 		striped_name(s2, npp2);
878*0Sstevel@tonic-gate 		return (strcmp(s1, s2));
879*0Sstevel@tonic-gate 	}
880*0Sstevel@tonic-gate }
881*0Sstevel@tonic-gate 
882*0Sstevel@tonic-gate void
883*0Sstevel@tonic-gate striped_name(char *s, nltype **npp)
884*0Sstevel@tonic-gate {
885*0Sstevel@tonic-gate 	char *d, *c;
886*0Sstevel@tonic-gate 
887*0Sstevel@tonic-gate 	c = (char *)s;
888*0Sstevel@tonic-gate 	d = demangled_name(*npp);
889*0Sstevel@tonic-gate 
890*0Sstevel@tonic-gate 	while ((*d != '(') && (*d != '\0')) {
891*0Sstevel@tonic-gate 		if (*d != ':')
892*0Sstevel@tonic-gate 			*c++ = *d++;
893*0Sstevel@tonic-gate 		else
894*0Sstevel@tonic-gate 			d++;
895*0Sstevel@tonic-gate 	}
896*0Sstevel@tonic-gate 	*c = '\0';
897*0Sstevel@tonic-gate }
898*0Sstevel@tonic-gate 
899*0Sstevel@tonic-gate /*
900*0Sstevel@tonic-gate  * Checks if the current symbol name is the same as its neighbour and
901*0Sstevel@tonic-gate  * returns TRUE if it is.
902*0Sstevel@tonic-gate  */
903*0Sstevel@tonic-gate static bool
904*0Sstevel@tonic-gate does_clash(nltype **nlp, int ndx, int nnames)
905*0Sstevel@tonic-gate {
906*0Sstevel@tonic-gate 	/*
907*0Sstevel@tonic-gate 	 * same as previous (if there's one) ?
908*0Sstevel@tonic-gate 	 */
909*0Sstevel@tonic-gate 	if (ndx && (strcmp(nlp[ndx]->name, nlp[ndx-1]->name) == 0))
910*0Sstevel@tonic-gate 		return (TRUE);
911*0Sstevel@tonic-gate 
912*0Sstevel@tonic-gate 	/*
913*0Sstevel@tonic-gate 	 * same as next (if there's one) ?
914*0Sstevel@tonic-gate 	 */
915*0Sstevel@tonic-gate 	if ((ndx < (nnames - 1)) &&
916*0Sstevel@tonic-gate 			    (strcmp(nlp[ndx]->name, nlp[ndx+1]->name) == 0)) {
917*0Sstevel@tonic-gate 		return (TRUE);
918*0Sstevel@tonic-gate 	}
919*0Sstevel@tonic-gate 
920*0Sstevel@tonic-gate 	return (FALSE);
921*0Sstevel@tonic-gate }
922*0Sstevel@tonic-gate 
923*0Sstevel@tonic-gate void
924*0Sstevel@tonic-gate printmodules()
925*0Sstevel@tonic-gate {
926*0Sstevel@tonic-gate 	mod_info_t	*mi;
927*0Sstevel@tonic-gate 
928*0Sstevel@tonic-gate 	printf("\f\nObject modules\n\n");
929*0Sstevel@tonic-gate 	for (mi = &modules; mi; mi = mi->next)
930*0Sstevel@tonic-gate 		printf(" %d: %s\n", mi->id, mi->name);
931*0Sstevel@tonic-gate }
932*0Sstevel@tonic-gate 
933*0Sstevel@tonic-gate #define	IDFMT(id)	((id) < 10 ? 1 : 2)
934*0Sstevel@tonic-gate #define	NMFMT(id)	((id) < 10 ? 17 : 16)
935*0Sstevel@tonic-gate 
936*0Sstevel@tonic-gate void
937*0Sstevel@tonic-gate printindex()
938*0Sstevel@tonic-gate {
939*0Sstevel@tonic-gate 	nltype	**namesortnlp;
940*0Sstevel@tonic-gate 	nltype	*nlp;
941*0Sstevel@tonic-gate 	int	index, nnames, todo, i, j;
942*0Sstevel@tonic-gate 	char	peterbuffer[BUFSIZ];
943*0Sstevel@tonic-gate 	mod_info_t	*mi;
944*0Sstevel@tonic-gate 
945*0Sstevel@tonic-gate 	/*
946*0Sstevel@tonic-gate 	 *	Now, sort regular function name alphabetically
947*0Sstevel@tonic-gate 	 *	to create an index.
948*0Sstevel@tonic-gate 	 */
949*0Sstevel@tonic-gate 	namesortnlp = calloc(total_names + ncycle, sizeof (nltype *));
950*0Sstevel@tonic-gate 
951*0Sstevel@tonic-gate 	if (namesortnlp == NULL)
952*0Sstevel@tonic-gate 		fprintf(stderr, "%s: ran out of memory for sorting\n", whoami);
953*0Sstevel@tonic-gate 
954*0Sstevel@tonic-gate 	nnames = 0;
955*0Sstevel@tonic-gate 	for (mi = &modules; mi; mi = mi->next) {
956*0Sstevel@tonic-gate 		for (index = 0; index < mi->nname; index++) {
957*0Sstevel@tonic-gate 			if (zflag == 0 && (mi->nl[index]).ncall == 0 &&
958*0Sstevel@tonic-gate 						(mi->nl[index]).time == 0) {
959*0Sstevel@tonic-gate 				continue;
960*0Sstevel@tonic-gate 			}
961*0Sstevel@tonic-gate 
962*0Sstevel@tonic-gate 			/*
963*0Sstevel@tonic-gate 			 * Do not print certain special symbols, like
964*0Sstevel@tonic-gate 			 * PRF_EXTSYM, etc. even if zflag was on.
965*0Sstevel@tonic-gate 			 */
966*0Sstevel@tonic-gate 			if (is_special_sym(&(mi->nl[index])))
967*0Sstevel@tonic-gate 				continue;
968*0Sstevel@tonic-gate 
969*0Sstevel@tonic-gate 			namesortnlp[nnames++] = &(mi->nl[index]);
970*0Sstevel@tonic-gate 		}
971*0Sstevel@tonic-gate 	}
972*0Sstevel@tonic-gate 
973*0Sstevel@tonic-gate 	if (Cflag) {
974*0Sstevel@tonic-gate 		s1 = malloc(500 * sizeof (char));
975*0Sstevel@tonic-gate 		s2 = malloc(500 * sizeof (char));
976*0Sstevel@tonic-gate 	}
977*0Sstevel@tonic-gate 
978*0Sstevel@tonic-gate 	qsort(namesortnlp, nnames, sizeof (nltype *),
979*0Sstevel@tonic-gate 	    (int(*)(const void *, const void *))namecmp);
980*0Sstevel@tonic-gate 
981*0Sstevel@tonic-gate 	for (index = 1, todo = nnames; index <= ncycle; index++)
982*0Sstevel@tonic-gate 		namesortnlp[todo++] = &cyclenl[index];
983*0Sstevel@tonic-gate 
984*0Sstevel@tonic-gate 	printf("\f\nIndex by function name\n\n");
985*0Sstevel@tonic-gate 
986*0Sstevel@tonic-gate 	if (!Cflag)
987*0Sstevel@tonic-gate 		index = (todo + 2) / 3;
988*0Sstevel@tonic-gate 	else
989*0Sstevel@tonic-gate 		index = todo;
990*0Sstevel@tonic-gate 
991*0Sstevel@tonic-gate 	for (i = 0; i < index; i++) {
992*0Sstevel@tonic-gate 		if (!Cflag) {
993*0Sstevel@tonic-gate 			for (j = i; j < todo; j += index) {
994*0Sstevel@tonic-gate 				nlp = namesortnlp[j];
995*0Sstevel@tonic-gate 
996*0Sstevel@tonic-gate 				if (nlp->printflag) {
997*0Sstevel@tonic-gate 					sprintf(peterbuffer,
998*0Sstevel@tonic-gate 					    "[%d]", nlp->index);
999*0Sstevel@tonic-gate 				} else {
1000*0Sstevel@tonic-gate 					sprintf(peterbuffer,
1001*0Sstevel@tonic-gate 					    "(%d)", nlp->index);
1002*0Sstevel@tonic-gate 				}
1003*0Sstevel@tonic-gate 
1004*0Sstevel@tonic-gate 				if (j < nnames) {
1005*0Sstevel@tonic-gate 					if (does_clash(namesortnlp,
1006*0Sstevel@tonic-gate 								j, nnames)) {
1007*0Sstevel@tonic-gate 						printf("%6.6s %*d:%-*.*s",
1008*0Sstevel@tonic-gate 							peterbuffer,
1009*0Sstevel@tonic-gate 							IDFMT(nlp->module->id),
1010*0Sstevel@tonic-gate 							nlp->module->id,
1011*0Sstevel@tonic-gate 							NMFMT(nlp->module->id),
1012*0Sstevel@tonic-gate 							NMFMT(nlp->module->id),
1013*0Sstevel@tonic-gate 							nlp->name);
1014*0Sstevel@tonic-gate 					} else {
1015*0Sstevel@tonic-gate 						printf("%6.6s %-19.19s",
1016*0Sstevel@tonic-gate 						    peterbuffer, nlp->name);
1017*0Sstevel@tonic-gate 					}
1018*0Sstevel@tonic-gate 				} else {
1019*0Sstevel@tonic-gate 					printf("%6.6s ", peterbuffer);
1020*0Sstevel@tonic-gate 					sprintf(peterbuffer,
1021*0Sstevel@tonic-gate 					    "<cycle %d>", nlp->cycleno);
1022*0Sstevel@tonic-gate 					printf("%-19.19s", peterbuffer);
1023*0Sstevel@tonic-gate 				}
1024*0Sstevel@tonic-gate 			}
1025*0Sstevel@tonic-gate 		} else {
1026*0Sstevel@tonic-gate 			nlp = namesortnlp[i];
1027*0Sstevel@tonic-gate 
1028*0Sstevel@tonic-gate 			if (nlp->printflag)
1029*0Sstevel@tonic-gate 				sprintf(peterbuffer, "[%d]", nlp->index);
1030*0Sstevel@tonic-gate 			else
1031*0Sstevel@tonic-gate 				sprintf(peterbuffer, "(%d)", nlp->index);
1032*0Sstevel@tonic-gate 
1033*0Sstevel@tonic-gate 			if (i < nnames) {
1034*0Sstevel@tonic-gate 				char *d = demangled_name(nlp);
1035*0Sstevel@tonic-gate 
1036*0Sstevel@tonic-gate 				if (does_clash(namesortnlp, i, nnames)) {
1037*0Sstevel@tonic-gate 					printf("%6.6s %d:%s\n", peterbuffer,
1038*0Sstevel@tonic-gate 							nlp->module->id, d);
1039*0Sstevel@tonic-gate 				} else
1040*0Sstevel@tonic-gate 					printf("%6.6s %s\n", peterbuffer, d);
1041*0Sstevel@tonic-gate 
1042*0Sstevel@tonic-gate 				if (d != nlp->name)
1043*0Sstevel@tonic-gate 					printf("%6.6s   [%s]", "", nlp->name);
1044*0Sstevel@tonic-gate 			} else {
1045*0Sstevel@tonic-gate 				printf("%6.6s ", peterbuffer);
1046*0Sstevel@tonic-gate 				sprintf(peterbuffer, "<cycle %d>",
1047*0Sstevel@tonic-gate 				    nlp->cycleno);
1048*0Sstevel@tonic-gate 				printf("%-33.33s", peterbuffer);
1049*0Sstevel@tonic-gate 			}
1050*0Sstevel@tonic-gate 		}
1051*0Sstevel@tonic-gate 		printf("\n");
1052*0Sstevel@tonic-gate 	}
1053*0Sstevel@tonic-gate 	free(namesortnlp);
1054*0Sstevel@tonic-gate }
1055*0Sstevel@tonic-gate 
1056*0Sstevel@tonic-gate 
1057*0Sstevel@tonic-gate char dname[500];
1058*0Sstevel@tonic-gate 
1059*0Sstevel@tonic-gate char *
1060*0Sstevel@tonic-gate exotic(char *s)
1061*0Sstevel@tonic-gate {
1062*0Sstevel@tonic-gate 	char *name;
1063*0Sstevel@tonic-gate 	int i = 0, j;
1064*0Sstevel@tonic-gate 	char *p, *s1 = "static constructor function for ";
1065*0Sstevel@tonic-gate 
1066*0Sstevel@tonic-gate 	name = malloc(500 * sizeof (char));
1067*0Sstevel@tonic-gate 
1068*0Sstevel@tonic-gate 	if (strncmp(s, "__sti__", 7) == 0) {
1069*0Sstevel@tonic-gate 		i = 0;
1070*0Sstevel@tonic-gate 		s += 7;
1071*0Sstevel@tonic-gate 
1072*0Sstevel@tonic-gate 		if ((p = strstr(s, "_c_")) == NULL) {
1073*0Sstevel@tonic-gate 			if ((p = strstr(s, "_C_")) == NULL) {
1074*0Sstevel@tonic-gate 				if ((p = strstr(s, "_cc_")) == NULL) {
1075*0Sstevel@tonic-gate 					if ((p = strstr(s, "_cxx_")) == NULL) {
1076*0Sstevel@tonic-gate 						if ((p =
1077*0Sstevel@tonic-gate 						    strstr(s, "_h_")) == NULL)
1078*0Sstevel@tonic-gate 							return (NULL);
1079*0Sstevel@tonic-gate 					}
1080*0Sstevel@tonic-gate 				}
1081*0Sstevel@tonic-gate 			}
1082*0Sstevel@tonic-gate 		} else {
1083*0Sstevel@tonic-gate 			p += 3;
1084*0Sstevel@tonic-gate 			*p = '\0';
1085*0Sstevel@tonic-gate 		}
1086*0Sstevel@tonic-gate 
1087*0Sstevel@tonic-gate 		for (i = 0; s1[i] != '\0'; i++)
1088*0Sstevel@tonic-gate 			dname[i] = s1[i];
1089*0Sstevel@tonic-gate 		j = i;
1090*0Sstevel@tonic-gate 
1091*0Sstevel@tonic-gate 		for (i = 0; s[i] != '\0'; i++)
1092*0Sstevel@tonic-gate 			dname[j + i] = s[i];
1093*0Sstevel@tonic-gate 		dname[j + i] = '\0';
1094*0Sstevel@tonic-gate 
1095*0Sstevel@tonic-gate 		free(name);
1096*0Sstevel@tonic-gate 		return (dname);
1097*0Sstevel@tonic-gate 	}
1098*0Sstevel@tonic-gate 
1099*0Sstevel@tonic-gate 	if (strncmp(s, "__std__", 7) == 0) {
1100*0Sstevel@tonic-gate 		char *s1 = "static destructor function for ";
1101*0Sstevel@tonic-gate 		i = 0;
1102*0Sstevel@tonic-gate 		s += 7;
1103*0Sstevel@tonic-gate 
1104*0Sstevel@tonic-gate 		if ((p = strstr(s, "_c_")) == NULL) {
1105*0Sstevel@tonic-gate 			if ((p = strstr(s, "_C_")) == NULL) {
1106*0Sstevel@tonic-gate 				if ((p = strstr(s, "_cc_")) == NULL) {
1107*0Sstevel@tonic-gate 					if ((p = strstr(s, "_cxx_")) == NULL) {
1108*0Sstevel@tonic-gate 						if ((p =
1109*0Sstevel@tonic-gate 						    strstr(s, "_h_")) == NULL)
1110*0Sstevel@tonic-gate 							return (NULL);
1111*0Sstevel@tonic-gate 					}
1112*0Sstevel@tonic-gate 				}
1113*0Sstevel@tonic-gate 			}
1114*0Sstevel@tonic-gate 		} else {
1115*0Sstevel@tonic-gate 			p += 3;
1116*0Sstevel@tonic-gate 			*p = '\0';
1117*0Sstevel@tonic-gate 		}
1118*0Sstevel@tonic-gate 
1119*0Sstevel@tonic-gate 		for (i = 0; s1[i] != '\0'; i++)
1120*0Sstevel@tonic-gate 			dname[i] = s1[i];
1121*0Sstevel@tonic-gate 		j = i;
1122*0Sstevel@tonic-gate 
1123*0Sstevel@tonic-gate 		for (i = 0; s[i] != '\0'; i++)
1124*0Sstevel@tonic-gate 			dname[j + i] = s[i];
1125*0Sstevel@tonic-gate 		dname[j + i] = '\0';
1126*0Sstevel@tonic-gate 
1127*0Sstevel@tonic-gate 		free(name);
1128*0Sstevel@tonic-gate 		return (dname);
1129*0Sstevel@tonic-gate 	}
1130*0Sstevel@tonic-gate 
1131*0Sstevel@tonic-gate 	if (strncmp(s, "__vtbl__", 8) == 0) {
1132*0Sstevel@tonic-gate 		char *s1 = "virtual table for ";
1133*0Sstevel@tonic-gate 		char *printname, *return_p = dname;
1134*0Sstevel@tonic-gate 
1135*0Sstevel@tonic-gate 		s += 8;
1136*0Sstevel@tonic-gate 		printname = parsename(s);
1137*0Sstevel@tonic-gate 		return_p = '\0';
1138*0Sstevel@tonic-gate 		strcat(return_p, s1);
1139*0Sstevel@tonic-gate 		strcat(return_p, printname);
1140*0Sstevel@tonic-gate 
1141*0Sstevel@tonic-gate 		free(name);
1142*0Sstevel@tonic-gate 		return (dname);
1143*0Sstevel@tonic-gate 	}
1144*0Sstevel@tonic-gate 
1145*0Sstevel@tonic-gate 	if (strncmp(s, "__ptbl__", 8) == 0) {
1146*0Sstevel@tonic-gate 		char *s1 = "pointer to the virtual table for ";
1147*0Sstevel@tonic-gate 		char *printname, *return_p = dname;
1148*0Sstevel@tonic-gate 
1149*0Sstevel@tonic-gate 		s += 8;
1150*0Sstevel@tonic-gate 		printname = parsename(s);
1151*0Sstevel@tonic-gate 		return_p = '\0';
1152*0Sstevel@tonic-gate 		strcat(return_p, s1);
1153*0Sstevel@tonic-gate 		strcat(return_p, printname);
1154*0Sstevel@tonic-gate 
1155*0Sstevel@tonic-gate 		free(name);
1156*0Sstevel@tonic-gate 		return (return_p);
1157*0Sstevel@tonic-gate 	}
1158*0Sstevel@tonic-gate 
1159*0Sstevel@tonic-gate 	free(name);
1160*0Sstevel@tonic-gate 	return (s);
1161*0Sstevel@tonic-gate }
1162*0Sstevel@tonic-gate 
1163*0Sstevel@tonic-gate char *
1164*0Sstevel@tonic-gate parsename(char *s)
1165*0Sstevel@tonic-gate {
1166*0Sstevel@tonic-gate 	char *d = name_buffer;
1167*0Sstevel@tonic-gate 	int len;
1168*0Sstevel@tonic-gate 	char c_init;
1169*0Sstevel@tonic-gate 	char *len_pointer = s;
1170*0Sstevel@tonic-gate 
1171*0Sstevel@tonic-gate 	*d = '\0';
1172*0Sstevel@tonic-gate 
1173*0Sstevel@tonic-gate 	strcat(d, "class ");
1174*0Sstevel@tonic-gate 
1175*0Sstevel@tonic-gate 	while (isdigit(*s))
1176*0Sstevel@tonic-gate 		s++;
1177*0Sstevel@tonic-gate 	c_init = *s;
1178*0Sstevel@tonic-gate 	*s = '\0';
1179*0Sstevel@tonic-gate 
1180*0Sstevel@tonic-gate 	len = atoi(len_pointer);
1181*0Sstevel@tonic-gate 	*s = c_init;
1182*0Sstevel@tonic-gate 
1183*0Sstevel@tonic-gate 	/*
1184*0Sstevel@tonic-gate 	 * only one class name
1185*0Sstevel@tonic-gate 	 */
1186*0Sstevel@tonic-gate 	if (*(s + len) == '\0') {
1187*0Sstevel@tonic-gate 		strcat(d, s);
1188*0Sstevel@tonic-gate 		return (d);
1189*0Sstevel@tonic-gate 	} else {
1190*0Sstevel@tonic-gate 		/*
1191*0Sstevel@tonic-gate 		 * two classname  %drootname__%dchildname
1192*0Sstevel@tonic-gate 		 */
1193*0Sstevel@tonic-gate 		char *child;
1194*0Sstevel@tonic-gate 		char *root;
1195*0Sstevel@tonic-gate 		int child_len;
1196*0Sstevel@tonic-gate 		char *child_len_p;
1197*0Sstevel@tonic-gate 		root = s;
1198*0Sstevel@tonic-gate 		child = s + len + 2;
1199*0Sstevel@tonic-gate 		child_len_p = child;
1200*0Sstevel@tonic-gate 
1201*0Sstevel@tonic-gate 		if (!isdigit(*child)) { /* ptbl file name */
1202*0Sstevel@tonic-gate 			c_init = *(root + len);
1203*0Sstevel@tonic-gate 			*(root + len) = '\0';
1204*0Sstevel@tonic-gate 			strcat(d, root);
1205*0Sstevel@tonic-gate 			*(root + len) = c_init;
1206*0Sstevel@tonic-gate 			strcat(d, " in ");
1207*0Sstevel@tonic-gate 			strcat(d, child);
1208*0Sstevel@tonic-gate 			return (d);
1209*0Sstevel@tonic-gate 		}
1210*0Sstevel@tonic-gate 
1211*0Sstevel@tonic-gate 		while (isdigit(*child))
1212*0Sstevel@tonic-gate 			child++;
1213*0Sstevel@tonic-gate 		c_init = *child;
1214*0Sstevel@tonic-gate 		*child = '\0';
1215*0Sstevel@tonic-gate 		child_len = atoi(child_len_p);
1216*0Sstevel@tonic-gate 		*child = c_init;
1217*0Sstevel@tonic-gate 		if (*(child + child_len) == '\0') {
1218*0Sstevel@tonic-gate 			strcat(d, child);
1219*0Sstevel@tonic-gate 			strcat(d, " derived from ");
1220*0Sstevel@tonic-gate 			c_init = *(root + len);
1221*0Sstevel@tonic-gate 			*(root + len) = '\0';
1222*0Sstevel@tonic-gate 			strcat(d, root);
1223*0Sstevel@tonic-gate 			*(root + len) = c_init;
1224*0Sstevel@tonic-gate 			return (d);
1225*0Sstevel@tonic-gate 		} else { /* %drootname__%dchildname__filename */
1226*0Sstevel@tonic-gate 			c_init = *(child + child_len);
1227*0Sstevel@tonic-gate 			*(child + child_len) = '\0';
1228*0Sstevel@tonic-gate 			strcat(d, child);
1229*0Sstevel@tonic-gate 			*(child+ child_len) = c_init;
1230*0Sstevel@tonic-gate 			strcat(d, " derived from ");
1231*0Sstevel@tonic-gate 			c_init = *(root + len);
1232*0Sstevel@tonic-gate 			*(root + len) = '\0';
1233*0Sstevel@tonic-gate 			strcat(d, root);
1234*0Sstevel@tonic-gate 			*(root + len) = c_init;
1235*0Sstevel@tonic-gate 			strcat(d, " in ");
1236*0Sstevel@tonic-gate 			strcat(d, child + child_len + 2);
1237*0Sstevel@tonic-gate 			return (d);
1238*0Sstevel@tonic-gate 		}
1239*0Sstevel@tonic-gate 	}
1240*0Sstevel@tonic-gate }
1241