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