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