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