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