Commit | Line | Data |
---|---|---|
b278c146 BJ |
1 | static char *sccsid = "@(#)set.c 4.1 %G%"; |
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 | } |