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