10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
54538Sdamico * Common Development and Distribution License (the "License").
64538Sdamico * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21211Smike_s
220Sstevel@tonic-gate /*
23*7008Sab196087 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24211Smike_s * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
280Sstevel@tonic-gate
290Sstevel@tonic-gate #include <ctype.h>
300Sstevel@tonic-gate #include <string.h>
310Sstevel@tonic-gate #include <sys/param.h>
320Sstevel@tonic-gate #include <stdlib.h>
33*7008Sab196087 #include "conv.h"
340Sstevel@tonic-gate #include "gprof.h"
350Sstevel@tonic-gate
360Sstevel@tonic-gate void print_demangled_name(int, nltype *);
370Sstevel@tonic-gate void striped_name(char *, nltype **);
380Sstevel@tonic-gate
390Sstevel@tonic-gate extern long hz;
400Sstevel@tonic-gate
410Sstevel@tonic-gate /*
420Sstevel@tonic-gate * Symbols that must never be printed, no matter what.
430Sstevel@tonic-gate */
440Sstevel@tonic-gate char *splsym[] = {
450Sstevel@tonic-gate PRF_ETEXT,
460Sstevel@tonic-gate PRF_EXTSYM,
470Sstevel@tonic-gate PRF_MEMTERM,
48211Smike_s NULL
490Sstevel@tonic-gate };
500Sstevel@tonic-gate
51211Smike_s static bool is_special_sym(nltype *nlp);
52211Smike_s
53*7008Sab196087 const char *
demangled_name(nltype * selfp)540Sstevel@tonic-gate demangled_name(nltype *selfp)
550Sstevel@tonic-gate {
560Sstevel@tonic-gate if (!Cflag)
570Sstevel@tonic-gate return (selfp->name);
580Sstevel@tonic-gate
59*7008Sab196087 return (conv_demangle_name(selfp->name));
600Sstevel@tonic-gate }
610Sstevel@tonic-gate
620Sstevel@tonic-gate void
printprof(void)63211Smike_s printprof(void)
640Sstevel@tonic-gate {
650Sstevel@tonic-gate nltype *np;
660Sstevel@tonic-gate nltype **sortednlp;
670Sstevel@tonic-gate int i, index;
680Sstevel@tonic-gate int print_count = number_funcs_toprint;
690Sstevel@tonic-gate bool print_flag = TRUE;
700Sstevel@tonic-gate mod_info_t *mi;
710Sstevel@tonic-gate
720Sstevel@tonic-gate actime = 0.0;
73211Smike_s (void) printf("\f\n");
740Sstevel@tonic-gate flatprofheader();
750Sstevel@tonic-gate
760Sstevel@tonic-gate /*
770Sstevel@tonic-gate * Sort the symbol table in by time
780Sstevel@tonic-gate */
790Sstevel@tonic-gate sortednlp = (nltype **) calloc(total_names, sizeof (nltype *));
800Sstevel@tonic-gate if (sortednlp == (nltype **) 0) {
81211Smike_s (void) fprintf(stderr,
820Sstevel@tonic-gate "[printprof] ran out of memory for time sorting\n");
830Sstevel@tonic-gate }
840Sstevel@tonic-gate
850Sstevel@tonic-gate index = 0;
860Sstevel@tonic-gate for (mi = &modules; mi; mi = mi->next) {
870Sstevel@tonic-gate for (i = 0; i < mi->nname; i++)
880Sstevel@tonic-gate sortednlp[index++] = &(mi->nl[i]);
890Sstevel@tonic-gate }
900Sstevel@tonic-gate
91211Smike_s qsort(sortednlp, total_names, sizeof (nltype *), timecmp);
920Sstevel@tonic-gate
930Sstevel@tonic-gate for (index = 0; (index < total_names) && print_flag; index += 1) {
940Sstevel@tonic-gate np = sortednlp[index];
950Sstevel@tonic-gate flatprofline(np);
960Sstevel@tonic-gate if (nflag) {
970Sstevel@tonic-gate if (--print_count == 0)
980Sstevel@tonic-gate print_flag = FALSE;
990Sstevel@tonic-gate }
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate actime = 0.0;
1020Sstevel@tonic-gate free(sortednlp);
1030Sstevel@tonic-gate }
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate int
timecmp(const void * arg1,const void * arg2)106211Smike_s timecmp(const void *arg1, const void *arg2)
1070Sstevel@tonic-gate {
108211Smike_s nltype **npp1 = (nltype **)arg1;
109211Smike_s nltype **npp2 = (nltype **)arg2;
1100Sstevel@tonic-gate double timediff;
1110Sstevel@tonic-gate long calldiff;
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate timediff = (*npp2)->time - (*npp1)->time;
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate if (timediff > 0.0)
1160Sstevel@tonic-gate return (1);
1170Sstevel@tonic-gate
1180Sstevel@tonic-gate if (timediff < 0.0)
1190Sstevel@tonic-gate return (-1);
1200Sstevel@tonic-gate
1210Sstevel@tonic-gate calldiff = (*npp2)->ncall - (*npp1)->ncall;
1220Sstevel@tonic-gate
1230Sstevel@tonic-gate if (calldiff > 0)
1240Sstevel@tonic-gate return (1);
1250Sstevel@tonic-gate
1260Sstevel@tonic-gate if (calldiff < 0)
1270Sstevel@tonic-gate return (-1);
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate return (strcmp((*npp1)->name, (*npp2)->name));
1300Sstevel@tonic-gate }
1310Sstevel@tonic-gate
1320Sstevel@tonic-gate /*
1330Sstevel@tonic-gate * header for flatprofline
1340Sstevel@tonic-gate */
1350Sstevel@tonic-gate void
flatprofheader()1360Sstevel@tonic-gate flatprofheader()
1370Sstevel@tonic-gate {
1380Sstevel@tonic-gate
1390Sstevel@tonic-gate if (bflag)
1400Sstevel@tonic-gate printblurb(FLAT_BLURB);
1410Sstevel@tonic-gate
1420Sstevel@tonic-gate if (old_style) {
143211Smike_s (void) printf(
144211Smike_s "\ngranularity: each sample hit covers %d byte(s)",
145211Smike_s (long)scale * sizeof (UNIT));
1460Sstevel@tonic-gate if (totime > 0.0) {
147211Smike_s (void) printf(" for %.2f%% of %.2f seconds\n\n",
1480Sstevel@tonic-gate 100.0/totime, totime / hz);
1490Sstevel@tonic-gate } else {
150211Smike_s (void) printf(" no time accumulated\n\n");
1510Sstevel@tonic-gate /*
1520Sstevel@tonic-gate * this doesn't hurt since all the numerators will
1530Sstevel@tonic-gate * be zero.
1540Sstevel@tonic-gate */
1550Sstevel@tonic-gate totime = 1.0;
1560Sstevel@tonic-gate }
1570Sstevel@tonic-gate }
1580Sstevel@tonic-gate
159211Smike_s (void) printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
1600Sstevel@tonic-gate "% ", "cumulative", "self ", "", "self ", "total ", "");
161211Smike_s (void) printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
1620Sstevel@tonic-gate "time", "seconds ", "seconds", "calls",
1630Sstevel@tonic-gate "ms/call", "ms/call", "name");
1640Sstevel@tonic-gate }
1650Sstevel@tonic-gate
1660Sstevel@tonic-gate void
flatprofline(nltype * np)1670Sstevel@tonic-gate flatprofline(nltype *np)
1680Sstevel@tonic-gate {
1690Sstevel@tonic-gate if (zflag == 0 && np->ncall == 0 && np->time == 0)
1700Sstevel@tonic-gate return;
1710Sstevel@tonic-gate
1720Sstevel@tonic-gate /*
1730Sstevel@tonic-gate * Do not print certain special symbols, like PRF_EXTSYM, etc.
1740Sstevel@tonic-gate * even if zflag was on.
1750Sstevel@tonic-gate */
1760Sstevel@tonic-gate if (is_special_sym(np))
1770Sstevel@tonic-gate return;
1780Sstevel@tonic-gate
1790Sstevel@tonic-gate actime += np->time;
1800Sstevel@tonic-gate
181211Smike_s (void) printf("%5.1f %10.2f %8.2f",
1820Sstevel@tonic-gate 100 * np->time / totime, actime / hz, np->time / hz);
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate if (np->ncall != 0) {
185211Smike_s (void) printf(" %8lld %8.2f %8.2f ", np->ncall,
1860Sstevel@tonic-gate 1000 * np->time / hz / np->ncall,
1870Sstevel@tonic-gate 1000 * (np->time + np->childtime) / hz / np->ncall);
1880Sstevel@tonic-gate } else {
1890Sstevel@tonic-gate if (!Cflag)
190211Smike_s (void) printf(" %8.8s %8.8s %8.8s ", "", "", "");
1910Sstevel@tonic-gate else
192211Smike_s (void) printf(" %8.8s %8.8s %8.8s ", "", "", "");
1930Sstevel@tonic-gate }
1940Sstevel@tonic-gate
1950Sstevel@tonic-gate printname(np);
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate if (Cflag)
1980Sstevel@tonic-gate print_demangled_name(55, np);
1990Sstevel@tonic-gate
200211Smike_s (void) printf("\n");
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate void
gprofheader()2040Sstevel@tonic-gate gprofheader()
2050Sstevel@tonic-gate {
2060Sstevel@tonic-gate
2070Sstevel@tonic-gate if (bflag)
2080Sstevel@tonic-gate printblurb(CALLG_BLURB);
2090Sstevel@tonic-gate
2100Sstevel@tonic-gate if (old_style) {
2110Sstevel@tonic-gate
212211Smike_s (void) printf(
213211Smike_s "\ngranularity: each sample hit covers %d byte(s)",
214211Smike_s (long)scale * sizeof (UNIT));
2150Sstevel@tonic-gate
2160Sstevel@tonic-gate if (printtime > 0.0) {
217211Smike_s (void) printf(" for %.2f%% of %.2f seconds\n\n",
2180Sstevel@tonic-gate 100.0/printtime, printtime / hz);
2190Sstevel@tonic-gate } else {
220211Smike_s (void) printf(" no time propagated\n\n");
2210Sstevel@tonic-gate /*
2220Sstevel@tonic-gate * this doesn't hurt, since all the numerators
2230Sstevel@tonic-gate * will be 0.0
2240Sstevel@tonic-gate */
2250Sstevel@tonic-gate printtime = 1.0;
2260Sstevel@tonic-gate }
2270Sstevel@tonic-gate } else {
228211Smike_s (void) printf(
229211Smike_s "\ngranularity: each pc-hit is considered 1 tick");
2300Sstevel@tonic-gate if (hz != 1) {
231211Smike_s (void) printf(" (@ %4.3f seconds per tick)",
232211Smike_s (double)1.0 / hz);
2330Sstevel@tonic-gate }
234211Smike_s (void) puts("\n\n");
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate
237211Smike_s (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n",
2380Sstevel@tonic-gate "", "", "", "", "called", "total", "parents");
239211Smike_s (void) printf("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n",
2400Sstevel@tonic-gate "index", "%time", "self", "descendents",
2410Sstevel@tonic-gate "called", "self", "name", "index");
242211Smike_s (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n",
2430Sstevel@tonic-gate "", "", "", "", "called", "total", "children");
244211Smike_s (void) printf("\n");
2450Sstevel@tonic-gate }
2460Sstevel@tonic-gate
2470Sstevel@tonic-gate void
gprofline(nltype * np)2480Sstevel@tonic-gate gprofline(nltype *np)
2490Sstevel@tonic-gate {
2500Sstevel@tonic-gate char kirkbuffer[BUFSIZ];
2510Sstevel@tonic-gate
252211Smike_s (void) sprintf(kirkbuffer, "[%d]", np->index);
253211Smike_s (void) printf("%-6.6s %5.1f %7.2f %11.2f", kirkbuffer,
2540Sstevel@tonic-gate 100 * (np->propself + np->propchild) / printtime,
2550Sstevel@tonic-gate np->propself / hz, np->propchild / hz);
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate if ((np->ncall + np->selfcalls) != 0) {
258211Smike_s (void) printf(" %7lld", np->ncall);
2590Sstevel@tonic-gate
2600Sstevel@tonic-gate if (np->selfcalls != 0)
261211Smike_s (void) printf("+%-7lld ", np->selfcalls);
2620Sstevel@tonic-gate else
263211Smike_s (void) printf(" %7.7s ", "");
2640Sstevel@tonic-gate } else {
265211Smike_s (void) printf(" %7.7s %7.7s ", "", "");
2660Sstevel@tonic-gate }
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate printname(np);
2690Sstevel@tonic-gate
2700Sstevel@tonic-gate if (Cflag)
2710Sstevel@tonic-gate print_demangled_name(50, np);
2720Sstevel@tonic-gate
273211Smike_s (void) printf("\n");
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate static bool
is_special_sym(nltype * nlp)2770Sstevel@tonic-gate is_special_sym(nltype *nlp)
2780Sstevel@tonic-gate {
2790Sstevel@tonic-gate int i;
2800Sstevel@tonic-gate
2810Sstevel@tonic-gate if (nlp->name == NULL)
2820Sstevel@tonic-gate return (FALSE);
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate for (i = 0; splsym[i]; i++)
2850Sstevel@tonic-gate if (strcmp(splsym[i], nlp->name) == 0)
2860Sstevel@tonic-gate return (TRUE);
2870Sstevel@tonic-gate
2880Sstevel@tonic-gate return (FALSE);
2890Sstevel@tonic-gate }
2900Sstevel@tonic-gate
2910Sstevel@tonic-gate void
printgprof(nltype ** timesortnlp)2920Sstevel@tonic-gate printgprof(nltype **timesortnlp)
2930Sstevel@tonic-gate {
2940Sstevel@tonic-gate int index;
2950Sstevel@tonic-gate nltype *parentp;
2960Sstevel@tonic-gate int print_count = number_funcs_toprint;
2970Sstevel@tonic-gate bool count_flag = TRUE;
2980Sstevel@tonic-gate
2990Sstevel@tonic-gate /*
3000Sstevel@tonic-gate * Print out the structured profiling list
3010Sstevel@tonic-gate */
3020Sstevel@tonic-gate gprofheader();
3030Sstevel@tonic-gate
3040Sstevel@tonic-gate for (index = 0; index < total_names + ncycle && count_flag; index++) {
3050Sstevel@tonic-gate parentp = timesortnlp[index];
3060Sstevel@tonic-gate if (zflag == 0 && parentp->ncall == 0 &&
3070Sstevel@tonic-gate parentp->selfcalls == 0 && parentp->propself == 0 &&
3080Sstevel@tonic-gate parentp -> propchild == 0)
3090Sstevel@tonic-gate continue;
3100Sstevel@tonic-gate
3110Sstevel@tonic-gate if (!parentp->printflag)
3120Sstevel@tonic-gate continue;
3130Sstevel@tonic-gate
3140Sstevel@tonic-gate /*
3150Sstevel@tonic-gate * Do not print certain special symbols, like PRF_EXTSYM, etc.
3160Sstevel@tonic-gate * even if zflag was on.
3170Sstevel@tonic-gate */
3180Sstevel@tonic-gate if (is_special_sym(parentp))
3190Sstevel@tonic-gate continue;
3200Sstevel@tonic-gate
3210Sstevel@tonic-gate if (parentp->name == 0 && parentp->cycleno != 0) {
3220Sstevel@tonic-gate /*
3230Sstevel@tonic-gate * cycle header
3240Sstevel@tonic-gate */
3250Sstevel@tonic-gate printcycle(parentp);
3260Sstevel@tonic-gate printmembers(parentp);
3270Sstevel@tonic-gate } else {
3280Sstevel@tonic-gate printparents(parentp);
3290Sstevel@tonic-gate gprofline(parentp);
3300Sstevel@tonic-gate printchildren(parentp);
3310Sstevel@tonic-gate }
3320Sstevel@tonic-gate
333211Smike_s (void) printf("\n");
334211Smike_s (void) printf(
335211Smike_s "-----------------------------------------------\n");
336211Smike_s (void) printf("\n");
3370Sstevel@tonic-gate
3380Sstevel@tonic-gate if (nflag) {
3390Sstevel@tonic-gate --print_count;
3400Sstevel@tonic-gate if (print_count == 0)
3410Sstevel@tonic-gate count_flag = FALSE;
3420Sstevel@tonic-gate }
3430Sstevel@tonic-gate }
3440Sstevel@tonic-gate free(timesortnlp);
3450Sstevel@tonic-gate }
3460Sstevel@tonic-gate
3470Sstevel@tonic-gate /*
3480Sstevel@tonic-gate * sort by decreasing propagated time
3490Sstevel@tonic-gate * if times are equal, but one is a cycle header,
3500Sstevel@tonic-gate * say that's first (e.g. less, i.e. -1).
3510Sstevel@tonic-gate * if one's name doesn't have an underscore and the other does,
3520Sstevel@tonic-gate * say the one is first.
3530Sstevel@tonic-gate * all else being equal, sort by names.
3540Sstevel@tonic-gate */
3550Sstevel@tonic-gate int
totalcmp(const void * arg1,const void * arg2)356211Smike_s totalcmp(const void *arg1, const void *arg2)
3570Sstevel@tonic-gate {
358211Smike_s nltype **npp1 = (nltype **)arg1;
359211Smike_s nltype **npp2 = (nltype **)arg2;
3600Sstevel@tonic-gate nltype *np1 = *npp1;
3610Sstevel@tonic-gate nltype *np2 = *npp2;
3620Sstevel@tonic-gate double diff;
3630Sstevel@tonic-gate
3640Sstevel@tonic-gate diff = (np1->propself + np1->propchild) -
3650Sstevel@tonic-gate (np2->propself + np2->propchild);
3660Sstevel@tonic-gate
3670Sstevel@tonic-gate if (diff < 0.0)
3680Sstevel@tonic-gate return (1);
3690Sstevel@tonic-gate if (diff > 0.0)
3700Sstevel@tonic-gate return (-1);
3710Sstevel@tonic-gate if (np1->name == 0 && np1->cycleno != 0)
3720Sstevel@tonic-gate return (-1);
3730Sstevel@tonic-gate if (np2->name == 0 && np2->cycleno != 0)
3740Sstevel@tonic-gate return (1);
3750Sstevel@tonic-gate if (np1->name == 0)
3760Sstevel@tonic-gate return (-1);
3770Sstevel@tonic-gate if (np2->name == 0)
3780Sstevel@tonic-gate return (1);
3790Sstevel@tonic-gate
3800Sstevel@tonic-gate if (*(np1->name) != '_' && *(np2->name) == '_')
3810Sstevel@tonic-gate return (-1);
3820Sstevel@tonic-gate if (*(np1->name) == '_' && *(np2->name) != '_')
3830Sstevel@tonic-gate return (1);
3840Sstevel@tonic-gate if (np1->ncall > np2->ncall)
3850Sstevel@tonic-gate return (-1);
3860Sstevel@tonic-gate if (np1->ncall < np2->ncall)
3870Sstevel@tonic-gate return (1);
3880Sstevel@tonic-gate return (strcmp(np1->name, np2->name));
3890Sstevel@tonic-gate }
3900Sstevel@tonic-gate
3910Sstevel@tonic-gate void
printparents(nltype * childp)3920Sstevel@tonic-gate printparents(nltype *childp)
3930Sstevel@tonic-gate {
3940Sstevel@tonic-gate nltype *parentp;
3950Sstevel@tonic-gate arctype *arcp;
3960Sstevel@tonic-gate nltype *cycleheadp;
3970Sstevel@tonic-gate
3980Sstevel@tonic-gate if (childp->cyclehead != 0)
3990Sstevel@tonic-gate cycleheadp = childp -> cyclehead;
4000Sstevel@tonic-gate else
4010Sstevel@tonic-gate cycleheadp = childp;
4020Sstevel@tonic-gate
4030Sstevel@tonic-gate if (childp->parents == 0) {
404211Smike_s (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s"
4050Sstevel@tonic-gate " <spontaneous>\n", "", "", "", "", "", "");
4060Sstevel@tonic-gate return;
4070Sstevel@tonic-gate }
4080Sstevel@tonic-gate
4090Sstevel@tonic-gate sortparents(childp);
4100Sstevel@tonic-gate
4110Sstevel@tonic-gate for (arcp = childp->parents; arcp; arcp = arcp->arc_parentlist) {
4120Sstevel@tonic-gate parentp = arcp -> arc_parentp;
4130Sstevel@tonic-gate if (childp == parentp || (childp->cycleno != 0 &&
4140Sstevel@tonic-gate parentp->cycleno == childp->cycleno)) {
4150Sstevel@tonic-gate /*
4160Sstevel@tonic-gate * selfcall or call among siblings
4170Sstevel@tonic-gate */
418211Smike_s (void) printf(
419211Smike_s "%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ",
4200Sstevel@tonic-gate "", "", "", "", arcp->arc_count, "");
4210Sstevel@tonic-gate printname(parentp);
4220Sstevel@tonic-gate
4230Sstevel@tonic-gate if (Cflag)
4240Sstevel@tonic-gate print_demangled_name(54, parentp);
4250Sstevel@tonic-gate
426211Smike_s (void) printf("\n");
4270Sstevel@tonic-gate } else {
4280Sstevel@tonic-gate /*
4290Sstevel@tonic-gate * regular parent of child
4300Sstevel@tonic-gate */
431211Smike_s (void) printf(
432211Smike_s "%6.6s %5.5s %7.2f %11.2f %7lld/%-7lld ", "",
4330Sstevel@tonic-gate "", arcp->arc_time / hz, arcp->arc_childtime / hz,
4340Sstevel@tonic-gate arcp->arc_count, cycleheadp->ncall);
4350Sstevel@tonic-gate printname(parentp);
4360Sstevel@tonic-gate
4370Sstevel@tonic-gate if (Cflag)
4380Sstevel@tonic-gate print_demangled_name(54, parentp);
4390Sstevel@tonic-gate
440211Smike_s (void) printf("\n");
4410Sstevel@tonic-gate }
4420Sstevel@tonic-gate }
4430Sstevel@tonic-gate }
4440Sstevel@tonic-gate
4450Sstevel@tonic-gate void
printchildren(nltype * parentp)4460Sstevel@tonic-gate printchildren(nltype *parentp)
4470Sstevel@tonic-gate {
4480Sstevel@tonic-gate nltype *childp;
4490Sstevel@tonic-gate arctype *arcp;
4500Sstevel@tonic-gate
4510Sstevel@tonic-gate sortchildren(parentp);
4520Sstevel@tonic-gate
4530Sstevel@tonic-gate for (arcp = parentp->children; arcp; arcp = arcp->arc_childlist) {
4540Sstevel@tonic-gate childp = arcp->arc_childp;
4550Sstevel@tonic-gate if (childp == parentp || (childp->cycleno != 0 &&
4560Sstevel@tonic-gate childp->cycleno == parentp->cycleno)) {
4570Sstevel@tonic-gate /*
4580Sstevel@tonic-gate * self call or call to sibling
4590Sstevel@tonic-gate */
460211Smike_s (void) printf(
461211Smike_s "%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ",
4620Sstevel@tonic-gate "", "", "", "", arcp->arc_count, "");
4630Sstevel@tonic-gate printname(childp);
4640Sstevel@tonic-gate
4650Sstevel@tonic-gate if (Cflag)
4660Sstevel@tonic-gate print_demangled_name(54, childp);
4670Sstevel@tonic-gate
468211Smike_s (void) printf("\n");
4690Sstevel@tonic-gate } else {
4700Sstevel@tonic-gate /*
4710Sstevel@tonic-gate * regular child of parent
4720Sstevel@tonic-gate */
4730Sstevel@tonic-gate if (childp->cyclehead)
474211Smike_s (void) printf("%6.6s %5.5s %7.2f %11.2f "
4750Sstevel@tonic-gate "%7lld/%-7lld ", "", "",
4760Sstevel@tonic-gate arcp->arc_time / hz,
4770Sstevel@tonic-gate arcp->arc_childtime / hz, arcp->arc_count,
4780Sstevel@tonic-gate childp->cyclehead->ncall);
4790Sstevel@tonic-gate else
480211Smike_s (void) printf("%6.6s %5.5s %7.2f %11.2f "
4810Sstevel@tonic-gate "%7lld %7.7s ",
4820Sstevel@tonic-gate "", "", arcp->arc_time / hz,
4830Sstevel@tonic-gate arcp->arc_childtime / hz, arcp->arc_count,
4840Sstevel@tonic-gate "");
4850Sstevel@tonic-gate
4860Sstevel@tonic-gate printname(childp);
4870Sstevel@tonic-gate
4880Sstevel@tonic-gate if (Cflag)
4890Sstevel@tonic-gate print_demangled_name(54, childp);
4900Sstevel@tonic-gate
491211Smike_s (void) printf("\n");
4920Sstevel@tonic-gate }
4930Sstevel@tonic-gate }
4940Sstevel@tonic-gate }
4950Sstevel@tonic-gate
4960Sstevel@tonic-gate void
printname(nltype * selfp)4970Sstevel@tonic-gate printname(nltype *selfp)
4980Sstevel@tonic-gate {
499*7008Sab196087 const char *c;
5000Sstevel@tonic-gate c = demangled_name(selfp);
5010Sstevel@tonic-gate
5020Sstevel@tonic-gate if (selfp->name != 0) {
5030Sstevel@tonic-gate if (!Cflag)
504211Smike_s (void) printf("%s", selfp->name);
5050Sstevel@tonic-gate else
506211Smike_s (void) printf("%s", c);
5070Sstevel@tonic-gate
5080Sstevel@tonic-gate #ifdef DEBUG
5090Sstevel@tonic-gate if (debug & DFNDEBUG)
510211Smike_s (void) printf("{%d} ", selfp->toporder);
5110Sstevel@tonic-gate
5120Sstevel@tonic-gate if (debug & PROPDEBUG)
513211Smike_s (void) printf("%5.2f%% ", selfp->propfraction);
514211Smike_s #endif /* DEBUG */
5150Sstevel@tonic-gate }
5160Sstevel@tonic-gate
5170Sstevel@tonic-gate if (selfp->cycleno != 0)
518211Smike_s (void) printf("\t<cycle %d>", selfp->cycleno);
5190Sstevel@tonic-gate
5200Sstevel@tonic-gate if (selfp->index != 0) {
5210Sstevel@tonic-gate if (selfp->printflag)
522211Smike_s (void) printf(" [%d]", selfp->index);
5230Sstevel@tonic-gate else
524211Smike_s (void) printf(" (%d)", selfp->index);
5250Sstevel@tonic-gate }
5260Sstevel@tonic-gate }
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate void
print_demangled_name(int n,nltype * selfp)5290Sstevel@tonic-gate print_demangled_name(int n, nltype *selfp)
5300Sstevel@tonic-gate {
5310Sstevel@tonic-gate char *c;
5320Sstevel@tonic-gate int i;
5330Sstevel@tonic-gate
5340Sstevel@tonic-gate c = selfp->name;
5350Sstevel@tonic-gate
5360Sstevel@tonic-gate if (strcmp(c, demangled_name(selfp)) == 0)
5370Sstevel@tonic-gate return;
5380Sstevel@tonic-gate else {
539211Smike_s (void) printf("\n");
5400Sstevel@tonic-gate for (i = 1; i < n; i++)
541211Smike_s (void) printf(" ");
542211Smike_s (void) printf("[%s]", selfp->name);
5430Sstevel@tonic-gate }
5440Sstevel@tonic-gate }
5450Sstevel@tonic-gate
5460Sstevel@tonic-gate void
sortchildren(nltype * parentp)5470Sstevel@tonic-gate sortchildren(nltype *parentp)
5480Sstevel@tonic-gate {
5490Sstevel@tonic-gate arctype *arcp;
5500Sstevel@tonic-gate arctype *detachedp;
5510Sstevel@tonic-gate arctype sorted;
5520Sstevel@tonic-gate arctype *prevp;
5530Sstevel@tonic-gate
5540Sstevel@tonic-gate /*
5550Sstevel@tonic-gate * unlink children from parent,
5560Sstevel@tonic-gate * then insertion sort back on to sorted's children.
5570Sstevel@tonic-gate * *arcp the arc you have detached and are inserting.
5580Sstevel@tonic-gate * *detachedp the rest of the arcs to be sorted.
5590Sstevel@tonic-gate * sorted arc list onto which you insertion sort.
5600Sstevel@tonic-gate * *prevp arc before the arc you are comparing.
5610Sstevel@tonic-gate */
5620Sstevel@tonic-gate sorted.arc_childlist = 0;
5630Sstevel@tonic-gate
564211Smike_s /* LINTED: warning: assignment operator */
5650Sstevel@tonic-gate for ((arcp = parentp->children) && (detachedp = arcp->arc_childlist);
5660Sstevel@tonic-gate arcp;
567211Smike_s /* LINTED: warning: assignment operator */
5680Sstevel@tonic-gate (arcp = detachedp) && (detachedp = detachedp->arc_childlist)) {
5690Sstevel@tonic-gate /*
5700Sstevel@tonic-gate * consider *arcp as disconnected
5710Sstevel@tonic-gate * insert it into sorted
5720Sstevel@tonic-gate */
5730Sstevel@tonic-gate for (prevp = &sorted; prevp->arc_childlist;
5740Sstevel@tonic-gate prevp = prevp->arc_childlist) {
5750Sstevel@tonic-gate if (arccmp(arcp, prevp->arc_childlist) != LESSTHAN)
5760Sstevel@tonic-gate break;
5770Sstevel@tonic-gate }
5780Sstevel@tonic-gate
5790Sstevel@tonic-gate arcp->arc_childlist = prevp->arc_childlist;
5800Sstevel@tonic-gate prevp->arc_childlist = arcp;
5810Sstevel@tonic-gate }
5820Sstevel@tonic-gate
5830Sstevel@tonic-gate /*
5840Sstevel@tonic-gate * reattach sorted children to parent
5850Sstevel@tonic-gate */
5860Sstevel@tonic-gate parentp->children = sorted.arc_childlist;
5870Sstevel@tonic-gate }
5880Sstevel@tonic-gate
5890Sstevel@tonic-gate void
sortparents(nltype * childp)5900Sstevel@tonic-gate sortparents(nltype *childp)
5910Sstevel@tonic-gate {
5920Sstevel@tonic-gate arctype *arcp;
5930Sstevel@tonic-gate arctype *detachedp;
5940Sstevel@tonic-gate arctype sorted;
5950Sstevel@tonic-gate arctype *prevp;
5960Sstevel@tonic-gate
5970Sstevel@tonic-gate /*
5980Sstevel@tonic-gate * unlink parents from child,
5990Sstevel@tonic-gate * then insertion sort back on to sorted's parents.
6000Sstevel@tonic-gate * *arcp the arc you have detached and are inserting.
6010Sstevel@tonic-gate * *detachedp the rest of the arcs to be sorted.
6020Sstevel@tonic-gate * sorted arc list onto which you insertion sort.
6030Sstevel@tonic-gate * *prevp arc before the arc you are comparing.
6040Sstevel@tonic-gate */
6050Sstevel@tonic-gate sorted.arc_parentlist = 0;
6060Sstevel@tonic-gate
607211Smike_s /* LINTED: warning: assignment operator */
6080Sstevel@tonic-gate for ((arcp = childp->parents) && (detachedp = arcp->arc_parentlist);
6090Sstevel@tonic-gate arcp;
610211Smike_s /* LINTED: warning: assignment operator */
6110Sstevel@tonic-gate (arcp = detachedp) && (detachedp = detachedp->arc_parentlist)) {
6120Sstevel@tonic-gate /*
6130Sstevel@tonic-gate * consider *arcp as disconnected
6140Sstevel@tonic-gate * insert it into sorted
6150Sstevel@tonic-gate */
6160Sstevel@tonic-gate for (prevp = &sorted; prevp->arc_parentlist;
6170Sstevel@tonic-gate prevp = prevp->arc_parentlist) {
6180Sstevel@tonic-gate if (arccmp(arcp, prevp->arc_parentlist) != GREATERTHAN)
6190Sstevel@tonic-gate break;
6200Sstevel@tonic-gate }
6210Sstevel@tonic-gate arcp->arc_parentlist = prevp->arc_parentlist;
6220Sstevel@tonic-gate prevp->arc_parentlist = arcp;
6230Sstevel@tonic-gate }
6240Sstevel@tonic-gate
6250Sstevel@tonic-gate /*
6260Sstevel@tonic-gate * reattach sorted arcs to child
6270Sstevel@tonic-gate */
6280Sstevel@tonic-gate childp->parents = sorted.arc_parentlist;
6290Sstevel@tonic-gate }
6300Sstevel@tonic-gate
6310Sstevel@tonic-gate void
printcycle(nltype * cyclep)6320Sstevel@tonic-gate printcycle(nltype *cyclep)
6330Sstevel@tonic-gate {
6340Sstevel@tonic-gate char kirkbuffer[BUFSIZ];
6350Sstevel@tonic-gate
636211Smike_s (void) sprintf(kirkbuffer, "[%d]", cyclep->index);
637211Smike_s (void) printf("%-6.6s %5.1f %7.2f %11.2f %7lld", kirkbuffer,
6380Sstevel@tonic-gate 100 * (cyclep->propself + cyclep->propchild) / printtime,
6390Sstevel@tonic-gate cyclep -> propself / hz, cyclep -> propchild / hz,
6400Sstevel@tonic-gate cyclep -> ncall);
6410Sstevel@tonic-gate
6420Sstevel@tonic-gate if (cyclep->selfcalls != 0)
643211Smike_s (void) printf("+%-7lld", cyclep->selfcalls);
6440Sstevel@tonic-gate else
645211Smike_s (void) printf(" %7.7s", "");
6460Sstevel@tonic-gate
647211Smike_s (void) printf(" <cycle %d as a whole>\t[%d]\n", cyclep->cycleno,
6480Sstevel@tonic-gate cyclep->index);
6490Sstevel@tonic-gate }
6500Sstevel@tonic-gate
6510Sstevel@tonic-gate /*
6520Sstevel@tonic-gate * print the members of a cycle
6530Sstevel@tonic-gate */
6540Sstevel@tonic-gate void
printmembers(nltype * cyclep)6550Sstevel@tonic-gate printmembers(nltype *cyclep)
6560Sstevel@tonic-gate {
6570Sstevel@tonic-gate nltype *memberp;
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate sortmembers(cyclep);
6600Sstevel@tonic-gate
6610Sstevel@tonic-gate for (memberp = cyclep->cnext; memberp; memberp = memberp->cnext) {
662211Smike_s (void) printf("%6.6s %5.5s %7.2f %11.2f %7lld", "", "",
6630Sstevel@tonic-gate memberp->propself / hz, memberp->propchild / hz,
6640Sstevel@tonic-gate memberp->ncall);
6650Sstevel@tonic-gate
6660Sstevel@tonic-gate if (memberp->selfcalls != 0)
667211Smike_s (void) printf("+%-7lld", memberp->selfcalls);
6680Sstevel@tonic-gate else
669211Smike_s (void) printf(" %7.7s", "");
6700Sstevel@tonic-gate
671211Smike_s (void) printf(" ");
6720Sstevel@tonic-gate printname(memberp);
6730Sstevel@tonic-gate if (Cflag)
6740Sstevel@tonic-gate print_demangled_name(54, memberp);
675211Smike_s (void) printf("\n");
6760Sstevel@tonic-gate }
6770Sstevel@tonic-gate }
6780Sstevel@tonic-gate
6790Sstevel@tonic-gate /*
6800Sstevel@tonic-gate * sort members of a cycle
6810Sstevel@tonic-gate */
6820Sstevel@tonic-gate void
sortmembers(nltype * cyclep)6830Sstevel@tonic-gate sortmembers(nltype *cyclep)
6840Sstevel@tonic-gate {
6850Sstevel@tonic-gate nltype *todo;
6860Sstevel@tonic-gate nltype *doing;
6870Sstevel@tonic-gate nltype *prev;
6880Sstevel@tonic-gate
6890Sstevel@tonic-gate /*
6900Sstevel@tonic-gate * detach cycle members from cyclehead,
6910Sstevel@tonic-gate * and insertion sort them back on.
6920Sstevel@tonic-gate */
6930Sstevel@tonic-gate todo = cyclep->cnext;
6940Sstevel@tonic-gate cyclep->cnext = 0;
6950Sstevel@tonic-gate
696211Smike_s /* LINTED: warning: assignment operator */
6970Sstevel@tonic-gate for ((doing = todo) && (todo = doing->cnext);
698211Smike_s doing;
699211Smike_s /* LINTED: warning: assignment operator */
700211Smike_s (doing = todo) && (todo = doing->cnext)) {
7010Sstevel@tonic-gate for (prev = cyclep; prev->cnext; prev = prev->cnext) {
7020Sstevel@tonic-gate if (membercmp(doing, prev->cnext) == GREATERTHAN)
7030Sstevel@tonic-gate break;
7040Sstevel@tonic-gate }
7050Sstevel@tonic-gate doing->cnext = prev->cnext;
7060Sstevel@tonic-gate prev->cnext = doing;
7070Sstevel@tonic-gate }
7080Sstevel@tonic-gate }
7090Sstevel@tonic-gate
7100Sstevel@tonic-gate /*
7110Sstevel@tonic-gate * major sort is on propself + propchild,
7120Sstevel@tonic-gate * next is sort on ncalls + selfcalls.
7130Sstevel@tonic-gate */
7140Sstevel@tonic-gate int
membercmp(nltype * this,nltype * that)7150Sstevel@tonic-gate membercmp(nltype *this, nltype *that)
7160Sstevel@tonic-gate {
7170Sstevel@tonic-gate double thistime = this->propself + this->propchild;
7180Sstevel@tonic-gate double thattime = that->propself + that->propchild;
7190Sstevel@tonic-gate actype thiscalls = this->ncall + this->selfcalls;
7200Sstevel@tonic-gate actype thatcalls = that->ncall + that->selfcalls;
7210Sstevel@tonic-gate
7220Sstevel@tonic-gate if (thistime > thattime)
7230Sstevel@tonic-gate return (GREATERTHAN);
7240Sstevel@tonic-gate
7250Sstevel@tonic-gate if (thistime < thattime)
7260Sstevel@tonic-gate return (LESSTHAN);
7270Sstevel@tonic-gate
7280Sstevel@tonic-gate if (thiscalls > thatcalls)
7290Sstevel@tonic-gate return (GREATERTHAN);
7300Sstevel@tonic-gate
7310Sstevel@tonic-gate if (thiscalls < thatcalls)
7320Sstevel@tonic-gate return (LESSTHAN);
7330Sstevel@tonic-gate
7340Sstevel@tonic-gate return (EQUALTO);
7350Sstevel@tonic-gate }
7360Sstevel@tonic-gate
7370Sstevel@tonic-gate /*
7380Sstevel@tonic-gate * compare two arcs to/from the same child/parent.
7390Sstevel@tonic-gate * - if one arc is a self arc, it's least.
7400Sstevel@tonic-gate * - if one arc is within a cycle, it's less than.
7410Sstevel@tonic-gate * - if both arcs are within a cycle, compare arc counts.
7420Sstevel@tonic-gate * - if neither arc is within a cycle, compare with
7430Sstevel@tonic-gate * arc_time + arc_childtime as major key
7440Sstevel@tonic-gate * arc count as minor key
7450Sstevel@tonic-gate */
7460Sstevel@tonic-gate int
arccmp(arctype * thisp,arctype * thatp)7470Sstevel@tonic-gate arccmp(arctype *thisp, arctype *thatp)
7480Sstevel@tonic-gate {
7490Sstevel@tonic-gate nltype *thisparentp = thisp->arc_parentp;
7500Sstevel@tonic-gate nltype *thischildp = thisp->arc_childp;
7510Sstevel@tonic-gate nltype *thatparentp = thatp->arc_parentp;
7520Sstevel@tonic-gate nltype *thatchildp = thatp->arc_childp;
7530Sstevel@tonic-gate double thistime;
7540Sstevel@tonic-gate double thattime;
7550Sstevel@tonic-gate
7560Sstevel@tonic-gate #ifdef DEBUG
7570Sstevel@tonic-gate if (debug & TIMEDEBUG) {
758211Smike_s (void) printf("[arccmp] ");
7590Sstevel@tonic-gate printname(thisparentp);
760211Smike_s (void) printf(" calls ");
7610Sstevel@tonic-gate printname(thischildp);
762211Smike_s (void) printf(" %f + %f %lld/%lld\n", thisp->arc_time,
7630Sstevel@tonic-gate thisp->arc_childtime, thisp->arc_count,
7640Sstevel@tonic-gate thischildp->ncall);
765211Smike_s (void) printf("[arccmp] ");
7660Sstevel@tonic-gate printname(thatparentp);
767211Smike_s (void) printf(" calls ");
7680Sstevel@tonic-gate printname(thatchildp);
769211Smike_s (void) printf(" %f + %f %lld/%lld\n", thatp->arc_time,
7700Sstevel@tonic-gate thatp->arc_childtime, thatp->arc_count,
7710Sstevel@tonic-gate thatchildp->ncall);
772211Smike_s (void) printf("\n");
7730Sstevel@tonic-gate }
774211Smike_s #endif /* DEBUG */
7750Sstevel@tonic-gate
7760Sstevel@tonic-gate if (thisparentp == thischildp) {
7770Sstevel@tonic-gate /*
7780Sstevel@tonic-gate * this is a self call
7790Sstevel@tonic-gate */
7800Sstevel@tonic-gate return (LESSTHAN);
7810Sstevel@tonic-gate }
7820Sstevel@tonic-gate
7830Sstevel@tonic-gate if (thatparentp == thatchildp) {
7840Sstevel@tonic-gate /*
7850Sstevel@tonic-gate * that is a self call
7860Sstevel@tonic-gate */
7870Sstevel@tonic-gate return (GREATERTHAN);
7880Sstevel@tonic-gate }
7890Sstevel@tonic-gate
7900Sstevel@tonic-gate if (thisparentp->cycleno != 0 && thischildp->cycleno != 0 &&
7910Sstevel@tonic-gate thisparentp->cycleno == thischildp->cycleno) {
7920Sstevel@tonic-gate /*
7930Sstevel@tonic-gate * this is a call within a cycle
7940Sstevel@tonic-gate */
7950Sstevel@tonic-gate if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 &&
7960Sstevel@tonic-gate thatparentp->cycleno == thatchildp->cycleno) {
7970Sstevel@tonic-gate /*
7980Sstevel@tonic-gate * that is a call within the cycle, too
7990Sstevel@tonic-gate */
8000Sstevel@tonic-gate if (thisp->arc_count < thatp->arc_count)
8010Sstevel@tonic-gate return (LESSTHAN);
8020Sstevel@tonic-gate
8030Sstevel@tonic-gate if (thisp->arc_count > thatp->arc_count)
8040Sstevel@tonic-gate return (GREATERTHAN);
8050Sstevel@tonic-gate
8060Sstevel@tonic-gate return (EQUALTO);
8070Sstevel@tonic-gate } else {
8080Sstevel@tonic-gate /*
8090Sstevel@tonic-gate * that isn't a call within the cycle
8100Sstevel@tonic-gate */
8110Sstevel@tonic-gate return (LESSTHAN);
8120Sstevel@tonic-gate }
8130Sstevel@tonic-gate } else {
8140Sstevel@tonic-gate /*
8150Sstevel@tonic-gate * this isn't a call within a cycle
8160Sstevel@tonic-gate */
8170Sstevel@tonic-gate if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 &&
8180Sstevel@tonic-gate thatparentp->cycleno == thatchildp->cycleno) {
8190Sstevel@tonic-gate /*
8200Sstevel@tonic-gate * that is a call within a cycle
8210Sstevel@tonic-gate */
8220Sstevel@tonic-gate return (GREATERTHAN);
8230Sstevel@tonic-gate } else {
8240Sstevel@tonic-gate /*
8250Sstevel@tonic-gate * neither is a call within a cycle
8260Sstevel@tonic-gate */
8270Sstevel@tonic-gate thistime = thisp->arc_time + thisp->arc_childtime;
8280Sstevel@tonic-gate thattime = thatp->arc_time + thatp->arc_childtime;
8290Sstevel@tonic-gate
8300Sstevel@tonic-gate if (thistime < thattime)
8310Sstevel@tonic-gate return (LESSTHAN);
8320Sstevel@tonic-gate
8330Sstevel@tonic-gate if (thistime > thattime)
8340Sstevel@tonic-gate return (GREATERTHAN);
8350Sstevel@tonic-gate
8360Sstevel@tonic-gate if (thisp->arc_count < thatp->arc_count)
8370Sstevel@tonic-gate return (LESSTHAN);
8380Sstevel@tonic-gate
8390Sstevel@tonic-gate if (thisp->arc_count > thatp->arc_count)
8400Sstevel@tonic-gate return (GREATERTHAN);
8410Sstevel@tonic-gate
8420Sstevel@tonic-gate return (EQUALTO);
8430Sstevel@tonic-gate }
8440Sstevel@tonic-gate }
8450Sstevel@tonic-gate }
8460Sstevel@tonic-gate
8470Sstevel@tonic-gate void
printblurb(char * blurbname)8480Sstevel@tonic-gate printblurb(char *blurbname)
8490Sstevel@tonic-gate {
8500Sstevel@tonic-gate FILE *blurbfile;
8510Sstevel@tonic-gate int input;
8520Sstevel@tonic-gate
8534538Sdamico blurbfile = fopen(blurbname, "r");
8540Sstevel@tonic-gate if (blurbfile == NULL) {
8554538Sdamico perror(blurbname);
8560Sstevel@tonic-gate return;
8570Sstevel@tonic-gate }
8580Sstevel@tonic-gate
8590Sstevel@tonic-gate while ((input = getc(blurbfile)) != EOF)
860211Smike_s (void) putchar(input);
8610Sstevel@tonic-gate
862211Smike_s (void) fclose(blurbfile);
8630Sstevel@tonic-gate }
8640Sstevel@tonic-gate
8650Sstevel@tonic-gate char *s1, *s2;
8660Sstevel@tonic-gate
867211Smike_s static int
namecmp(const void * arg1,const void * arg2)868211Smike_s namecmp(const void *arg1, const void *arg2)
8690Sstevel@tonic-gate {
870211Smike_s nltype **npp1 = (nltype **)arg1;
871211Smike_s nltype **npp2 = (nltype **)arg2;
872211Smike_s
8730Sstevel@tonic-gate if (!Cflag)
8740Sstevel@tonic-gate return (strcmp((*npp1)->name, (*npp2)->name));
8750Sstevel@tonic-gate else {
8760Sstevel@tonic-gate striped_name(s1, npp1);
8770Sstevel@tonic-gate striped_name(s2, npp2);
8780Sstevel@tonic-gate return (strcmp(s1, s2));
8790Sstevel@tonic-gate }
8800Sstevel@tonic-gate }
8810Sstevel@tonic-gate
8820Sstevel@tonic-gate void
striped_name(char * s,nltype ** npp)8830Sstevel@tonic-gate striped_name(char *s, nltype **npp)
8840Sstevel@tonic-gate {
885*7008Sab196087 const char *d;
886*7008Sab196087 char *c;
8870Sstevel@tonic-gate
8880Sstevel@tonic-gate c = (char *)s;
8890Sstevel@tonic-gate d = demangled_name(*npp);
8900Sstevel@tonic-gate
8910Sstevel@tonic-gate while ((*d != '(') && (*d != '\0')) {
8920Sstevel@tonic-gate if (*d != ':')
8930Sstevel@tonic-gate *c++ = *d++;
8940Sstevel@tonic-gate else
8950Sstevel@tonic-gate d++;
8960Sstevel@tonic-gate }
8970Sstevel@tonic-gate *c = '\0';
8980Sstevel@tonic-gate }
8990Sstevel@tonic-gate
9000Sstevel@tonic-gate /*
9010Sstevel@tonic-gate * Checks if the current symbol name is the same as its neighbour and
9020Sstevel@tonic-gate * returns TRUE if it is.
9030Sstevel@tonic-gate */
9040Sstevel@tonic-gate static bool
does_clash(nltype ** nlp,int ndx,int nnames)9050Sstevel@tonic-gate does_clash(nltype **nlp, int ndx, int nnames)
9060Sstevel@tonic-gate {
9070Sstevel@tonic-gate /*
9080Sstevel@tonic-gate * same as previous (if there's one) ?
9090Sstevel@tonic-gate */
9100Sstevel@tonic-gate if (ndx && (strcmp(nlp[ndx]->name, nlp[ndx-1]->name) == 0))
9110Sstevel@tonic-gate return (TRUE);
9120Sstevel@tonic-gate
9130Sstevel@tonic-gate /*
9140Sstevel@tonic-gate * same as next (if there's one) ?
9150Sstevel@tonic-gate */
9160Sstevel@tonic-gate if ((ndx < (nnames - 1)) &&
9174538Sdamico (strcmp(nlp[ndx]->name, nlp[ndx+1]->name) == 0)) {
9180Sstevel@tonic-gate return (TRUE);
9190Sstevel@tonic-gate }
9200Sstevel@tonic-gate
9210Sstevel@tonic-gate return (FALSE);
9220Sstevel@tonic-gate }
9230Sstevel@tonic-gate
9240Sstevel@tonic-gate void
printmodules()9250Sstevel@tonic-gate printmodules()
9260Sstevel@tonic-gate {
9270Sstevel@tonic-gate mod_info_t *mi;
9280Sstevel@tonic-gate
929211Smike_s (void) printf("\f\nObject modules\n\n");
9300Sstevel@tonic-gate for (mi = &modules; mi; mi = mi->next)
931211Smike_s (void) printf(" %d: %s\n", mi->id, mi->name);
9320Sstevel@tonic-gate }
9330Sstevel@tonic-gate
9340Sstevel@tonic-gate #define IDFMT(id) ((id) < 10 ? 1 : 2)
9350Sstevel@tonic-gate #define NMFMT(id) ((id) < 10 ? 17 : 16)
9360Sstevel@tonic-gate
9370Sstevel@tonic-gate void
printindex()9380Sstevel@tonic-gate printindex()
9390Sstevel@tonic-gate {
9400Sstevel@tonic-gate nltype **namesortnlp;
9410Sstevel@tonic-gate nltype *nlp;
9420Sstevel@tonic-gate int index, nnames, todo, i, j;
9430Sstevel@tonic-gate char peterbuffer[BUFSIZ];
9440Sstevel@tonic-gate mod_info_t *mi;
9450Sstevel@tonic-gate
9460Sstevel@tonic-gate /*
9470Sstevel@tonic-gate * Now, sort regular function name alphabetically
9480Sstevel@tonic-gate * to create an index.
9490Sstevel@tonic-gate */
9500Sstevel@tonic-gate namesortnlp = calloc(total_names + ncycle, sizeof (nltype *));
9510Sstevel@tonic-gate
9520Sstevel@tonic-gate if (namesortnlp == NULL)
953211Smike_s (void) fprintf(stderr, "%s: ran out of memory for sorting\n",
954211Smike_s whoami);
9550Sstevel@tonic-gate
9560Sstevel@tonic-gate nnames = 0;
9570Sstevel@tonic-gate for (mi = &modules; mi; mi = mi->next) {
9580Sstevel@tonic-gate for (index = 0; index < mi->nname; index++) {
9590Sstevel@tonic-gate if (zflag == 0 && (mi->nl[index]).ncall == 0 &&
9604538Sdamico (mi->nl[index]).time == 0) {
9610Sstevel@tonic-gate continue;
9620Sstevel@tonic-gate }
9630Sstevel@tonic-gate
9640Sstevel@tonic-gate /*
9650Sstevel@tonic-gate * Do not print certain special symbols, like
9660Sstevel@tonic-gate * PRF_EXTSYM, etc. even if zflag was on.
9670Sstevel@tonic-gate */
9680Sstevel@tonic-gate if (is_special_sym(&(mi->nl[index])))
9690Sstevel@tonic-gate continue;
9700Sstevel@tonic-gate
9710Sstevel@tonic-gate namesortnlp[nnames++] = &(mi->nl[index]);
9720Sstevel@tonic-gate }
9730Sstevel@tonic-gate }
9740Sstevel@tonic-gate
9750Sstevel@tonic-gate if (Cflag) {
9760Sstevel@tonic-gate s1 = malloc(500 * sizeof (char));
9770Sstevel@tonic-gate s2 = malloc(500 * sizeof (char));
9780Sstevel@tonic-gate }
9790Sstevel@tonic-gate
980211Smike_s qsort(namesortnlp, nnames, sizeof (nltype *), namecmp);
9810Sstevel@tonic-gate
9820Sstevel@tonic-gate for (index = 1, todo = nnames; index <= ncycle; index++)
9830Sstevel@tonic-gate namesortnlp[todo++] = &cyclenl[index];
9840Sstevel@tonic-gate
985211Smike_s (void) printf("\f\nIndex by function name\n\n");
9860Sstevel@tonic-gate
9870Sstevel@tonic-gate if (!Cflag)
9880Sstevel@tonic-gate index = (todo + 2) / 3;
9890Sstevel@tonic-gate else
9900Sstevel@tonic-gate index = todo;
9910Sstevel@tonic-gate
9920Sstevel@tonic-gate for (i = 0; i < index; i++) {
9930Sstevel@tonic-gate if (!Cflag) {
9940Sstevel@tonic-gate for (j = i; j < todo; j += index) {
9950Sstevel@tonic-gate nlp = namesortnlp[j];
9960Sstevel@tonic-gate
9970Sstevel@tonic-gate if (nlp->printflag) {
998211Smike_s (void) sprintf(peterbuffer,
9990Sstevel@tonic-gate "[%d]", nlp->index);
10000Sstevel@tonic-gate } else {
1001211Smike_s (void) sprintf(peterbuffer,
10020Sstevel@tonic-gate "(%d)", nlp->index);
10030Sstevel@tonic-gate }
10040Sstevel@tonic-gate
10050Sstevel@tonic-gate if (j < nnames) {
10060Sstevel@tonic-gate if (does_clash(namesortnlp,
10074538Sdamico j, nnames)) {
1008211Smike_s (void) printf(
1009211Smike_s "%6.6s %*d:%-*.*s",
10104538Sdamico peterbuffer,
10114538Sdamico IDFMT(nlp->module->id),
10124538Sdamico nlp->module->id,
10134538Sdamico NMFMT(nlp->module->id),
10144538Sdamico NMFMT(nlp->module->id),
10154538Sdamico nlp->name);
10160Sstevel@tonic-gate } else {
10174538Sdamico (void) printf("%6.6s %-19.19s",
10184538Sdamico peterbuffer, nlp->name);
10190Sstevel@tonic-gate }
10200Sstevel@tonic-gate } else {
1021211Smike_s (void) printf("%6.6s ", peterbuffer);
1022211Smike_s (void) sprintf(peterbuffer,
10230Sstevel@tonic-gate "<cycle %d>", nlp->cycleno);
1024211Smike_s (void) printf("%-19.19s", peterbuffer);
10250Sstevel@tonic-gate }
10260Sstevel@tonic-gate }
10270Sstevel@tonic-gate } else {
10280Sstevel@tonic-gate nlp = namesortnlp[i];
10290Sstevel@tonic-gate
10300Sstevel@tonic-gate if (nlp->printflag)
1031211Smike_s (void) sprintf(peterbuffer, "[%d]", nlp->index);
10320Sstevel@tonic-gate else
1033211Smike_s (void) sprintf(peterbuffer, "(%d)", nlp->index);
10340Sstevel@tonic-gate
10350Sstevel@tonic-gate if (i < nnames) {
1036*7008Sab196087 const char *d = demangled_name(nlp);
10370Sstevel@tonic-gate
10380Sstevel@tonic-gate if (does_clash(namesortnlp, i, nnames)) {
1039211Smike_s (void) printf("%6.6s %d:%s\n",
1040211Smike_s peterbuffer, nlp->module->id, d);
10410Sstevel@tonic-gate } else
1042211Smike_s (void) printf("%6.6s %s\n", peterbuffer,
1043211Smike_s d);
10440Sstevel@tonic-gate
10450Sstevel@tonic-gate if (d != nlp->name)
1046211Smike_s (void) printf("%6.6s [%s]", "",
1047211Smike_s nlp->name);
10480Sstevel@tonic-gate } else {
1049211Smike_s (void) printf("%6.6s ", peterbuffer);
1050211Smike_s (void) sprintf(peterbuffer, "<cycle %d>",
10510Sstevel@tonic-gate nlp->cycleno);
1052211Smike_s (void) printf("%-33.33s", peterbuffer);
10530Sstevel@tonic-gate }
10540Sstevel@tonic-gate }
1055211Smike_s (void) printf("\n");
10560Sstevel@tonic-gate }
10570Sstevel@tonic-gate free(namesortnlp);
10580Sstevel@tonic-gate }
1059