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