xref: /csrg-svn/bin/csh/set.c (revision 1305)
1*1305Sbill static	char *sccsid = "@(#)set.c 4.1 10/09/80";
2*1305Sbill 
3*1305Sbill #include "sh.h"
4*1305Sbill 
5*1305Sbill /*
6*1305Sbill  * C Shell
7*1305Sbill  */
8*1305Sbill 
9*1305Sbill doset(v)
10*1305Sbill 	register char **v;
11*1305Sbill {
12*1305Sbill 	register char *p;
13*1305Sbill 	char *vp, op;
14*1305Sbill 	char **vecp;
15*1305Sbill 	bool hadsub;
16*1305Sbill 	int subscr;
17*1305Sbill 
18*1305Sbill 	v++;
19*1305Sbill 	p = *v++;
20*1305Sbill 	if (p == 0) {
21*1305Sbill 		prvars();
22*1305Sbill 		return;
23*1305Sbill 	}
24*1305Sbill 	do {
25*1305Sbill 		hadsub = 0;
26*1305Sbill 		for (vp = p; alnum(*p); p++)
27*1305Sbill 			continue;
28*1305Sbill 		if (vp == p)
29*1305Sbill 			goto setsyn;
30*1305Sbill 		if (*p == '[') {
31*1305Sbill 			hadsub++;
32*1305Sbill 			p = getinx(p, &subscr);
33*1305Sbill 		}
34*1305Sbill 		if (op = *p) {
35*1305Sbill 			*p++ = 0;
36*1305Sbill 			if (*p == 0 && *v && **v == '(')
37*1305Sbill 				p = *v++;
38*1305Sbill 		} else if (*v && eq(*v, "=")) {
39*1305Sbill 			op = '=', v++;
40*1305Sbill 			if (*v)
41*1305Sbill 				p = *v++;
42*1305Sbill 		}
43*1305Sbill 		if (op && op != '=')
44*1305Sbill setsyn:
45*1305Sbill 			bferr("Syntax error");
46*1305Sbill 		if (eq(p, "(")) {
47*1305Sbill 			register char **e = v;
48*1305Sbill 
49*1305Sbill 			if (hadsub)
50*1305Sbill 				goto setsyn;
51*1305Sbill 			for (;;) {
52*1305Sbill 				if (!*e)
53*1305Sbill 					bferr("Missing )");
54*1305Sbill 				if (**e == ')')
55*1305Sbill 					break;
56*1305Sbill 				e++;
57*1305Sbill 			}
58*1305Sbill 			p = *e;
59*1305Sbill 			*e = 0;
60*1305Sbill 			vecp = saveblk(v);
61*1305Sbill 			set1(vp, vecp, &shvhed);
62*1305Sbill 			*e = p;
63*1305Sbill 			v = e + 1;
64*1305Sbill 		} else if (hadsub)
65*1305Sbill 			asx(vp, subscr, savestr(p));
66*1305Sbill 		else
67*1305Sbill 			set(vp, savestr(p));
68*1305Sbill 		if (eq(vp, "path")) {
69*1305Sbill 			exportpath(adrof("path")->vec);
70*1305Sbill 			dohash();
71*1305Sbill 		} else if (eq(vp, "histchars")) {
72*1305Sbill 			register char *p = value("histchars");
73*1305Sbill 
74*1305Sbill 			HIST = *p++;
75*1305Sbill 			HISTSUB = *p;
76*1305Sbill 		} else if (eq(vp, "user"))
77*1305Sbill 			setenv("USER", value(vp));
78*1305Sbill 		else if (eq(vp, "term"))
79*1305Sbill 			setenv("TERM", value(vp));
80*1305Sbill 		else if (eq(vp, "home"))
81*1305Sbill 			setenv("HOME", value(vp));
82*1305Sbill 	} while (p = *v++);
83*1305Sbill }
84*1305Sbill 
85*1305Sbill char *
86*1305Sbill getinx(cp, ip)
87*1305Sbill 	register char *cp;
88*1305Sbill 	register int *ip;
89*1305Sbill {
90*1305Sbill 
91*1305Sbill 	*ip = 0;
92*1305Sbill 	*cp++ = 0;
93*1305Sbill 	while (*cp && digit(*cp))
94*1305Sbill 		*ip = *ip * 10 + *cp++ - '0';
95*1305Sbill 	if (*cp++ != ']')
96*1305Sbill 		bferr("Subscript error");
97*1305Sbill 	return (cp);
98*1305Sbill }
99*1305Sbill 
100*1305Sbill asx(vp, subscr, p)
101*1305Sbill 	char *vp;
102*1305Sbill 	int subscr;
103*1305Sbill 	char *p;
104*1305Sbill {
105*1305Sbill 	register struct varent *v = getvx(vp, subscr);
106*1305Sbill 
107*1305Sbill 	xfree(v->vec[subscr - 1]);
108*1305Sbill 	v->vec[subscr - 1] = globone(p);
109*1305Sbill }
110*1305Sbill 
111*1305Sbill struct varent *
112*1305Sbill getvx(vp, subscr)
113*1305Sbill {
114*1305Sbill 	register struct varent *v = adrof(vp);
115*1305Sbill 
116*1305Sbill 	if (v == 0)
117*1305Sbill 		udvar(vp);
118*1305Sbill 	if (subscr < 1 || subscr > blklen(v->vec))
119*1305Sbill 		bferr("Subscript out of range");
120*1305Sbill 	return (v);
121*1305Sbill }
122*1305Sbill 
123*1305Sbill char	plusplus[2] = { '1', 0 };
124*1305Sbill 
125*1305Sbill 
126*1305Sbill dolet(v)
127*1305Sbill 	char **v;
128*1305Sbill {
129*1305Sbill 	register char *p;
130*1305Sbill 	char *vp, c, op;
131*1305Sbill 	bool hadsub;
132*1305Sbill 	int subscr;
133*1305Sbill 
134*1305Sbill 	v++;
135*1305Sbill 	p = *v++;
136*1305Sbill 	if (p == 0) {
137*1305Sbill 		prvars();
138*1305Sbill 		return;
139*1305Sbill 	}
140*1305Sbill 	do {
141*1305Sbill 		hadsub = 0;
142*1305Sbill 		for (vp = p; letter(*p); p++)
143*1305Sbill 			continue;
144*1305Sbill 		if (vp == p)
145*1305Sbill 			goto letsyn;
146*1305Sbill 		if (*p == '[') {
147*1305Sbill 			hadsub++;
148*1305Sbill 			p = getinx(p, &subscr);
149*1305Sbill 		}
150*1305Sbill 		if (*p == 0 && *v)
151*1305Sbill 			p = *v++;
152*1305Sbill 		if (op = *p)
153*1305Sbill 			*p++ = 0;
154*1305Sbill 		else
155*1305Sbill 			goto letsyn;
156*1305Sbill 		vp = savestr(vp);
157*1305Sbill 		if (op == '=') {
158*1305Sbill 			c = '=';
159*1305Sbill 			p = xset(p, &v);
160*1305Sbill 		} else {
161*1305Sbill 			c = *p++;
162*1305Sbill 			if (any(c, "+-")) {
163*1305Sbill 				if (c != op || *p)
164*1305Sbill 					goto letsyn;
165*1305Sbill 				p = plusplus;
166*1305Sbill 			} else {
167*1305Sbill 				if (any(op, "<>")) {
168*1305Sbill 					if (c != op)
169*1305Sbill 						goto letsyn;
170*1305Sbill 					c = *p++;
171*1305Sbill letsyn:
172*1305Sbill 					bferr("Syntax error");
173*1305Sbill 				}
174*1305Sbill 				if (c != '=')
175*1305Sbill 					goto letsyn;
176*1305Sbill 				p = xset(p, &v);
177*1305Sbill 			}
178*1305Sbill 		}
179*1305Sbill 		if (op == '=')
180*1305Sbill 			if (hadsub)
181*1305Sbill 				asx(vp, subscr, p);
182*1305Sbill 			else
183*1305Sbill 				set(vp, p);
184*1305Sbill 		else
185*1305Sbill 			if (hadsub)
186*1305Sbill #ifndef V6
187*1305Sbill 				/* avoid bug in vax CC */
188*1305Sbill 				{
189*1305Sbill 					struct varent *gv = getvx(vp, subscr);
190*1305Sbill 
191*1305Sbill 					asx(vp, subscr, operate(op, gv->vec[subscr - 1], p));
192*1305Sbill 				}
193*1305Sbill #else
194*1305Sbill 				asx(vp, subscr, operate(op, getvx(vp, subscr)->vec[subscr - 1], p));
195*1305Sbill #endif
196*1305Sbill 			else
197*1305Sbill 				set(vp, operate(op, value(vp), p));
198*1305Sbill 		if (strcmp(vp, "path") == 0)
199*1305Sbill 			dohash();
200*1305Sbill 		xfree(vp);
201*1305Sbill 		if (c != '=')
202*1305Sbill 			xfree(p);
203*1305Sbill 	} while (p = *v++);
204*1305Sbill }
205*1305Sbill 
206*1305Sbill char *
207*1305Sbill xset(cp, vp)
208*1305Sbill 	char *cp, ***vp;
209*1305Sbill {
210*1305Sbill 	register char *dp;
211*1305Sbill 
212*1305Sbill 	if (*cp) {
213*1305Sbill 		dp = savestr(cp);
214*1305Sbill 		--(*vp);
215*1305Sbill 		xfree(**vp);
216*1305Sbill 		**vp = dp;
217*1305Sbill 	}
218*1305Sbill 	return (putn(exp(vp)));
219*1305Sbill }
220*1305Sbill 
221*1305Sbill char *
222*1305Sbill operate(op, vp, p)
223*1305Sbill 	char op, *vp, *p;
224*1305Sbill {
225*1305Sbill 	char opr[2];
226*1305Sbill 	char *vec[5];
227*1305Sbill 	register char **v = vec;
228*1305Sbill 	char **vecp = v;
229*1305Sbill 	register int i;
230*1305Sbill 
231*1305Sbill 	if (op != '=') {
232*1305Sbill 		if (*vp)
233*1305Sbill 			*v++ = vp;
234*1305Sbill 		opr[0] = op;
235*1305Sbill 		opr[1] = 0;
236*1305Sbill 		*v++ = opr;
237*1305Sbill 		if (op == '<' || op == '>')
238*1305Sbill 			*v++ = opr;
239*1305Sbill 	}
240*1305Sbill 	*v++ = p;
241*1305Sbill 	*v++ = 0;
242*1305Sbill 	i = exp(&vecp);
243*1305Sbill 	if (*vecp)
244*1305Sbill 		bferr("Expression syntax");
245*1305Sbill 	return (putn(i));
246*1305Sbill }
247*1305Sbill 
248*1305Sbill onlyread(cp)
249*1305Sbill 	char *cp;
250*1305Sbill {
251*1305Sbill 	extern char end[];
252*1305Sbill 
253*1305Sbill 	return (cp < end);
254*1305Sbill }
255*1305Sbill 
256*1305Sbill xfree(cp)
257*1305Sbill 	char *cp;
258*1305Sbill {
259*1305Sbill 	extern char end[];
260*1305Sbill 
261*1305Sbill 	if (cp >= end && cp < (char *) &cp)
262*1305Sbill 		cfree(cp);
263*1305Sbill }
264*1305Sbill 
265*1305Sbill char *
266*1305Sbill savestr(s)
267*1305Sbill 	register char *s;
268*1305Sbill {
269*1305Sbill 	register char *n;
270*1305Sbill 
271*1305Sbill 	if (s == 0)
272*1305Sbill 		s = "";
273*1305Sbill 	strcpy(n = calloc(1, strlen(s) + 1), s);
274*1305Sbill 	return (n);
275*1305Sbill }
276*1305Sbill 
277*1305Sbill static	char *putp;
278*1305Sbill 
279*1305Sbill char *
280*1305Sbill putn(n)
281*1305Sbill 	register int n;
282*1305Sbill {
283*1305Sbill 	static char number[15];
284*1305Sbill 
285*1305Sbill 	putp = number;
286*1305Sbill 	if (n < 0) {
287*1305Sbill 		n = -n;
288*1305Sbill 		*putp++ = '-';
289*1305Sbill 	}
290*1305Sbill 	if (sizeof (int) == 2 && n == -32768) {
291*1305Sbill 		*putp++ = '3';
292*1305Sbill 		n = 2768;
293*1305Sbill #ifdef pdp11
294*1305Sbill 	}
295*1305Sbill #else
296*1305Sbill 	} else if (sizeof (int) == 4 && n == -2147483648) {
297*1305Sbill 		*putp++ = '2';
298*1305Sbill 		n = 147483648;
299*1305Sbill 	}
300*1305Sbill #endif
301*1305Sbill 	putn1(n);
302*1305Sbill 	*putp = 0;
303*1305Sbill 	return (savestr(number));
304*1305Sbill }
305*1305Sbill 
306*1305Sbill putn1(n)
307*1305Sbill 	register int n;
308*1305Sbill {
309*1305Sbill 	if (n > 9)
310*1305Sbill 		putn1(n / 10);
311*1305Sbill 	*putp++ = n % 10 + '0';
312*1305Sbill }
313*1305Sbill 
314*1305Sbill getn(cp)
315*1305Sbill 	register char *cp;
316*1305Sbill {
317*1305Sbill 	register int n;
318*1305Sbill 	int sign;
319*1305Sbill 
320*1305Sbill 	sign = 0;
321*1305Sbill 	if (cp[0] == '+' && cp[1])
322*1305Sbill 		cp++;
323*1305Sbill 	if (*cp == '-') {
324*1305Sbill 		sign++;
325*1305Sbill 		cp++;
326*1305Sbill 		if (!digit(*cp))
327*1305Sbill 			goto badnum;
328*1305Sbill 	}
329*1305Sbill 	n = 0;
330*1305Sbill 	while (digit(*cp))
331*1305Sbill 		n = n * 10 + *cp++ - '0';
332*1305Sbill 	if (*cp)
333*1305Sbill 		goto badnum;
334*1305Sbill 	return (sign ? -n : n);
335*1305Sbill badnum:
336*1305Sbill 	bferr("Badly formed number");
337*1305Sbill 	return (0);
338*1305Sbill }
339*1305Sbill 
340*1305Sbill char *
341*1305Sbill value(var)
342*1305Sbill 	char *var;
343*1305Sbill {
344*1305Sbill 
345*1305Sbill 	return (value1(var, &shvhed));
346*1305Sbill }
347*1305Sbill 
348*1305Sbill char *
349*1305Sbill value1(var, head)
350*1305Sbill 	char *var;
351*1305Sbill 	struct varent *head;
352*1305Sbill {
353*1305Sbill 	register struct varent *vp;
354*1305Sbill 
355*1305Sbill 	vp = adrof1(var, head);
356*1305Sbill 	return (vp == 0 || vp->vec[0] == 0 ? "" : vp->vec[0]);
357*1305Sbill }
358*1305Sbill 
359*1305Sbill static	struct varent *shprev;
360*1305Sbill 
361*1305Sbill struct varent *
362*1305Sbill adrof(var)
363*1305Sbill 	char *var;
364*1305Sbill {
365*1305Sbill 
366*1305Sbill 	return (adrof1(var, &shvhed));
367*1305Sbill }
368*1305Sbill 
369*1305Sbill struct varent *
370*1305Sbill madrof(pat, head)
371*1305Sbill 	char *pat;
372*1305Sbill 	struct varent *head;
373*1305Sbill {
374*1305Sbill 	register struct varent *vp;
375*1305Sbill 
376*1305Sbill 	shprev = head;
377*1305Sbill 	for (vp = shprev->link; vp != 0; vp = vp->link) {
378*1305Sbill 		if (Gmatch(vp->name, pat))
379*1305Sbill 			return (vp);
380*1305Sbill 		shprev = vp;
381*1305Sbill 	}
382*1305Sbill 	return (0);
383*1305Sbill }
384*1305Sbill 
385*1305Sbill struct varent *
386*1305Sbill adrof1(var, head)
387*1305Sbill 	char *var;
388*1305Sbill 	struct varent *head;
389*1305Sbill {
390*1305Sbill 	register struct varent *vp;
391*1305Sbill 	int cmp;
392*1305Sbill 
393*1305Sbill 	shprev = head;
394*1305Sbill 	for (vp = shprev->link; vp != 0; vp = vp->link) {
395*1305Sbill 		cmp = strcmp(vp->name, var);
396*1305Sbill 		if (cmp == 0)
397*1305Sbill 			return (vp);
398*1305Sbill 		else if (cmp > 0)
399*1305Sbill 			return (0);
400*1305Sbill 		shprev = vp;
401*1305Sbill 	}
402*1305Sbill 	return (0);
403*1305Sbill }
404*1305Sbill 
405*1305Sbill /*
406*1305Sbill  * The caller is responsible for putting value in a safe place
407*1305Sbill  */
408*1305Sbill set(var, value)
409*1305Sbill 	char *var, *value;
410*1305Sbill {
411*1305Sbill 	register char **vec = (char **) calloc(2, sizeof (char **));
412*1305Sbill 
413*1305Sbill 	vec[0] = onlyread(value) ? savestr(value) : value;
414*1305Sbill 	set1(var, vec, &shvhed);
415*1305Sbill }
416*1305Sbill 
417*1305Sbill set1(var, vec, head)
418*1305Sbill 	char *var, **vec;
419*1305Sbill 	struct varent *head;
420*1305Sbill {
421*1305Sbill 
422*1305Sbill 	register char **oldv = vec;
423*1305Sbill 
424*1305Sbill 	gflag = 0; rscan(oldv, tglob);
425*1305Sbill 	if (gflag) {
426*1305Sbill 		vec = glob(oldv);
427*1305Sbill 		if (vec == 0) {
428*1305Sbill 			bferr("No match");
429*1305Sbill 			blkfree(oldv);
430*1305Sbill 			return;
431*1305Sbill 		}
432*1305Sbill 		blkfree(oldv);
433*1305Sbill 		gargv = 0;
434*1305Sbill 	}
435*1305Sbill 	setq(var, vec, head);
436*1305Sbill }
437*1305Sbill 
438*1305Sbill setq(var, vec, head)
439*1305Sbill 	char *var, **vec;
440*1305Sbill 	struct varent *head;
441*1305Sbill {
442*1305Sbill 	register struct varent *vp;
443*1305Sbill 
444*1305Sbill 	vp = adrof1(var, head);
445*1305Sbill 	if (vp == 0) {
446*1305Sbill 		vp = (struct varent *) calloc(1, sizeof *vp);
447*1305Sbill 		vp->name = savestr(var);
448*1305Sbill 		vp->link = shprev->link;
449*1305Sbill 		shprev->link = vp;
450*1305Sbill 	}
451*1305Sbill 	if (vp->vec)
452*1305Sbill 		blkfree(vp->vec);
453*1305Sbill 	scan(vec, trim);
454*1305Sbill 	vp->vec = vec;
455*1305Sbill }
456*1305Sbill 
457*1305Sbill unset(v)
458*1305Sbill 	register char *v[];
459*1305Sbill {
460*1305Sbill 
461*1305Sbill 	unset1(v, &shvhed);
462*1305Sbill 	if (adrof("histchars") == 0) {
463*1305Sbill 		HIST = '!';
464*1305Sbill 		HISTSUB = '^';
465*1305Sbill 	}
466*1305Sbill }
467*1305Sbill 
468*1305Sbill unset1(v, head)
469*1305Sbill 	register char *v[];
470*1305Sbill 	struct varent *head;
471*1305Sbill {
472*1305Sbill 	register char *var;
473*1305Sbill 	register struct varent *vp;
474*1305Sbill 	register int cnt;
475*1305Sbill 
476*1305Sbill 	v++;
477*1305Sbill 	while (var = *v++) {
478*1305Sbill 		cnt = 0;
479*1305Sbill 		while (vp = madrof(var, head))
480*1305Sbill 			unsetv1(vp->name, head), cnt++;
481*1305Sbill 		if (cnt == 0)
482*1305Sbill 			setname(var);
483*1305Sbill 	}
484*1305Sbill }
485*1305Sbill 
486*1305Sbill unsetv(var)
487*1305Sbill 	char *var;
488*1305Sbill {
489*1305Sbill 
490*1305Sbill 	unsetv1(var, &shvhed);
491*1305Sbill }
492*1305Sbill 
493*1305Sbill unsetv1(var, head)
494*1305Sbill 	char *var;
495*1305Sbill 	struct varent *head;
496*1305Sbill {
497*1305Sbill 	register struct varent *vp;
498*1305Sbill 
499*1305Sbill 	vp = adrof1(var, head);
500*1305Sbill 	if (vp == 0)
501*1305Sbill 		udvar(var);
502*1305Sbill 	vp = shprev->link;
503*1305Sbill 	shprev->link = vp->link;
504*1305Sbill 	blkfree(vp->vec);
505*1305Sbill 	xfree(vp->name);
506*1305Sbill 	xfree((char *)vp);
507*1305Sbill }
508*1305Sbill 
509*1305Sbill setNS(cp)
510*1305Sbill 	char *cp;
511*1305Sbill {
512*1305Sbill 
513*1305Sbill 	set(cp, "");
514*1305Sbill }
515*1305Sbill 
516*1305Sbill shift(v)
517*1305Sbill 	register char **v;
518*1305Sbill {
519*1305Sbill 	register struct varent *argv;
520*1305Sbill 	register char *name;
521*1305Sbill 
522*1305Sbill 	v++;
523*1305Sbill 	name = *v;
524*1305Sbill 	if (name == 0)
525*1305Sbill 		name = "argv";
526*1305Sbill 	else
527*1305Sbill 		strip(name);
528*1305Sbill 	argv = adrof(name);
529*1305Sbill 	if (argv == 0)
530*1305Sbill 		udvar(name);
531*1305Sbill 	if (argv->vec[0] == 0)
532*1305Sbill 		bferr("No more words");
533*1305Sbill 	lshift(argv->vec, 1);
534*1305Sbill }
535*1305Sbill 
536*1305Sbill exportpath(val)
537*1305Sbill char **val;
538*1305Sbill {
539*1305Sbill 	char exppath[BUFSIZ];
540*1305Sbill 	register char *dir;
541*1305Sbill 
542*1305Sbill 	exppath[0] = 0;
543*1305Sbill 	if (val)
544*1305Sbill 		while (*val) {
545*1305Sbill 			if (strlen(*val) + strlen(exppath) + 2 > BUFSIZ) {
546*1305Sbill 				printf("Warning: ridiculously long PATH truncated\n");
547*1305Sbill 				break;
548*1305Sbill 			}
549*1305Sbill 			strcat(exppath, *val++);
550*1305Sbill 			if (*val == 0 || eq(*val, ")"))
551*1305Sbill 				break;
552*1305Sbill 			strcat(exppath, ":");
553*1305Sbill 		}
554*1305Sbill 	setenv("PATH", exppath);
555*1305Sbill }
556