dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / sgs / gprof / common / printgprof.c
blobd02e9a3d9a73c3b199308b8a15c7a7aec0e963be
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <ctype.h>
30 #include <string.h>
31 #include <sys/param.h>
32 #include <stdlib.h>
33 #include "conv.h"
34 #include "gprof.h"
36 void print_demangled_name(int, nltype *);
37 void striped_name(char *, nltype **);
39 extern long hz;
42 * Symbols that must never be printed, no matter what.
44 char *splsym[] = {
45 PRF_ETEXT,
46 PRF_EXTSYM,
47 PRF_MEMTERM,
48 NULL
51 static bool is_special_sym(nltype *nlp);
53 const char *
54 demangled_name(nltype *selfp)
56 if (!Cflag)
57 return (selfp->name);
59 return (conv_demangle_name(selfp->name));
62 void
63 printprof(void)
65 nltype *np;
66 nltype **sortednlp;
67 int i, index;
68 int print_count = number_funcs_toprint;
69 bool print_flag = TRUE;
70 mod_info_t *mi;
72 actime = 0.0;
73 (void) printf("\f\n");
74 flatprofheader();
77 * Sort the symbol table in by time
79 sortednlp = (nltype **) calloc(total_names, sizeof (nltype *));
80 if (sortednlp == (nltype **) 0) {
81 (void) fprintf(stderr,
82 "[printprof] ran out of memory for time sorting\n");
85 index = 0;
86 for (mi = &modules; mi; mi = mi->next) {
87 for (i = 0; i < mi->nname; i++)
88 sortednlp[index++] = &(mi->nl[i]);
91 qsort(sortednlp, total_names, sizeof (nltype *), timecmp);
93 for (index = 0; (index < total_names) && print_flag; index += 1) {
94 np = sortednlp[index];
95 flatprofline(np);
96 if (nflag) {
97 if (--print_count == 0)
98 print_flag = FALSE;
101 actime = 0.0;
102 free(sortednlp);
106 timecmp(const void *arg1, const void *arg2)
108 nltype **npp1 = (nltype **)arg1;
109 nltype **npp2 = (nltype **)arg2;
110 double timediff;
111 long calldiff;
113 timediff = (*npp2)->time - (*npp1)->time;
115 if (timediff > 0.0)
116 return (1);
118 if (timediff < 0.0)
119 return (-1);
121 calldiff = (*npp2)->ncall - (*npp1)->ncall;
123 if (calldiff > 0)
124 return (1);
126 if (calldiff < 0)
127 return (-1);
129 return (strcmp((*npp1)->name, (*npp2)->name));
133 * header for flatprofline
135 void
136 flatprofheader()
139 if (bflag)
140 printblurb(FLAT_BLURB);
142 if (old_style) {
143 (void) printf(
144 "\ngranularity: each sample hit covers %d byte(s)",
145 (long)scale * sizeof (UNIT));
146 if (totime > 0.0) {
147 (void) printf(" for %.2f%% of %.2f seconds\n\n",
148 100.0/totime, totime / hz);
149 } else {
150 (void) printf(" no time accumulated\n\n");
152 * this doesn't hurt since all the numerators will
153 * be zero.
155 totime = 1.0;
159 (void) printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
160 "% ", "cumulative", "self ", "", "self ", "total ", "");
161 (void) printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
162 "time", "seconds ", "seconds", "calls",
163 "ms/call", "ms/call", "name");
166 void
167 flatprofline(nltype *np)
169 if (zflag == 0 && np->ncall == 0 && np->time == 0)
170 return;
173 * Do not print certain special symbols, like PRF_EXTSYM, etc.
174 * even if zflag was on.
176 if (is_special_sym(np))
177 return;
179 actime += np->time;
181 (void) printf("%5.1f %10.2f %8.2f",
182 100 * np->time / totime, actime / hz, np->time / hz);
184 if (np->ncall != 0) {
185 (void) printf(" %8lld %8.2f %8.2f ", np->ncall,
186 1000 * np->time / hz / np->ncall,
187 1000 * (np->time + np->childtime) / hz / np->ncall);
188 } else {
189 if (!Cflag)
190 (void) printf(" %8.8s %8.8s %8.8s ", "", "", "");
191 else
192 (void) printf(" %8.8s %8.8s %8.8s ", "", "", "");
195 printname(np);
197 if (Cflag)
198 print_demangled_name(55, np);
200 (void) printf("\n");
203 void
204 gprofheader()
207 if (bflag)
208 printblurb(CALLG_BLURB);
210 if (old_style) {
212 (void) printf(
213 "\ngranularity: each sample hit covers %d byte(s)",
214 (long)scale * sizeof (UNIT));
216 if (printtime > 0.0) {
217 (void) printf(" for %.2f%% of %.2f seconds\n\n",
218 100.0/printtime, printtime / hz);
219 } else {
220 (void) printf(" no time propagated\n\n");
222 * this doesn't hurt, since all the numerators
223 * will be 0.0
225 printtime = 1.0;
227 } else {
228 (void) printf(
229 "\ngranularity: each pc-hit is considered 1 tick");
230 if (hz != 1) {
231 (void) printf(" (@ %4.3f seconds per tick)",
232 (double)1.0 / hz);
234 (void) puts("\n\n");
237 (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n",
238 "", "", "", "", "called", "total", "parents");
239 (void) printf("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n",
240 "index", "%time", "self", "descendents",
241 "called", "self", "name", "index");
242 (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n",
243 "", "", "", "", "called", "total", "children");
244 (void) printf("\n");
247 void
248 gprofline(nltype *np)
250 char kirkbuffer[BUFSIZ];
252 (void) sprintf(kirkbuffer, "[%d]", np->index);
253 (void) printf("%-6.6s %5.1f %7.2f %11.2f", kirkbuffer,
254 100 * (np->propself + np->propchild) / printtime,
255 np->propself / hz, np->propchild / hz);
257 if ((np->ncall + np->selfcalls) != 0) {
258 (void) printf(" %7lld", np->ncall);
260 if (np->selfcalls != 0)
261 (void) printf("+%-7lld ", np->selfcalls);
262 else
263 (void) printf(" %7.7s ", "");
264 } else {
265 (void) printf(" %7.7s %7.7s ", "", "");
268 printname(np);
270 if (Cflag)
271 print_demangled_name(50, np);
273 (void) printf("\n");
276 static bool
277 is_special_sym(nltype *nlp)
279 int i;
281 if (nlp->name == NULL)
282 return (FALSE);
284 for (i = 0; splsym[i]; i++)
285 if (strcmp(splsym[i], nlp->name) == 0)
286 return (TRUE);
288 return (FALSE);
291 void
292 printgprof(nltype **timesortnlp)
294 int index;
295 nltype *parentp;
296 int print_count = number_funcs_toprint;
297 bool count_flag = TRUE;
300 * Print out the structured profiling list
302 gprofheader();
304 for (index = 0; index < total_names + ncycle && count_flag; index++) {
305 parentp = timesortnlp[index];
306 if (zflag == 0 && parentp->ncall == 0 &&
307 parentp->selfcalls == 0 && parentp->propself == 0 &&
308 parentp -> propchild == 0)
309 continue;
311 if (!parentp->printflag)
312 continue;
315 * Do not print certain special symbols, like PRF_EXTSYM, etc.
316 * even if zflag was on.
318 if (is_special_sym(parentp))
319 continue;
321 if (parentp->name == 0 && parentp->cycleno != 0) {
323 * cycle header
325 printcycle(parentp);
326 printmembers(parentp);
327 } else {
328 printparents(parentp);
329 gprofline(parentp);
330 printchildren(parentp);
333 (void) printf("\n");
334 (void) printf(
335 "-----------------------------------------------\n");
336 (void) printf("\n");
338 if (nflag) {
339 --print_count;
340 if (print_count == 0)
341 count_flag = FALSE;
344 free(timesortnlp);
348 * sort by decreasing propagated time
349 * if times are equal, but one is a cycle header,
350 * say that's first (e.g. less, i.e. -1).
351 * if one's name doesn't have an underscore and the other does,
352 * say the one is first.
353 * all else being equal, sort by names.
356 totalcmp(const void *arg1, const void *arg2)
358 nltype **npp1 = (nltype **)arg1;
359 nltype **npp2 = (nltype **)arg2;
360 nltype *np1 = *npp1;
361 nltype *np2 = *npp2;
362 double diff;
364 diff = (np1->propself + np1->propchild) -
365 (np2->propself + np2->propchild);
367 if (diff < 0.0)
368 return (1);
369 if (diff > 0.0)
370 return (-1);
371 if (np1->name == 0 && np1->cycleno != 0)
372 return (-1);
373 if (np2->name == 0 && np2->cycleno != 0)
374 return (1);
375 if (np1->name == 0)
376 return (-1);
377 if (np2->name == 0)
378 return (1);
380 if (*(np1->name) != '_' && *(np2->name) == '_')
381 return (-1);
382 if (*(np1->name) == '_' && *(np2->name) != '_')
383 return (1);
384 if (np1->ncall > np2->ncall)
385 return (-1);
386 if (np1->ncall < np2->ncall)
387 return (1);
388 return (strcmp(np1->name, np2->name));
391 void
392 printparents(nltype *childp)
394 nltype *parentp;
395 arctype *arcp;
396 nltype *cycleheadp;
398 if (childp->cyclehead != 0)
399 cycleheadp = childp -> cyclehead;
400 else
401 cycleheadp = childp;
403 if (childp->parents == 0) {
404 (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s"
405 " <spontaneous>\n", "", "", "", "", "", "");
406 return;
409 sortparents(childp);
411 for (arcp = childp->parents; arcp; arcp = arcp->arc_parentlist) {
412 parentp = arcp -> arc_parentp;
413 if (childp == parentp || (childp->cycleno != 0 &&
414 parentp->cycleno == childp->cycleno)) {
416 * selfcall or call among siblings
418 (void) printf(
419 "%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ",
420 "", "", "", "", arcp->arc_count, "");
421 printname(parentp);
423 if (Cflag)
424 print_demangled_name(54, parentp);
426 (void) printf("\n");
427 } else {
429 * regular parent of child
431 (void) printf(
432 "%6.6s %5.5s %7.2f %11.2f %7lld/%-7lld ", "",
433 "", arcp->arc_time / hz, arcp->arc_childtime / hz,
434 arcp->arc_count, cycleheadp->ncall);
435 printname(parentp);
437 if (Cflag)
438 print_demangled_name(54, parentp);
440 (void) printf("\n");
445 void
446 printchildren(nltype *parentp)
448 nltype *childp;
449 arctype *arcp;
451 sortchildren(parentp);
453 for (arcp = parentp->children; arcp; arcp = arcp->arc_childlist) {
454 childp = arcp->arc_childp;
455 if (childp == parentp || (childp->cycleno != 0 &&
456 childp->cycleno == parentp->cycleno)) {
458 * self call or call to sibling
460 (void) printf(
461 "%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ",
462 "", "", "", "", arcp->arc_count, "");
463 printname(childp);
465 if (Cflag)
466 print_demangled_name(54, childp);
468 (void) printf("\n");
469 } else {
471 * regular child of parent
473 if (childp->cyclehead)
474 (void) printf("%6.6s %5.5s %7.2f %11.2f "
475 "%7lld/%-7lld ", "", "",
476 arcp->arc_time / hz,
477 arcp->arc_childtime / hz, arcp->arc_count,
478 childp->cyclehead->ncall);
479 else
480 (void) printf("%6.6s %5.5s %7.2f %11.2f "
481 "%7lld %7.7s ",
482 "", "", arcp->arc_time / hz,
483 arcp->arc_childtime / hz, arcp->arc_count,
484 "");
486 printname(childp);
488 if (Cflag)
489 print_demangled_name(54, childp);
491 (void) printf("\n");
496 void
497 printname(nltype *selfp)
499 const char *c;
500 c = demangled_name(selfp);
502 if (selfp->name != 0) {
503 if (!Cflag)
504 (void) printf("%s", selfp->name);
505 else
506 (void) printf("%s", c);
508 #ifdef DEBUG
509 if (debug & DFNDEBUG)
510 (void) printf("{%d} ", selfp->toporder);
512 if (debug & PROPDEBUG)
513 (void) printf("%5.2f%% ", selfp->propfraction);
514 #endif /* DEBUG */
517 if (selfp->cycleno != 0)
518 (void) printf("\t<cycle %d>", selfp->cycleno);
520 if (selfp->index != 0) {
521 if (selfp->printflag)
522 (void) printf(" [%d]", selfp->index);
523 else
524 (void) printf(" (%d)", selfp->index);
528 void
529 print_demangled_name(int n, nltype *selfp)
531 char *c;
532 int i;
534 c = selfp->name;
536 if (strcmp(c, demangled_name(selfp)) == 0)
537 return;
538 else {
539 (void) printf("\n");
540 for (i = 1; i < n; i++)
541 (void) printf(" ");
542 (void) printf("[%s]", selfp->name);
546 void
547 sortchildren(nltype *parentp)
549 arctype *arcp;
550 arctype *detachedp;
551 arctype sorted;
552 arctype *prevp;
555 * unlink children from parent,
556 * then insertion sort back on to sorted's children.
557 * *arcp the arc you have detached and are inserting.
558 * *detachedp the rest of the arcs to be sorted.
559 * sorted arc list onto which you insertion sort.
560 * *prevp arc before the arc you are comparing.
562 sorted.arc_childlist = 0;
564 /* LINTED: warning: assignment operator */
565 for ((arcp = parentp->children) && (detachedp = arcp->arc_childlist);
566 arcp;
567 /* LINTED: warning: assignment operator */
568 (arcp = detachedp) && (detachedp = detachedp->arc_childlist)) {
570 * consider *arcp as disconnected
571 * insert it into sorted
573 for (prevp = &sorted; prevp->arc_childlist;
574 prevp = prevp->arc_childlist) {
575 if (arccmp(arcp, prevp->arc_childlist) != LESSTHAN)
576 break;
579 arcp->arc_childlist = prevp->arc_childlist;
580 prevp->arc_childlist = arcp;
584 * reattach sorted children to parent
586 parentp->children = sorted.arc_childlist;
589 void
590 sortparents(nltype *childp)
592 arctype *arcp;
593 arctype *detachedp;
594 arctype sorted;
595 arctype *prevp;
598 * unlink parents from child,
599 * then insertion sort back on to sorted's parents.
600 * *arcp the arc you have detached and are inserting.
601 * *detachedp the rest of the arcs to be sorted.
602 * sorted arc list onto which you insertion sort.
603 * *prevp arc before the arc you are comparing.
605 sorted.arc_parentlist = 0;
607 /* LINTED: warning: assignment operator */
608 for ((arcp = childp->parents) && (detachedp = arcp->arc_parentlist);
609 arcp;
610 /* LINTED: warning: assignment operator */
611 (arcp = detachedp) && (detachedp = detachedp->arc_parentlist)) {
613 * consider *arcp as disconnected
614 * insert it into sorted
616 for (prevp = &sorted; prevp->arc_parentlist;
617 prevp = prevp->arc_parentlist) {
618 if (arccmp(arcp, prevp->arc_parentlist) != GREATERTHAN)
619 break;
621 arcp->arc_parentlist = prevp->arc_parentlist;
622 prevp->arc_parentlist = arcp;
626 * reattach sorted arcs to child
628 childp->parents = sorted.arc_parentlist;
631 void
632 printcycle(nltype *cyclep)
634 char kirkbuffer[BUFSIZ];
636 (void) sprintf(kirkbuffer, "[%d]", cyclep->index);
637 (void) printf("%-6.6s %5.1f %7.2f %11.2f %7lld", kirkbuffer,
638 100 * (cyclep->propself + cyclep->propchild) / printtime,
639 cyclep -> propself / hz, cyclep -> propchild / hz,
640 cyclep -> ncall);
642 if (cyclep->selfcalls != 0)
643 (void) printf("+%-7lld", cyclep->selfcalls);
644 else
645 (void) printf(" %7.7s", "");
647 (void) printf(" <cycle %d as a whole>\t[%d]\n", cyclep->cycleno,
648 cyclep->index);
652 * print the members of a cycle
654 void
655 printmembers(nltype *cyclep)
657 nltype *memberp;
659 sortmembers(cyclep);
661 for (memberp = cyclep->cnext; memberp; memberp = memberp->cnext) {
662 (void) printf("%6.6s %5.5s %7.2f %11.2f %7lld", "", "",
663 memberp->propself / hz, memberp->propchild / hz,
664 memberp->ncall);
666 if (memberp->selfcalls != 0)
667 (void) printf("+%-7lld", memberp->selfcalls);
668 else
669 (void) printf(" %7.7s", "");
671 (void) printf(" ");
672 printname(memberp);
673 if (Cflag)
674 print_demangled_name(54, memberp);
675 (void) printf("\n");
680 * sort members of a cycle
682 void
683 sortmembers(nltype *cyclep)
685 nltype *todo;
686 nltype *doing;
687 nltype *prev;
690 * detach cycle members from cyclehead,
691 * and insertion sort them back on.
693 todo = cyclep->cnext;
694 cyclep->cnext = 0;
696 /* LINTED: warning: assignment operator */
697 for ((doing = todo) && (todo = doing->cnext);
698 doing;
699 /* LINTED: warning: assignment operator */
700 (doing = todo) && (todo = doing->cnext)) {
701 for (prev = cyclep; prev->cnext; prev = prev->cnext) {
702 if (membercmp(doing, prev->cnext) == GREATERTHAN)
703 break;
705 doing->cnext = prev->cnext;
706 prev->cnext = doing;
711 * major sort is on propself + propchild,
712 * next is sort on ncalls + selfcalls.
715 membercmp(nltype *this, nltype *that)
717 double thistime = this->propself + this->propchild;
718 double thattime = that->propself + that->propchild;
719 actype thiscalls = this->ncall + this->selfcalls;
720 actype thatcalls = that->ncall + that->selfcalls;
722 if (thistime > thattime)
723 return (GREATERTHAN);
725 if (thistime < thattime)
726 return (LESSTHAN);
728 if (thiscalls > thatcalls)
729 return (GREATERTHAN);
731 if (thiscalls < thatcalls)
732 return (LESSTHAN);
734 return (EQUALTO);
738 * compare two arcs to/from the same child/parent.
739 * - if one arc is a self arc, it's least.
740 * - if one arc is within a cycle, it's less than.
741 * - if both arcs are within a cycle, compare arc counts.
742 * - if neither arc is within a cycle, compare with
743 * arc_time + arc_childtime as major key
744 * arc count as minor key
747 arccmp(arctype *thisp, arctype *thatp)
749 nltype *thisparentp = thisp->arc_parentp;
750 nltype *thischildp = thisp->arc_childp;
751 nltype *thatparentp = thatp->arc_parentp;
752 nltype *thatchildp = thatp->arc_childp;
753 double thistime;
754 double thattime;
756 #ifdef DEBUG
757 if (debug & TIMEDEBUG) {
758 (void) printf("[arccmp] ");
759 printname(thisparentp);
760 (void) printf(" calls ");
761 printname(thischildp);
762 (void) printf(" %f + %f %lld/%lld\n", thisp->arc_time,
763 thisp->arc_childtime, thisp->arc_count,
764 thischildp->ncall);
765 (void) printf("[arccmp] ");
766 printname(thatparentp);
767 (void) printf(" calls ");
768 printname(thatchildp);
769 (void) printf(" %f + %f %lld/%lld\n", thatp->arc_time,
770 thatp->arc_childtime, thatp->arc_count,
771 thatchildp->ncall);
772 (void) printf("\n");
774 #endif /* DEBUG */
776 if (thisparentp == thischildp) {
778 * this is a self call
780 return (LESSTHAN);
783 if (thatparentp == thatchildp) {
785 * that is a self call
787 return (GREATERTHAN);
790 if (thisparentp->cycleno != 0 && thischildp->cycleno != 0 &&
791 thisparentp->cycleno == thischildp->cycleno) {
793 * this is a call within a cycle
795 if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 &&
796 thatparentp->cycleno == thatchildp->cycleno) {
798 * that is a call within the cycle, too
800 if (thisp->arc_count < thatp->arc_count)
801 return (LESSTHAN);
803 if (thisp->arc_count > thatp->arc_count)
804 return (GREATERTHAN);
806 return (EQUALTO);
807 } else {
809 * that isn't a call within the cycle
811 return (LESSTHAN);
813 } else {
815 * this isn't a call within a cycle
817 if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 &&
818 thatparentp->cycleno == thatchildp->cycleno) {
820 * that is a call within a cycle
822 return (GREATERTHAN);
823 } else {
825 * neither is a call within a cycle
827 thistime = thisp->arc_time + thisp->arc_childtime;
828 thattime = thatp->arc_time + thatp->arc_childtime;
830 if (thistime < thattime)
831 return (LESSTHAN);
833 if (thistime > thattime)
834 return (GREATERTHAN);
836 if (thisp->arc_count < thatp->arc_count)
837 return (LESSTHAN);
839 if (thisp->arc_count > thatp->arc_count)
840 return (GREATERTHAN);
842 return (EQUALTO);
847 void
848 printblurb(char *blurbname)
850 FILE *blurbfile;
851 int input;
853 blurbfile = fopen(blurbname, "r");
854 if (blurbfile == NULL) {
855 perror(blurbname);
856 return;
859 while ((input = getc(blurbfile)) != EOF)
860 (void) putchar(input);
862 (void) fclose(blurbfile);
865 char *s1, *s2;
867 static int
868 namecmp(const void *arg1, const void *arg2)
870 nltype **npp1 = (nltype **)arg1;
871 nltype **npp2 = (nltype **)arg2;
873 if (!Cflag)
874 return (strcmp((*npp1)->name, (*npp2)->name));
875 else {
876 striped_name(s1, npp1);
877 striped_name(s2, npp2);
878 return (strcmp(s1, s2));
882 void
883 striped_name(char *s, nltype **npp)
885 const char *d;
886 char *c;
888 c = (char *)s;
889 d = demangled_name(*npp);
891 while ((*d != '(') && (*d != '\0')) {
892 if (*d != ':')
893 *c++ = *d++;
894 else
895 d++;
897 *c = '\0';
901 * Checks if the current symbol name is the same as its neighbour and
902 * returns TRUE if it is.
904 static bool
905 does_clash(nltype **nlp, int ndx, int nnames)
908 * same as previous (if there's one) ?
910 if (ndx && (strcmp(nlp[ndx]->name, nlp[ndx-1]->name) == 0))
911 return (TRUE);
914 * same as next (if there's one) ?
916 if ((ndx < (nnames - 1)) &&
917 (strcmp(nlp[ndx]->name, nlp[ndx+1]->name) == 0)) {
918 return (TRUE);
921 return (FALSE);
924 void
925 printmodules()
927 mod_info_t *mi;
929 (void) printf("\f\nObject modules\n\n");
930 for (mi = &modules; mi; mi = mi->next)
931 (void) printf(" %d: %s\n", mi->id, mi->name);
934 #define IDFMT(id) ((id) < 10 ? 1 : 2)
935 #define NMFMT(id) ((id) < 10 ? 17 : 16)
937 void
938 printindex()
940 nltype **namesortnlp;
941 nltype *nlp;
942 int index, nnames, todo, i, j;
943 char peterbuffer[BUFSIZ];
944 mod_info_t *mi;
947 * Now, sort regular function name alphabetically
948 * to create an index.
950 namesortnlp = calloc(total_names + ncycle, sizeof (nltype *));
952 if (namesortnlp == NULL)
953 (void) fprintf(stderr, "%s: ran out of memory for sorting\n",
954 whoami);
956 nnames = 0;
957 for (mi = &modules; mi; mi = mi->next) {
958 for (index = 0; index < mi->nname; index++) {
959 if (zflag == 0 && (mi->nl[index]).ncall == 0 &&
960 (mi->nl[index]).time == 0) {
961 continue;
965 * Do not print certain special symbols, like
966 * PRF_EXTSYM, etc. even if zflag was on.
968 if (is_special_sym(&(mi->nl[index])))
969 continue;
971 namesortnlp[nnames++] = &(mi->nl[index]);
975 if (Cflag) {
976 s1 = malloc(500 * sizeof (char));
977 s2 = malloc(500 * sizeof (char));
980 qsort(namesortnlp, nnames, sizeof (nltype *), namecmp);
982 for (index = 1, todo = nnames; index <= ncycle; index++)
983 namesortnlp[todo++] = &cyclenl[index];
985 (void) printf("\f\nIndex by function name\n\n");
987 if (!Cflag)
988 index = (todo + 2) / 3;
989 else
990 index = todo;
992 for (i = 0; i < index; i++) {
993 if (!Cflag) {
994 for (j = i; j < todo; j += index) {
995 nlp = namesortnlp[j];
997 if (nlp->printflag) {
998 (void) sprintf(peterbuffer,
999 "[%d]", nlp->index);
1000 } else {
1001 (void) sprintf(peterbuffer,
1002 "(%d)", nlp->index);
1005 if (j < nnames) {
1006 if (does_clash(namesortnlp,
1007 j, nnames)) {
1008 (void) printf(
1009 "%6.6s %*d:%-*.*s",
1010 peterbuffer,
1011 IDFMT(nlp->module->id),
1012 nlp->module->id,
1013 NMFMT(nlp->module->id),
1014 NMFMT(nlp->module->id),
1015 nlp->name);
1016 } else {
1017 (void) printf("%6.6s %-19.19s",
1018 peterbuffer, nlp->name);
1020 } else {
1021 (void) printf("%6.6s ", peterbuffer);
1022 (void) sprintf(peterbuffer,
1023 "<cycle %d>", nlp->cycleno);
1024 (void) printf("%-19.19s", peterbuffer);
1027 } else {
1028 nlp = namesortnlp[i];
1030 if (nlp->printflag)
1031 (void) sprintf(peterbuffer, "[%d]", nlp->index);
1032 else
1033 (void) sprintf(peterbuffer, "(%d)", nlp->index);
1035 if (i < nnames) {
1036 const char *d = demangled_name(nlp);
1038 if (does_clash(namesortnlp, i, nnames)) {
1039 (void) printf("%6.6s %d:%s\n",
1040 peterbuffer, nlp->module->id, d);
1041 } else
1042 (void) printf("%6.6s %s\n", peterbuffer,
1045 if (d != nlp->name)
1046 (void) printf("%6.6s [%s]", "",
1047 nlp->name);
1048 } else {
1049 (void) printf("%6.6s ", peterbuffer);
1050 (void) sprintf(peterbuffer, "<cycle %d>",
1051 nlp->cycleno);
1052 (void) printf("%-33.33s", peterbuffer);
1055 (void) printf("\n");
1057 free(namesortnlp);