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