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