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