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