1: #include <stdio.h>
   2: #include <ctype.h>
   3: #include <math.h>
   4: #define INF 1.e+37
   5: #define F   .25
   6: 
   7: struct xy {
   8:     int xlbf;   /*flag:explicit lower bound*/
   9:     int     xubf;   /*flag:explicit upper bound*/
  10:     int xqf;    /*flag:explicit quantum*/
  11:     double (*xf)(); /*transform function, e.g. log*/
  12:     float   xa,xb;  /*scaling coefficients*/
  13:     float   xlb,xub;    /*lower and upper bound*/
  14:     float   xquant; /*quantum*/
  15:     float   xoff;       /*screen offset fraction*/
  16:     float   xsize;      /*screen fraction*/
  17:     int xbot,xtop;  /*screen coords of border*/
  18:     float   xmult;  /*scaling constant*/
  19: } xd,yd;
  20: struct val {
  21:     float xv;
  22:     float yv;
  23:     int lblptr;
  24: } *xx;
  25: 
  26: char *labs;
  27: int labsiz;
  28: 
  29: int tick = 50;
  30: int top = 4000;
  31: int bot = 200;
  32: float absbot;
  33: int n;
  34: int erasf = 1;
  35: int gridf = 2;
  36: int symbf = 0;
  37: int absf = 0;
  38: int transf;
  39: int brkf;
  40: float   dx;
  41: char    *plotsymb;
  42: 
  43: double  atof();
  44: #define BSIZ 80
  45: char    labbuf[BSIZ];
  46: char    titlebuf[BSIZ];
  47: 
  48: char *modes[] = {
  49:     "disconnected",
  50:     "solid",
  51:     "dotted",
  52:     "dotdashed",
  53:     "shortdashed",
  54:     "longdashed"
  55: };
  56: int mode = 1;
  57: char *realloc();
  58: char *malloc();
  59: 
  60: double ident(x)
  61: double x;
  62: {
  63:     return(x);
  64: }
  65: 
  66: main(argc,argv)
  67: char *argv[];
  68: {
  69: 
  70:     space(0,0,4096,4096);
  71:     init(&xd);
  72:     init(&yd);
  73:     xd.xsize = yd.xsize = 1.;
  74:     xx = (struct val *)malloc((unsigned)sizeof(struct val));
  75:     labs = malloc(1);
  76:     labs[labsiz++] = 0;
  77:     setopt(argc,argv);
  78:     if(erasf)
  79:         erase();
  80:     readin();
  81:     transpose();
  82:     scale(&xd,(struct val *)&xx->xv);
  83:     scale(&yd,(struct val *)&xx->yv);
  84:     axes();
  85:     title();
  86:     plot();
  87:     move(1,1);
  88:     closevt();
  89:     return(0);
  90: }
  91: 
  92: init(p)
  93: struct xy *p;
  94: {
  95:     p->xf = ident;
  96:     p->xmult = 1;
  97: }
  98: 
  99: setopt(argc,argv)
 100: char *argv[];
 101: {
 102:     char *p1, *p2;
 103:     float temp;
 104: 
 105:     xd.xlb = yd.xlb = INF;
 106:     xd.xub = yd.xub = -INF;
 107:     while(--argc > 0) {
 108:         argv++;
 109: again:      switch(argv[0][0]) {
 110:         case '-':
 111:             argv[0]++;
 112:             goto again;
 113:         case 'l': /* label for plot */
 114:             p1 = titlebuf;
 115:             if (argc>=2) {
 116:                 argv++;
 117:                 argc--;
 118:                 p2 = argv[0];
 119:                 while (*p1++ = *p2++);
 120:             }
 121:             break;
 122: 
 123:         case 'd':   /*disconnected,obsolete option*/
 124:         case 'm': /*line mode*/
 125:             mode = 0;
 126:             if(!numb(&temp,&argc,&argv))
 127:                 break;
 128:             if(temp>=sizeof(modes)/sizeof(*modes))
 129:                 mode = 1;
 130:             else if(temp>=0)
 131:                 mode = temp;
 132:             break;
 133: 
 134:         case 'a': /*automatic abscissas*/
 135:             absf = 1;
 136:             dx = 1;
 137:             if(!numb(&dx,&argc,&argv))
 138:                 break;
 139:             if(numb(&absbot,&argc,&argv))
 140:                 absf = 2;
 141:             break;
 142: 
 143:         case 's': /*save screen, overlay plot*/
 144:             erasf = 0;
 145:             break;
 146: 
 147:         case 'g': /*grid style 0 none, 1 ticks, 2 full*/
 148:             gridf = 0;
 149:             if(!numb(&temp,&argc,&argv))
 150:                 temp = argv[0][1]-'0';  /*for caompatibility*/
 151:             if(temp>=0&&temp<=2)
 152:                 gridf = temp;
 153:             break;
 154: 
 155:         case 'c': /*character(s) for plotting*/
 156:             if(argc >= 2) {
 157:                 symbf = 1;
 158:                 plotsymb = argv[1];
 159:                 argv++;
 160:                 argc--;
 161:             }
 162:             break;
 163: 
 164:         case 't':   /*transpose*/
 165:             transf = 1;
 166:             break;
 167:         case 'b':   /*breaks*/
 168:             brkf = 1;
 169:             break;
 170:         case 'x':   /*x limits */
 171:             limread(&xd,&argc,&argv);
 172:             break;
 173:         case 'y':
 174:             limread(&yd,&argc,&argv);
 175:             break;
 176:         case 'h': /*set height of plot */
 177:             if(!numb(&yd.xsize, &argc,&argv))
 178:                 badarg();
 179:             break;
 180:         case 'w': /*set width of plot */
 181:             if(!numb(&xd.xsize, &argc, &argv))
 182:                 badarg();
 183:             break;
 184:         case 'r': /* set offset to right */
 185:             if(!numb(&xd.xoff, &argc, &argv))
 186:                 badarg();
 187:             break;
 188:         case 'u': /*set offset up the screen*/
 189:             if(!numb(&yd.xoff,&argc,&argv))
 190:                 badarg();
 191:             break;
 192:         default:
 193:             badarg();
 194:         }
 195:     }
 196: }
 197: 
 198: limread(p, argcp, argvp)
 199: register struct xy *p;
 200: int *argcp;
 201: char ***argvp;
 202: {
 203:     if(*argcp>1 && (*argvp)[1][0]=='l') {
 204:         (*argcp)--;
 205:         (*argvp)++;
 206:         p->xf = log10;
 207:     }
 208:     if(!numb(&p->xlb,argcp,argvp))
 209:         return;
 210:     p->xlbf = 1;
 211:     if(!numb(&p->xub,argcp,argvp))
 212:         return;
 213:     p->xubf = 1;
 214:     if(!numb(&p->xquant,argcp,argvp))
 215:         return;
 216:     p->xqf = 1;
 217: }
 218: 
 219: numb(np, argcp, argvp)
 220: int *argcp;
 221: float *np;
 222: register char ***argvp;
 223: {
 224:     register char c;
 225: 
 226:     if(*argcp <= 1)
 227:         return(0);
 228:     while((c=(*argvp)[1][0]) == '+')
 229:         (*argvp)[1]++;
 230:     if(!(isdigit(c) || c=='-'&&(*argvp)[1][1]<'A' || c=='.'))
 231:         return(0);
 232:     *np = atof((*argvp)[1]);
 233:     (*argcp)--;
 234:     (*argvp)++;
 235:     return(1);
 236: }
 237: 
 238: readin()
 239: {
 240:     register t;
 241:     struct val *temp;
 242: 
 243:     if(absf==1) {
 244:         if(xd.xlbf)
 245:             absbot = xd.xlb;
 246:         else if(xd.xf==log10)
 247:             absbot = 1;
 248:     }
 249:     for(;;) {
 250:         temp = (struct val *)realloc((char*)xx,
 251:             (unsigned)(n+1)*sizeof(struct val));
 252:         if(temp==0)
 253:             return;
 254:         xx = temp;
 255:         if(absf)
 256:             xx[n].xv = n*dx + absbot;
 257:         else
 258:             if(!getfloat(&xx[n].xv))
 259:                 return;
 260:         if(!getfloat(&xx[n].yv))
 261:             return;
 262:         xx[n].lblptr = -1;
 263:         t = getstring();
 264:         if(t>0)
 265:             xx[n].lblptr = copystring(t);
 266:         n++;
 267:         if(t<0)
 268:             return;
 269:     }
 270: }
 271: 
 272: transpose()
 273: {
 274:     register i;
 275:     float f;
 276:     struct xy t;
 277:     if(!transf)
 278:         return;
 279:     t = xd; xd = yd; yd = t;
 280:     for(i= 0;i<n;i++) {
 281:         f = xx[i].xv; xx[i].xv = xx[i].yv; xx[i].yv = f;
 282:     }
 283: }
 284: 
 285: copystring(k)
 286: {
 287:     register char *temp;
 288:     register i;
 289:     int q;
 290: 
 291:     temp = realloc(labs,(unsigned)(labsiz+1+k));
 292:     if(temp==0)
 293:         return(0);
 294:     labs = temp;
 295:     q = labsiz;
 296:     for(i=0;i<=k;i++)
 297:         labs[labsiz++] = labbuf[i];
 298:     return(q);
 299: }
 300: 
 301: float
 302: modceil(f,t)
 303: float f,t;
 304: {
 305: 
 306:     t = fabs(t);
 307:     return(ceil(f/t)*t);
 308: }
 309: 
 310: float
 311: modfloor(f,t)
 312: float f,t;
 313: {
 314:     t = fabs(t);
 315:     return(floor(f/t)*t);
 316: }
 317: 
 318: getlim(p,v)
 319: register struct xy *p;
 320: struct val *v;
 321: {
 322:     register i;
 323: 
 324:     i = 0;
 325:     do {
 326:         if(!p->xlbf && p->xlb>v[i].xv)
 327:             p->xlb = v[i].xv;
 328:         if(!p->xubf && p->xub<v[i].xv)
 329:             p->xub = v[i].xv;
 330:         i++;
 331:     } while(i < n);
 332: }
 333: 
 334: struct z {
 335:     float lb,ub,mult,quant;
 336: } setloglim(), setlinlim();
 337: 
 338: setlim(p)
 339: register struct xy *p;
 340: {
 341:     float t,delta,sign;
 342:     struct z z;
 343:     int mark[50];
 344:     float lb,ub;
 345:     int lbf,ubf;
 346: 
 347:     lb = p->xlb;
 348:     ub = p->xub;
 349:     delta = ub-lb;
 350:     if(p->xqf) {
 351:         if(delta*p->xquant <=0 )
 352:             badarg();
 353:         return;
 354:     }
 355:     sign = 1;
 356:     lbf = p->xlbf;
 357:     ubf = p->xubf;
 358:     if(delta < 0) {
 359:         sign = -1;
 360:         t = lb;
 361:         lb = ub;
 362:         ub = t;
 363:         t = lbf;
 364:         lbf = ubf;
 365:         ubf = t;
 366:     }
 367:     else if(delta == 0) {
 368:         if(ub > 0) {
 369:             ub = 2*ub;
 370:             lb = 0;
 371:         }
 372:         else
 373:             if(lb < 0) {
 374:                 lb = 2*lb;
 375:                 ub = 0;
 376:             }
 377:             else {
 378:                 ub = 1;
 379:                 lb = -1;
 380:             }
 381:     }
 382:     if(p->xf==log10 && lb>0 && ub>lb) {
 383:         z = setloglim(lbf,ubf,lb,ub);
 384:         p->xlb = z.lb;
 385:         p->xub = z.ub;
 386:         p->xmult *= z.mult;
 387:         p->xquant = z.quant;
 388:         if(setmark(mark,p)<2) {
 389:             p->xqf = lbf = ubf = 1;
 390:             lb = z.lb; ub = z.ub;
 391:         } else
 392:             return;
 393:     }
 394:     z = setlinlim(lbf,ubf,lb,ub);
 395:     if(sign > 0) {
 396:         p->xlb = z.lb;
 397:         p->xub = z.ub;
 398:     } else {
 399:         p->xlb = z.ub;
 400:         p->xub = z.lb;
 401:     }
 402:     p->xmult *= z.mult;
 403:     p->xquant = sign*z.quant;
 404: }
 405: 
 406: struct z
 407: setloglim(lbf,ubf,lb,ub)
 408: float lb,ub;
 409: {
 410:     float r,s,t;
 411:     struct z z;
 412: 
 413:     for(s=1; lb*s<1; s*=10) ;
 414:     lb *= s;
 415:     ub *= s;
 416:     for(r=1; 10*r<=lb; r*=10) ;
 417:     for(t=1; t<ub; t*=10) ;
 418:     z.lb = !lbf ? r : lb;
 419:     z.ub = !ubf ? t : ub;
 420:     if(ub/lb<100) {
 421:         if(!lbf) {
 422:             if(lb >= 5*z.lb)
 423:                 z.lb *= 5;
 424:             else if(lb >= 2*z.lb)
 425:                 z.lb *= 2;
 426:         }
 427:         if(!ubf) {
 428:             if(ub*5 <= z.ub)
 429:                 z.ub /= 5;
 430:             else if(ub*2 <= z.ub)
 431:                 z.ub /= 2;
 432:         }
 433:     }
 434:     z.mult = s;
 435:     z.quant = r;
 436:     return(z);
 437: }
 438: 
 439: struct z
 440: setlinlim(lbf,ubf,xlb,xub)
 441: int lbf,ubf;
 442: float xlb,xub;
 443: {
 444:     struct z z;
 445:     float r,s,delta;
 446:     float ub,lb;
 447: 
 448: loop:
 449:     ub = xub;
 450:     lb = xlb;
 451:     delta = ub - lb;
 452:     /*scale up by s, a power of 10, so range (delta) exceeds 1*/
 453:     /*find power of 10 quantum, r, such that delta/10<=r<delta*/
 454:     r = s = 1;
 455:     while(delta*s < 10)
 456:         s *= 10;
 457:     delta *= s;
 458:     while(10*r < delta)
 459:         r *= 10;
 460:     lb *= s;
 461:     ub *= s;
 462:     /*set r=(1,2,5)*10**n so that 3-5 quanta cover range*/
 463:     if(r>=delta/2)
 464:         r /= 2;
 465:     else if(r<delta/5)
 466:         r *= 2;
 467:     z.ub = ubf? ub: modceil(ub,r);
 468:     z.lb = lbf? lb: modfloor(lb,r);
 469:     if(!lbf && z.lb<=r && z.lb>0) {
 470:         xlb = 0;
 471:         goto loop;
 472:     }
 473:     else if(!ubf && z.ub>=-r && z.ub<0) {
 474:         xub = 0;
 475:         goto loop;
 476:     }
 477:     z.quant = r;
 478:     z.mult = s;
 479:     return(z);
 480: }
 481: 
 482: scale(p,v)
 483: register struct xy *p;
 484: struct val *v;
 485: {
 486:     float edge;
 487: 
 488:     getlim(p,v);
 489:     setlim(p);
 490:     edge = top-bot;
 491:     p->xa = p->xsize*edge/((*p->xf)(p->xub) - (*p->xf)(p->xlb));
 492:     p->xbot = bot + edge*p->xoff;
 493:     p->xtop = p->xbot + (top-bot)*p->xsize;
 494:     p->xb = p->xbot - (*p->xf)(p->xlb)*p->xa + .5;
 495: }
 496: 
 497: axes()
 498: {
 499:     register i;
 500:     int mark[50];
 501:     int xn, yn;
 502:     if(gridf==0)
 503:         return;
 504: 
 505:     line(xd.xbot,yd.xbot,xd.xtop,yd.xbot);
 506:     cont(xd.xtop,yd.xtop);
 507:     cont(xd.xbot,yd.xtop);
 508:     cont(xd.xbot,yd.xbot);
 509: 
 510:     xn = setmark(mark,&xd);
 511:     for(i=0; i<xn; i++) {
 512:         if(gridf==2)
 513:             line(mark[i],yd.xbot,mark[i],yd.xtop);
 514:         if(gridf==1) {
 515:             line(mark[i],yd.xbot,mark[i],yd.xbot+tick);
 516:             line(mark[i],yd.xtop-tick,mark[i],yd.xtop);
 517:         }
 518:     }
 519:     yn = setmark(mark,&yd);
 520:     for(i=0; i<yn; i++) {
 521:         if(gridf==2)
 522:             line(xd.xbot,mark[i],xd.xtop,mark[i]);
 523:         if(gridf==1) {
 524:             line(xd.xbot,mark[i],xd.xbot+tick,mark[i]);
 525:             line(xd.xtop-tick,mark[i],xd.xtop,mark[i]);
 526:         }
 527:     }
 528: }
 529: 
 530: setmark(xmark,p)
 531: int *xmark;
 532: register struct xy *p;
 533: {
 534:     int xn = 0;
 535:     float x,xl,xu;
 536:     float q;
 537:     if(p->xf==log10&&!p->xqf) {
 538:         for(x=p->xquant; x<p->xub; x*=10) {
 539:             submark(xmark,&xn,x,p);
 540:             if(p->xub/p->xlb<=100) {
 541:                 submark(xmark,&xn,2*x,p);
 542:                 submark(xmark,&xn,5*x,p);
 543:             }
 544:         }
 545:     } else {
 546:         xn = 0;
 547:         q = p->xquant;
 548:         if(q>0) {
 549:             xl = modceil(p->xlb+q/6,q);
 550:             xu = modfloor(p->xub-q/6,q)+q/2;
 551:         } else {
 552:             xl = modceil(p->xub-q/6,q);
 553:             xu = modfloor(p->xlb+q/6,q)-q/2;
 554:         }
 555:         for(x=xl; x<=xu; x+=fabs(p->xquant))
 556:             xmark[xn++] = (*p->xf)(x)*p->xa + p->xb;
 557:     }
 558:     return(xn);
 559: }
 560: submark(xmark,pxn,x,p)
 561: int *xmark;
 562: int *pxn;
 563: float x;
 564: struct xy *p;
 565: {
 566:     if(1.001*p->xlb < x && .999*p->xub > x)
 567:         xmark[(*pxn)++] = log10(x)*p->xa + p->xb;
 568: }
 569: 
 570: plot()
 571: {
 572:     int ix,iy;
 573:     int i;
 574:     int conn;
 575: 
 576:     conn = 0;
 577:     if(mode!=0)
 578:         linemod(modes[mode]);
 579:     for(i=0; i<n; i++) {
 580:         if(!conv(xx[i].xv,&xd,&ix) ||
 581:            !conv(xx[i].yv,&yd,&iy)) {
 582:             conn = 0;
 583:             continue;
 584:         }
 585:         if(mode!=0) {
 586:             if(conn != 0)
 587:                 cont(ix,iy);
 588:             else
 589:                 move(ix,iy);
 590:             conn = 1;
 591:         }
 592:         conn &= symbol(ix,iy,xx[i].lblptr);
 593:     }
 594:     linemod(modes[1]);
 595: }
 596: 
 597: conv(xv,p,ip)
 598: float xv;
 599: register struct xy *p;
 600: int *ip;
 601: {
 602:     long ix;
 603:     ix = p->xa*(*p->xf)(xv*p->xmult) + p->xb;
 604:     if(ix<p->xbot || ix>p->xtop)
 605:         return(0);
 606:     *ip = ix;
 607:     return(1);
 608: }
 609: 
 610: getfloat(p)
 611: float *p;
 612: {
 613:     register i;
 614: 
 615:     i = scanf("%f",p);
 616:     return(i==1);
 617: }
 618: 
 619: getstring()
 620: {
 621:     register i;
 622:     char junk[20];
 623:     i = scanf("%1s",labbuf);
 624:     if(i==-1)
 625:         return(-1);
 626:     switch(*labbuf) {
 627:     default:
 628:         if(!isdigit(*labbuf)) {
 629:             ungetc(*labbuf,stdin);
 630:             i = scanf("%s",labbuf);
 631:             break;
 632:         }
 633:     case '.':
 634:     case '+':
 635:     case '-':
 636:         ungetc(*labbuf,stdin);
 637:         return(0);
 638:     case '"':
 639:         i = scanf("%[^\"\n]",labbuf);
 640:         scanf("%[\"]",junk);
 641:         break;
 642:     }
 643:     if(i==-1)
 644:         return(-1);
 645:     return(strlen(labbuf));
 646: }
 647: 
 648: 
 649: symbol(ix,iy,k)
 650: {
 651: 
 652:     if(symbf==0&&k<0) {
 653:         if(mode==0)
 654:             point(ix,iy);
 655:         return(1);
 656:     }
 657:     else {
 658:         move(ix,iy);
 659:         label(k>=0?labs+k:plotsymb);
 660:         move(ix,iy);
 661:         return(!brkf|k<0);
 662:     }
 663: }
 664: 
 665: title()
 666: {
 667:     move(xd.xbot,yd.xbot-60);
 668:     if (titlebuf[0]) {
 669:         label(titlebuf);
 670:         label("       ");
 671:     }
 672:     if(erasf&&gridf) {
 673:         axlab('x',&xd);
 674:         label("  ");
 675:         axlab('y',&yd);
 676:     }
 677: }
 678: 
 679: axlab(c,p)
 680: char c;
 681: struct xy *p;
 682: {
 683:     char buf[50];
 684:     sprintf(buf,"%g -%s%c- %g", p->xlb/p->xmult,
 685:         p->xf==log10?"log ":"", c, p->xub/p->xmult);
 686:     label(buf);
 687: }
 688: 
 689: badarg()
 690: {
 691:     fprintf(stderr,"graph: error in arguments\n");
 692:     exit(1);
 693: }

