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