+ register Char *p;
+ Char *vp, op;
+ Char **vecp;
+ bool hadsub;
+ int subscr;
+
+ v++;
+ p = *v++;
+ if (p == 0) {
+ prvars();
+ return;
+ }
+ do {
+ hadsub = 0;
+ vp = p;
+ if (letter(*p))
+ for (; alnum(*p); p++)
+ continue;
+ if (vp == p || !letter(*vp))
+ stderror(ERR_NAME | ERR_VARBEGIN);
+ if ((p - vp) > MAXVARLEN) {
+ stderror(ERR_NAME | ERR_VARTOOLONG);
+ return;
+ }
+ if (*p == '[') {
+ hadsub++;
+ p = getinx(p, &subscr);
+ }
+ if ((op = *p) != '\0') {
+ *p++ = 0;
+ if (*p == 0 && *v && **v == '(')
+ p = *v++;
+ }
+ else if (*v && eq(*v, STRequal)) {
+ op = '=', v++;
+ if (*v)
+ p = *v++;
+ }
+ if (op && op != '=')
+ stderror(ERR_NAME | ERR_SYNTAX);
+ if (eq(p, STRLparen)) {
+ register Char **e = v;
+
+ if (hadsub)
+ stderror(ERR_NAME | ERR_SYNTAX);
+ for (;;) {
+ if (!*e)
+ stderror(ERR_NAME | ERR_MISSING, ')');
+ if (**e == ')')
+ break;
+ e++;
+ }
+ p = *e;
+ *e = 0;
+ vecp = saveblk(v);
+ set1(vp, vecp, &shvhed);
+ *e = p;
+ v = e + 1;
+ }
+ else if (hadsub)
+ asx(vp, subscr, Strsave(p));
+ else
+ set(vp, Strsave(p));
+ if (eq(vp, STRpath)) {
+ exportpath(adrof(STRpath)->vec);
+ dohash(NULL, NULL);
+ }
+ else if (eq(vp, STRhistchars)) {
+ register Char *pn = value(STRhistchars);
+
+ HIST = *pn++;
+ HISTSUB = *pn;
+ }
+ else if (eq(vp, STRuser)) {
+ Setenv(STRUSER, value(vp));
+ Setenv(STRLOGNAME, value(vp));
+ }
+ else if (eq(vp, STRwordchars)) {
+ word_chars = value(vp);
+ }
+ else if (eq(vp, STRterm))
+ Setenv(STRTERM, value(vp));
+ else if (eq(vp, STRhome)) {
+ register Char *cp;
+
+ cp = Strsave(value(vp)); /* get the old value back */
+
+ /*
+ * convert to cononical pathname (possibly resolving symlinks)
+ */
+ cp = dcanon(cp, cp);
+
+ set(vp, Strsave(cp)); /* have to save the new val */
+
+ /* and now mirror home with HOME */
+ Setenv(STRHOME, cp);
+ /* fix directory stack for new tilde home */
+ dtilde();
+ xfree((ptr_t) cp);