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