Defined functions

axes defined in line 497; used 1 times
  • in line 84
axlab defined in line 679; used 2 times
badarg defined in line 689; used 6 times
conv defined in line 597; used 2 times
copystring defined in line 285; used 1 times
getfloat defined in line 610; used 2 times
getlim defined in line 318; used 1 times
getstring defined in line 619; used 1 times
ident defined in line 60; used 1 times
  • in line 95
init defined in line 92; used 2 times
limread defined in line 198; used 2 times
main defined in line 66; never used
modceil defined in line 301; used 3 times
modfloor defined in line 310; used 3 times
numb defined in line 219; used 11 times
plot defined in line 570; used 1 times
  • in line 86
readin defined in line 238; used 1 times
  • in line 80
scale defined in line 482; used 2 times
setlim defined in line 338; used 1 times
setlinlim defined in line 439; used 2 times
setloglim defined in line 406; used 2 times
setmark defined in line 530; used 3 times
setopt defined in line 99; used 1 times
  • in line 77
submark defined in line 560; used 3 times
symbol defined in line 649; used 1 times
title defined in line 665; used 1 times
  • in line 85
transpose defined in line 272; used 1 times
  • in line 81

Defined variables

absbot defined in line 32; used 4 times
absf defined in line 37; used 4 times
bot defined in line 31; used 3 times
brkf defined in line 39; used 2 times
dx defined in line 40; used 3 times
erasf defined in line 34; used 3 times
gridf defined in line 35; used 8 times
labbuf defined in line 45; used 9 times
labs defined in line 26; used 6 times
labsiz defined in line 27; used 4 times
mode defined in line 56; used 7 times
modes defined in line 48; used 4 times
n defined in line 33; used 11 times
plotsymb defined in line 41; used 2 times
symbf defined in line 36; used 2 times
tick defined in line 29; used 4 times
titlebuf defined in line 46; used 3 times
top defined in line 30; used 2 times
transf defined in line 38; used 2 times
xd defined in line 19; used 28 times
xx defined in line 24; used 17 times
yd defined in line 19; used 25 times

Defined struct's

val defined in line 20; used 18 times
xy defined in line 7; used 20 times
z defined in line 334; used 10 times

Defined macros

BSIZ defined in line 44; used 2 times
F defined in line 5; never used
INF defined in line 4; used 2 times
Last modified: 1979-01-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1945
Valid CSS Valid XHTML 1.0 Strict