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