17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
567298654Sdamico  * Common Development and Distribution License (the "License").
667298654Sdamico  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
2192ed1782Smike_s 
227c478bd9Sstevel@tonic-gate /*
23b9bd317cSab  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
2492ed1782Smike_s  * Use is subject to license terms.
254226f635SJason King  *
264226f635SJason King  * Copyright 2018 Jason King
274226f635SJason King  * Copyright 2018, Joyent, Inc.
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <ctype.h>
317c478bd9Sstevel@tonic-gate #include <string.h>
327c478bd9Sstevel@tonic-gate #include <sys/param.h>
337c478bd9Sstevel@tonic-gate #include <stdlib.h>
34b9bd317cSab #include "conv.h"
357c478bd9Sstevel@tonic-gate #include "gprof.h"
367c478bd9Sstevel@tonic-gate 
3714448871SToomas Soome double	actime;
3814448871SToomas Soome 
397c478bd9Sstevel@tonic-gate void print_demangled_name(int, nltype *);
404226f635SJason King static void stripped_name(char **, size_t *, nltype **);
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate /*
437c478bd9Sstevel@tonic-gate  * Symbols that must never be printed, no matter what.
447c478bd9Sstevel@tonic-gate  */
457c478bd9Sstevel@tonic-gate char *splsym[] = {
467c478bd9Sstevel@tonic-gate 	PRF_ETEXT,
477c478bd9Sstevel@tonic-gate 	PRF_EXTSYM,
487c478bd9Sstevel@tonic-gate 	PRF_MEMTERM,
4992ed1782Smike_s 	NULL
507c478bd9Sstevel@tonic-gate };
517c478bd9Sstevel@tonic-gate 
5292ed1782Smike_s static bool is_special_sym(nltype *nlp);
5392ed1782Smike_s 
54b9bd317cSab const char *
demangled_name(nltype * selfp)557c478bd9Sstevel@tonic-gate demangled_name(nltype *selfp)
567c478bd9Sstevel@tonic-gate {
577c478bd9Sstevel@tonic-gate 	if (!Cflag)
587c478bd9Sstevel@tonic-gate 		return (selfp->name);
597c478bd9Sstevel@tonic-gate 
60b9bd317cSab 	return (conv_demangle_name(selfp->name));
617c478bd9Sstevel@tonic-gate }
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate void
printprof(void)6492ed1782Smike_s printprof(void)
657c478bd9Sstevel@tonic-gate {
667c478bd9Sstevel@tonic-gate 	nltype	*np;
677c478bd9Sstevel@tonic-gate 	nltype	**sortednlp;
687c478bd9Sstevel@tonic-gate 	int	i, index;
694226f635SJason King 	int	print_count = number_funcs_toprint;
707c478bd9Sstevel@tonic-gate 	bool	print_flag = TRUE;
717c478bd9Sstevel@tonic-gate 	mod_info_t	*mi;
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate 	actime = 0.0;
7492ed1782Smike_s 	(void) printf("\f\n");
757c478bd9Sstevel@tonic-gate 	flatprofheader();
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	/*
787c478bd9Sstevel@tonic-gate 	 *	Sort the symbol table in by time
797c478bd9Sstevel@tonic-gate 	 */
807c478bd9Sstevel@tonic-gate 	sortednlp = (nltype **) calloc(total_names, sizeof (nltype *));
817c478bd9Sstevel@tonic-gate 	if (sortednlp == (nltype **) 0) {
8292ed1782Smike_s 		(void) fprintf(stderr,
837c478bd9Sstevel@tonic-gate 		    "[printprof] ran out of memory for time sorting\n");
847c478bd9Sstevel@tonic-gate 	}
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 	index = 0;
877c478bd9Sstevel@tonic-gate 	for (mi = &modules; mi; mi = mi->next) {
887c478bd9Sstevel@tonic-gate 		for (i = 0; i < mi->nname; i++)
897c478bd9Sstevel@tonic-gate 			sortednlp[index++] = &(mi->nl[i]);
907c478bd9Sstevel@tonic-gate 	}
917c478bd9Sstevel@tonic-gate 
9292ed1782Smike_s 	qsort(sortednlp, total_names, sizeof (nltype *), timecmp);
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 	for (index = 0; (index < total_names) && print_flag; index += 1) {
957c478bd9Sstevel@tonic-gate 		np = sortednlp[index];
967c478bd9Sstevel@tonic-gate 		flatprofline(np);
977c478bd9Sstevel@tonic-gate 		if (nflag) {
987c478bd9Sstevel@tonic-gate 			if (--print_count == 0)
997c478bd9Sstevel@tonic-gate 				print_flag = FALSE;
1007c478bd9Sstevel@tonic-gate 		}
1017c478bd9Sstevel@tonic-gate 	}
1027c478bd9Sstevel@tonic-gate 	actime = 0.0;
1037c478bd9Sstevel@tonic-gate 	free(sortednlp);
1047c478bd9Sstevel@tonic-gate }
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate int
timecmp(const void * arg1,const void * arg2)10792ed1782Smike_s timecmp(const void *arg1, const void *arg2)
1087c478bd9Sstevel@tonic-gate {
10992ed1782Smike_s 	nltype **npp1 = (nltype **)arg1;
11092ed1782Smike_s 	nltype **npp2 = (nltype **)arg2;
1117c478bd9Sstevel@tonic-gate 	double	timediff;
1127c478bd9Sstevel@tonic-gate 	long	calldiff;
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 	timediff = (*npp2)->time - (*npp1)->time;
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	if (timediff > 0.0)
1177c478bd9Sstevel@tonic-gate 		return (1);
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	if (timediff < 0.0)
1207c478bd9Sstevel@tonic-gate 		return (-1);
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 	calldiff = (*npp2)->ncall - (*npp1)->ncall;
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	if (calldiff > 0)
1257c478bd9Sstevel@tonic-gate 		return (1);
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	if (calldiff < 0)
1287c478bd9Sstevel@tonic-gate 		return (-1);
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	return (strcmp((*npp1)->name, (*npp2)->name));
1317c478bd9Sstevel@tonic-gate }
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate /*
1347c478bd9Sstevel@tonic-gate  *	header for flatprofline
1357c478bd9Sstevel@tonic-gate  */
1367c478bd9Sstevel@tonic-gate void
flatprofheader()1377c478bd9Sstevel@tonic-gate flatprofheader()
1387c478bd9Sstevel@tonic-gate {
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	if (bflag)
1417c478bd9Sstevel@tonic-gate 		printblurb(FLAT_BLURB);
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	if (old_style) {
14492ed1782Smike_s 		(void) printf(
14592ed1782Smike_s 		    "\ngranularity: each sample hit covers %d byte(s)",
14692ed1782Smike_s 		    (long)scale * sizeof (UNIT));
1477c478bd9Sstevel@tonic-gate 		if (totime > 0.0) {
14892ed1782Smike_s 			(void) printf(" for %.2f%% of %.2f seconds\n\n",
1497c478bd9Sstevel@tonic-gate 			    100.0/totime, totime / hz);
1507c478bd9Sstevel@tonic-gate 		} else {
15192ed1782Smike_s 			(void) printf(" no time accumulated\n\n");
1527c478bd9Sstevel@tonic-gate 			/*
1537c478bd9Sstevel@tonic-gate 			 * this doesn't hurt since all the numerators will
1547c478bd9Sstevel@tonic-gate 			 * be zero.
1557c478bd9Sstevel@tonic-gate 			 */
1567c478bd9Sstevel@tonic-gate 			totime = 1.0;
1577c478bd9Sstevel@tonic-gate 		}
1587c478bd9Sstevel@tonic-gate 	}
1597c478bd9Sstevel@tonic-gate 
16092ed1782Smike_s 	(void) printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
1617c478bd9Sstevel@tonic-gate 	    "% ", "cumulative", "self ", "", "self ", "total ", "");
16292ed1782Smike_s 	(void) printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
1637c478bd9Sstevel@tonic-gate 	    "time", "seconds ", "seconds", "calls",
1647c478bd9Sstevel@tonic-gate 	    "ms/call", "ms/call", "name");
1657c478bd9Sstevel@tonic-gate }
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate void
flatprofline(nltype * np)1687c478bd9Sstevel@tonic-gate flatprofline(nltype *np)
1697c478bd9Sstevel@tonic-gate {
1707c478bd9Sstevel@tonic-gate 	if (zflag == 0 && np->ncall == 0 && np->time == 0)
1717c478bd9Sstevel@tonic-gate 		return;
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 	/*
1747c478bd9Sstevel@tonic-gate 	 * Do not print certain special symbols, like PRF_EXTSYM, etc.
1757c478bd9Sstevel@tonic-gate 	 * even if zflag was on.
1767c478bd9Sstevel@tonic-gate 	 */
1777c478bd9Sstevel@tonic-gate 	if (is_special_sym(np))
1787c478bd9Sstevel@tonic-gate 		return;
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	actime += np->time;
1817c478bd9Sstevel@tonic-gate 
18292ed1782Smike_s 	(void) printf("%5.1f %10.2f %8.2f",
1837c478bd9Sstevel@tonic-gate 	    100 * np->time / totime, actime / hz, np->time / hz);
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	if (np->ncall != 0) {
18692ed1782Smike_s 		(void) printf(" %8lld %8.2f %8.2f  ", np->ncall,
1877c478bd9Sstevel@tonic-gate 		    1000 * np->time / hz / np->ncall,
1887c478bd9Sstevel@tonic-gate 		    1000 * (np->time + np->childtime) / hz / np->ncall);
1897c478bd9Sstevel@tonic-gate 	} else {
1907c478bd9Sstevel@tonic-gate 		if (!Cflag)
19192ed1782Smike_s 			(void) printf(" %8.8s %8.8s %8.8s ", "", "", "");
1927c478bd9Sstevel@tonic-gate 		else
19392ed1782Smike_s 			(void) printf(" %8.8s %8.8s %8.8s  ", "", "", "");
1947c478bd9Sstevel@tonic-gate 	}
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	printname(np);
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	if (Cflag)
1997c478bd9Sstevel@tonic-gate 		print_demangled_name(55, np);
2007c478bd9Sstevel@tonic-gate 
20192ed1782Smike_s 	(void) printf("\n");
2027c478bd9Sstevel@tonic-gate }
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate void
gprofheader()2057c478bd9Sstevel@tonic-gate gprofheader()
2067c478bd9Sstevel@tonic-gate {
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	if (bflag)
2097c478bd9Sstevel@tonic-gate 		printblurb(CALLG_BLURB);
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	if (old_style) {
2127c478bd9Sstevel@tonic-gate 
21392ed1782Smike_s 		(void) printf(
21492ed1782Smike_s 		    "\ngranularity: each sample hit covers %d byte(s)",
21592ed1782Smike_s 		    (long)scale * sizeof (UNIT));
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 		if (printtime > 0.0) {
21892ed1782Smike_s 			(void) printf(" for %.2f%% of %.2f seconds\n\n",
2197c478bd9Sstevel@tonic-gate 			    100.0/printtime, printtime / hz);
2207c478bd9Sstevel@tonic-gate 		} else {
22192ed1782Smike_s 			(void) printf(" no time propagated\n\n");
2227c478bd9Sstevel@tonic-gate 			/*
2237c478bd9Sstevel@tonic-gate 			 * this doesn't hurt, since all the numerators
2247c478bd9Sstevel@tonic-gate 			 * will be 0.0
2257c478bd9Sstevel@tonic-gate 			 */
2267c478bd9Sstevel@tonic-gate 			printtime = 1.0;
2277c478bd9Sstevel@tonic-gate 		}
2287c478bd9Sstevel@tonic-gate 	} else {
22992ed1782Smike_s 		(void) printf(
23092ed1782Smike_s 		    "\ngranularity: each pc-hit is considered 1 tick");
2317c478bd9Sstevel@tonic-gate 		if (hz != 1) {
23292ed1782Smike_s 			(void) printf(" (@ %4.3f seconds per tick)",
23392ed1782Smike_s 			    (double)1.0 / hz);
2347c478bd9Sstevel@tonic-gate 		}
23592ed1782Smike_s 		(void) puts("\n\n");
2367c478bd9Sstevel@tonic-gate 	}
2377c478bd9Sstevel@tonic-gate 
23892ed1782Smike_s 	(void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n",
2397c478bd9Sstevel@tonic-gate 	    "", "", "", "", "called", "total", "parents");
24092ed1782Smike_s 	(void) printf("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n",
2417c478bd9Sstevel@tonic-gate 	    "index", "%time", "self", "descendents",
2427c478bd9Sstevel@tonic-gate 	    "called", "self", "name", "index");
24392ed1782Smike_s 	(void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n",
2447c478bd9Sstevel@tonic-gate 	    "", "", "", "", "called", "total", "children");
24592ed1782Smike_s 	(void) printf("\n");
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate void
gprofline(nltype * np)2497c478bd9Sstevel@tonic-gate gprofline(nltype *np)
2507c478bd9Sstevel@tonic-gate {
2517c478bd9Sstevel@tonic-gate 	char	kirkbuffer[BUFSIZ];
2527c478bd9Sstevel@tonic-gate 
25392ed1782Smike_s 	(void) sprintf(kirkbuffer, "[%d]", np->index);
25492ed1782Smike_s 	(void) printf("%-6.6s %5.1f %7.2f %11.2f", kirkbuffer,
2557c478bd9Sstevel@tonic-gate 	    100 * (np->propself + np->propchild) / printtime,
2567c478bd9Sstevel@tonic-gate 	    np->propself / hz, np->propchild / hz);
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	if ((np->ncall + np->selfcalls) != 0) {
25992ed1782Smike_s 		(void) printf(" %7lld", np->ncall);
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 		if (np->selfcalls != 0)
26292ed1782Smike_s 			(void) printf("+%-7lld ", np->selfcalls);
2637c478bd9Sstevel@tonic-gate 		else
26492ed1782Smike_s 			(void) printf(" %7.7s ", "");
2657c478bd9Sstevel@tonic-gate 	} else {
26692ed1782Smike_s 		(void) printf(" %7.7s %7.7s ", "", "");
2677c478bd9Sstevel@tonic-gate 	}
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	printname(np);
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 	if (Cflag)
2727c478bd9Sstevel@tonic-gate 		print_demangled_name(50, np);
2737c478bd9Sstevel@tonic-gate 
27492ed1782Smike_s 	(void) printf("\n");
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate static bool
is_special_sym(nltype * nlp)2787c478bd9Sstevel@tonic-gate is_special_sym(nltype *nlp)
2797c478bd9Sstevel@tonic-gate {
2807c478bd9Sstevel@tonic-gate 	int	i;
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	if (nlp->name == NULL)
2837c478bd9Sstevel@tonic-gate 		return (FALSE);
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	for (i = 0;  splsym[i]; i++)
2867c478bd9Sstevel@tonic-gate 		if (strcmp(splsym[i], nlp->name) == 0)
2877c478bd9Sstevel@tonic-gate 			return (TRUE);
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	return (FALSE);
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate void
printgprof(nltype ** timesortnlp)2937c478bd9Sstevel@tonic-gate printgprof(nltype **timesortnlp)
2947c478bd9Sstevel@tonic-gate {
2957c478bd9Sstevel@tonic-gate 	int	index;
2967c478bd9Sstevel@tonic-gate 	nltype	*parentp;
2974226f635SJason King 	int	print_count = number_funcs_toprint;
2987c478bd9Sstevel@tonic-gate 	bool	count_flag = TRUE;
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	/*
3017c478bd9Sstevel@tonic-gate 	 * Print out the structured profiling list
3027c478bd9Sstevel@tonic-gate 	 */
3037c478bd9Sstevel@tonic-gate 	gprofheader();
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	for (index = 0; index < total_names + ncycle && count_flag; index++) {
3067c478bd9Sstevel@tonic-gate 		parentp = timesortnlp[index];
3077c478bd9Sstevel@tonic-gate 		if (zflag == 0 && parentp->ncall == 0 &&
3087c478bd9Sstevel@tonic-gate 		    parentp->selfcalls == 0 && parentp->propself == 0 &&
3097c478bd9Sstevel@tonic-gate 		    parentp -> propchild == 0)
3107c478bd9Sstevel@tonic-gate 			continue;
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 		if (!parentp->printflag)
3137c478bd9Sstevel@tonic-gate 			continue;
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 		/*
3167c478bd9Sstevel@tonic-gate 		 * Do not print certain special symbols, like PRF_EXTSYM, etc.
3177c478bd9Sstevel@tonic-gate 		 * even if zflag was on.
3187c478bd9Sstevel@tonic-gate 		 */
3197c478bd9Sstevel@tonic-gate 		if (is_special_sym(parentp))
3207c478bd9Sstevel@tonic-gate 			continue;
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 		if (parentp->name == 0 && parentp->cycleno != 0) {
3237c478bd9Sstevel@tonic-gate 			/*
3247c478bd9Sstevel@tonic-gate 			 *	cycle header
3257c478bd9Sstevel@tonic-gate 			 */
3267c478bd9Sstevel@tonic-gate 			printcycle(parentp);
3277c478bd9Sstevel@tonic-gate 			printmembers(parentp);
3287c478bd9Sstevel@tonic-gate 		} else {
3297c478bd9Sstevel@tonic-gate 			printparents(parentp);
3307c478bd9Sstevel@tonic-gate 			gprofline(parentp);
3317c478bd9Sstevel@tonic-gate 			printchildren(parentp);
3327c478bd9Sstevel@tonic-gate 		}
3337c478bd9Sstevel@tonic-gate 
33492ed1782Smike_s 		(void) printf("\n");
33592ed1782Smike_s 		(void) printf(
33692ed1782Smike_s 		    "-----------------------------------------------\n");
33792ed1782Smike_s 		(void) printf("\n");
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 		if (nflag) {
3407c478bd9Sstevel@tonic-gate 			--print_count;
3417c478bd9Sstevel@tonic-gate 			if (print_count == 0)
3427c478bd9Sstevel@tonic-gate 				count_flag = FALSE;
3437c478bd9Sstevel@tonic-gate 		}
3447c478bd9Sstevel@tonic-gate 	}
3457c478bd9Sstevel@tonic-gate 	free(timesortnlp);
3467c478bd9Sstevel@tonic-gate }
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate /*
3497c478bd9Sstevel@tonic-gate  *	sort by decreasing propagated time
3507c478bd9Sstevel@tonic-gate  *	if times are equal, but one is a cycle header,
3517c478bd9Sstevel@tonic-gate  *		say that's first (e.g. less, i.e. -1).
3527c478bd9Sstevel@tonic-gate  *	if one's name doesn't have an underscore and the other does,
3537c478bd9Sstevel@tonic-gate  *		say the one is first.
3547c478bd9Sstevel@tonic-gate  *	all else being equal, sort by names.
3557c478bd9Sstevel@tonic-gate  */
3567c478bd9Sstevel@tonic-gate int
totalcmp(const void * arg1,const void * arg2)35792ed1782Smike_s totalcmp(const void *arg1, const void *arg2)
3587c478bd9Sstevel@tonic-gate {
35992ed1782Smike_s 	nltype **npp1 = (nltype **)arg1;
36092ed1782Smike_s 	nltype **npp2 = (nltype **)arg2;
3617c478bd9Sstevel@tonic-gate 	nltype	*np1 = *npp1;
3627c478bd9Sstevel@tonic-gate 	nltype	*np2 = *npp2;
3637c478bd9Sstevel@tonic-gate 	double	diff;
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 	diff = (np1->propself + np1->propchild) -
3667c478bd9Sstevel@tonic-gate 	    (np2->propself + np2->propchild);
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	if (diff < 0.0)
3697c478bd9Sstevel@tonic-gate 		return (1);
3707c478bd9Sstevel@tonic-gate 	if (diff > 0.0)
3717c478bd9Sstevel@tonic-gate 		return (-1);
3727c478bd9Sstevel@tonic-gate 	if (np1->name == 0 && np1->cycleno != 0)
3737c478bd9Sstevel@tonic-gate 		return (-1);
3747c478bd9Sstevel@tonic-gate 	if (np2->name == 0 && np2->cycleno != 0)
3757c478bd9Sstevel@tonic-gate 		return (1);
3767c478bd9Sstevel@tonic-gate 	if (np1->name == 0)
3777c478bd9Sstevel@tonic-gate 		return (-1);
3787c478bd9Sstevel@tonic-gate 	if (np2->name == 0)
3797c478bd9Sstevel@tonic-gate 		return (1);
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	if (*(np1->name) != '_' && *(np2->name) == '_')
3827c478bd9Sstevel@tonic-gate 		return (-1);
3837c478bd9Sstevel@tonic-gate 	if (*(np1->name) == '_' && *(np2->name) != '_')
3847c478bd9Sstevel@tonic-gate 		return (1);
3857c478bd9Sstevel@tonic-gate 	if (np1->ncall > np2->ncall)
3867c478bd9Sstevel@tonic-gate 		return (-1);
3877c478bd9Sstevel@tonic-gate 	if (np1->ncall < np2->ncall)
3887c478bd9Sstevel@tonic-gate 		return (1);
3897c478bd9Sstevel@tonic-gate 	return (strcmp(np1->name, np2->name));
3907c478bd9Sstevel@tonic-gate }
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate void
printparents(nltype * childp)3937c478bd9Sstevel@tonic-gate printparents(nltype *childp)
3947c478bd9Sstevel@tonic-gate {
3957c478bd9Sstevel@tonic-gate 	nltype	*parentp;
3967c478bd9Sstevel@tonic-gate 	arctype	*arcp;
3977c478bd9Sstevel@tonic-gate 	nltype	*cycleheadp;
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	if (childp->cyclehead != 0)
4007c478bd9Sstevel@tonic-gate 		cycleheadp = childp -> cyclehead;
4017c478bd9Sstevel@tonic-gate 	else
4027c478bd9Sstevel@tonic-gate 		cycleheadp = childp;
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	if (childp->parents == 0) {
40592ed1782Smike_s 		(void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s"
4067c478bd9Sstevel@tonic-gate 		    "     <spontaneous>\n", "", "", "", "", "", "");
4077c478bd9Sstevel@tonic-gate 		return;
4087c478bd9Sstevel@tonic-gate 	}
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	sortparents(childp);
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 	for (arcp = childp->parents; arcp; arcp = arcp->arc_parentlist) {
4137c478bd9Sstevel@tonic-gate 		parentp = arcp -> arc_parentp;
4147c478bd9Sstevel@tonic-gate 		if (childp == parentp || (childp->cycleno != 0 &&
4157c478bd9Sstevel@tonic-gate 		    parentp->cycleno == childp->cycleno)) {
4167c478bd9Sstevel@tonic-gate 			/*
4177c478bd9Sstevel@tonic-gate 			 *	selfcall or call among siblings
4187c478bd9Sstevel@tonic-gate 			 */
41992ed1782Smike_s 			(void) printf(
42092ed1782Smike_s 			    "%6.6s %5.5s %7.7s %11.11s %7lld %7.7s     ",
4217c478bd9Sstevel@tonic-gate 			    "", "", "", "", arcp->arc_count, "");
4227c478bd9Sstevel@tonic-gate 			printname(parentp);
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 			if (Cflag)
4257c478bd9Sstevel@tonic-gate 				print_demangled_name(54, parentp);
4267c478bd9Sstevel@tonic-gate 
42792ed1782Smike_s 			(void) printf("\n");
4287c478bd9Sstevel@tonic-gate 		} else {
4297c478bd9Sstevel@tonic-gate 			/*
4307c478bd9Sstevel@tonic-gate 			 *	regular parent of child
4317c478bd9Sstevel@tonic-gate 			 */
43292ed1782Smike_s 			(void) printf(
43392ed1782Smike_s 			    "%6.6s %5.5s %7.2f %11.2f %7lld/%-7lld     ", "",
4347c478bd9Sstevel@tonic-gate 			    "", arcp->arc_time / hz, arcp->arc_childtime / hz,
4357c478bd9Sstevel@tonic-gate 			    arcp->arc_count, cycleheadp->ncall);
4367c478bd9Sstevel@tonic-gate 			printname(parentp);
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 			if (Cflag)
4397c478bd9Sstevel@tonic-gate 				print_demangled_name(54, parentp);
4407c478bd9Sstevel@tonic-gate 
44192ed1782Smike_s 			(void) printf("\n");
4427c478bd9Sstevel@tonic-gate 		}
4437c478bd9Sstevel@tonic-gate 	}
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate void
printchildren(nltype * parentp)4477c478bd9Sstevel@tonic-gate printchildren(nltype *parentp)
4487c478bd9Sstevel@tonic-gate {
4497c478bd9Sstevel@tonic-gate 	nltype	*childp;
4507c478bd9Sstevel@tonic-gate 	arctype	*arcp;
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	sortchildren(parentp);
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	for (arcp = parentp->children; arcp; arcp = arcp->arc_childlist) {
4557c478bd9Sstevel@tonic-gate 		childp = arcp->arc_childp;
4567c478bd9Sstevel@tonic-gate 		if (childp == parentp || (childp->cycleno != 0 &&
4577c478bd9Sstevel@tonic-gate 		    childp->cycleno == parentp->cycleno)) {
4587c478bd9Sstevel@tonic-gate 			/*
4597c478bd9Sstevel@tonic-gate 			 * self call or call to sibling
4607c478bd9Sstevel@tonic-gate 			 */
46192ed1782Smike_s 			(void) printf(
46292ed1782Smike_s 			    "%6.6s %5.5s %7.7s %11.11s %7lld %7.7s     ",
4637c478bd9Sstevel@tonic-gate 			    "", "", "", "", arcp->arc_count, "");
4647c478bd9Sstevel@tonic-gate 			printname(childp);
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 			if (Cflag)
4677c478bd9Sstevel@tonic-gate 				print_demangled_name(54, childp);
4687c478bd9Sstevel@tonic-gate 
46992ed1782Smike_s 			(void) printf("\n");
4707c478bd9Sstevel@tonic-gate 		} else {
4717c478bd9Sstevel@tonic-gate 			/*
4727c478bd9Sstevel@tonic-gate 			 *	regular child of parent
4737c478bd9Sstevel@tonic-gate 			 */
4747c478bd9Sstevel@tonic-gate 			if (childp->cyclehead)
47592ed1782Smike_s 				(void) printf("%6.6s %5.5s %7.2f %11.2f "
4767c478bd9Sstevel@tonic-gate 				    "%7lld/%-7lld     ", "", "",
4777c478bd9Sstevel@tonic-gate 				    arcp->arc_time / hz,
4787c478bd9Sstevel@tonic-gate 				    arcp->arc_childtime / hz, arcp->arc_count,
4797c478bd9Sstevel@tonic-gate 				    childp->cyclehead->ncall);
4807c478bd9Sstevel@tonic-gate 			else
48192ed1782Smike_s 				(void) printf("%6.6s %5.5s %7.2f %11.2f "
4827c478bd9Sstevel@tonic-gate 				    "%7lld %7.7s    ",
4837c478bd9Sstevel@tonic-gate 				    "", "", arcp->arc_time / hz,
4847c478bd9Sstevel@tonic-gate 				    arcp->arc_childtime / hz, arcp->arc_count,
4857c478bd9Sstevel@tonic-gate 				    "");
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 			printname(childp);
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 			if (Cflag)
4907c478bd9Sstevel@tonic-gate 				print_demangled_name(54, childp);
4917c478bd9Sstevel@tonic-gate 
49292ed1782Smike_s 			(void) printf("\n");
4937c478bd9Sstevel@tonic-gate 		}
4947c478bd9Sstevel@tonic-gate 	}
4957c478bd9Sstevel@tonic-gate }
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate void
printname(nltype * selfp)4987c478bd9Sstevel@tonic-gate printname(nltype *selfp)
4997c478bd9Sstevel@tonic-gate {
500b9bd317cSab 	const char  *c;
5017c478bd9Sstevel@tonic-gate 	c = demangled_name(selfp);
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 	if (selfp->name != 0) {
5044226f635SJason King 		(void) printf("%s", c);
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate #ifdef DEBUG
5077c478bd9Sstevel@tonic-gate 		if (debug & DFNDEBUG)
50892ed1782Smike_s 			(void) printf("{%d} ", selfp->toporder);
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 		if (debug & PROPDEBUG)
51192ed1782Smike_s 			(void) printf("%5.2f%% ", selfp->propfraction);
51292ed1782Smike_s #endif /* DEBUG */
5137c478bd9Sstevel@tonic-gate 	}
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 	if (selfp->cycleno != 0)
51692ed1782Smike_s 		(void) printf("\t<cycle %d>", selfp->cycleno);
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	if (selfp->index != 0) {
5197c478bd9Sstevel@tonic-gate 		if (selfp->printflag)
52092ed1782Smike_s 			(void) printf(" [%d]", selfp->index);
5217c478bd9Sstevel@tonic-gate 		else
52292ed1782Smike_s 			(void) printf(" (%d)", selfp->index);
5237c478bd9Sstevel@tonic-gate 	}
5244226f635SJason King 
5254226f635SJason King 	if (c != selfp->name)
5264226f635SJason King 		free((void *)c);
5277c478bd9Sstevel@tonic-gate }
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate void
print_demangled_name(int n,nltype * selfp)5307c478bd9Sstevel@tonic-gate print_demangled_name(int n, nltype *selfp)
5317c478bd9Sstevel@tonic-gate {
5324226f635SJason King 	char *c = (char *)demangled_name(selfp);
5337c478bd9Sstevel@tonic-gate 	int i;
5347c478bd9Sstevel@tonic-gate 
5354226f635SJason King 	if (c == selfp->name)
5367c478bd9Sstevel@tonic-gate 		return;
5374226f635SJason King 
5384226f635SJason King 	(void) printf("\n");
5394226f635SJason King 	for (i = 1; i < n; i++)
5404226f635SJason King 		(void) printf(" ");
5414226f635SJason King 	(void) printf("[%s]", selfp->name);
5424226f635SJason King 
5434226f635SJason King 	free(c);
5447c478bd9Sstevel@tonic-gate }
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate void
sortchildren(nltype * parentp)5477c478bd9Sstevel@tonic-gate sortchildren(nltype *parentp)
5487c478bd9Sstevel@tonic-gate {
5497c478bd9Sstevel@tonic-gate 	arctype	*arcp;
5507c478bd9Sstevel@tonic-gate 	arctype	*detachedp;
5517c478bd9Sstevel@tonic-gate 	arctype	sorted;
5527c478bd9Sstevel@tonic-gate 	arctype	*prevp;
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 	/*
5557c478bd9Sstevel@tonic-gate 	 *	unlink children from parent,
5567c478bd9Sstevel@tonic-gate 	 *	then insertion sort back on to sorted's children.
5577c478bd9Sstevel@tonic-gate 	 *	    *arcp	the arc you have detached and are inserting.
5587c478bd9Sstevel@tonic-gate 	 *	    *detachedp	the rest of the arcs to be sorted.
5597c478bd9Sstevel@tonic-gate 	 *	    sorted	arc list onto which you insertion sort.
5607c478bd9Sstevel@tonic-gate 	 *	    *prevp	arc before the arc you are comparing.
5617c478bd9Sstevel@tonic-gate 	 */
5627c478bd9Sstevel@tonic-gate 	sorted.arc_childlist = 0;
5637c478bd9Sstevel@tonic-gate 
564*326c1bafSToomas Soome 	arcp = parentp->children;
565*326c1bafSToomas Soome 	if (arcp != NULL)
566*326c1bafSToomas Soome 		detachedp = arcp->arc_childlist;
567*326c1bafSToomas Soome 	while (arcp != NULL) {
5687c478bd9Sstevel@tonic-gate 		/*
5697c478bd9Sstevel@tonic-gate 		 *	consider *arcp as disconnected
5707c478bd9Sstevel@tonic-gate 		 *	insert it into sorted
5717c478bd9Sstevel@tonic-gate 		 */
5727c478bd9Sstevel@tonic-gate 		for (prevp = &sorted; prevp->arc_childlist;
5737c478bd9Sstevel@tonic-gate 		    prevp = prevp->arc_childlist) {
5747c478bd9Sstevel@tonic-gate 			if (arccmp(arcp, prevp->arc_childlist) != LESSTHAN)
5757c478bd9Sstevel@tonic-gate 				break;
5767c478bd9Sstevel@tonic-gate 		}
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 		arcp->arc_childlist = prevp->arc_childlist;
5797c478bd9Sstevel@tonic-gate 		prevp->arc_childlist = arcp;
580*326c1bafSToomas Soome 
581*326c1bafSToomas Soome 		arcp = detachedp;
582*326c1bafSToomas Soome 		if (arcp != NULL)
583*326c1bafSToomas Soome 			detachedp = detachedp->arc_childlist;
5847c478bd9Sstevel@tonic-gate 	}
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 	/*
5877c478bd9Sstevel@tonic-gate 	 *	reattach sorted children to parent
5887c478bd9Sstevel@tonic-gate 	 */
5897c478bd9Sstevel@tonic-gate 	parentp->children = sorted.arc_childlist;
5907c478bd9Sstevel@tonic-gate }
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate void
sortparents(nltype * childp)5937c478bd9Sstevel@tonic-gate sortparents(nltype *childp)
5947c478bd9Sstevel@tonic-gate {
5957c478bd9Sstevel@tonic-gate 	arctype	*arcp;
5967c478bd9Sstevel@tonic-gate 	arctype	*detachedp;
5977c478bd9Sstevel@tonic-gate 	arctype	sorted;
5987c478bd9Sstevel@tonic-gate 	arctype	*prevp;
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate 	/*
6017c478bd9Sstevel@tonic-gate 	 *	unlink parents from child,
6027c478bd9Sstevel@tonic-gate 	 *	then insertion sort back on to sorted's parents.
6037c478bd9Sstevel@tonic-gate 	 *	    *arcp	the arc you have detached and are inserting.
6047c478bd9Sstevel@tonic-gate 	 *	    *detachedp	the rest of the arcs to be sorted.
6057c478bd9Sstevel@tonic-gate 	 *	    sorted	arc list onto which you insertion sort.
6067c478bd9Sstevel@tonic-gate 	 *	    *prevp	arc before the arc you are comparing.
6077c478bd9Sstevel@tonic-gate 	 */
6087c478bd9Sstevel@tonic-gate 	sorted.arc_parentlist = 0;
6097c478bd9Sstevel@tonic-gate 
610*326c1bafSToomas Soome 	arcp = childp->parents;
611*326c1bafSToomas Soome 	if (arcp != NULL)
612*326c1bafSToomas Soome 		detachedp = arcp->arc_parentlist;
613*326c1bafSToomas Soome 	while (arcp != NULL) {
6147c478bd9Sstevel@tonic-gate 		/*
6157c478bd9Sstevel@tonic-gate 		 *	consider *arcp as disconnected
6167c478bd9Sstevel@tonic-gate 		 *	insert it into sorted
6177c478bd9Sstevel@tonic-gate 		 */
6187c478bd9Sstevel@tonic-gate 		for (prevp = &sorted; prevp->arc_parentlist;
6197c478bd9Sstevel@tonic-gate 		    prevp = prevp->arc_parentlist) {
6207c478bd9Sstevel@tonic-gate 			if (arccmp(arcp, prevp->arc_parentlist) != GREATERTHAN)
6217c478bd9Sstevel@tonic-gate 				break;
6227c478bd9Sstevel@tonic-gate 		}
6237c478bd9Sstevel@tonic-gate 		arcp->arc_parentlist = prevp->arc_parentlist;
6247c478bd9Sstevel@tonic-gate 		prevp->arc_parentlist = arcp;
625*326c1bafSToomas Soome 		arcp = detachedp;
626*326c1bafSToomas Soome 		if (detachedp != NULL)
627*326c1bafSToomas Soome 			detachedp = detachedp->arc_parentlist;
6287c478bd9Sstevel@tonic-gate 	}
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 	/*
6317c478bd9Sstevel@tonic-gate 	 *	reattach sorted arcs to child
6327c478bd9Sstevel@tonic-gate 	 */
6337c478bd9Sstevel@tonic-gate 	childp->parents = sorted.arc_parentlist;
6347c478bd9Sstevel@tonic-gate }
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate void
printcycle(nltype * cyclep)6377c478bd9Sstevel@tonic-gate printcycle(nltype *cyclep)
6387c478bd9Sstevel@tonic-gate {
6397c478bd9Sstevel@tonic-gate 	char	kirkbuffer[BUFSIZ];
6407c478bd9Sstevel@tonic-gate 
64192ed1782Smike_s 	(void) sprintf(kirkbuffer, "[%d]", cyclep->index);
64292ed1782Smike_s 	(void) printf("%-6.6s %5.1f %7.2f %11.2f %7lld", kirkbuffer,
6437c478bd9Sstevel@tonic-gate 	    100 * (cyclep->propself + cyclep->propchild) / printtime,
6447c478bd9Sstevel@tonic-gate 	    cyclep -> propself / hz, cyclep -> propchild / hz,
6457c478bd9Sstevel@tonic-gate 	    cyclep -> ncall);
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 	if (cyclep->selfcalls != 0)
64892ed1782Smike_s 		(void) printf("+%-7lld", cyclep->selfcalls);
6497c478bd9Sstevel@tonic-gate 	else
65092ed1782Smike_s 		(void) printf(" %7.7s", "");
6517c478bd9Sstevel@tonic-gate 
65292ed1782Smike_s 	(void) printf(" <cycle %d as a whole>\t[%d]\n", cyclep->cycleno,
6537c478bd9Sstevel@tonic-gate 	    cyclep->index);
6547c478bd9Sstevel@tonic-gate }
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate /*
6577c478bd9Sstevel@tonic-gate  *	print the members of a cycle
6587c478bd9Sstevel@tonic-gate  */
6597c478bd9Sstevel@tonic-gate void
printmembers(nltype * cyclep)6607c478bd9Sstevel@tonic-gate printmembers(nltype *cyclep)
6617c478bd9Sstevel@tonic-gate {
6627c478bd9Sstevel@tonic-gate 	nltype	*memberp;
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 	sortmembers(cyclep);
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 	for (memberp = cyclep->cnext; memberp; memberp = memberp->cnext) {
66792ed1782Smike_s 		(void) printf("%6.6s %5.5s %7.2f %11.2f %7lld", "", "",
6687c478bd9Sstevel@tonic-gate 		    memberp->propself / hz, memberp->propchild / hz,
6697c478bd9Sstevel@tonic-gate 		    memberp->ncall);
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 		if (memberp->selfcalls != 0)
67292ed1782Smike_s 			(void) printf("+%-7lld", memberp->selfcalls);
6737c478bd9Sstevel@tonic-gate 		else
67492ed1782Smike_s 			(void) printf(" %7.7s", "");
6757c478bd9Sstevel@tonic-gate 
67692ed1782Smike_s 		(void) printf("     ");
6777c478bd9Sstevel@tonic-gate 		printname(memberp);
6787c478bd9Sstevel@tonic-gate 		if (Cflag)
6797c478bd9Sstevel@tonic-gate 			print_demangled_name(54, memberp);
68092ed1782Smike_s 		(void) printf("\n");
6817c478bd9Sstevel@tonic-gate 	}
6827c478bd9Sstevel@tonic-gate }
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate /*
6857c478bd9Sstevel@tonic-gate  * sort members of a cycle
6867c478bd9Sstevel@tonic-gate  */
6877c478bd9Sstevel@tonic-gate void
sortmembers(nltype * cyclep)6887c478bd9Sstevel@tonic-gate sortmembers(nltype *cyclep)
6897c478bd9Sstevel@tonic-gate {
6907c478bd9Sstevel@tonic-gate 	nltype	*todo;
6917c478bd9Sstevel@tonic-gate 	nltype	*doing;
6927c478bd9Sstevel@tonic-gate 	nltype	*prev;
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 	/*
6957c478bd9Sstevel@tonic-gate 	 *	detach cycle members from cyclehead,
6967c478bd9Sstevel@tonic-gate 	 *	and insertion sort them back on.
6977c478bd9Sstevel@tonic-gate 	 */
6987c478bd9Sstevel@tonic-gate 	todo = cyclep->cnext;
6997c478bd9Sstevel@tonic-gate 	cyclep->cnext = 0;
7007c478bd9Sstevel@tonic-gate 
701*326c1bafSToomas Soome 	doing = todo;
702*326c1bafSToomas Soome 	if (doing != NULL)
703*326c1bafSToomas Soome 		todo = doing->cnext;
704*326c1bafSToomas Soome 	while (doing != NULL) {
7057c478bd9Sstevel@tonic-gate 		for (prev = cyclep; prev->cnext; prev = prev->cnext) {
7067c478bd9Sstevel@tonic-gate 			if (membercmp(doing, prev->cnext) == GREATERTHAN)
7077c478bd9Sstevel@tonic-gate 				break;
7087c478bd9Sstevel@tonic-gate 		}
7097c478bd9Sstevel@tonic-gate 		doing->cnext = prev->cnext;
7107c478bd9Sstevel@tonic-gate 		prev->cnext = doing;
711*326c1bafSToomas Soome 		doing = todo;
712*326c1bafSToomas Soome 		if (doing != NULL)
713*326c1bafSToomas Soome 			todo = doing->cnext;
7147c478bd9Sstevel@tonic-gate 	}
7157c478bd9Sstevel@tonic-gate }
7167c478bd9Sstevel@tonic-gate 
7177c478bd9Sstevel@tonic-gate /*
7187c478bd9Sstevel@tonic-gate  *	major sort is on propself + propchild,
7197c478bd9Sstevel@tonic-gate  *	next is sort on ncalls + selfcalls.
7207c478bd9Sstevel@tonic-gate  */
7217c478bd9Sstevel@tonic-gate int
membercmp(nltype * this,nltype * that)7227c478bd9Sstevel@tonic-gate membercmp(nltype *this, nltype *that)
7237c478bd9Sstevel@tonic-gate {
7247c478bd9Sstevel@tonic-gate 	double	thistime = this->propself + this->propchild;
7257c478bd9Sstevel@tonic-gate 	double	thattime = that->propself + that->propchild;
7267c478bd9Sstevel@tonic-gate 	actype	thiscalls = this->ncall + this->selfcalls;
7277c478bd9Sstevel@tonic-gate 	actype	thatcalls = that->ncall + that->selfcalls;
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate 	if (thistime > thattime)
7307c478bd9Sstevel@tonic-gate 		return (GREATERTHAN);
7317c478bd9Sstevel@tonic-gate 
7327c478bd9Sstevel@tonic-gate 	if (thistime < thattime)
7337c478bd9Sstevel@tonic-gate 		return (LESSTHAN);
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate 	if (thiscalls > thatcalls)
7367c478bd9Sstevel@tonic-gate 		return (GREATERTHAN);
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate 	if (thiscalls < thatcalls)
7397c478bd9Sstevel@tonic-gate 		return (LESSTHAN);
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate 	return (EQUALTO);
7427c478bd9Sstevel@tonic-gate }
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate /*
7457c478bd9Sstevel@tonic-gate  *	compare two arcs to/from the same child/parent.
7467c478bd9Sstevel@tonic-gate  *	- if one arc is a self arc, it's least.
7477c478bd9Sstevel@tonic-gate  *	- if one arc is within a cycle, it's less than.
7487c478bd9Sstevel@tonic-gate  *	- if both arcs are within a cycle, compare arc counts.
7497c478bd9Sstevel@tonic-gate  *	- if neither arc is within a cycle, compare with
7507c478bd9Sstevel@tonic-gate  *		arc_time + arc_childtime as major key
7517c478bd9Sstevel@tonic-gate  *		arc count as minor key
7527c478bd9Sstevel@tonic-gate  */
7537c478bd9Sstevel@tonic-gate int
arccmp(arctype * thisp,arctype * thatp)7547c478bd9Sstevel@tonic-gate arccmp(arctype *thisp, arctype *thatp)
7557c478bd9Sstevel@tonic-gate {
7567c478bd9Sstevel@tonic-gate 	nltype	*thisparentp = thisp->arc_parentp;
7577c478bd9Sstevel@tonic-gate 	nltype	*thischildp = thisp->arc_childp;
7587c478bd9Sstevel@tonic-gate 	nltype	*thatparentp = thatp->arc_parentp;
7597c478bd9Sstevel@tonic-gate 	nltype	*thatchildp = thatp->arc_childp;
7607c478bd9Sstevel@tonic-gate 	double	thistime;
7617c478bd9Sstevel@tonic-gate 	double	thattime;
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate #ifdef DEBUG
7647c478bd9Sstevel@tonic-gate 	if (debug & TIMEDEBUG) {
76592ed1782Smike_s 		(void) printf("[arccmp] ");
7667c478bd9Sstevel@tonic-gate 		printname(thisparentp);
76792ed1782Smike_s 		(void) printf(" calls ");
7687c478bd9Sstevel@tonic-gate 		printname(thischildp);
76992ed1782Smike_s 		(void) printf(" %f + %f %lld/%lld\n", thisp->arc_time,
7707c478bd9Sstevel@tonic-gate 		    thisp->arc_childtime, thisp->arc_count,
7717c478bd9Sstevel@tonic-gate 		    thischildp->ncall);
77292ed1782Smike_s 		(void) printf("[arccmp] ");
7737c478bd9Sstevel@tonic-gate 		printname(thatparentp);
77492ed1782Smike_s 		(void) printf(" calls ");
7757c478bd9Sstevel@tonic-gate 		printname(thatchildp);
77692ed1782Smike_s 		(void) printf(" %f + %f %lld/%lld\n", thatp->arc_time,
7777c478bd9Sstevel@tonic-gate 		    thatp->arc_childtime, thatp->arc_count,
7787c478bd9Sstevel@tonic-gate 		    thatchildp->ncall);
77992ed1782Smike_s 		(void) printf("\n");
7807c478bd9Sstevel@tonic-gate 	}
78192ed1782Smike_s #endif /* DEBUG */
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate 	if (thisparentp == thischildp) {
7847c478bd9Sstevel@tonic-gate 		/*
7857c478bd9Sstevel@tonic-gate 		 * this is a self call
7867c478bd9Sstevel@tonic-gate 		 */
7877c478bd9Sstevel@tonic-gate 		return (LESSTHAN);
7887c478bd9Sstevel@tonic-gate 	}
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 	if (thatparentp == thatchildp) {
7917c478bd9Sstevel@tonic-gate 		/*
7927c478bd9Sstevel@tonic-gate 		 * that is a self call
7937c478bd9Sstevel@tonic-gate 		 */
7947c478bd9Sstevel@tonic-gate 		return (GREATERTHAN);
7957c478bd9Sstevel@tonic-gate 	}
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 	if (thisparentp->cycleno != 0 && thischildp->cycleno != 0 &&
7987c478bd9Sstevel@tonic-gate 	    thisparentp->cycleno == thischildp->cycleno) {
7997c478bd9Sstevel@tonic-gate 		/*
8007c478bd9Sstevel@tonic-gate 		 * this is a call within a cycle
8017c478bd9Sstevel@tonic-gate 		 */
8027c478bd9Sstevel@tonic-gate 		if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 &&
8037c478bd9Sstevel@tonic-gate 		    thatparentp->cycleno == thatchildp->cycleno) {
8047c478bd9Sstevel@tonic-gate 			/*
8057c478bd9Sstevel@tonic-gate 			 * that is a call within the cycle, too
8067c478bd9Sstevel@tonic-gate 			 */
8077c478bd9Sstevel@tonic-gate 			if (thisp->arc_count < thatp->arc_count)
8087c478bd9Sstevel@tonic-gate 				return (LESSTHAN);
8097c478bd9Sstevel@tonic-gate 
8107c478bd9Sstevel@tonic-gate 			if (thisp->arc_count > thatp->arc_count)
8117c478bd9Sstevel@tonic-gate 				return (GREATERTHAN);
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 			return (EQUALTO);
8147c478bd9Sstevel@tonic-gate 		} else {
8157c478bd9Sstevel@tonic-gate 			/*
8167c478bd9Sstevel@tonic-gate 			 * that isn't a call within the cycle
8177c478bd9Sstevel@tonic-gate 			 */
8187c478bd9Sstevel@tonic-gate 			return (LESSTHAN);
8197c478bd9Sstevel@tonic-gate 		}
8207c478bd9Sstevel@tonic-gate 	} else {
8217c478bd9Sstevel@tonic-gate 		/*
8227c478bd9Sstevel@tonic-gate 		 * this isn't a call within a cycle
8237c478bd9Sstevel@tonic-gate 		 */
8247c478bd9Sstevel@tonic-gate 		if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 &&
8257c478bd9Sstevel@tonic-gate 		    thatparentp->cycleno == thatchildp->cycleno) {
8267c478bd9Sstevel@tonic-gate 			/*
8277c478bd9Sstevel@tonic-gate 			 * that is a call within a cycle
8287c478bd9Sstevel@tonic-gate 			 */
8297c478bd9Sstevel@tonic-gate 			return (GREATERTHAN);
8307c478bd9Sstevel@tonic-gate 		} else {
8317c478bd9Sstevel@tonic-gate 			/*
8327c478bd9Sstevel@tonic-gate 			 * neither is a call within a cycle
8337c478bd9Sstevel@tonic-gate 			 */
8347c478bd9Sstevel@tonic-gate 			thistime = thisp->arc_time + thisp->arc_childtime;
8357c478bd9Sstevel@tonic-gate 			thattime = thatp->arc_time + thatp->arc_childtime;
8367c478bd9Sstevel@tonic-gate 
8377c478bd9Sstevel@tonic-gate 			if (thistime < thattime)
8387c478bd9Sstevel@tonic-gate 				return (LESSTHAN);
8397c478bd9Sstevel@tonic-gate 
8407c478bd9Sstevel@tonic-gate 			if (thistime > thattime)
8417c478bd9Sstevel@tonic-gate 				return (GREATERTHAN);
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate 			if (thisp->arc_count < thatp->arc_count)
8447c478bd9Sstevel@tonic-gate 				return (LESSTHAN);
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate 			if (thisp->arc_count > thatp->arc_count)
8477c478bd9Sstevel@tonic-gate 				return (GREATERTHAN);
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate 			return (EQUALTO);
8507c478bd9Sstevel@tonic-gate 		}
8517c478bd9Sstevel@tonic-gate 	}
8527c478bd9Sstevel@tonic-gate }
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate void
printblurb(char * blurbname)8557c478bd9Sstevel@tonic-gate printblurb(char *blurbname)
8567c478bd9Sstevel@tonic-gate {
8577c478bd9Sstevel@tonic-gate 	FILE	*blurbfile;
8587c478bd9Sstevel@tonic-gate 	int	input;
8597c478bd9Sstevel@tonic-gate 
86067298654Sdamico 	blurbfile = fopen(blurbname, "r");
8617c478bd9Sstevel@tonic-gate 	if (blurbfile == NULL) {
86267298654Sdamico 		perror(blurbname);
8637c478bd9Sstevel@tonic-gate 		return;
8647c478bd9Sstevel@tonic-gate 	}
8657c478bd9Sstevel@tonic-gate 
8667c478bd9Sstevel@tonic-gate 	while ((input = getc(blurbfile)) != EOF)
86792ed1782Smike_s 		(void) putchar(input);
8687c478bd9Sstevel@tonic-gate 
86992ed1782Smike_s 	(void) fclose(blurbfile);
8707c478bd9Sstevel@tonic-gate }
8717c478bd9Sstevel@tonic-gate 
87292ed1782Smike_s static int
namecmp(const void * arg1,const void * arg2)87392ed1782Smike_s namecmp(const void *arg1, const void *arg2)
8747c478bd9Sstevel@tonic-gate {
87592ed1782Smike_s 	nltype **npp1 = (nltype **)arg1;
87692ed1782Smike_s 	nltype **npp2 = (nltype **)arg2;
87792ed1782Smike_s 
8787c478bd9Sstevel@tonic-gate 	if (!Cflag)
8797c478bd9Sstevel@tonic-gate 		return (strcmp((*npp1)->name, (*npp2)->name));
8807c478bd9Sstevel@tonic-gate 	else {
8814226f635SJason King 		static char *s1 = NULL, *s2 = NULL;
8824226f635SJason King 		static size_t s1len = 0, s2len = 0;
8834226f635SJason King 
8844226f635SJason King 		stripped_name(&s1, &s1len, npp1);
8854226f635SJason King 		stripped_name(&s2, &s2len, npp2);
8867c478bd9Sstevel@tonic-gate 		return (strcmp(s1, s2));
8877c478bd9Sstevel@tonic-gate 	}
8887c478bd9Sstevel@tonic-gate }
8897c478bd9Sstevel@tonic-gate 
8904226f635SJason King #define	NAME_CHUNK 512
8914226f635SJason King #define	ROUNDLEN(x) (((x) + NAME_CHUNK - 1) / NAME_CHUNK * NAME_CHUNK)
8924226f635SJason King static void
adjust_size(char ** pp,size_t * lenp,const char * name)8934226f635SJason King adjust_size(char **pp, size_t *lenp, const char *name)
8947c478bd9Sstevel@tonic-gate {
8954226f635SJason King 	void *newp;
8964226f635SJason King 	size_t nlen = strlen(name);
8974226f635SJason King 	size_t buflen;
8984226f635SJason King 
8994226f635SJason King 	if (*lenp > nlen) {
9004226f635SJason King 		(void) memset(*pp, '\0', *lenp);
9014226f635SJason King 		return;
9024226f635SJason King 	}
9034226f635SJason King 
9044226f635SJason King 	buflen = ROUNDLEN(nlen + 1);
9054226f635SJason King 	if ((newp = realloc(*pp, buflen)) == NULL) {
9064226f635SJason King 		(void) fprintf(stderr,
9074226f635SJason King 		    "gprof: out of memory comparing names\n");
9084226f635SJason King 		exit(EXIT_FAILURE);
9094226f635SJason King 	}
9104226f635SJason King 	(void) memset(newp, '\0', buflen);
9114226f635SJason King 
9124226f635SJason King 	*lenp = buflen;
9134226f635SJason King 	*pp = newp;
9144226f635SJason King }
9154226f635SJason King 
9164226f635SJason King static void
stripped_name(char ** sp,size_t * slenp,nltype ** npp)9174226f635SJason King stripped_name(char **sp, size_t *slenp, nltype **npp)
9184226f635SJason King {
9194226f635SJason King 	const char *name, *d;
920b9bd317cSab 	char *c;
9217c478bd9Sstevel@tonic-gate 
9224226f635SJason King 	name = d = demangled_name(*npp);
9234226f635SJason King 	adjust_size(sp, slenp, name);
9244226f635SJason King 	c = *sp;
9257c478bd9Sstevel@tonic-gate 
9267c478bd9Sstevel@tonic-gate 	while ((*d != '(') && (*d != '\0')) {
9277c478bd9Sstevel@tonic-gate 		if (*d != ':')
9287c478bd9Sstevel@tonic-gate 			*c++ = *d++;
9297c478bd9Sstevel@tonic-gate 		else
9307c478bd9Sstevel@tonic-gate 			d++;
9317c478bd9Sstevel@tonic-gate 	}
9327c478bd9Sstevel@tonic-gate 	*c = '\0';
9334226f635SJason King 
9344226f635SJason King 	if ((*npp)->name != name)
9354226f635SJason King 		free((void *)name);
9367c478bd9Sstevel@tonic-gate }
9377c478bd9Sstevel@tonic-gate 
9387c478bd9Sstevel@tonic-gate /*
9397c478bd9Sstevel@tonic-gate  * Checks if the current symbol name is the same as its neighbour and
9407c478bd9Sstevel@tonic-gate  * returns TRUE if it is.
9417c478bd9Sstevel@tonic-gate  */
9427c478bd9Sstevel@tonic-gate static bool
does_clash(nltype ** nlp,int ndx,int nnames)9437c478bd9Sstevel@tonic-gate does_clash(nltype **nlp, int ndx, int nnames)
9447c478bd9Sstevel@tonic-gate {
9457c478bd9Sstevel@tonic-gate 	/*
9467c478bd9Sstevel@tonic-gate 	 * same as previous (if there's one) ?
9477c478bd9Sstevel@tonic-gate 	 */
9487c478bd9Sstevel@tonic-gate 	if (ndx && (strcmp(nlp[ndx]->name, nlp[ndx-1]->name) == 0))
9497c478bd9Sstevel@tonic-gate 		return (TRUE);
9507c478bd9Sstevel@tonic-gate 
9517c478bd9Sstevel@tonic-gate 	/*
9527c478bd9Sstevel@tonic-gate 	 * same as next (if there's one) ?
9537c478bd9Sstevel@tonic-gate 	 */
9547c478bd9Sstevel@tonic-gate 	if ((ndx < (nnames - 1)) &&
95567298654Sdamico 	    (strcmp(nlp[ndx]->name, nlp[ndx+1]->name) == 0)) {
9567c478bd9Sstevel@tonic-gate 		return (TRUE);
9577c478bd9Sstevel@tonic-gate 	}
9587c478bd9Sstevel@tonic-gate 
9597c478bd9Sstevel@tonic-gate 	return (FALSE);
9607c478bd9Sstevel@tonic-gate }
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate void
printmodules()9637c478bd9Sstevel@tonic-gate printmodules()
9647c478bd9Sstevel@tonic-gate {
9657c478bd9Sstevel@tonic-gate 	mod_info_t	*mi;
9667c478bd9Sstevel@tonic-gate 
96792ed1782Smike_s 	(void) printf("\f\nObject modules\n\n");
9687c478bd9Sstevel@tonic-gate 	for (mi = &modules; mi; mi = mi->next)
96992ed1782Smike_s 		(void) printf(" %d: %s\n", mi->id, mi->name);
9707c478bd9Sstevel@tonic-gate }
9717c478bd9Sstevel@tonic-gate 
9727c478bd9Sstevel@tonic-gate #define	IDFMT(id)	((id) < 10 ? 1 : 2)
9737c478bd9Sstevel@tonic-gate #define	NMFMT(id)	((id) < 10 ? 17 : 16)
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate void
printindex()9767c478bd9Sstevel@tonic-gate printindex()
9777c478bd9Sstevel@tonic-gate {
9787c478bd9Sstevel@tonic-gate 	nltype	**namesortnlp;
9797c478bd9Sstevel@tonic-gate 	nltype	*nlp;
9807c478bd9Sstevel@tonic-gate 	int	index, nnames, todo, i, j;
9817c478bd9Sstevel@tonic-gate 	char	peterbuffer[BUFSIZ];
9827c478bd9Sstevel@tonic-gate 	mod_info_t	*mi;
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 	/*
9857c478bd9Sstevel@tonic-gate 	 *	Now, sort regular function name alphabetically
9867c478bd9Sstevel@tonic-gate 	 *	to create an index.
9877c478bd9Sstevel@tonic-gate 	 */
9887c478bd9Sstevel@tonic-gate 	namesortnlp = calloc(total_names + ncycle, sizeof (nltype *));
9897c478bd9Sstevel@tonic-gate 
9907c478bd9Sstevel@tonic-gate 	if (namesortnlp == NULL)
99192ed1782Smike_s 		(void) fprintf(stderr, "%s: ran out of memory for sorting\n",
99292ed1782Smike_s 		    whoami);
9937c478bd9Sstevel@tonic-gate 
9947c478bd9Sstevel@tonic-gate 	nnames = 0;
9957c478bd9Sstevel@tonic-gate 	for (mi = &modules; mi; mi = mi->next) {
9967c478bd9Sstevel@tonic-gate 		for (index = 0; index < mi->nname; index++) {
9977c478bd9Sstevel@tonic-gate 			if (zflag == 0 && (mi->nl[index]).ncall == 0 &&
99867298654Sdamico 			    (mi->nl[index]).time == 0) {
9997c478bd9Sstevel@tonic-gate 				continue;
10007c478bd9Sstevel@tonic-gate 			}
10017c478bd9Sstevel@tonic-gate 
10027c478bd9Sstevel@tonic-gate 			/*
10037c478bd9Sstevel@tonic-gate 			 * Do not print certain special symbols, like
10047c478bd9Sstevel@tonic-gate 			 * PRF_EXTSYM, etc. even if zflag was on.
10057c478bd9Sstevel@tonic-gate 			 */
10067c478bd9Sstevel@tonic-gate 			if (is_special_sym(&(mi->nl[index])))
10077c478bd9Sstevel@tonic-gate 				continue;
10087c478bd9Sstevel@tonic-gate 
10097c478bd9Sstevel@tonic-gate 			namesortnlp[nnames++] = &(mi->nl[index]);
10107c478bd9Sstevel@tonic-gate 		}
10117c478bd9Sstevel@tonic-gate 	}
10127c478bd9Sstevel@tonic-gate 
101392ed1782Smike_s 	qsort(namesortnlp, nnames, sizeof (nltype *), namecmp);
10147c478bd9Sstevel@tonic-gate 
10157c478bd9Sstevel@tonic-gate 	for (index = 1, todo = nnames; index <= ncycle; index++)
10167c478bd9Sstevel@tonic-gate 		namesortnlp[todo++] = &cyclenl[index];
10177c478bd9Sstevel@tonic-gate 
101892ed1782Smike_s 	(void) printf("\f\nIndex by function name\n\n");
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate 	if (!Cflag)
10217c478bd9Sstevel@tonic-gate 		index = (todo + 2) / 3;
10227c478bd9Sstevel@tonic-gate 	else
10237c478bd9Sstevel@tonic-gate 		index = todo;
10247c478bd9Sstevel@tonic-gate 
10257c478bd9Sstevel@tonic-gate 	for (i = 0; i < index; i++) {
10267c478bd9Sstevel@tonic-gate 		if (!Cflag) {
10277c478bd9Sstevel@tonic-gate 			for (j = i; j < todo; j += index) {
10287c478bd9Sstevel@tonic-gate 				nlp = namesortnlp[j];
10297c478bd9Sstevel@tonic-gate 
10307c478bd9Sstevel@tonic-gate 				if (nlp->printflag) {
103192ed1782Smike_s 					(void) sprintf(peterbuffer,
10327c478bd9Sstevel@tonic-gate 					    "[%d]", nlp->index);
10337c478bd9Sstevel@tonic-gate 				} else {
103492ed1782Smike_s 					(void) sprintf(peterbuffer,
10357c478bd9Sstevel@tonic-gate 					    "(%d)", nlp->index);
10367c478bd9Sstevel@tonic-gate 				}
10377c478bd9Sstevel@tonic-gate 
10387c478bd9Sstevel@tonic-gate 				if (j < nnames) {
10397c478bd9Sstevel@tonic-gate 					if (does_clash(namesortnlp,
104067298654Sdamico 					    j, nnames)) {
104192ed1782Smike_s 						(void) printf(
104292ed1782Smike_s 						    "%6.6s %*d:%-*.*s",
104367298654Sdamico 						    peterbuffer,
104467298654Sdamico 						    IDFMT(nlp->module->id),
104567298654Sdamico 						    nlp->module->id,
104667298654Sdamico 						    NMFMT(nlp->module->id),
104767298654Sdamico 						    NMFMT(nlp->module->id),
104867298654Sdamico 						    nlp->name);
10497c478bd9Sstevel@tonic-gate 					} else {
105067298654Sdamico 					(void) printf("%6.6s %-19.19s",
105167298654Sdamico 					    peterbuffer, nlp->name);
10527c478bd9Sstevel@tonic-gate 					}
10537c478bd9Sstevel@tonic-gate 				} else {
105492ed1782Smike_s 					(void) printf("%6.6s ", peterbuffer);
105592ed1782Smike_s 					(void) sprintf(peterbuffer,
10567c478bd9Sstevel@tonic-gate 					    "<cycle %d>", nlp->cycleno);
105792ed1782Smike_s 					(void) printf("%-19.19s", peterbuffer);
10587c478bd9Sstevel@tonic-gate 				}
10597c478bd9Sstevel@tonic-gate 			}
10607c478bd9Sstevel@tonic-gate 		} else {
10617c478bd9Sstevel@tonic-gate 			nlp = namesortnlp[i];
10627c478bd9Sstevel@tonic-gate 
10637c478bd9Sstevel@tonic-gate 			if (nlp->printflag)
106492ed1782Smike_s 				(void) sprintf(peterbuffer, "[%d]", nlp->index);
10657c478bd9Sstevel@tonic-gate 			else
106692ed1782Smike_s 				(void) sprintf(peterbuffer, "(%d)", nlp->index);
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate 			if (i < nnames) {
1069b9bd317cSab 				const char *d = demangled_name(nlp);
10707c478bd9Sstevel@tonic-gate 
10717c478bd9Sstevel@tonic-gate 				if (does_clash(namesortnlp, i, nnames)) {
107292ed1782Smike_s 					(void) printf("%6.6s %d:%s\n",
107392ed1782Smike_s 					    peterbuffer, nlp->module->id, d);
10744226f635SJason King 				} else {
107592ed1782Smike_s 					(void) printf("%6.6s %s\n", peterbuffer,
107692ed1782Smike_s 					    d);
10774226f635SJason King 				}
10787c478bd9Sstevel@tonic-gate 
10794226f635SJason King 				if (d != nlp->name) {
108092ed1782Smike_s 					(void) printf("%6.6s   [%s]", "",
108192ed1782Smike_s 					    nlp->name);
10824226f635SJason King 					free((void *)d);
10834226f635SJason King 				}
10847c478bd9Sstevel@tonic-gate 			} else {
108592ed1782Smike_s 				(void) printf("%6.6s ", peterbuffer);
108692ed1782Smike_s 				(void) sprintf(peterbuffer, "<cycle %d>",
10877c478bd9Sstevel@tonic-gate 				    nlp->cycleno);
108892ed1782Smike_s 				(void) printf("%-33.33s", peterbuffer);
10897c478bd9Sstevel@tonic-gate 			}
10907c478bd9Sstevel@tonic-gate 		}
109192ed1782Smike_s 		(void) printf("\n");
10927c478bd9Sstevel@tonic-gate 	}
10937c478bd9Sstevel@tonic-gate 	free(namesortnlp);
10947c478bd9Sstevel@tonic-gate }
1095