1*12892Ssam #ifndef lint 2*12892Ssam static char *sccsid = "@(#)prof.c 4.1 (Berkeley) 06/02/83"; 3*12892Ssam #endif 4*12892Ssam /* 5*12892Ssam * prof 6*12892Ssam */ 7*12892Ssam #include <stdio.h> 8*12892Ssam #include <sys/types.h> 9*12892Ssam #include <sys/stat.h> 10*12892Ssam #include <a.out.h> 11*12892Ssam 12*12892Ssam typedef short UNIT; /* unit of profiling */ 13*12892Ssam #define A_OUTNAME "a.out" 14*12892Ssam #define MON_OUTNAME "mon.out" 15*12892Ssam #define MON_SUMNAME "mon.sum" 16*12892Ssam 17*12892Ssam /* 18*12892Ssam * The symbol table; 19*12892Ssam * for each external in the specified file we gather 20*12892Ssam * its address, the number of calls and compute its share of cpu time. 21*12892Ssam */ 22*12892Ssam struct nl { 23*12892Ssam char *name; 24*12892Ssam unsigned value; 25*12892Ssam float time; 26*12892Ssam long ncall; 27*12892Ssam } *nl; 28*12892Ssam int nname; 29*12892Ssam struct nl *np; 30*12892Ssam struct nl *npe; 31*12892Ssam 32*12892Ssam /* 33*12892Ssam * The header on the mon.out file. 34*12892Ssam * Mon.out consists of one of these headers, an array of ncount 35*12892Ssam * cnt structures (as below) and then an array of samples 36*12892Ssam * representing the discretized program counter values. 37*12892Ssam */ 38*12892Ssam struct hdr { 39*12892Ssam UNIT *lowpc, *highpc; 40*12892Ssam int ncount; 41*12892Ssam } h; 42*12892Ssam 43*12892Ssam /* 44*12892Ssam * Each counter has an address and a number of calls. 45*12892Ssam */ 46*12892Ssam struct cnt { 47*12892Ssam unsigned cvalue; 48*12892Ssam long cncall; 49*12892Ssam } *cbuf; 50*12892Ssam 51*12892Ssam /* 52*12892Ssam * Each discretized pc sample has 53*12892Ssam * a count of the number of samples in its range 54*12892Ssam */ 55*12892Ssam unsigned UNIT *samples; 56*12892Ssam 57*12892Ssam FILE *pfile, *nfile; 58*12892Ssam 59*12892Ssam unsigned lowpc, highpc; /* range profiled */ 60*12892Ssam double ransca, ranoff; /* scaling for blowing up plots */ 61*12892Ssam unsigned sampbytes; /* number of bytes of samples */ 62*12892Ssam int nsamples; /* number of samples */ 63*12892Ssam double totime; /* total time for all routines */ 64*12892Ssam double maxtime; /* maximum time of any routine (for plot) */ 65*12892Ssam double scale; /* scale factor converting samples to pc 66*12892Ssam values: each sample covers scale bytes */ 67*12892Ssam char *strtab; /* string table in core */ 68*12892Ssam off_t ssiz; /* size of the string table */ 69*12892Ssam struct exec xbuf; /* exec header of a.out */ 70*12892Ssam 71*12892Ssam int aflg; 72*12892Ssam int nflg; 73*12892Ssam int vflg; 74*12892Ssam int lflg; 75*12892Ssam int zflg; 76*12892Ssam int sflag; 77*12892Ssam 78*12892Ssam char *namfil; 79*12892Ssam 80*12892Ssam int timcmp(), valcmp(), cntcmp(); 81*12892Ssam 82*12892Ssam main(argc, argv) 83*12892Ssam char **argv; 84*12892Ssam { 85*12892Ssam int lowpct, highpct; 86*12892Ssam 87*12892Ssam /* 88*12892Ssam * Use highpct and lowpc as percentages, temporarily 89*12892Ssam * for graphing options involving blow-up 90*12892Ssam */ 91*12892Ssam lowpct = -1; 92*12892Ssam highpct = -1; 93*12892Ssam argv++; 94*12892Ssam while ( *argv != 0 && **argv == '-' ) { 95*12892Ssam *argv += 1; 96*12892Ssam if (**argv == 'l') 97*12892Ssam lflg++; 98*12892Ssam else if (**argv == 'a') 99*12892Ssam aflg++; 100*12892Ssam else if (**argv == 'n') 101*12892Ssam nflg++; 102*12892Ssam else if (**argv == 'z') 103*12892Ssam zflg++; 104*12892Ssam else if (**argv == 'v') 105*12892Ssam vflg++; 106*12892Ssam else if ( **argv == 's' ) 107*12892Ssam sflag++; 108*12892Ssam else if (**argv >= '0' && **argv <= '9') { 109*12892Ssam int i = atoi(*argv); 110*12892Ssam if (lowpct == -1) 111*12892Ssam lowpct = i; 112*12892Ssam else 113*12892Ssam highpct = i; 114*12892Ssam } 115*12892Ssam argv++; 116*12892Ssam } 117*12892Ssam if ( *argv != 0 ) { 118*12892Ssam namfil = *argv; 119*12892Ssam argv++; 120*12892Ssam } else { 121*12892Ssam namfil = A_OUTNAME; 122*12892Ssam } 123*12892Ssam if (lowpct >= 100) 124*12892Ssam lowpct = 0; 125*12892Ssam if (highpct <= lowpct || highpct > 100) 126*12892Ssam highpct = 100; 127*12892Ssam ransca = 100./(highpct-lowpct); 128*12892Ssam ranoff = 2040. + 40.8*lowpc*ransca; 129*12892Ssam /* 130*12892Ssam * get information about a.out file. 131*12892Ssam */ 132*12892Ssam getnfile(); 133*12892Ssam /* 134*12892Ssam * get information about mon.out file(s). 135*12892Ssam */ 136*12892Ssam if ( *argv == 0 ) { 137*12892Ssam getpfile( MON_OUTNAME ); 138*12892Ssam } else { 139*12892Ssam do { 140*12892Ssam getpfile( *argv ); 141*12892Ssam argv++; 142*12892Ssam } while ( *argv != 0 ); 143*12892Ssam } 144*12892Ssam asgnsamples(); /* assign samples to procedures */ 145*12892Ssam #ifdef plot 146*12892Ssam if (vflg) 147*12892Ssam plotprof(); /* a plotted or ... */ 148*12892Ssam else 149*12892Ssam #endif 150*12892Ssam printprof(); /* a printed profile */ 151*12892Ssam if ( sflag != 0 ) { 152*12892Ssam putprof(); 153*12892Ssam } 154*12892Ssam done(); 155*12892Ssam } 156*12892Ssam 157*12892Ssam printprof() 158*12892Ssam { 159*12892Ssam double time, actime; 160*12892Ssam 161*12892Ssam actime = 0; 162*12892Ssam printf(" %%time cumsecs #call ms/call name\n"); 163*12892Ssam if (!lflg) 164*12892Ssam qsort(nl, nname, sizeof(struct nl), timcmp); 165*12892Ssam for (np = nl; np<npe-1; np++) { 166*12892Ssam if (zflg == 0 && np->time == 0 && np->ncall == 0) 167*12892Ssam continue; 168*12892Ssam time = np->time/totime; 169*12892Ssam actime += np->time; 170*12892Ssam printf("%6.1f%9.2f", 100*time, actime/60); 171*12892Ssam if (np->ncall != 0) 172*12892Ssam printf("%7ld %8.2f", 173*12892Ssam np->ncall, np->time/(np->ncall*.06)); 174*12892Ssam else 175*12892Ssam printf("%7.7s %8.8s", "", ""); 176*12892Ssam printf(" %s\n", np->name); 177*12892Ssam } 178*12892Ssam } 179*12892Ssam 180*12892Ssam /* 181*12892Ssam * Set up string and symbol tables from a.out. 182*12892Ssam * On return symbol table is sorted by value. 183*12892Ssam */ 184*12892Ssam getnfile() 185*12892Ssam { 186*12892Ssam 187*12892Ssam nfile = fopen(namfil,"r"); 188*12892Ssam if (nfile == NULL) { 189*12892Ssam perror(namfil); 190*12892Ssam done(); 191*12892Ssam } 192*12892Ssam fread(&xbuf, 1, sizeof(xbuf), nfile); 193*12892Ssam if (N_BADMAG(xbuf)) { 194*12892Ssam fprintf(stderr, "%s: bad format\n", namfil); 195*12892Ssam done(); 196*12892Ssam } 197*12892Ssam getstrtab(); 198*12892Ssam getsymtab(); 199*12892Ssam qsort(nl, nname, sizeof(struct nl), valcmp); 200*12892Ssam } 201*12892Ssam 202*12892Ssam getstrtab() 203*12892Ssam { 204*12892Ssam 205*12892Ssam fseek(nfile, N_SYMOFF(xbuf) + xbuf.a_syms, 0); 206*12892Ssam if (fread(&ssiz, sizeof (ssiz), 1, nfile) == 0) { 207*12892Ssam fprintf(stderr, "%s: no string table (old format?)\n", namfil); 208*12892Ssam done(); 209*12892Ssam } 210*12892Ssam strtab = (char *)calloc(ssiz, 1); 211*12892Ssam if (strtab == NULL) { 212*12892Ssam fprintf(stderr, "%s: no room for %d bytes of string table", 213*12892Ssam namfil, ssiz); 214*12892Ssam done(); 215*12892Ssam } 216*12892Ssam if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1) { 217*12892Ssam fprintf(stderr, "%s: error reading string table\n", namfil); 218*12892Ssam done(); 219*12892Ssam } 220*12892Ssam } 221*12892Ssam 222*12892Ssam /* 223*12892Ssam * Read in symbol table 224*12892Ssam */ 225*12892Ssam getsymtab() 226*12892Ssam { 227*12892Ssam register int i; 228*12892Ssam 229*12892Ssam /* pass1 - count symbols */ 230*12892Ssam fseek(nfile, N_SYMOFF(xbuf), 0); 231*12892Ssam nname = 0; 232*12892Ssam for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { 233*12892Ssam struct nlist nbuf; 234*12892Ssam fread(&nbuf, sizeof(nbuf), 1, nfile); 235*12892Ssam if (nbuf.n_type!=N_TEXT && nbuf.n_type!=N_TEXT+N_EXT) 236*12892Ssam continue; 237*12892Ssam if (aflg==0 && nbuf.n_type!=N_TEXT+N_EXT) 238*12892Ssam continue; 239*12892Ssam nname++; 240*12892Ssam } 241*12892Ssam if (nname == 0) { 242*12892Ssam fprintf(stderr, "%s: no symbols\n", namfil); 243*12892Ssam done(); 244*12892Ssam } 245*12892Ssam nl = (struct nl *)calloc((nname+1), sizeof (struct nl)); 246*12892Ssam if (nl == 0) { 247*12892Ssam fprintf(stderr, "prof: No room for %d bytes of symbol table\n", 248*12892Ssam (nname+1) * sizeof (struct nlist)); 249*12892Ssam done(); 250*12892Ssam } 251*12892Ssam 252*12892Ssam /* pass2 - read symbols */ 253*12892Ssam fseek(nfile, N_SYMOFF(xbuf), 0); 254*12892Ssam npe = nl; 255*12892Ssam nname = 0; 256*12892Ssam for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { 257*12892Ssam struct nlist nbuf; 258*12892Ssam fread(&nbuf, sizeof(nbuf), 1, nfile); 259*12892Ssam if (nbuf.n_type!=N_TEXT && nbuf.n_type!=N_TEXT+N_EXT) 260*12892Ssam continue; 261*12892Ssam if (aflg==0 && nbuf.n_type!=N_TEXT+N_EXT) 262*12892Ssam continue; 263*12892Ssam npe->value = nbuf.n_value/sizeof(UNIT); 264*12892Ssam npe->name = strtab+nbuf.n_un.n_strx; 265*12892Ssam npe++; 266*12892Ssam nname++; 267*12892Ssam } 268*12892Ssam npe->value = -1; 269*12892Ssam npe++; 270*12892Ssam } 271*12892Ssam 272*12892Ssam /* 273*12892Ssam * information from a mon.out file is in two parts: 274*12892Ssam * the counters of how many times each procedure was called, 275*12892Ssam * if it was called at all; 276*12892Ssam * and an array of sampling hits within pc ranges. 277*12892Ssam * the counters must be dealt with on a file-by-file basis, 278*12892Ssam * since which procedures are represented may vary. 279*12892Ssam * the samples ranges are fixed, but must be summed across 280*12892Ssam * files, and then distributed among procedures, because 281*12892Ssam * of the wierd way the plotting is done. 282*12892Ssam */ 283*12892Ssam getpfile(filename) 284*12892Ssam char *filename; 285*12892Ssam { 286*12892Ssam 287*12892Ssam openpfile(filename); 288*12892Ssam readcntrs(); 289*12892Ssam asgncntrs(); /* assign counts to procedures */ 290*12892Ssam readsamples(); 291*12892Ssam closepfile(); 292*12892Ssam } 293*12892Ssam 294*12892Ssam openpfile(filename) 295*12892Ssam char *filename; 296*12892Ssam { 297*12892Ssam struct stat stb; 298*12892Ssam 299*12892Ssam if((pfile = fopen(filename, "r")) == NULL) { 300*12892Ssam perror(filename); 301*12892Ssam done(); 302*12892Ssam } 303*12892Ssam fstat(fileno(pfile), &stb); 304*12892Ssam fread(&h, sizeof(struct hdr), 1, pfile); 305*12892Ssam lowpc = h.lowpc - (UNIT *)0; 306*12892Ssam highpc = h.highpc - (UNIT *)0; 307*12892Ssam sampbytes = 308*12892Ssam stb.st_size - sizeof(struct hdr) - h.ncount*sizeof(struct cnt); 309*12892Ssam nsamples = sampbytes / sizeof (unsigned UNIT); 310*12892Ssam } 311*12892Ssam 312*12892Ssam closepfile() 313*12892Ssam { 314*12892Ssam 315*12892Ssam fclose(pfile); 316*12892Ssam free(cbuf); 317*12892Ssam } 318*12892Ssam 319*12892Ssam readcntrs() 320*12892Ssam { 321*12892Ssam struct cnt *kp; 322*12892Ssam 323*12892Ssam cbuf = (struct cnt *)calloc((h.ncount+1), sizeof (struct cnt)); 324*12892Ssam if (cbuf == 0) { 325*12892Ssam fprintf(stderr, "prof: No room for %d bytes of count buffer\n", 326*12892Ssam (h.ncount+1) * sizeof (struct cnt)); 327*12892Ssam exit(1); 328*12892Ssam } 329*12892Ssam fread(cbuf, sizeof(struct cnt), h.ncount, pfile); 330*12892Ssam /* eliminate zero counters and scale counter pc values */ 331*12892Ssam if (h.ncount) { 332*12892Ssam kp = &cbuf[h.ncount - 1]; 333*12892Ssam for (;;) { 334*12892Ssam if (kp->cvalue==0) { 335*12892Ssam h.ncount=kp-cbuf; 336*12892Ssam ++kp; 337*12892Ssam break; 338*12892Ssam } 339*12892Ssam if (kp == cbuf) { 340*12892Ssam h.ncount = 0; 341*12892Ssam break; 342*12892Ssam } 343*12892Ssam --kp; 344*12892Ssam } 345*12892Ssam for (; --kp>=cbuf; ) 346*12892Ssam kp->cvalue /= sizeof(UNIT); 347*12892Ssam } 348*12892Ssam /* sort counters */ 349*12892Ssam qsort(cbuf, h.ncount, sizeof(struct cnt), cntcmp); 350*12892Ssam } 351*12892Ssam 352*12892Ssam /* 353*12892Ssam * Assign counters to the procedures to which they belong 354*12892Ssam */ 355*12892Ssam asgncntrs() 356*12892Ssam { 357*12892Ssam register int i; 358*12892Ssam struct cnt *kp; 359*12892Ssam 360*12892Ssam kp = &cbuf[h.ncount-1]; 361*12892Ssam np = npe; 362*12892Ssam while (--np>=nl) { 363*12892Ssam if (kp<cbuf || np->value > kp->cvalue) 364*12892Ssam continue; 365*12892Ssam /* skip ``static'' functions */ 366*12892Ssam while (kp >= cbuf && kp->cvalue > np->value + 11) 367*12892Ssam --kp; 368*12892Ssam if (kp->cvalue >= np->value) { 369*12892Ssam np->ncall += kp->cncall; 370*12892Ssam --kp; 371*12892Ssam } 372*12892Ssam } 373*12892Ssam } 374*12892Ssam 375*12892Ssam readsamples() 376*12892Ssam { 377*12892Ssam register i; 378*12892Ssam unsigned UNIT sample; 379*12892Ssam int totalt; 380*12892Ssam 381*12892Ssam if (samples == 0) { 382*12892Ssam samples = (unsigned UNIT *) 383*12892Ssam calloc(sampbytes, sizeof (unsigned UNIT)); 384*12892Ssam if (samples == 0) { 385*12892Ssam printf("prof: No room for %d sample pc's\n", 386*12892Ssam sampbytes / sizeof (unsigned UNIT)); 387*12892Ssam done(); 388*12892Ssam } 389*12892Ssam } 390*12892Ssam for (i = 0; ; i++) { 391*12892Ssam fread(&sample, sizeof (unsigned UNIT), 1, pfile); 392*12892Ssam if (feof(pfile)) 393*12892Ssam break; 394*12892Ssam samples[i] += sample; 395*12892Ssam totalt += sample; 396*12892Ssam } 397*12892Ssam if (i != nsamples) { 398*12892Ssam fprintf(stderr, 399*12892Ssam "prof: unexpected EOF after reading %d/%d samples\n", 400*12892Ssam --i, nsamples); 401*12892Ssam done(); 402*12892Ssam } 403*12892Ssam } 404*12892Ssam 405*12892Ssam /* 406*12892Ssam * Assign samples to the procedures to which they belong. 407*12892Ssam */ 408*12892Ssam asgnsamples() 409*12892Ssam { 410*12892Ssam register j; 411*12892Ssam unsigned UNIT ccnt; 412*12892Ssam double time; 413*12892Ssam unsigned pcl, pch; 414*12892Ssam register int i; 415*12892Ssam int overlap; 416*12892Ssam 417*12892Ssam /* read samples and assign to namelist symbols */ 418*12892Ssam scale = highpc - lowpc; 419*12892Ssam scale /= nsamples; 420*12892Ssam for (i=0; i < nsamples; i++) { 421*12892Ssam ccnt = samples[i]; 422*12892Ssam if (ccnt == 0) 423*12892Ssam continue; 424*12892Ssam pcl = lowpc + scale*i; 425*12892Ssam pch = lowpc + scale*(i+1); 426*12892Ssam time = ccnt; 427*12892Ssam totime += time; 428*12892Ssam if(time > maxtime) 429*12892Ssam maxtime = time; 430*12892Ssam for (j=0; j<nname; j++) { 431*12892Ssam if (pch < nl[j].value) 432*12892Ssam break; 433*12892Ssam if (pcl >= nl[j+1].value) 434*12892Ssam continue; 435*12892Ssam overlap=(min(pch,nl[j+1].value)-max(pcl,nl[j].value)); 436*12892Ssam if (overlap>0) 437*12892Ssam nl[j].time += overlap*time/scale; 438*12892Ssam } 439*12892Ssam } 440*12892Ssam if (totime==0.0) { 441*12892Ssam fprintf(stderr, "No time accumulated\n"); 442*12892Ssam /* 443*12892Ssam done(); 444*12892Ssam */ 445*12892Ssam totime=1.0; 446*12892Ssam } 447*12892Ssam } 448*12892Ssam 449*12892Ssam /* 450*12892Ssam * dump what you have out to a mon.out style file. 451*12892Ssam */ 452*12892Ssam putprof() 453*12892Ssam { 454*12892Ssam FILE *sfile; 455*12892Ssam struct nl *np; 456*12892Ssam struct cnt kp; 457*12892Ssam int i; 458*12892Ssam 459*12892Ssam sfile = fopen(MON_SUMNAME, "w"); 460*12892Ssam if (sfile == NULL) { 461*12892Ssam perror(MON_SUMNAME); 462*12892Ssam done(); 463*12892Ssam } 464*12892Ssam /* 465*12892Ssam * build a new header. 466*12892Ssam * h.lowpc and h.highpc are already fine. 467*12892Ssam * fix h.ncount to count non-zero calls, 468*12892Ssam * and the one zero call which marks the end. 469*12892Ssam */ 470*12892Ssam h.ncount = 0; 471*12892Ssam for (np = nl; np < npe-1 ; np++) 472*12892Ssam if (np->ncall > 0) 473*12892Ssam h.ncount++; 474*12892Ssam h.ncount++; 475*12892Ssam fwrite(&h, sizeof (struct hdr), 1, sfile); 476*12892Ssam for (np = nl; np < npe-1; np++) { 477*12892Ssam if (np->ncall > 0) { 478*12892Ssam kp.cvalue = np->value * sizeof (unsigned UNIT); 479*12892Ssam kp.cncall = np->ncall; 480*12892Ssam fwrite(&kp, sizeof (struct cnt), 1, sfile); 481*12892Ssam } 482*12892Ssam } 483*12892Ssam kp.cvalue = 0; 484*12892Ssam kp.cncall = 0; 485*12892Ssam fwrite(&kp, sizeof (struct cnt), 1, sfile); 486*12892Ssam fwrite(samples, sizeof (unsigned UNIT), nsamples, sfile); 487*12892Ssam fclose(sfile); 488*12892Ssam } 489*12892Ssam 490*12892Ssam min(a, b) 491*12892Ssam { 492*12892Ssam if (a<b) 493*12892Ssam return(a); 494*12892Ssam return(b); 495*12892Ssam } 496*12892Ssam 497*12892Ssam max(a, b) 498*12892Ssam { 499*12892Ssam if (a>b) 500*12892Ssam return(a); 501*12892Ssam return(b); 502*12892Ssam } 503*12892Ssam 504*12892Ssam valcmp(p1, p2) 505*12892Ssam struct nl *p1, *p2; 506*12892Ssam { 507*12892Ssam 508*12892Ssam return(p1->value - p2->value); 509*12892Ssam } 510*12892Ssam 511*12892Ssam timcmp(p1, p2) 512*12892Ssam struct nl *p1, *p2; 513*12892Ssam { 514*12892Ssam float d; 515*12892Ssam 516*12892Ssam if (nflg && p2->ncall != p1->ncall) 517*12892Ssam return (p2->ncall - p1->ncall); 518*12892Ssam d = p2->time - p1->time; 519*12892Ssam if (d > 0.0) 520*12892Ssam return(1); 521*12892Ssam if (d < 0.0) 522*12892Ssam return(-1); 523*12892Ssam return(strcmp(p1->name,p2->name)); 524*12892Ssam } 525*12892Ssam 526*12892Ssam cntcmp(p1, p2) 527*12892Ssam struct cnt *p1, *p2; 528*12892Ssam { 529*12892Ssam 530*12892Ssam return(p1->cvalue - p2->cvalue); 531*12892Ssam } 532*12892Ssam 533*12892Ssam done() 534*12892Ssam { 535*12892Ssam 536*12892Ssam #ifdef plot 537*12892Ssam if(vflg) { 538*12892Ssam point(0, -2040); 539*12892Ssam closepl(); 540*12892Ssam } 541*12892Ssam #endif 542*12892Ssam exit(0); 543*12892Ssam } 544*12892Ssam 545*12892Ssam #ifdef plot 546*12892Ssam plotprof() 547*12892Ssam { 548*12892Ssam double time, lastx, lasty, lastsx; 549*12892Ssam register i; 550*12892Ssam 551*12892Ssam openpl(); 552*12892Ssam erase(); 553*12892Ssam space(-2048, -2048, 2048, 2048); 554*12892Ssam line(-2040, -2040, -2040, 2040); 555*12892Ssam line(0, 2040, 0, -2040); 556*12892Ssam for(i=0; i<11; i++) 557*12892Ssam line(-2040, 2040-i*408, 0, 2040-i*408); 558*12892Ssam lastx = 0.; 559*12892Ssam lasty = ranoff; 560*12892Ssam scale = (4080.*ransca)/(sampbytes/sizeof(UNIT)); 561*12892Ssam lastsx = 0.0; 562*12892Ssam for(i = 0; i < nsamples; i++) { 563*12892Ssam unsigned UNIT ccnt; 564*12892Ssam double tx, ty; 565*12892Ssam ccnt = samples[i]; 566*12892Ssam time = ccnt; 567*12892Ssam tx = lastsx; 568*12892Ssam ty = lasty; 569*12892Ssam lastsx -= 2000.*time/totime; 570*12892Ssam lasty -= scale; 571*12892Ssam if(lasty >= -2040. && ty <= 2040.) { 572*12892Ssam line((int)tx, (int)ty, (int)lastsx, (int)lasty); 573*12892Ssam if (ccnt!=0 || lastx!=0.0) { 574*12892Ssam tx = lastx; 575*12892Ssam lastx = -time*2000./maxtime; 576*12892Ssam ty += scale/2; 577*12892Ssam line(0, (int)ty, (int)tx, (int)ty); 578*12892Ssam } 579*12892Ssam } 580*12892Ssam } 581*12892Ssam scale = (4080.*ransca)/(highpc-lowpc); 582*12892Ssam lastx = 50.; 583*12892Ssam for(np = nl; np<npe; np++) { 584*12892Ssam if(np->value < lowpc) 585*12892Ssam continue; 586*12892Ssam if(np->value >= highpc) 587*12892Ssam continue; 588*12892Ssam time = np->time/totime; 589*12892Ssam lasty = ranoff - (np->value - lowpc)*scale; 590*12892Ssam if(lasty >= -2040. && lasty <= 2040.) { 591*12892Ssam char bufl[BUFSIZ], *namp; 592*12892Ssam register j; 593*12892Ssam line(0, (int)lasty, 50, (int)lasty); 594*12892Ssam line((int)(lastx-50),(int)lasty,(int)lastx,(int)lasty); 595*12892Ssam move((int)(lastx+30), (int)(lasty+10)); 596*12892Ssam sprintf(bufl, "%s", np->name + (np->name[0] == '_')); 597*12892Ssam label(bufl); 598*12892Ssam } 599*12892Ssam lastx += 500.; 600*12892Ssam if(lastx > 2000.) 601*12892Ssam lastx = 50.; 602*12892Ssam } 603*12892Ssam } 604*12892Ssam #endif 605