148262Sbostic /*- 248262Sbostic * Copyright (c) 1991 The Regents of the University of California. 348262Sbostic * All rights reserved. 448262Sbostic * 548262Sbostic * %sccs.include.proprietary.c% 648262Sbostic */ 748262Sbostic 811779Ssam #ifndef lint 948262Sbostic char copyright[] = 1048262Sbostic "@(#) Copyright (c) 1991 The Regents of the University of California.\n\ 1148262Sbostic All rights reserved.\n"; 1248262Sbostic #endif /* not lint */ 1311779Ssam 1448262Sbostic #ifndef lint 15*56022Sbostic static char sccsid[] = "@(#)graph.c 5.1 (Berkeley) 08/25/92"; 1648262Sbostic #endif /* not lint */ 1748262Sbostic 1811778Ssam #include <stdio.h> 1911778Ssam #include <ctype.h> 2011778Ssam #include <math.h> 2111778Ssam #define F .25 2211778Ssam 2311778Ssam struct xy { 2411778Ssam int xlbf; /*flag:explicit lower bound*/ 2511778Ssam int xubf; /*flag:explicit upper bound*/ 2611778Ssam int xqf; /*flag:explicit quantum*/ 27*56022Sbostic double __pure (*xf)(); /*transform function, e.g. log*/ 2811778Ssam float xa,xb; /*scaling coefficients*/ 2911778Ssam float xlb,xub; /*lower and upper bound*/ 3011778Ssam float xquant; /*quantum*/ 3111778Ssam float xoff; /*screen offset fraction*/ 3211778Ssam float xsize; /*screen fraction*/ 3311778Ssam int xbot,xtop; /*screen coords of border*/ 3411778Ssam float xmult; /*scaling constant*/ 3511778Ssam } xd,yd; 3611778Ssam struct val { 3711778Ssam float xv; 3811778Ssam float yv; 3911778Ssam int lblptr; 4011778Ssam } *xx; 4111778Ssam 42*56022Sbostic char *labels; 4311778Ssam int labsiz; 4411778Ssam 4511778Ssam int tick = 50; 4611778Ssam int top = 4000; 4711778Ssam int bot = 200; 4811778Ssam float absbot; 4911778Ssam int n; 5011778Ssam int erasf = 1; 5111778Ssam int gridf = 2; 5211778Ssam int symbf = 0; 5311778Ssam int absf = 0; 5411778Ssam int transf; 5511778Ssam int brkf; 5611778Ssam float dx; 5711778Ssam char *plotsymb; 5811778Ssam 5911778Ssam double atof(); 6011778Ssam #define BSIZ 80 6111778Ssam char labbuf[BSIZ]; 6211778Ssam char titlebuf[BSIZ]; 6311778Ssam 6411778Ssam char *modes[] = { 6511778Ssam "disconnected", 6611778Ssam "solid", 6711778Ssam "dotted", 6811778Ssam "dotdashed", 6911778Ssam "shortdashed", 7011778Ssam "longdashed" 7111778Ssam }; 7211778Ssam int mode = 1; 7311778Ssam char *realloc(); 7411778Ssam char *malloc(); 7511778Ssam 76*56022Sbostic double __pure ident(x) 7711778Ssam double x; 7811778Ssam { 7911778Ssam return(x); 8011778Ssam } 8111778Ssam 8211778Ssam main(argc,argv) 8311778Ssam char *argv[]; 8411778Ssam { 8511778Ssam 8611778Ssam space(0,0,4096,4096); 8711778Ssam init(&xd); 8811778Ssam init(&yd); 8911778Ssam xd.xsize = yd.xsize = 1.; 9011778Ssam xx = (struct val *)malloc((unsigned)sizeof(struct val)); 91*56022Sbostic labels = malloc(1); 92*56022Sbostic labels[labsiz++] = 0; 9311778Ssam setopt(argc,argv); 9411778Ssam if(erasf) 9511778Ssam erase(); 9611778Ssam readin(); 9711778Ssam transpose(); 9811778Ssam scale(&xd,(struct val *)&xx->xv); 9911778Ssam scale(&yd,(struct val *)&xx->yv); 10011778Ssam axes(); 10111778Ssam title(); 10211778Ssam plot(); 10311778Ssam move(1,1); 10411778Ssam closevt(); 10511778Ssam return(0); 10611778Ssam } 10711778Ssam 10811778Ssam init(p) 10911778Ssam struct xy *p; 11011778Ssam { 11111778Ssam p->xf = ident; 11211778Ssam p->xmult = 1; 11311778Ssam } 11411778Ssam 11511778Ssam setopt(argc,argv) 11611778Ssam char *argv[]; 11711778Ssam { 11811778Ssam char *p1, *p2; 11911778Ssam float temp; 12011778Ssam 12150845Storek xd.xlb = yd.xlb = 0; 12250845Storek xd.xub = yd.xub = 0; 12311778Ssam while(--argc > 0) { 12411778Ssam argv++; 12511778Ssam again: switch(argv[0][0]) { 12611778Ssam case '-': 12711778Ssam argv[0]++; 12811778Ssam goto again; 12911778Ssam case 'l': /* label for plot */ 13011778Ssam p1 = titlebuf; 13111778Ssam if (argc>=2) { 13211778Ssam argv++; 13311778Ssam argc--; 13411778Ssam p2 = argv[0]; 13511778Ssam while (*p1++ = *p2++); 13611778Ssam } 13711778Ssam break; 13811778Ssam 13911778Ssam case 'd': /*disconnected,obsolete option*/ 14011778Ssam case 'm': /*line mode*/ 14111778Ssam mode = 0; 14211778Ssam if(!numb(&temp,&argc,&argv)) 14311778Ssam break; 14411778Ssam if(temp>=sizeof(modes)/sizeof(*modes)) 14511778Ssam mode = 1; 14611778Ssam else if(temp>=0) 14711778Ssam mode = temp; 14811778Ssam break; 14911778Ssam 15011778Ssam case 'a': /*automatic abscissas*/ 15111778Ssam absf = 1; 15211778Ssam dx = 1; 15311778Ssam if(!numb(&dx,&argc,&argv)) 15411778Ssam break; 15511778Ssam if(numb(&absbot,&argc,&argv)) 15611778Ssam absf = 2; 15711778Ssam break; 15811778Ssam 15911778Ssam case 's': /*save screen, overlay plot*/ 16011778Ssam erasf = 0; 16111778Ssam break; 16211778Ssam 16311778Ssam case 'g': /*grid style 0 none, 1 ticks, 2 full*/ 16411778Ssam gridf = 0; 16511778Ssam if(!numb(&temp,&argc,&argv)) 16611778Ssam temp = argv[0][1]-'0'; /*for caompatibility*/ 16711778Ssam if(temp>=0&&temp<=2) 16811778Ssam gridf = temp; 16911778Ssam break; 17011778Ssam 17111778Ssam case 'c': /*character(s) for plotting*/ 17211778Ssam if(argc >= 2) { 17311778Ssam symbf = 1; 17411778Ssam plotsymb = argv[1]; 17511778Ssam argv++; 17611778Ssam argc--; 17711778Ssam } 17811778Ssam break; 17911778Ssam 18011778Ssam case 't': /*transpose*/ 18111778Ssam transf = 1; 18211778Ssam break; 18311778Ssam case 'b': /*breaks*/ 18411778Ssam brkf = 1; 18511778Ssam break; 18611778Ssam case 'x': /*x limits */ 18711778Ssam limread(&xd,&argc,&argv); 18811778Ssam break; 18911778Ssam case 'y': 19011778Ssam limread(&yd,&argc,&argv); 19111778Ssam break; 19211778Ssam case 'h': /*set height of plot */ 19311778Ssam if(!numb(&yd.xsize, &argc,&argv)) 19411778Ssam badarg(); 19511778Ssam break; 19611778Ssam case 'w': /*set width of plot */ 19711778Ssam if(!numb(&xd.xsize, &argc, &argv)) 19811778Ssam badarg(); 19911778Ssam break; 20011778Ssam case 'r': /* set offset to right */ 20111778Ssam if(!numb(&xd.xoff, &argc, &argv)) 20211778Ssam badarg(); 20311778Ssam break; 20411778Ssam case 'u': /*set offset up the screen*/ 20511778Ssam if(!numb(&yd.xoff,&argc,&argv)) 20611778Ssam badarg(); 20711778Ssam break; 20811778Ssam default: 20911778Ssam badarg(); 21011778Ssam } 21111778Ssam } 21211778Ssam } 21311778Ssam 21411778Ssam limread(p, argcp, argvp) 21511778Ssam register struct xy *p; 21611778Ssam int *argcp; 21711778Ssam char ***argvp; 21811778Ssam { 21911778Ssam if(*argcp>1 && (*argvp)[1][0]=='l') { 22011778Ssam (*argcp)--; 22111778Ssam (*argvp)++; 22211778Ssam p->xf = log10; 22311778Ssam } 22411778Ssam if(!numb(&p->xlb,argcp,argvp)) 22511778Ssam return; 22611778Ssam p->xlbf = 1; 22711778Ssam if(!numb(&p->xub,argcp,argvp)) 22811778Ssam return; 22911778Ssam p->xubf = 1; 23011778Ssam if(!numb(&p->xquant,argcp,argvp)) 23111778Ssam return; 23211778Ssam p->xqf = 1; 23311778Ssam } 23411778Ssam 23511778Ssam numb(np, argcp, argvp) 23611778Ssam int *argcp; 23711778Ssam float *np; 23811778Ssam register char ***argvp; 23911778Ssam { 24011778Ssam register char c; 24111778Ssam 24211778Ssam if(*argcp <= 1) 24311778Ssam return(0); 24411778Ssam while((c=(*argvp)[1][0]) == '+') 24511778Ssam (*argvp)[1]++; 24611778Ssam if(!(isdigit(c) || c=='-'&&(*argvp)[1][1]<'A' || c=='.')) 24711778Ssam return(0); 24811778Ssam *np = atof((*argvp)[1]); 24911778Ssam (*argcp)--; 25011778Ssam (*argvp)++; 25111778Ssam return(1); 25211778Ssam } 25311778Ssam 25411778Ssam readin() 25511778Ssam { 25611778Ssam register t; 25711778Ssam struct val *temp; 25811778Ssam 25911778Ssam if(absf==1) { 26011778Ssam if(xd.xlbf) 26111778Ssam absbot = xd.xlb; 26211778Ssam else if(xd.xf==log10) 26311778Ssam absbot = 1; 26411778Ssam } 26511778Ssam for(;;) { 26611778Ssam temp = (struct val *)realloc((char*)xx, 26711778Ssam (unsigned)(n+1)*sizeof(struct val)); 26811778Ssam if(temp==0) 26911778Ssam return; 27011778Ssam xx = temp; 27111778Ssam if(absf) 27211778Ssam xx[n].xv = n*dx + absbot; 27311778Ssam else 27411778Ssam if(!getfloat(&xx[n].xv)) 27511778Ssam return; 27611778Ssam if(!getfloat(&xx[n].yv)) 27711778Ssam return; 27811778Ssam xx[n].lblptr = -1; 27911778Ssam t = getstring(); 28011778Ssam if(t>0) 28111778Ssam xx[n].lblptr = copystring(t); 28211778Ssam n++; 28311778Ssam if(t<0) 28411778Ssam return; 28511778Ssam } 28611778Ssam } 28711778Ssam 28811778Ssam transpose() 28911778Ssam { 29011778Ssam register i; 29111778Ssam float f; 29211778Ssam struct xy t; 29311778Ssam if(!transf) 29411778Ssam return; 29511778Ssam t = xd; xd = yd; yd = t; 29611778Ssam for(i= 0;i<n;i++) { 29711778Ssam f = xx[i].xv; xx[i].xv = xx[i].yv; xx[i].yv = f; 29811778Ssam } 29911778Ssam } 30011778Ssam 30111778Ssam copystring(k) 30211778Ssam { 30311778Ssam register char *temp; 30411778Ssam register i; 30511778Ssam int q; 30611778Ssam 307*56022Sbostic temp = realloc(labels,(unsigned)(labsiz+1+k)); 30811778Ssam if(temp==0) 30911778Ssam return(0); 310*56022Sbostic labels = temp; 31111778Ssam q = labsiz; 31211778Ssam for(i=0;i<=k;i++) 313*56022Sbostic labels[labsiz++] = labbuf[i]; 31411778Ssam return(q); 31511778Ssam } 31611778Ssam 31711778Ssam float 31811778Ssam modceil(f,t) 31911778Ssam float f,t; 32011778Ssam { 32111778Ssam 32211778Ssam t = fabs(t); 32311778Ssam return(ceil(f/t)*t); 32411778Ssam } 32511778Ssam 32611778Ssam float 32711778Ssam modfloor(f,t) 32811778Ssam float f,t; 32911778Ssam { 33011778Ssam t = fabs(t); 33111778Ssam return(floor(f/t)*t); 33211778Ssam } 33311778Ssam 33450845Storek /* 33550845Storek * Compute upper and lower bounds for the given descriptor. 33650845Storek * We may already have one or both. We assume that if n==0, 33750845Storek * v[0].xv is a valid limit value. 33850845Storek */ 33911778Ssam getlim(p,v) 34011778Ssam register struct xy *p; 34111778Ssam struct val *v; 34211778Ssam { 34311778Ssam register i; 34411778Ssam 34550845Storek if (!p->xlbf) { /* need lower bound */ 34650845Storek p->xlb = v[0].xv; 34750845Storek for (i = 1; i < n; i++) 34850845Storek if (p->xlb > v[i].xv) 34950845Storek p->xlb = v[i].xv; 35050845Storek } 35150845Storek if (!p->xubf) { /* need upper bound */ 35250845Storek p->xub = v[0].xv; 35350845Storek for (i = 1; i < n; i++) 35450845Storek if (p->xub < v[i].xv) 35550845Storek p->xub = v[i].xv; 35650845Storek } 35711778Ssam } 35811778Ssam 35911778Ssam struct z { 36011778Ssam float lb,ub,mult,quant; 36111778Ssam } setloglim(), setlinlim(); 36211778Ssam 36311778Ssam setlim(p) 36411778Ssam register struct xy *p; 36511778Ssam { 36611778Ssam float t,delta,sign; 36711778Ssam struct z z; 36811778Ssam int mark[50]; 36911778Ssam float lb,ub; 37011778Ssam int lbf,ubf; 37111778Ssam 37211778Ssam lb = p->xlb; 37311778Ssam ub = p->xub; 37411778Ssam delta = ub-lb; 37511778Ssam if(p->xqf) { 37611778Ssam if(delta*p->xquant <=0 ) 37711778Ssam badarg(); 37811778Ssam return; 37911778Ssam } 38011778Ssam sign = 1; 38111778Ssam lbf = p->xlbf; 38211778Ssam ubf = p->xubf; 38311778Ssam if(delta < 0) { 38411778Ssam sign = -1; 38511778Ssam t = lb; 38611778Ssam lb = ub; 38711778Ssam ub = t; 38811778Ssam t = lbf; 38911778Ssam lbf = ubf; 39011778Ssam ubf = t; 39111778Ssam } 39211778Ssam else if(delta == 0) { 39311778Ssam if(ub > 0) { 39411778Ssam ub = 2*ub; 39511778Ssam lb = 0; 39611778Ssam } 39711778Ssam else 39811778Ssam if(lb < 0) { 39911778Ssam lb = 2*lb; 40011778Ssam ub = 0; 40111778Ssam } 40211778Ssam else { 40311778Ssam ub = 1; 40411778Ssam lb = -1; 40511778Ssam } 40611778Ssam } 40711778Ssam if(p->xf==log10 && lb>0 && ub>lb) { 40811778Ssam z = setloglim(lbf,ubf,lb,ub); 40911778Ssam p->xlb = z.lb; 41011778Ssam p->xub = z.ub; 41111778Ssam p->xmult *= z.mult; 41211778Ssam p->xquant = z.quant; 41311778Ssam if(setmark(mark,p)<2) { 41411778Ssam p->xqf = lbf = ubf = 1; 41511778Ssam lb = z.lb; ub = z.ub; 41611778Ssam } else 41711778Ssam return; 41811778Ssam } 41911778Ssam z = setlinlim(lbf,ubf,lb,ub); 42011778Ssam if(sign > 0) { 42111778Ssam p->xlb = z.lb; 42211778Ssam p->xub = z.ub; 42311778Ssam } else { 42411778Ssam p->xlb = z.ub; 42511778Ssam p->xub = z.lb; 42611778Ssam } 42711778Ssam p->xmult *= z.mult; 42811778Ssam p->xquant = sign*z.quant; 42911778Ssam } 43011778Ssam 43111778Ssam struct z 43211778Ssam setloglim(lbf,ubf,lb,ub) 43311778Ssam float lb,ub; 43411778Ssam { 43511778Ssam float r,s,t; 43611778Ssam struct z z; 43711778Ssam 43811778Ssam for(s=1; lb*s<1; s*=10) ; 43911778Ssam lb *= s; 44011778Ssam ub *= s; 44111778Ssam for(r=1; 10*r<=lb; r*=10) ; 44211778Ssam for(t=1; t<ub; t*=10) ; 44311778Ssam z.lb = !lbf ? r : lb; 44411778Ssam z.ub = !ubf ? t : ub; 44511778Ssam if(ub/lb<100) { 44611778Ssam if(!lbf) { 44711778Ssam if(lb >= 5*z.lb) 44811778Ssam z.lb *= 5; 44911778Ssam else if(lb >= 2*z.lb) 45011778Ssam z.lb *= 2; 45111778Ssam } 45211778Ssam if(!ubf) { 45311778Ssam if(ub*5 <= z.ub) 45411778Ssam z.ub /= 5; 45511778Ssam else if(ub*2 <= z.ub) 45611778Ssam z.ub /= 2; 45711778Ssam } 45811778Ssam } 45911778Ssam z.mult = s; 46011778Ssam z.quant = r; 46111778Ssam return(z); 46211778Ssam } 46311778Ssam 46411778Ssam struct z 46511778Ssam setlinlim(lbf,ubf,xlb,xub) 46611778Ssam int lbf,ubf; 46711778Ssam float xlb,xub; 46811778Ssam { 46911778Ssam struct z z; 47011778Ssam float r,s,delta; 47111778Ssam float ub,lb; 47211778Ssam 47311778Ssam loop: 47411778Ssam ub = xub; 47511778Ssam lb = xlb; 47611778Ssam delta = ub - lb; 47711778Ssam /*scale up by s, a power of 10, so range (delta) exceeds 1*/ 47811778Ssam /*find power of 10 quantum, r, such that delta/10<=r<delta*/ 47911778Ssam r = s = 1; 48011778Ssam while(delta*s < 10) 48111778Ssam s *= 10; 48211778Ssam delta *= s; 48311778Ssam while(10*r < delta) 48411778Ssam r *= 10; 48511778Ssam lb *= s; 48611778Ssam ub *= s; 48711778Ssam /*set r=(1,2,5)*10**n so that 3-5 quanta cover range*/ 48811778Ssam if(r>=delta/2) 48911778Ssam r /= 2; 49011778Ssam else if(r<delta/5) 49111778Ssam r *= 2; 49211778Ssam z.ub = ubf? ub: modceil(ub,r); 49311778Ssam z.lb = lbf? lb: modfloor(lb,r); 49411778Ssam if(!lbf && z.lb<=r && z.lb>0) { 49511778Ssam xlb = 0; 49611778Ssam goto loop; 49711778Ssam } 49811778Ssam else if(!ubf && z.ub>=-r && z.ub<0) { 49911778Ssam xub = 0; 50011778Ssam goto loop; 50111778Ssam } 50211778Ssam z.quant = r; 50311778Ssam z.mult = s; 50411778Ssam return(z); 50511778Ssam } 50611778Ssam 50711778Ssam scale(p,v) 50811778Ssam register struct xy *p; 50911778Ssam struct val *v; 51011778Ssam { 51111778Ssam float edge; 51211778Ssam 51311778Ssam getlim(p,v); 51411778Ssam setlim(p); 51511778Ssam edge = top-bot; 51611778Ssam p->xa = p->xsize*edge/((*p->xf)(p->xub) - (*p->xf)(p->xlb)); 51711778Ssam p->xbot = bot + edge*p->xoff; 51811778Ssam p->xtop = p->xbot + (top-bot)*p->xsize; 51911778Ssam p->xb = p->xbot - (*p->xf)(p->xlb)*p->xa + .5; 52011778Ssam } 52111778Ssam 52211778Ssam axes() 52311778Ssam { 52411778Ssam register i; 52511778Ssam int mark[50]; 52611778Ssam int xn, yn; 52711778Ssam if(gridf==0) 52811778Ssam return; 52911778Ssam 53011778Ssam line(xd.xbot,yd.xbot,xd.xtop,yd.xbot); 53111778Ssam cont(xd.xtop,yd.xtop); 53211778Ssam cont(xd.xbot,yd.xtop); 53311778Ssam cont(xd.xbot,yd.xbot); 53411778Ssam 53511778Ssam xn = setmark(mark,&xd); 53611778Ssam for(i=0; i<xn; i++) { 53711778Ssam if(gridf==2) 53811778Ssam line(mark[i],yd.xbot,mark[i],yd.xtop); 53911778Ssam if(gridf==1) { 54011778Ssam line(mark[i],yd.xbot,mark[i],yd.xbot+tick); 54111778Ssam line(mark[i],yd.xtop-tick,mark[i],yd.xtop); 54211778Ssam } 54311778Ssam } 54411778Ssam yn = setmark(mark,&yd); 54511778Ssam for(i=0; i<yn; i++) { 54611778Ssam if(gridf==2) 54711778Ssam line(xd.xbot,mark[i],xd.xtop,mark[i]); 54811778Ssam if(gridf==1) { 54911778Ssam line(xd.xbot,mark[i],xd.xbot+tick,mark[i]); 55011778Ssam line(xd.xtop-tick,mark[i],xd.xtop,mark[i]); 55111778Ssam } 55211778Ssam } 55311778Ssam } 55411778Ssam 55511778Ssam setmark(xmark,p) 55611778Ssam int *xmark; 55711778Ssam register struct xy *p; 55811778Ssam { 55911778Ssam int xn = 0; 56011778Ssam float x,xl,xu; 56111778Ssam float q; 56211778Ssam if(p->xf==log10&&!p->xqf) { 56311778Ssam for(x=p->xquant; x<p->xub; x*=10) { 56411778Ssam submark(xmark,&xn,x,p); 56511778Ssam if(p->xub/p->xlb<=100) { 56611778Ssam submark(xmark,&xn,2*x,p); 56711778Ssam submark(xmark,&xn,5*x,p); 56811778Ssam } 56911778Ssam } 57011778Ssam } else { 57111778Ssam xn = 0; 57211778Ssam q = p->xquant; 57311778Ssam if(q>0) { 57411778Ssam xl = modceil(p->xlb+q/6,q); 57511778Ssam xu = modfloor(p->xub-q/6,q)+q/2; 57611778Ssam } else { 57711778Ssam xl = modceil(p->xub-q/6,q); 57811778Ssam xu = modfloor(p->xlb+q/6,q)-q/2; 57911778Ssam } 58011778Ssam for(x=xl; x<=xu; x+=fabs(p->xquant)) 58111778Ssam xmark[xn++] = (*p->xf)(x)*p->xa + p->xb; 58211778Ssam } 58311778Ssam return(xn); 58411778Ssam } 58511778Ssam submark(xmark,pxn,x,p) 58611778Ssam int *xmark; 58711778Ssam int *pxn; 58811778Ssam float x; 58911778Ssam struct xy *p; 59011778Ssam { 59111778Ssam if(1.001*p->xlb < x && .999*p->xub > x) 59211778Ssam xmark[(*pxn)++] = log10(x)*p->xa + p->xb; 59311778Ssam } 59411778Ssam 59511778Ssam plot() 59611778Ssam { 59711778Ssam int ix,iy; 59811778Ssam int i; 59911778Ssam int conn; 60011778Ssam 60111778Ssam conn = 0; 60211778Ssam if(mode!=0) 60311778Ssam linemod(modes[mode]); 60411778Ssam for(i=0; i<n; i++) { 60511778Ssam if(!conv(xx[i].xv,&xd,&ix) || 60611778Ssam !conv(xx[i].yv,&yd,&iy)) { 60711778Ssam conn = 0; 60811778Ssam continue; 60911778Ssam } 61011778Ssam if(mode!=0) { 61111778Ssam if(conn != 0) 61211778Ssam cont(ix,iy); 61311778Ssam else 61411778Ssam move(ix,iy); 61511778Ssam conn = 1; 61611778Ssam } 61711778Ssam conn &= symbol(ix,iy,xx[i].lblptr); 61811778Ssam } 61911778Ssam linemod(modes[1]); 62011778Ssam } 62111778Ssam 62211778Ssam conv(xv,p,ip) 62311778Ssam float xv; 62411778Ssam register struct xy *p; 62511778Ssam int *ip; 62611778Ssam { 62711778Ssam long ix; 62811778Ssam ix = p->xa*(*p->xf)(xv*p->xmult) + p->xb; 62911778Ssam if(ix<p->xbot || ix>p->xtop) 63011778Ssam return(0); 63111778Ssam *ip = ix; 63211778Ssam return(1); 63311778Ssam } 63411778Ssam 63511778Ssam getfloat(p) 63611778Ssam float *p; 63711778Ssam { 63811778Ssam register i; 63911778Ssam 64011778Ssam i = scanf("%f",p); 64111778Ssam return(i==1); 64211778Ssam } 64311778Ssam 64411778Ssam getstring() 64511778Ssam { 64611778Ssam register i; 64711778Ssam char junk[20]; 64811778Ssam i = scanf("%1s",labbuf); 64911778Ssam if(i==-1) 65011778Ssam return(-1); 65111778Ssam switch(*labbuf) { 65211778Ssam default: 65311778Ssam if(!isdigit(*labbuf)) { 65411778Ssam ungetc(*labbuf,stdin); 65511778Ssam i = scanf("%s",labbuf); 65611778Ssam break; 65711778Ssam } 65811778Ssam case '.': 65911778Ssam case '+': 66011778Ssam case '-': 66111778Ssam ungetc(*labbuf,stdin); 66211778Ssam return(0); 66311778Ssam case '"': 66411778Ssam i = scanf("%[^\"\n]",labbuf); 66511778Ssam scanf("%[\"]",junk); 66611778Ssam break; 66711778Ssam } 66811778Ssam if(i==-1) 66911778Ssam return(-1); 67011778Ssam return(strlen(labbuf)); 67111778Ssam } 67211778Ssam 67311778Ssam 67411778Ssam symbol(ix,iy,k) 67511778Ssam { 67611778Ssam 67711778Ssam if(symbf==0&&k<0) { 67811778Ssam if(mode==0) 67911778Ssam point(ix,iy); 68011778Ssam return(1); 68111778Ssam } 68211778Ssam else { 68311778Ssam move(ix,iy); 684*56022Sbostic label(k>=0?labels+k:plotsymb); 68511778Ssam move(ix,iy); 68611778Ssam return(!brkf|k<0); 68711778Ssam } 68811778Ssam } 68911778Ssam 69011778Ssam title() 69111778Ssam { 69211778Ssam move(xd.xbot,yd.xbot-60); 69311778Ssam if (titlebuf[0]) { 69411778Ssam label(titlebuf); 69511778Ssam label(" "); 69611778Ssam } 69711778Ssam if(erasf&&gridf) { 69811778Ssam axlab('x',&xd); 69911778Ssam label(" "); 70011778Ssam axlab('y',&yd); 70111778Ssam } 70211778Ssam } 70311778Ssam 70411778Ssam axlab(c,p) 70511778Ssam char c; 70611778Ssam struct xy *p; 70711778Ssam { 70811778Ssam char buf[50]; 70911778Ssam sprintf(buf,"%g -%s%c- %g", p->xlb/p->xmult, 71011778Ssam p->xf==log10?"log ":"", c, p->xub/p->xmult); 71111778Ssam label(buf); 71211778Ssam } 71311778Ssam 71411778Ssam badarg() 71511778Ssam { 71611778Ssam fprintf(stderr,"graph: error in arguments\n"); 71711778Ssam exit(1); 71811778Ssam } 719