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