1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #if 0 31 #ifndef lint 32 static char sccsid[] = "@(#)printgprof.c 8.1 (Berkeley) 6/6/93"; 33 #endif /* not lint */ 34 #endif 35 36 #include <sys/cdefs.h> 37 __FBSDID("$FreeBSD$"); 38 39 #include <err.h> 40 #include <string.h> 41 42 #include "gprof.h" 43 #include "pathnames.h" 44 45 int namecmp(const void *, const void *); 46 int timecmp(const void *, const void *); 47 48 void 49 printprof(void) 50 { 51 register nltype *np; 52 nltype **sortednlp; 53 int idx; 54 55 actime = 0.0; 56 printf( "\f\n" ); 57 flatprofheader(); 58 /* 59 * Sort the symbol table in by time 60 */ 61 sortednlp = (nltype **) calloc( nname , sizeof(nltype *) ); 62 if ( sortednlp == (nltype **) 0 ) 63 errx( 1 , "[printprof] ran out of memory for time sorting" ); 64 for ( idx = 0 ; idx < nname ; idx += 1 ) { 65 sortednlp[ idx ] = &nl[ idx ]; 66 } 67 qsort( sortednlp , nname , sizeof(nltype *) , timecmp ); 68 for ( idx = 0 ; idx < nname ; idx += 1 ) { 69 np = sortednlp[ idx ]; 70 flatprofline( np ); 71 } 72 actime = 0.0; 73 free( sortednlp ); 74 } 75 76 int 77 timecmp(const void *v1, const void *v2) 78 { 79 const nltype **npp1 = (const nltype **)v1; 80 const nltype **npp2 = (const nltype **)v2; 81 double timediff; 82 long calldiff; 83 84 timediff = (*npp2) -> time - (*npp1) -> time; 85 if ( timediff > 0.0 ) 86 return 1 ; 87 if ( timediff < 0.0 ) 88 return -1; 89 calldiff = (*npp2) -> ncall - (*npp1) -> ncall; 90 if ( calldiff > 0 ) 91 return 1; 92 if ( calldiff < 0 ) 93 return -1; 94 return( strcmp( (*npp1) -> name , (*npp2) -> name ) ); 95 } 96 97 /* 98 * header for flatprofline 99 */ 100 void 101 flatprofheader(void) 102 { 103 104 if ( bflag ) { 105 printblurb( _PATH_FLAT_BLURB ); 106 } 107 printf( "\ngranularity: each sample hit covers %g byte(s)" , 108 scale * HISTORICAL_SCALE_2 ); 109 if ( totime > 0.0 ) { 110 printf( " for %.2f%% of %.2f seconds\n\n" , 111 100.0/totime , totime / hz ); 112 } else { 113 printf( " no time accumulated\n\n" ); 114 /* 115 * this doesn't hurt since all the numerators will be zero. 116 */ 117 totime = 1.0; 118 } 119 printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" , 120 "% " , "cumulative" , "self " , "" , "self " , "total " , "" ); 121 printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" , 122 "time" , "seconds " , "seconds" , "calls" , 123 hz >= 10000000 ? "ns/call" : hz >= 10000 ? "us/call" : "ms/call" , 124 hz >= 10000000 ? "ns/call" : hz >= 10000 ? "us/call" : "ms/call" , 125 "name" ); 126 } 127 128 void 129 flatprofline(register nltype *np) 130 { 131 132 if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 && 133 np -> childtime == 0 ) { 134 return; 135 } 136 actime += np -> time; 137 if (hz >= 10000) 138 printf( "%5.1f %10.3f %8.3f" , 139 100 * np -> time / totime , actime / hz , np -> time / hz ); 140 else 141 printf( "%5.1f %10.2f %8.2f" , 142 100 * np -> time / totime , actime / hz , np -> time / hz ); 143 if ( np -> ncall != 0 ) { 144 if (hz >= 10000000) 145 printf( " %8ld %8.0f %8.0f " , np -> ncall , 146 1e9 * np -> time / hz / np -> ncall , 147 1e9 * ( np -> time + np -> childtime ) / hz / np -> ncall ); 148 else if (hz >= 10000) 149 printf( " %8ld %8.0f %8.0f " , np -> ncall , 150 1e6 * np -> time / hz / np -> ncall , 151 1e6 * ( np -> time + np -> childtime ) / hz / np -> ncall ); 152 else 153 printf( " %8ld %8.2f %8.2f " , np -> ncall , 154 1000 * np -> time / hz / np -> ncall , 155 1000 * ( np -> time + np -> childtime ) / hz / np -> ncall ); 156 } else if ( np -> time != 0 || np -> childtime != 0 ) { 157 printf( " %8ld %7.2f%% %8.8s " , np -> ncall , 158 100 * np -> time / ( np -> time + np -> childtime ) , "" ); 159 } else { 160 printf( " %8.8s %8.8s %8.8s " , "" , "" , "" ); 161 } 162 printname( np ); 163 printf( "\n" ); 164 } 165 166 void 167 gprofheader(void) 168 { 169 170 if ( bflag ) { 171 printblurb( _PATH_CALLG_BLURB ); 172 } 173 printf( "\ngranularity: each sample hit covers %g byte(s)" , 174 scale * HISTORICAL_SCALE_2 ); 175 if ( printtime > 0.0 ) { 176 printf( " for %.2f%% of %.2f seconds\n\n" , 177 100.0/printtime , printtime / hz ); 178 } else { 179 printf( " no time propagated\n\n" ); 180 /* 181 * this doesn't hurt, since all the numerators will be 0.0 182 */ 183 printtime = 1.0; 184 } 185 printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , 186 "" , "" , "" , "" , "called" , "total" , "parents"); 187 printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" , 188 "index" , "%time" , "self" , "descendents" , 189 "called" , "self" , "name" , "index" ); 190 printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , 191 "" , "" , "" , "" , "called" , "total" , "children"); 192 printf( "\n" ); 193 } 194 195 void 196 gprofline(register nltype *np) 197 { 198 char kirkbuffer[ BUFSIZ ]; 199 200 sprintf( kirkbuffer , "[%d]" , np -> index ); 201 printf( "%-6.6s %5.1f %7.2f %11.2f" , 202 kirkbuffer , 203 100 * ( np -> propself + np -> propchild ) / printtime , 204 np -> propself / hz , 205 np -> propchild / hz ); 206 if ( ( np -> ncall + np -> selfcalls ) != 0 ) { 207 printf( " %7ld" , np -> npropcall ); 208 if ( np -> selfcalls != 0 ) { 209 printf( "+%-7ld " , np -> selfcalls ); 210 } else { 211 printf( " %7.7s " , "" ); 212 } 213 } else { 214 printf( " %7.7s %7.7s " , "" , "" ); 215 } 216 printname( np ); 217 printf( "\n" ); 218 } 219 220 void 221 printgprof(nltype **timesortnlp) 222 { 223 int idx; 224 nltype *parentp; 225 226 /* 227 * Print out the structured profiling list 228 */ 229 gprofheader(); 230 for ( idx = 0 ; idx < nname + ncycle ; idx ++ ) { 231 parentp = timesortnlp[ idx ]; 232 if ( zflag == 0 && 233 parentp -> ncall == 0 && 234 parentp -> selfcalls == 0 && 235 parentp -> propself == 0 && 236 parentp -> propchild == 0 ) { 237 continue; 238 } 239 if ( ! parentp -> printflag ) { 240 continue; 241 } 242 if ( parentp -> name == 0 && parentp -> cycleno != 0 ) { 243 /* 244 * cycle header 245 */ 246 printcycle( parentp ); 247 printmembers( parentp ); 248 } else { 249 printparents( parentp ); 250 gprofline( parentp ); 251 printchildren( parentp ); 252 } 253 printf( "\n" ); 254 printf( "-----------------------------------------------\n" ); 255 printf( "\n" ); 256 } 257 free( timesortnlp ); 258 } 259 260 /* 261 * sort by decreasing propagated time 262 * if times are equal, but one is a cycle header, 263 * say that's first (e.g. less, i.e. -1). 264 * if one's name doesn't have an underscore and the other does, 265 * say the one is first. 266 * all else being equal, sort by names. 267 */ 268 int 269 totalcmp(const void *v1, const void *v2) 270 { 271 const nltype **npp1 = (const nltype **)v1; 272 const nltype **npp2 = (const nltype **)v2; 273 register const nltype *np1 = *npp1; 274 register const nltype *np2 = *npp2; 275 double diff; 276 277 diff = ( np1 -> propself + np1 -> propchild ) 278 - ( np2 -> propself + np2 -> propchild ); 279 if ( diff < 0.0 ) 280 return 1; 281 if ( diff > 0.0 ) 282 return -1; 283 if ( np1 -> name == 0 && np1 -> cycleno != 0 ) 284 return -1; 285 if ( np2 -> name == 0 && np2 -> cycleno != 0 ) 286 return 1; 287 if ( np1 -> name == 0 ) 288 return -1; 289 if ( np2 -> name == 0 ) 290 return 1; 291 if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' ) 292 return -1; 293 if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' ) 294 return 1; 295 if ( np1 -> ncall > np2 -> ncall ) 296 return -1; 297 if ( np1 -> ncall < np2 -> ncall ) 298 return 1; 299 return strcmp( np1 -> name , np2 -> name ); 300 } 301 302 void 303 printparents(nltype *childp) 304 { 305 nltype *parentp; 306 arctype *arcp; 307 nltype *cycleheadp; 308 309 if ( childp -> cyclehead != 0 ) { 310 cycleheadp = childp -> cyclehead; 311 } else { 312 cycleheadp = childp; 313 } 314 if ( childp -> parents == 0 ) { 315 printf( "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n" , 316 "" , "" , "" , "" , "" , "" ); 317 return; 318 } 319 sortparents( childp ); 320 for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) { 321 parentp = arcp -> arc_parentp; 322 if ( childp == parentp || ( arcp -> arc_flags & DEADARC ) || 323 ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) { 324 /* 325 * selfcall or call among siblings 326 */ 327 printf( "%6.6s %5.5s %7.7s %11.11s %7ld %7.7s " , 328 "" , "" , "" , "" , 329 arcp -> arc_count , "" ); 330 printname( parentp ); 331 printf( "\n" ); 332 } else { 333 /* 334 * regular parent of child 335 */ 336 printf( "%6.6s %5.5s %7.2f %11.2f %7ld/%-7ld " , 337 "" , "" , 338 arcp -> arc_time / hz , arcp -> arc_childtime / hz , 339 arcp -> arc_count , cycleheadp -> npropcall ); 340 printname( parentp ); 341 printf( "\n" ); 342 } 343 } 344 } 345 346 void 347 printchildren(nltype *parentp) 348 { 349 nltype *childp; 350 arctype *arcp; 351 352 sortchildren( parentp ); 353 arcp = parentp -> children; 354 for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 355 childp = arcp -> arc_childp; 356 if ( childp == parentp || ( arcp -> arc_flags & DEADARC ) || 357 ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) { 358 /* 359 * self call or call to sibling 360 */ 361 printf( "%6.6s %5.5s %7.7s %11.11s %7ld %7.7s " , 362 "" , "" , "" , "" , arcp -> arc_count , "" ); 363 printname( childp ); 364 printf( "\n" ); 365 } else { 366 /* 367 * regular child of parent 368 */ 369 printf( "%6.6s %5.5s %7.2f %11.2f %7ld/%-7ld " , 370 "" , "" , 371 arcp -> arc_time / hz , arcp -> arc_childtime / hz , 372 arcp -> arc_count , childp -> cyclehead -> npropcall ); 373 printname( childp ); 374 printf( "\n" ); 375 } 376 } 377 } 378 379 void 380 printname(nltype *selfp) 381 { 382 383 if ( selfp -> name != 0 ) { 384 printf( "%s" , selfp -> name ); 385 # ifdef DEBUG 386 if ( debug & DFNDEBUG ) { 387 printf( "{%d} " , selfp -> toporder ); 388 } 389 if ( debug & PROPDEBUG ) { 390 printf( "%5.2f%% " , selfp -> propfraction ); 391 } 392 # endif /* DEBUG */ 393 } 394 if ( selfp -> cycleno != 0 ) { 395 printf( " <cycle %d>" , selfp -> cycleno ); 396 } 397 if ( selfp -> index != 0 ) { 398 if ( selfp -> printflag ) { 399 printf( " [%d]" , selfp -> index ); 400 } else { 401 printf( " (%d)" , selfp -> index ); 402 } 403 } 404 } 405 406 void 407 sortchildren(nltype *parentp) 408 { 409 arctype *arcp; 410 arctype *detachedp; 411 arctype sorted; 412 arctype *prevp; 413 414 /* 415 * unlink children from parent, 416 * then insertion sort back on to sorted's children. 417 * *arcp the arc you have detached and are inserting. 418 * *detachedp the rest of the arcs to be sorted. 419 * sorted arc list onto which you insertion sort. 420 * *prevp arc before the arc you are comparing. 421 */ 422 sorted.arc_childlist = 0; 423 for ( (arcp = parentp -> children)&&(detachedp = arcp -> arc_childlist); 424 arcp ; 425 (arcp = detachedp)&&(detachedp = detachedp -> arc_childlist)) { 426 /* 427 * consider *arcp as disconnected 428 * insert it into sorted 429 */ 430 for ( prevp = &sorted ; 431 prevp -> arc_childlist ; 432 prevp = prevp -> arc_childlist ) { 433 if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN ) { 434 break; 435 } 436 } 437 arcp -> arc_childlist = prevp -> arc_childlist; 438 prevp -> arc_childlist = arcp; 439 } 440 /* 441 * reattach sorted children to parent 442 */ 443 parentp -> children = sorted.arc_childlist; 444 } 445 446 void 447 sortparents(nltype *childp) 448 { 449 arctype *arcp; 450 arctype *detachedp; 451 arctype sorted; 452 arctype *prevp; 453 454 /* 455 * unlink parents from child, 456 * then insertion sort back on to sorted's parents. 457 * *arcp the arc you have detached and are inserting. 458 * *detachedp the rest of the arcs to be sorted. 459 * sorted arc list onto which you insertion sort. 460 * *prevp arc before the arc you are comparing. 461 */ 462 sorted.arc_parentlist = 0; 463 for ( (arcp = childp -> parents)&&(detachedp = arcp -> arc_parentlist); 464 arcp ; 465 (arcp = detachedp)&&(detachedp = detachedp -> arc_parentlist)) { 466 /* 467 * consider *arcp as disconnected 468 * insert it into sorted 469 */ 470 for ( prevp = &sorted ; 471 prevp -> arc_parentlist ; 472 prevp = prevp -> arc_parentlist ) { 473 if ( arccmp( arcp , prevp -> arc_parentlist ) != GREATERTHAN ) { 474 break; 475 } 476 } 477 arcp -> arc_parentlist = prevp -> arc_parentlist; 478 prevp -> arc_parentlist = arcp; 479 } 480 /* 481 * reattach sorted arcs to child 482 */ 483 childp -> parents = sorted.arc_parentlist; 484 } 485 486 /* 487 * print a cycle header 488 */ 489 void 490 printcycle(nltype *cyclep) 491 { 492 char kirkbuffer[ BUFSIZ ]; 493 494 sprintf( kirkbuffer , "[%d]" , cyclep -> index ); 495 printf( "%-6.6s %5.1f %7.2f %11.2f %7ld" , 496 kirkbuffer , 497 100 * ( cyclep -> propself + cyclep -> propchild ) / printtime , 498 cyclep -> propself / hz , 499 cyclep -> propchild / hz , 500 cyclep -> npropcall ); 501 if ( cyclep -> selfcalls != 0 ) { 502 printf( "+%-7ld" , cyclep -> selfcalls ); 503 } else { 504 printf( " %7.7s" , "" ); 505 } 506 printf( " <cycle %d as a whole>\t[%d]\n" , 507 cyclep -> cycleno , cyclep -> index ); 508 } 509 510 /* 511 * print the members of a cycle 512 */ 513 void 514 printmembers(nltype *cyclep) 515 { 516 nltype *memberp; 517 518 sortmembers( cyclep ); 519 for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) { 520 printf( "%6.6s %5.5s %7.2f %11.2f %7ld" , 521 "" , "" , memberp -> propself / hz , memberp -> propchild / hz , 522 memberp -> npropcall ); 523 if ( memberp -> selfcalls != 0 ) { 524 printf( "+%-7ld" , memberp -> selfcalls ); 525 } else { 526 printf( " %7.7s" , "" ); 527 } 528 printf( " " ); 529 printname( memberp ); 530 printf( "\n" ); 531 } 532 } 533 534 /* 535 * sort members of a cycle 536 */ 537 void 538 sortmembers(nltype *cyclep) 539 { 540 nltype *todo; 541 nltype *doing; 542 nltype *prev; 543 544 /* 545 * detach cycle members from cyclehead, 546 * and insertion sort them back on. 547 */ 548 todo = cyclep -> cnext; 549 cyclep -> cnext = 0; 550 for ( (doing = todo)&&(todo = doing -> cnext); 551 doing ; 552 (doing = todo )&&(todo = doing -> cnext )){ 553 for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) { 554 if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) { 555 break; 556 } 557 } 558 doing -> cnext = prev -> cnext; 559 prev -> cnext = doing; 560 } 561 } 562 563 /* 564 * major sort is on propself + propchild, 565 * next is sort on ncalls + selfcalls. 566 */ 567 int 568 membercmp(nltype *this, nltype *that) 569 { 570 double thistime = this -> propself + this -> propchild; 571 double thattime = that -> propself + that -> propchild; 572 long thiscalls = this -> ncall + this -> selfcalls; 573 long thatcalls = that -> ncall + that -> selfcalls; 574 575 if ( thistime > thattime ) { 576 return GREATERTHAN; 577 } 578 if ( thistime < thattime ) { 579 return LESSTHAN; 580 } 581 if ( thiscalls > thatcalls ) { 582 return GREATERTHAN; 583 } 584 if ( thiscalls < thatcalls ) { 585 return LESSTHAN; 586 } 587 return EQUALTO; 588 } 589 /* 590 * compare two arcs to/from the same child/parent. 591 * - if one arc is a self arc, it's least. 592 * - if one arc is within a cycle, it's less than. 593 * - if both arcs are within a cycle, compare arc counts. 594 * - if neither arc is within a cycle, compare with 595 * arc_time + arc_childtime as major key 596 * arc count as minor key 597 */ 598 int 599 arccmp(arctype *thisp, arctype *thatp) 600 { 601 nltype *thisparentp = thisp -> arc_parentp; 602 nltype *thischildp = thisp -> arc_childp; 603 nltype *thatparentp = thatp -> arc_parentp; 604 nltype *thatchildp = thatp -> arc_childp; 605 double thistime; 606 double thattime; 607 608 # ifdef DEBUG 609 if ( debug & TIMEDEBUG ) { 610 printf( "[arccmp] " ); 611 printname( thisparentp ); 612 printf( " calls " ); 613 printname ( thischildp ); 614 printf( " %f + %f %ld/%ld\n" , 615 thisp -> arc_time , thisp -> arc_childtime , 616 thisp -> arc_count , thischildp -> ncall ); 617 printf( "[arccmp] " ); 618 printname( thatparentp ); 619 printf( " calls " ); 620 printname( thatchildp ); 621 printf( " %f + %f %ld/%ld\n" , 622 thatp -> arc_time , thatp -> arc_childtime , 623 thatp -> arc_count , thatchildp -> ncall ); 624 printf( "\n" ); 625 } 626 # endif /* DEBUG */ 627 if ( thisparentp == thischildp ) { 628 /* this is a self call */ 629 return LESSTHAN; 630 } 631 if ( thatparentp == thatchildp ) { 632 /* that is a self call */ 633 return GREATERTHAN; 634 } 635 if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 && 636 thisparentp -> cycleno == thischildp -> cycleno ) { 637 /* this is a call within a cycle */ 638 if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && 639 thatparentp -> cycleno == thatchildp -> cycleno ) { 640 /* that is a call within the cycle, too */ 641 if ( thisp -> arc_count < thatp -> arc_count ) { 642 return LESSTHAN; 643 } 644 if ( thisp -> arc_count > thatp -> arc_count ) { 645 return GREATERTHAN; 646 } 647 return EQUALTO; 648 } else { 649 /* that isn't a call within the cycle */ 650 return LESSTHAN; 651 } 652 } else { 653 /* this isn't a call within a cycle */ 654 if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && 655 thatparentp -> cycleno == thatchildp -> cycleno ) { 656 /* that is a call within a cycle */ 657 return GREATERTHAN; 658 } else { 659 /* neither is a call within a cycle */ 660 thistime = thisp -> arc_time + thisp -> arc_childtime; 661 thattime = thatp -> arc_time + thatp -> arc_childtime; 662 if ( thistime < thattime ) 663 return LESSTHAN; 664 if ( thistime > thattime ) 665 return GREATERTHAN; 666 if ( thisp -> arc_count < thatp -> arc_count ) 667 return LESSTHAN; 668 if ( thisp -> arc_count > thatp -> arc_count ) 669 return GREATERTHAN; 670 return EQUALTO; 671 } 672 } 673 } 674 675 void 676 printblurb(const char *blurbname) 677 { 678 FILE *blurbfile; 679 int input; 680 681 blurbfile = fopen( blurbname , "r" ); 682 if ( blurbfile == NULL ) { 683 warn( "%s" , blurbname ); 684 return; 685 } 686 while ( ( input = getc( blurbfile ) ) != EOF ) { 687 putchar( input ); 688 } 689 fclose( blurbfile ); 690 } 691 692 int 693 namecmp(const void *v1, const void *v2) 694 { 695 const nltype **npp1 = (const nltype **)v1; 696 const nltype **npp2 = (const nltype **)v2; 697 698 return( strcmp( (*npp1) -> name , (*npp2) -> name ) ); 699 } 700 701 void 702 printindex(void) 703 { 704 nltype **namesortnlp; 705 register nltype *nlp; 706 int idx, nnames, todo, i, j; 707 char peterbuffer[ BUFSIZ ]; 708 709 /* 710 * Now, sort regular function name alphabetically 711 * to create an index. 712 */ 713 namesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); 714 if ( namesortnlp == (nltype **) 0 ) 715 errx( 1 , "ran out of memory for sorting"); 716 for ( idx = 0 , nnames = 0 ; idx < nname ; idx++ ) { 717 if ( zflag == 0 && nl[idx].ncall == 0 && nl[idx].time == 0 ) 718 continue; 719 namesortnlp[nnames++] = &nl[idx]; 720 } 721 qsort( namesortnlp , nnames , sizeof(nltype *) , namecmp ); 722 for ( idx = 1 , todo = nnames ; idx <= ncycle ; idx++ ) { 723 namesortnlp[todo++] = &cyclenl[idx]; 724 } 725 printf( "\f\nIndex by function name\n\n" ); 726 idx = ( todo + 2 ) / 3; 727 for ( i = 0; i < idx ; i++ ) { 728 for ( j = i; j < todo ; j += idx ) { 729 nlp = namesortnlp[ j ]; 730 if ( nlp -> printflag ) { 731 sprintf( peterbuffer , "[%d]" , nlp -> index ); 732 } else { 733 sprintf( peterbuffer , "(%d)" , nlp -> index ); 734 } 735 if ( j < nnames ) { 736 printf( "%6.6s %-19.19s" , peterbuffer , nlp -> name ); 737 } else { 738 printf( "%6.6s " , peterbuffer ); 739 sprintf( peterbuffer , "<cycle %d>" , nlp -> cycleno ); 740 printf( "%-19.19s" , peterbuffer ); 741 } 742 } 743 printf( "\n" ); 744 } 745 free( namesortnlp ); 746 } 747