148262Sbostic /*-
2*62018Sbostic * Copyright (c) 1991, 1993
3*62018Sbostic * The Regents of the University of California. All rights reserved.
448262Sbostic *
548262Sbostic * %sccs.include.proprietary.c%
648262Sbostic */
748262Sbostic
811779Ssam #ifndef lint
9*62018Sbostic static char copyright[] =
10*62018Sbostic "@(#) Copyright (c) 1991, 1993\n\
11*62018Sbostic The Regents of the University of California. All rights reserved.\n";
1248262Sbostic #endif /* not lint */
1311779Ssam
1448262Sbostic #ifndef lint
15*62018Sbostic static char sccsid[] = "@(#)graph.c 8.1 (Berkeley) 06/06/93";
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*/
2756022Sbostic 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
4256022Sbostic 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
ident(x)7656022Sbostic double __pure ident(x)
7711778Ssam double x;
7811778Ssam {
7911778Ssam return(x);
8011778Ssam }
8111778Ssam
main(argc,argv)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));
9156022Sbostic labels = malloc(1);
9256022Sbostic 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
setopt(argc,argv)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
limread(p,argcp,argvp)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
numb(np,argcp,argvp)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
readin()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
transpose()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
copystring(k)30111778Ssam copystring(k)
30211778Ssam {
30311778Ssam register char *temp;
30411778Ssam register i;
30511778Ssam int q;
30611778Ssam
30756022Sbostic temp = realloc(labels,(unsigned)(labsiz+1+k));
30811778Ssam if(temp==0)
30911778Ssam return(0);
31056022Sbostic labels = temp;
31111778Ssam q = labsiz;
31211778Ssam for(i=0;i<=k;i++)
31356022Sbostic labels[labsiz++] = labbuf[i];
31411778Ssam return(q);
31511778Ssam }
31611778Ssam
31711778Ssam float
modceil(f,t)31811778Ssam modceil(f,t)
31911778Ssam float f,t;
32011778Ssam {
32111778Ssam
32211778Ssam t = fabs(t);
32311778Ssam return(ceil(f/t)*t);
32411778Ssam }
32511778Ssam
32611778Ssam float
modfloor(f,t)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 */
getlim(p,v)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
setlim(p)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
setloglim(lbf,ubf,lb,ub)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
setlinlim(lbf,ubf,xlb,xub)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
scale(p,v)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
axes()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
setmark(xmark,p)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 }
submark(xmark,pxn,x,p)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
plot()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
conv(xv,p,ip)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
getfloat(p)63511778Ssam getfloat(p)
63611778Ssam float *p;
63711778Ssam {
63811778Ssam register i;
63911778Ssam
64011778Ssam i = scanf("%f",p);
64111778Ssam return(i==1);
64211778Ssam }
64311778Ssam
getstring()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
symbol(ix,iy,k)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);
68456022Sbostic label(k>=0?labels+k:plotsymb);
68511778Ssam move(ix,iy);
68611778Ssam return(!brkf|k<0);
68711778Ssam }
68811778Ssam }
68911778Ssam
title()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
axlab(c,p)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
badarg()71411778Ssam badarg()
71511778Ssam {
71611778Ssam fprintf(stderr,"graph: error in arguments\n");
71711778Ssam exit(1);
71811778Ssam }
719