|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley Software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char *sccsid = "@(#)sh.set.c 5.2 (Berkeley) 6/6/85";
9: #endif
10:
11: #include "sh.h"
12:
13: /*
14: * C Shell
15: */
16:
17: doset(v)
18: register char **v;
19: {
20: register char *p;
21: char *vp, op;
22: char **vecp;
23: bool hadsub;
24: int subscr;
25:
26: v++;
27: p = *v++;
28: if (p == 0) {
29: prvars();
30: return;
31: }
32: do {
33: hadsub = 0;
34: for (vp = p; alnum(*p); p++)
35: continue;
36: if (vp == p || !letter(*vp))
37: goto setsyn;
38: if (*p == '[') {
39: hadsub++;
40: p = getinx(p, &subscr);
41: }
42: if (op = *p) {
43: *p++ = 0;
44: if (*p == 0 && *v && **v == '(')
45: p = *v++;
46: } else if (*v && eq(*v, "=")) {
47: op = '=', v++;
48: if (*v)
49: p = *v++;
50: }
51: if (op && op != '=')
52: setsyn:
53: bferr("Syntax error");
54: if (eq(p, "(")) {
55: register char **e = v;
56:
57: if (hadsub)
58: goto setsyn;
59: for (;;) {
60: if (!*e)
61: bferr("Missing )");
62: if (**e == ')')
63: break;
64: e++;
65: }
66: p = *e;
67: *e = 0;
68: vecp = saveblk(v);
69: set1(vp, vecp, &shvhed);
70: *e = p;
71: v = e + 1;
72: } else if (hadsub)
73: asx(vp, subscr, savestr(p));
74: else
75: set(vp, savestr(p));
76: if (eq(vp, "path")) {
77: exportpath(adrof("path")->vec);
78: dohash();
79: } else if (eq(vp, "histchars")) {
80: register char *p = value("histchars");
81:
82: HIST = *p++;
83: HISTSUB = *p;
84: } else if (eq(vp, "user"))
85: setenv("USER", value(vp));
86: else if (eq(vp, "term"))
87: setenv("TERM", value(vp));
88: else if (eq(vp, "home"))
89: setenv("HOME", value(vp));
90: #ifdef FILEC
91: else if (eq(vp, "filec"))
92: filec = 1;
93: #endif
94: } while (p = *v++);
95: }
96:
97: char *
98: getinx(cp, ip)
99: register char *cp;
100: register int *ip;
101: {
102:
103: *ip = 0;
104: *cp++ = 0;
105: while (*cp && digit(*cp))
106: *ip = *ip * 10 + *cp++ - '0';
107: if (*cp++ != ']')
108: bferr("Subscript error");
109: return (cp);
110: }
111:
112: asx(vp, subscr, p)
113: char *vp;
114: int subscr;
115: char *p;
116: {
117: register struct varent *v = getvx(vp, subscr);
118:
119: xfree(v->vec[subscr - 1]);
120: v->vec[subscr - 1] = globone(p);
121: }
122:
123: struct varent *
124: getvx(vp, subscr)
125: char *vp;
126: {
127: register struct varent *v = adrof(vp);
128:
129: if (v == 0)
130: udvar(vp);
131: if (subscr < 1 || subscr > blklen(v->vec))
132: bferr("Subscript out of range");
133: return (v);
134: }
135:
136: char plusplus[2] = { '1', 0 };
137:
138: dolet(v)
139: char **v;
140: {
141: register char *p;
142: char *vp, c, op;
143: bool hadsub;
144: int subscr;
145:
146: v++;
147: p = *v++;
148: if (p == 0) {
149: prvars();
150: return;
151: }
152: do {
153: hadsub = 0;
154: for (vp = p; alnum(*p); p++)
155: continue;
156: if (vp == p || !letter(*vp))
157: goto letsyn;
158: if (*p == '[') {
159: hadsub++;
160: p = getinx(p, &subscr);
161: }
162: if (*p == 0 && *v)
163: p = *v++;
164: if (op = *p)
165: *p++ = 0;
166: else
167: goto letsyn;
168: vp = savestr(vp);
169: if (op == '=') {
170: c = '=';
171: p = xset(p, &v);
172: } else {
173: c = *p++;
174: if (any(c, "+-")) {
175: if (c != op || *p)
176: goto letsyn;
177: p = plusplus;
178: } else {
179: if (any(op, "<>")) {
180: if (c != op)
181: goto letsyn;
182: c = *p++;
183: letsyn:
184: bferr("Syntax error");
185: }
186: if (c != '=')
187: goto letsyn;
188: p = xset(p, &v);
189: }
190: }
191: if (op == '=')
192: if (hadsub)
193: asx(vp, subscr, p);
194: else
195: set(vp, p);
196: else
197: if (hadsub)
198: #ifndef V6
199: /* avoid bug in vax CC */
200: {
201: struct varent *gv = getvx(vp, subscr);
202:
203: asx(vp, subscr, operate(op, gv->vec[subscr - 1], p));
204: }
205: #else
206: asx(vp, subscr, operate(op, getvx(vp, subscr)->vec[subscr - 1], p));
207: #endif
208: else
209: set(vp, operate(op, value(vp), p));
210: if (eq(vp, "path")) {
211: exportpath(adrof("path")->vec);
212: dohash();
213: }
214: XFREE(vp)
215: if (c != '=')
216: XFREE(p)
217: } while (p = *v++);
218: }
219:
220: char *
221: xset(cp, vp)
222: char *cp, ***vp;
223: {
224: register char *dp;
225:
226: if (*cp) {
227: dp = savestr(cp);
228: --(*vp);
229: xfree(**vp);
230: **vp = dp;
231: }
232: return (putn(exp(vp)));
233: }
234:
235: char *
236: operate(op, vp, p)
237: char op, *vp, *p;
238: {
239: char opr[2];
240: char *vec[5];
241: register char **v = vec;
242: char **vecp = v;
243: register int i;
244:
245: if (op != '=') {
246: if (*vp)
247: *v++ = vp;
248: opr[0] = op;
249: opr[1] = 0;
250: *v++ = opr;
251: if (op == '<' || op == '>')
252: *v++ = opr;
253: }
254: *v++ = p;
255: *v++ = 0;
256: i = exp(&vecp);
257: if (*vecp)
258: bferr("Expression syntax");
259: return (putn(i));
260: }
261:
262: static char *putp;
263:
264: char *
265: putn(n)
266: register int n;
267: {
268: static char number[15];
269:
270: putp = number;
271: if (n < 0) {
272: n = -n;
273: *putp++ = '-';
274: }
275: if (sizeof (int) == 2 && n == -32768) {
276: *putp++ = '3';
277: n = 2768;
278: #ifdef pdp11
279: }
280: #else
281: } else if (sizeof (int) == 4 && n == -2147483648) {
282: *putp++ = '2';
283: n = 147483648;
284: }
285: #endif
286: putn1(n);
287: *putp = 0;
288: return (savestr(number));
289: }
290:
291: putn1(n)
292: register int n;
293: {
294: if (n > 9)
295: putn1(n / 10);
296: *putp++ = n % 10 + '0';
297: }
298:
299: getn(cp)
300: register char *cp;
301: {
302: register int n;
303: int sign;
304:
305: sign = 0;
306: if (cp[0] == '+' && cp[1])
307: cp++;
308: if (*cp == '-') {
309: sign++;
310: cp++;
311: if (!digit(*cp))
312: goto badnum;
313: }
314: n = 0;
315: while (digit(*cp))
316: n = n * 10 + *cp++ - '0';
317: if (*cp)
318: goto badnum;
319: return (sign ? -n : n);
320: badnum:
321: bferr("Badly formed number");
322: return (0);
323: }
324:
325: char *
326: value1(var, head)
327: char *var;
328: struct varent *head;
329: {
330: register struct varent *vp;
331:
332: vp = adrof1(var, head);
333: return (vp == 0 || vp->vec[0] == 0 ? "" : vp->vec[0]);
334: }
335:
336: struct varent *
337: madrof(pat, vp)
338: char *pat;
339: register struct varent *vp;
340: {
341: register struct varent *vp1;
342:
343: for (; vp; vp = vp->v_right) {
344: if (vp->v_left && (vp1 = madrof(pat, vp->v_left)))
345: return vp1;
346: if (Gmatch(vp->v_name, pat))
347: return vp;
348: }
349: return vp;
350: }
351:
352: struct varent *
353: adrof1(name, v)
354: register char *name;
355: register struct varent *v;
356: {
357: register cmp;
358:
359: v = v->v_left;
360: while (v && ((cmp = *name - *v->v_name) ||
361: (cmp = strcmp(name, v->v_name))))
362: if (cmp < 0)
363: v = v->v_left;
364: else
365: v = v->v_right;
366: return v;
367: }
368:
369: /*
370: * The caller is responsible for putting value in a safe place
371: */
372: set(var, val)
373: char *var, *val;
374: {
375: register char **vec = (char **) xalloc(2 * sizeof (char **));
376:
377: vec[0] = onlyread(val) ? savestr(val) : val;
378: vec[1] = 0;
379: set1(var, vec, &shvhed);
380: }
381:
382: set1(var, vec, head)
383: char *var, **vec;
384: struct varent *head;
385: {
386: register char **oldv = vec;
387:
388: gflag = 0; tglob(oldv);
389: if (gflag) {
390: vec = glob(oldv);
391: if (vec == 0) {
392: bferr("No match");
393: blkfree(oldv);
394: return;
395: }
396: blkfree(oldv);
397: gargv = 0;
398: }
399: setq(var, vec, head);
400: }
401:
402: setq(name, vec, p)
403: char *name, **vec;
404: register struct varent *p;
405: {
406: register struct varent *c;
407: register f;
408:
409: f = 0; /* tree hangs off the header's left link */
410: while (c = p->v_link[f]) {
411: if ((f = *name - *c->v_name) == 0 &&
412: (f = strcmp(name, c->v_name)) == 0) {
413: blkfree(c->vec);
414: goto found;
415: }
416: p = c;
417: f = f > 0;
418: }
419: p->v_link[f] = c = (struct varent *)xalloc(sizeof (struct varent));
420: c->v_name = savestr(name);
421: c->v_bal = 0;
422: c->v_left = c->v_right = 0;
423: c->v_parent = p;
424: balance(p, f, 0);
425: found:
426: trim(c->vec = vec);
427: }
428:
429: unset(v)
430: char *v[];
431: {
432:
433: unset1(v, &shvhed);
434: if (adrof("histchars") == 0) {
435: HIST = '!';
436: HISTSUB = '^';
437: }
438: #ifdef FILEC
439: if (adrof("filec") == 0)
440: filec = 0;
441: #endif
442: }
443:
444: unset1(v, head)
445: register char *v[];
446: struct varent *head;
447: {
448: register struct varent *vp;
449: register int cnt;
450:
451: while (*++v) {
452: cnt = 0;
453: while (vp = madrof(*v, head->v_left))
454: unsetv1(vp), cnt++;
455: if (cnt == 0)
456: setname(*v);
457: }
458: }
459:
460: unsetv(var)
461: char *var;
462: {
463: register struct varent *vp;
464:
465: if ((vp = adrof1(var, &shvhed)) == 0)
466: udvar(var);
467: unsetv1(vp);
468: }
469:
470: unsetv1(p)
471: register struct varent *p;
472: {
473: register struct varent *c, *pp;
474: register f;
475:
476: /*
477: * Free associated memory first to avoid complications.
478: */
479: blkfree(p->vec);
480: XFREE(p->v_name);
481: /*
482: * If p is missing one child, then we can move the other
483: * into where p is. Otherwise, we find the predecessor
484: * of p, which is guaranteed to have no right child, copy
485: * it into p, and move it's left child into it.
486: */
487: if (p->v_right == 0)
488: c = p->v_left;
489: else if (p->v_left == 0)
490: c = p->v_right;
491: else {
492: for (c = p->v_left; c->v_right; c = c->v_right)
493: ;
494: p->v_name = c->v_name;
495: p->vec = c->vec;
496: p = c;
497: c = p->v_left;
498: }
499: /*
500: * Move c into where p is.
501: */
502: pp = p->v_parent;
503: f = pp->v_right == p;
504: if (pp->v_link[f] = c)
505: c->v_parent = pp;
506: /*
507: * Free the deleted node, and rebalance.
508: */
509: XFREE((char *)p);
510: balance(pp, f, 1);
511: }
512:
513: setNS(cp)
514: char *cp;
515: {
516:
517: set(cp, "");
518: }
519:
520: shift(v)
521: register char **v;
522: {
523: register struct varent *argv;
524: register char *name;
525:
526: v++;
527: name = *v;
528: if (name == 0)
529: name = "argv";
530: else
531: (void) strip(name);
532: argv = adrof(name);
533: if (argv == 0)
534: udvar(name);
535: if (argv->vec[0] == 0)
536: bferr("No more words");
537: lshift(argv->vec, 1);
538: }
539:
540: exportpath(val)
541: char **val;
542: {
543: char exppath[BUFSIZ];
544:
545: exppath[0] = 0;
546: if (val)
547: while (*val) {
548: if (strlen(*val) + strlen(exppath) + 2 > BUFSIZ) {
549: printf("Warning: ridiculously long PATH truncated\n");
550: break;
551: }
552: (void) strcat(exppath, *val++);
553: if (*val == 0 || eq(*val, ")"))
554: break;
555: (void) strcat(exppath, ":");
556: }
557: setenv("PATH", exppath);
558: }
559:
560: /* macros to do single rotations on node p */
561: #define rright(p) (\
562: t = (p)->v_left,\
563: (t)->v_parent = (p)->v_parent,\
564: ((p)->v_left = t->v_right) ? (t->v_right->v_parent = (p)) : 0,\
565: (t->v_right = (p))->v_parent = t,\
566: (p) = t)
567: #define rleft(p) (\
568: t = (p)->v_right,\
569: (t)->v_parent = (p)->v_parent,\
570: ((p)->v_right = t->v_left) ? (t->v_left->v_parent = (p)) : 0,\
571: (t->v_left = (p))->v_parent = t,\
572: (p) = t)
573:
574: /*
575: * Rebalance a tree, starting at p and up.
576: * F == 0 means we've come from p's left child.
577: * D == 1 means we've just done a delete, otherwise an insert.
578: */
579: balance(p, f, d)
580: register struct varent *p;
581: register f;
582: {
583: register struct varent *pp;
584: register struct varent *t; /* used by the rotate macros */
585: register ff;
586:
587: /*
588: * Ok, from here on, p is the node we're operating on;
589: * pp is it's parent; f is the branch of p from which we have come;
590: * ff is the branch of pp which is p.
591: */
592: for (; pp = p->v_parent; p = pp, f = ff) {
593: ff = pp->v_right == p;
594: if (f ^ d) { /* right heavy */
595: switch (p->v_bal) {
596: case -1: /* was left heavy */
597: p->v_bal = 0;
598: break;
599: case 0: /* was balanced */
600: p->v_bal = 1;
601: break;
602: case 1: /* was already right heavy */
603: switch (p->v_right->v_bal) {
604: case 1: /* sigle rotate */
605: pp->v_link[ff] = rleft(p);
606: p->v_left->v_bal = 0;
607: p->v_bal = 0;
608: break;
609: case 0: /* single rotate */
610: pp->v_link[ff] = rleft(p);
611: p->v_left->v_bal = 1;
612: p->v_bal = -1;
613: break;
614: case -1: /* double rotate */
615: rright(p->v_right);
616: pp->v_link[ff] = rleft(p);
617: p->v_left->v_bal =
618: p->v_bal < 1 ? 0 : -1;
619: p->v_right->v_bal =
620: p->v_bal > -1 ? 0 : 1;
621: p->v_bal = 0;
622: break;
623: }
624: break;
625: }
626: } else { /* left heavy */
627: switch (p->v_bal) {
628: case 1: /* was right heavy */
629: p->v_bal = 0;
630: break;
631: case 0: /* was balanced */
632: p->v_bal = -1;
633: break;
634: case -1: /* was already left heavy */
635: switch (p->v_left->v_bal) {
636: case -1: /* single rotate */
637: pp->v_link[ff] = rright(p);
638: p->v_right->v_bal = 0;
639: p->v_bal = 0;
640: break;
641: case 0: /* signle rotate */
642: pp->v_link[ff] = rright(p);
643: p->v_right->v_bal = -1;
644: p->v_bal = 1;
645: break;
646: case 1: /* double rotate */
647: rleft(p->v_left);
648: pp->v_link[ff] = rright(p);
649: p->v_left->v_bal =
650: p->v_bal < 1 ? 0 : -1;
651: p->v_right->v_bal =
652: p->v_bal > -1 ? 0 : 1;
653: p->v_bal = 0;
654: break;
655: }
656: break;
657: }
658: }
659: /*
660: * If from insert, then we terminate when p is balanced.
661: * If from delete, then we terminate when p is unbalanced.
662: */
663: if ((p->v_bal == 0) ^ d)
664: break;
665: }
666: }
667:
668: plist(p)
669: register struct varent *p;
670: {
671: register struct varent *c;
672: register len;
673:
674: if (setintr)
675: (void) sigsetmask(sigblock(0) & ~ sigmask(SIGINT));
676: for (;;) {
677: while (p->v_left)
678: p = p->v_left;
679: x:
680: if (p->v_parent == 0) /* is it the header? */
681: return;
682: len = blklen(p->vec);
683: printf(p->v_name);
684: putchar('\t');
685: if (len != 1)
686: putchar('(');
687: blkpr(p->vec);
688: if (len != 1)
689: putchar(')');
690: putchar('\n');
691: if (p->v_right) {
692: p = p->v_right;
693: continue;
694: }
695: do {
696: c = p;
697: p = p->v_parent;
698: } while (p->v_right == c);
699: goto x;
700: }
701: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.