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