home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / Shells / zsh / Source / src / params.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-07  |  33.1 KB  |  1,716 lines

  1. /*
  2.  *
  3.  * params.c - parameters
  4.  *
  5.  * This file is part of zsh, the Z shell.
  6.  *
  7.  * This software is Copyright 1992 by Paul Falstad
  8.  *
  9.  * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  10.  * use this software as long as: there is no monetary profit gained
  11.  * specifically from the use or reproduction of this software, it is not
  12.  * sold, rented, traded or otherwise marketed, and this copyright notice is
  13.  * included prominently in any copy made.
  14.  *
  15.  * The author make no claims as to the fitness or correctness of this software
  16.  * for any use whatsoever, and it is provided as is. Any use of this software
  17.  * is at the user's own risk.
  18.  *
  19.  */
  20.  
  21. #include "zsh.h"
  22. #include "version.h"
  23. #include <pwd.h>
  24.  
  25. static Param argvparam;
  26.  
  27. struct iparam {
  28.     struct hashnode *next;
  29.     char *nam;            /* hash data */
  30.     vptr value;
  31.     int (*func1) ();        /* set func */
  32.     int (*func2) ();        /* get func */
  33.     int ct;            /* output base or field width */
  34.     int flags;
  35.     vptr data;            /* used by getfns */
  36.     char *env;            /* location in environment, if exported */
  37.     char *ename;        /* name of corresponding environment var */
  38.     Param old;            /* old struct for use with local */
  39.     int level;            /* if (old != NULL), level of localness */
  40. };
  41.  
  42. #define IFN(X) ((int (*)())(X))
  43.  
  44. /* put predefined params in hash table */
  45.  
  46. void setupparams()
  47. {                /**/
  48.     static struct iparam pinit[] =
  49.     {
  50. #define IPDEF1(A,B,C,D) {NULL,A,NULL,IFN(C),IFN(B),10,\
  51.         PMFLAG_i|PMFLAG_SPECIAL|D,NULL,NULL,NULL,NULL,0}
  52.     IPDEF1("#", poundgetfn, IFN(nullsetfn), PMFLAG_r),
  53.     IPDEF1("ARGC", poundgetfn, IFN(nullsetfn), PMFLAG_r),
  54.     IPDEF1("ERRNO", errnogetfn, IFN(nullsetfn), PMFLAG_r),
  55.     IPDEF1("GID", gidgetfn, IFN(nullsetfn), PMFLAG_r),
  56.     IPDEF1("EGID", egidgetfn, IFN(nullsetfn), PMFLAG_r),
  57.     IPDEF1("HISTSIZE", histsizegetfn, histsizesetfn, 0),
  58.     IPDEF1("LITHISTSIZE", lithistsizegetfn, lithistsizesetfn, 0),
  59.     IPDEF1("RANDOM", randomgetfn, randomsetfn, 0),
  60.     IPDEF1("SECONDS", secondsgetfn, secondssetfn, 0),
  61.     IPDEF1("UID", uidgetfn, IFN(nullsetfn), PMFLAG_r),
  62.     IPDEF1("EUID", euidgetfn, IFN(nullsetfn), PMFLAG_r),
  63.  
  64. #define IPDEF2(A,B,C,D) {NULL,A,NULL,IFN(C),IFN(B),0,\
  65.         PMFLAG_SPECIAL|D,NULL,NULL,NULL,NULL,0}
  66.     IPDEF2("-", dashgetfn, IFN(nullsetfn), PMFLAG_r),
  67.     IPDEF2("HISTCHARS", histcharsgetfn, histcharssetfn, 0),
  68.     IPDEF2("HOME", homegetfn, homesetfn, 0),
  69.     IPDEF2("TERM", termgetfn, termsetfn, 0),
  70.     IPDEF2("WORDCHARS", wordcharsgetfn, wordcharssetfn, 0),
  71.     IPDEF2("IFS", ifsgetfn, ifssetfn, 0),
  72.     IPDEF2("_", underscoregetfn, IFN(nullsetfn), PMFLAG_r),
  73.  
  74. #define IPDEF3(A) {NULL,A,NULL,IFN(nullsetfn),IFN(strconstgetfn),0,PMFLAG_r|\
  75.         PMFLAG_SPECIAL,NULL,NULL,NULL,NULL,0}
  76.     IPDEF3("HOSTTYPE"),
  77.     IPDEF3("VERSION"),
  78.  
  79. #define IPDEF4(A,B) {NULL,A,NULL,IFN(nullsetfn),IFN(intvargetfn),10,\
  80.         PMFLAG_r|PMFLAG_i|PMFLAG_SPECIAL,(vptr)B,NULL,NULL,NULL,0}
  81.     IPDEF4("!", &lastpid),
  82.     IPDEF4("$", &mypid),
  83.     IPDEF4("?", &lastval),
  84.     IPDEF4("status", &lastval),
  85.     IPDEF4("LINENO", &lineno),
  86.     IPDEF4("PPID", &ppid),
  87.  
  88. #define IPDEF5(A,B) {NULL,A,NULL,IFN(intvarsetfn),IFN(intvargetfn),10,\
  89.         PMFLAG_i|PMFLAG_SPECIAL,(vptr)B,NULL,NULL,NULL,0}
  90.     IPDEF5("BAUD", &baud),
  91.     IPDEF5("COLUMNS", &columns),
  92.     IPDEF5("DIRSTACKSIZE", &dirstacksize),
  93.     IPDEF5("KEYTIMEOUT", &keytimeout),
  94.     IPDEF5("LINES", &lines),
  95.     IPDEF5("LISTMAX", &listmax),
  96.     IPDEF5("LOGCHECK", &logcheck),
  97.     IPDEF5("MAILCHECK", &mailcheck),
  98.     IPDEF5("OPTIND", &zoptind),
  99.     IPDEF5("PERIOD", &period),
  100.     IPDEF5("REPORTTIME", &reporttime),
  101.     IPDEF5("SAVEHIST", &savehist),
  102.     IPDEF5("SHLVL", &shlvl),
  103.     IPDEF5("TMOUT", &tmout),
  104.  
  105. #define IPDEF6(A,B) {NULL,A,NULL,IFN(nullsetfn),IFN(strvargetfn),0,\
  106.         PMFLAG_r|PMFLAG_SPECIAL,(vptr)B,NULL,NULL,NULL,0}
  107.     IPDEF6("LOGNAME", &zlogname),
  108.     IPDEF6("PWD", &pwd),
  109.     IPDEF6("TTY", &ttystrname),
  110.     IPDEF6("USERNAME", &username),
  111.  
  112. #define IPDEF7(A,B) {NULL,A,NULL,IFN(strvarsetfn),IFN(strvargetfn),0,\
  113.         PMFLAG_SPECIAL,(vptr)B,NULL,NULL,NULL,0}
  114.     IPDEF7("FCEDIT", &fceditparam),
  115.     IPDEF7("HOST", &hostnam),
  116.     IPDEF7("OLDPWD", &oldpwd),
  117.     IPDEF7("OPTARG", &zoptarg),
  118.     IPDEF7("MAIL", &mailfile),
  119.     IPDEF7("NULLCMD", &nullcmd),
  120.     IPDEF7("POSTEDIT", &postedit),
  121.     IPDEF7("prompt", &prompt),
  122.     IPDEF7("PROMPT", &prompt),
  123.     IPDEF7("PROMPT2", &prompt2),
  124.     IPDEF7("PROMPT3", &prompt3),
  125.     IPDEF7("PROMPT4", &prompt4),
  126.     IPDEF7("READNULLCMD", &readnullcmd),
  127.     IPDEF7("RPROMPT", &rprompt),
  128.     IPDEF7("PS1", &prompt),
  129.     IPDEF7("PS2", &prompt2),
  130.     IPDEF7("PS3", &prompt3),
  131.     IPDEF7("PS4", &prompt4),
  132.     IPDEF7("RPS1", &rprompt),
  133.     IPDEF7("SPROMPT", &sprompt),
  134.     IPDEF7("TIMEFMT", &timefmt),
  135.     IPDEF7("TMPPREFIX", &tmpprefix),
  136.     IPDEF7("WATCHFMT", &watchfmt),
  137.     IPDEF7("0", &argzero),
  138.  
  139. #define IPDEF8(A,B,C) {NULL,A,NULL,IFN(colonarrsetfn),IFN(colonarrgetfn),0,\
  140.         PMFLAG_SPECIAL,(vptr)C,NULL,B,NULL,0}
  141.     IPDEF8("CDPATH", "cdpath", &cdpath),
  142.     IPDEF8("FIGNORE", "fignore", &fignore),
  143.     IPDEF8("FPATH", "fpath", &fpath),
  144.     IPDEF8("MAILPATH", "mailpath", &mailpath),
  145.     IPDEF8("MANPATH", "manpath", &manpath),
  146.     IPDEF8("WATCH", "watch", &watch),
  147.     IPDEF8("PSVAR", "psvar", &psvar),
  148.     {NULL,"PATH",NULL,IFN(colonpathsetfn),IFN(colonpathgetfn),0,
  149.          PMFLAG_SPECIAL,(vptr)NULL,NULL,"path",NULL,0},
  150.  
  151. #define IPDEF9(A,B,C,D) {NULL,A,NULL,IFN(arrvarsetfn),IFN(arrvargetfn),0,\
  152.         PMFLAG_A|PMFLAG_SPECIAL|C,(vptr)B,NULL,D,NULL,0}
  153.     IPDEF9("cdpath", &cdpath, 0, "CDPATH"),
  154.     IPDEF9("fignore", &fignore, 0, "FIGNORE"),
  155.     IPDEF9("fpath", &fpath, 0, "FPATH"),
  156.     IPDEF9("mailpath", &mailpath, 0, "MAILPATH"),
  157.     IPDEF9("manpath", &manpath, 0, "MANPATH"),
  158.     IPDEF9("watch", &watch, 0, "WATCH"),
  159.     IPDEF9("psvar", &psvar, 0, "PSVAR"),
  160.     IPDEF9("signals", &sigptr, PMFLAG_r, NULL),
  161.     IPDEF9("argv", &pparams, 0, NULL),
  162.     IPDEF9("*", &pparams, 0, NULL),
  163.     IPDEF9("@", &pparams, 0, NULL),
  164.  
  165.     {NULL,"path",NULL,IFN(pathsetfn),IFN(pathgetfn),0,
  166.          PMFLAG_A|PMFLAG_SPECIAL,NULL,NULL,"PATH",NULL,0},
  167.  
  168.     {NULL,}
  169.     };
  170.     struct iparam *ip;
  171.  
  172.     for (ip = pinit; ip->nam; ip++)
  173.     addhnode(ztrdup(ip->nam), ip, paramtab, (FFunc) 0);
  174.     argvparam = (Param) gethnode("argv", paramtab);
  175.  
  176.     ((struct iparam *)gethnode("HOSTTYPE", paramtab))->data = (vptr) ztrdup(HOSTTYPE);
  177.     ((struct iparam *)gethnode("VERSION", paramtab))->data = (vptr) ztrdup(VERSIONSTR);
  178. }
  179.  
  180. struct param *createparam(name, flags)    /**/
  181. char *name;
  182. int flags;
  183. {
  184.     struct param *pm, *oldpm = (Param) gethnode(name, paramtab);
  185.     int spec;
  186.  
  187.     spec = oldpm && (oldpm->flags & PMFLAG_SPECIAL);
  188.     if ((oldpm && oldpm->level == locallevel) || spec) {
  189.     pm = oldpm;
  190.     pm->ct = 0;
  191.     oldpm = pm->old;
  192.     pm->flags = (flags & (PMFLAG_x|PMFLAG_L|PMFLAG_R|PMFLAG_Z|
  193.                   PMFLAG_l|PMFLAG_u|PMFLAG_r|PMFLAG_t)) |
  194.             (pm->flags & (PMFLAG_s|PMFLAG_i|PMFLAG_A|PMFLAG_SPECIAL));
  195.     if (pm->ename) {
  196.         Param altpm = (Param) gethnode(pm->ename, paramtab);
  197.         if (altpm) altpm->flags &= ~(PMFLAG_UNSET|PMFLAG_x|PMFLAG_L|
  198.                      PMFLAG_R|PMFLAG_Z|PMFLAG_l|
  199.                      PMFLAG_u|PMFLAG_r|PMFLAG_t);
  200.     }
  201.     } else {
  202.     pm = (struct param *)zcalloc(sizeof *pm);
  203.     if ((pm->old = oldpm))
  204.         remhnode(name, paramtab);  /* needed to avoid freeing oldpm */
  205.     addhnode(ztrdup(name), pm, paramtab, freepm);
  206.     }
  207.     if (isset(ALLEXPORT) && !oldpm)
  208.     pm->flags |= PMFLAG_x;
  209.     if (!spec) {
  210.     pm->flags = flags;
  211.     if ((flags & PMTYPE) == PMFLAG_s) {
  212.         pm->sets.cfn = strsetfn;
  213.         pm->gets.cfn = strgetfn;
  214.     } else if ((flags & PMTYPE) == PMFLAG_A) {
  215.         pm->sets.afn = arrsetfn;
  216.         pm->gets.afn = arrgetfn;
  217.     } else {
  218.         pm->sets.ifn = intsetfn;
  219.         pm->gets.ifn = intgetfn;
  220.     }
  221.     }
  222.     return pm;
  223. }
  224.  
  225.  
  226. int isident(s)            /**/
  227. char *s;
  228. {
  229.     char *ss;
  230.     int ne = noeval;
  231.  
  232.     if (!*s)
  233.     return 0;
  234.  
  235.     for (ss = s; *ss; ss++)
  236.     if (!iident(*ss))
  237.         break;
  238.     if (!*ss || (*ss == '[' && ss[1] == '('))
  239.     return 1;
  240.     if (*ss != '[')
  241.     return 0;
  242.     noeval = 1;
  243.     (void)mathevalarg(++ss, &ss);
  244.     if (*ss == ',' || *ss == Comma)
  245.     (void)mathevalarg(++ss, &ss);
  246.     noeval = ne;
  247.     if (*ss != ']' || ss[1])
  248.     return 0;
  249.     return 1;
  250. }
  251.  
  252. char **garr;
  253.  
  254. long getarg(str, inv, v, a2, w)        /**/
  255. char **str;
  256. int *inv;
  257. Value v;
  258. int a2;
  259. long *w;
  260. {
  261.     int num = 1, word = 0, rev = 0, ind = 0, down = 0, exp = 0, l, i;
  262.     char *s = *str, *sep = NULL, *t, sav, *d, **ta, **p, *tt;
  263.     long r = 0, rr, rrr;
  264.     Comp c;
  265.  
  266.     if (*s == '(' || *s == Inpar) {
  267.     for (s++; *s != ')' && *s != Outpar && s != *str; s++) {
  268.         switch (*s) {
  269.         case 'r':
  270.         rev = 1;
  271.         down = ind = 0;
  272.         break;
  273.         case 'R':
  274.         rev = down = 1;
  275.         ind = 0;
  276.         break;
  277.         case 'i':
  278.         rev = ind = 1;
  279.         down = 0;
  280.         break;
  281.         case 'I':
  282.         rev = ind = down = 1;
  283.         break;
  284.         case 'w':
  285.         word = 1;
  286.         break;
  287.         case 'e':
  288.         exp = 1;
  289.         break;
  290.         case 'n':
  291.         t = get_strarg(++s);
  292.         if (!*t)
  293.             goto flagerr;
  294.         sav = *t;
  295.         *t = '\0';
  296.         num = mathevalarg(s + 1, &d);
  297.         if (!num)
  298.             num = 1;
  299.         *t = sav;
  300.         s = t;
  301.         break;
  302.         case 's':
  303.         t = get_strarg(++s);
  304.         if (!*t)
  305.             goto flagerr;
  306.         sav = *t;
  307.         *t = '\0';
  308.         sep = dupstring(s + 1);
  309.         *t = sav;
  310.         s = t;
  311.         break;
  312.         default:
  313.           flagerr:
  314.         num = 1;
  315.         word = rev = ind = down = exp = 0;
  316.         sep = NULL;
  317.         s = *str - 1;
  318.         }
  319.     }
  320.     if (s != *str)
  321.         s++;
  322.     }
  323.     if (num < 0) {
  324.     down = !down;
  325.     num = -num;
  326.     }
  327.     *inv = ind;
  328.  
  329.     for (t = s, i = 0; *t && (*t != ']' || i) &&
  330.      (*t != Outbrack || i) && *t != ','; t++)
  331.     if (*t == '[' || *t == Inbrack)
  332.         i++;
  333.     else if (*t == ']' || *t == Outbrack)
  334.         i--;
  335.  
  336.     if (!*t)
  337.     return 0;
  338.     sav = *t;
  339.     *t = '\0';
  340.     s = dupstring(s);
  341.     *t = sav;
  342.     *str = tt = t;
  343.  
  344.     if (exp) {
  345.     tokenize(s);
  346.     lexsave();
  347.     strinbeg();
  348.     singsub(&s);
  349.     strinend();
  350.     lexrestore();
  351.     untokenize(s);
  352.     }
  353.     if (!rev) {
  354.     if (!(r = mathevalarg(s, &s)))
  355.         r = 1;
  356.     if (word && !v->isarr) {
  357.         s = t = getstrvalue(v);
  358.         i = wordcount(s, sep, 0);
  359.         if (r < 0)
  360.         r += i + 1;
  361.         if (r < 1)
  362.         r = 1;
  363.         if (r > i)
  364.         r = i;
  365.         if (!s || !*s)
  366.         return 0;
  367.         rrr = r;
  368.         while ((d = findword(&s, sep)) && --r);
  369.         if (!d)
  370.         return 0;
  371.  
  372.         if (a2) {
  373.         if ((d = findword(&s, sep))) {
  374.             r = (long)(d - t) - (sep ? strlen(sep) + (rrr == i ? 0 : 1) : 1);
  375.         } else
  376.             r = -1;
  377.         } else {
  378.         rr = (long)(d - t);
  379.         if (rrr > 1)
  380.             rr++;
  381.         r = rr;
  382.         }
  383.  
  384.         if (!a2 && *tt != ',' && *tt != Comma)
  385.         *w = (long)(s - t) - 1;
  386.     }
  387.     } else {
  388.     if (!v->isarr && !word) {
  389.         l = strlen(s);
  390.         if (a2) {
  391.         if (!l || *s != '*') {
  392.             d = (char *)ncalloc(l + 2);
  393.             *d = '*';
  394.             strcpy(d + 1, s);
  395.             s = d;
  396.         }
  397.         } else {
  398.         if (!l || s[l - 1] != '*') {
  399.             d = (char *)ncalloc(l + 2);
  400.             strcpy(d, s);
  401.             strcat(d, "*");
  402.             s = d;
  403.         }
  404.         }
  405.     }
  406.     tokenize(s);
  407.  
  408.     if ((c = parsereg(s))) {
  409.         if (v->isarr) {
  410.         ta = getarrvalue(v);
  411.         if (!ta || !*ta)
  412.             return 0;
  413.         if (down)
  414.             for (r = -1, p = ta + arrlen(ta) - 1; p >= ta; r--, p--) {
  415.             if (domatch(*p, c, 0) && !--num)
  416.                 return r;
  417.         } else
  418.             for (r = 1, p = ta; *p; r++, p++)
  419.             if (domatch(*p, c, 0) && !--num)
  420.                 return r;
  421.         } else if (word) {
  422.         ta = sepsplit(d = s = getstrvalue(v), sep);
  423.         if (down) {
  424.             for (p = ta + (r = arrlen(ta)) - 1; p >= ta; p--, r--)
  425.             if (domatch(*p, c, 0) && !--num)
  426.                 break;
  427.             if (p < ta)
  428.             return 0;
  429.         } else {
  430.             for (r = 1, p = ta; *p; r++, p++)
  431.             if (domatch(*p, c, 0) && !--num)
  432.                 break;
  433.             if (!*p)
  434.             return 0;
  435.         }
  436.         if (a2)
  437.             r++;
  438.         for (i = 0, t = findword(&d, sep); t && *t;
  439.              i++, t = findword(&d, sep))
  440.             if (!--r) {
  441.             r = (long)(t - s + (a2 ? -1 : 1));
  442.             if (!a2 && *tt != ',' && *tt != Comma)
  443.                 *w = r + strlen(ta[i]) - 2;
  444.             return r;
  445.             }
  446.         return a2 ? -1 : 0;
  447.         } else {
  448.         d = getstrvalue(v);
  449.         if (!d || !*d)
  450.             return 0;
  451.         if (a2) {
  452.             if (down)
  453.             for (r = -2, t = d + strlen(d) - 1; t >= d; r--, t--) {
  454.                 sav = *t;
  455.                 *t = '\0';
  456.                 if (domatch(d, c, 0) && !--num) {
  457.                 *t = sav;
  458.                 return r;
  459.                 }
  460.                 *t = sav;
  461.             } else
  462.             for (r = 0, t = d; *t; r++, t++) {
  463.                 sav = *t;
  464.                 *t = '\0';
  465.                 if (domatch(d, c, 0) && !--num) {
  466.                 *t = sav;
  467.                 return r;
  468.                 }
  469.                 *t = sav;
  470.             }
  471.         } else {
  472.             if (down)
  473.             for (r = -1, t = d + strlen(d) - 1; t >= d; r--, t--) {
  474.                 if (domatch(t, c, 0) && !--num)
  475.                 return r;
  476.             } else
  477.             for (r = 1, t = d; *t; r++, t++)
  478.                 if (domatch(t, c, 0) && !--num)
  479.                 return r;
  480.         }
  481.         }
  482.     }
  483.     }
  484.     return r;
  485. }
  486.  
  487. Value getvalue(pptr, bracks)    /**/
  488. char **pptr;
  489. int bracks;
  490. {
  491.     char *s = *pptr, *t = *pptr;
  492.     char sav;
  493.     Value v;
  494.     int inv = 0;
  495.  
  496.     garr = NULL;
  497.  
  498.     if (idigit(*s))
  499.     while (idigit(*s))
  500.         s++;
  501.     else if (iident(*s))
  502.     while (iident(*s))
  503.         s++;
  504.     else if (*s == Quest)
  505.     *s++ = '?';
  506.     else if (*s == Pound)
  507.     *s++ = '#';
  508.     else if (*s == String)
  509.     *s++ = '$';
  510.     else if (*s == Qstring)
  511.     *s++ = '$';
  512.     else if (*s == Star)
  513.     *s++ = '*';
  514.     else if (*s == '#' || *s == '-' || *s == '?' || *s == '$' ||
  515.          *s == '_' || *s == '!' || *s == '@' || *s == '*')
  516.     s++;
  517.     else
  518.     return NULL;
  519.     if ((sav = *s))
  520.     *s = '\0';
  521.     if (idigit(*t) && *t != '0') {
  522.     v = (Value) hcalloc(sizeof *v);
  523.     v->pm = argvparam;
  524.     v->inv = 0;
  525.     v->a = v->b = atoi(t) - 1;
  526.     if (sav)
  527.         *s = sav;
  528.     } else {
  529.     struct param *pm;
  530.     int isvarat = !strcmp(t, "@");
  531.  
  532.     pm = (struct param *)gethnode(t, paramtab);
  533.     if (sav)
  534.         *s = sav;
  535.     *pptr = s;
  536.     if (!pm || (pm->flags & PMFLAG_UNSET))
  537.         return NULL;
  538.     v = (Value) hcalloc(sizeof *v);
  539.     if (pmtype(pm) == PMFLAG_A)
  540.         v->isarr = isvarat ? -1 : 1;
  541.     v->pm = pm;
  542.     v->inv = 0;
  543.     v->a = 0;
  544.     v->b = -1;
  545.     if (bracks && (*s == '[' || *s == Inbrack)) {
  546.         int a, b;
  547.         char *olds = s, *tbrack;
  548.  
  549.         *s++ = '[';
  550.         for (tbrack = s; *tbrack && *tbrack != ']' && *tbrack != Outbrack; tbrack++)
  551.         if (itok(*tbrack))
  552.             *tbrack = ztokens[*tbrack - Pound];
  553.         if (*tbrack == Outbrack)
  554.         *tbrack = ']';
  555.         if ((s[0] == '*' || s[0] == '@') && s[1] == ']') {
  556.         if (v->isarr)
  557.             v->isarr = (s[0] == '*') ? 1 : -1;
  558.         v->a = 0;
  559.         v->b = -1;
  560.         s += 2;
  561.         } else {
  562.         long we = 0, dummy;
  563.  
  564.         a = getarg(&s, &inv, v, 0, &we);
  565.         if (a > 0 && !inv)
  566.             a--;
  567.  
  568.         if (inv) {
  569.             v->inv = 1;
  570.             if (*s == ']' || *s == Outbrack)
  571.             s++;
  572.             v->isarr = 0;
  573.             v->a = v->b = a;
  574.             if (*s == ',' || *s == Comma) {
  575.             zerr("invalid subscript", NULL, 0);
  576.             while (*s != ']' && *s != Outbrack)
  577.                 s++;
  578.             *pptr = s;
  579.             return v;
  580.             }
  581.         } else {
  582.             if (*s == ',' || *s == Comma) {
  583.             s++;
  584.             b = getarg(&s, &inv, v, 1, &dummy);
  585.             if (b > 0)
  586.                 b--;
  587.             } else {
  588.             b = we ? we : a;
  589.             }
  590.             if (*s == ']' || *s == Outbrack) {
  591.             s++;
  592.             if (v->isarr && a == b)
  593.                 v->isarr = 0;
  594.             v->a = a;
  595.             v->b = b;
  596.             } else
  597.             s = olds;
  598.         }
  599.         }
  600.     }
  601.     }
  602.     if (!bracks && *s)
  603.     return NULL;
  604.     *pptr = s;
  605.     return v;
  606. }
  607.  
  608. char *getstrvalue(v)        /**/
  609. Value v;
  610. {
  611.     char *s, **ss;
  612.     static char buf[20];
  613.  
  614.     if (!v)
  615.     return "";
  616.     if (v->inv) {
  617.     sprintf(buf, "%d", v->a);
  618.     return dupstring(buf);
  619.     }
  620.     if (pmtype(v->pm) != PMFLAG_A) {
  621.     if ((pmtype(v->pm) == PMFLAG_i))
  622.         convbase(s = buf, v->pm->gets.ifn(v->pm), v->pm->ct);
  623.     else
  624.         s = v->pm->gets.cfn(v->pm);
  625.     if (v->a == 0 && v->b == -1)
  626.         return s;
  627.     if (v->a < 0)
  628.         v->a += strlen(s);
  629.     if (v->b < 0)
  630.         v->b += strlen(s);
  631.     s = (v->a > (int) strlen(s)) ? dupstring("") : dupstring(s + v->a);
  632.     if (v->b < v->a)
  633.         s[0] = '\0';
  634.     else if (v->b - v->a < (int) strlen(s))
  635.         s[v->b - v->a + 1] = '\0';
  636.     return s;
  637.     }
  638.     if (v->isarr)
  639.     return spacejoin(v->pm->gets.afn(v->pm));
  640.  
  641.     ss = v->pm->gets.afn(v->pm);
  642.     if (v->a < 0)
  643.     v->a += arrlen(ss);
  644.     s = (v->a >= arrlen(ss) || v->a < 0) ? "" : ss[v->a];
  645.     return s;
  646. }
  647.  
  648. static char *nular[] =
  649. {"", NULL};
  650.  
  651. char **getarrvalue(v)        /**/
  652. Value v;
  653. {
  654.     char **s;
  655.  
  656.     if (!v)
  657.     return arrdup(nular);
  658.     if (v->inv) {
  659.     char buf[20];
  660.  
  661.     s = arrdup(nular);
  662.     sprintf(buf, "%d", v->a);
  663.     s[0] = dupstring(buf);
  664.     return s;
  665.     }
  666.     s = v->pm->gets.afn(v->pm);
  667.     if (v->a == 0 && v->b == -1)
  668.     return s;
  669.     if (v->a < 0)
  670.     v->a += arrlen(s);
  671.     if (v->b < 0)
  672.     v->b += arrlen(s);
  673.     if (v->a > arrlen(s) || v->a < 0)
  674.     s = arrdup(nular);
  675.     else
  676.     s = arrdup(s) + v->a;
  677.     if (v->b < v->a)
  678.     s[0] = NULL;
  679.     else if (v->b - v->a < arrlen(s))
  680.     s[v->b - v->a + 1] = NULL;
  681.     return s;
  682. }
  683.  
  684. long getintvalue(v)        /**/
  685. Value v;
  686. {
  687.     char **ss;
  688.  
  689.     if (!v || v->isarr)
  690.     return 0;
  691.     if (v->inv)
  692.     return v->a;
  693.     if (pmtype(v->pm) != PMFLAG_A) {
  694.     if (pmtype(v->pm) == PMFLAG_i)
  695.         return v->pm->gets.ifn(v->pm);
  696.     return atol(v->pm->gets.cfn(v->pm));
  697.     }
  698.     ss = v->pm->gets.afn(v->pm);
  699.     if (v->a < 0)
  700.     v->a += arrlen(ss);
  701.     if (v->a < 0 || v->a >= arrlen(ss))
  702.     return 0;
  703.     return atol(ss[v->a]);
  704. }
  705.  
  706. void setstrvalue(v, val)    /**/
  707. Value v;
  708. char *val;
  709. {
  710.     char buf[20];
  711.  
  712.     if (v->pm->flags & PMFLAG_r) {
  713.     zsfree(val);
  714.     return;
  715.     }
  716.     switch (pmtype(v->pm)) {
  717.     case PMFLAG_s:
  718.     if (v->a == 0 && v->b == -1) {
  719.         (v->pm->sets.cfn) (v->pm, val);
  720.         if (v->pm->flags & (PMFLAG_L | PMFLAG_R | PMFLAG_Z) && !v->pm->ct)
  721.         v->pm->ct = strlen(val);
  722.     } else {
  723.         char *z, *y, *x;
  724.         int zlen;
  725.  
  726.         z = dupstring((v->pm->gets.cfn) (v->pm));
  727.         zlen = strlen(z);
  728.         if (v->inv)
  729.         v->a--, v->b--;
  730.         if (v->a < 0) {
  731.         v->a += zlen;
  732.         if (v->a < 0)
  733.             v->a = 0;
  734.         }
  735.         if (v->a > zlen)
  736.         v->a = zlen;
  737.         if (v->b < 0)
  738.         v->b += zlen;
  739.         if (v->b < v->a)
  740.         v->b = v->a;
  741.         if (v->b > zlen - 1)
  742.         v->b = zlen - 1;
  743.         z[v->a] = '\0';
  744.         y = z + v->b + 1;
  745.         x = (char *)zalloc(strlen(z) + strlen(y) + strlen(val) + 1);
  746.         strcpy(x, z);
  747.         strcat(x, val);
  748.         strcat(x, y);
  749.         (v->pm->sets.cfn) (v->pm, x);
  750.         zsfree(val);
  751.     }
  752.     break;
  753.     case PMFLAG_i:
  754.     (v->pm->sets.ifn) (v->pm, matheval(val));
  755.     if (!v->pm->ct && lastbase != 1)
  756.         v->pm->ct = lastbase;
  757.     zsfree(val);
  758.     break;
  759.     case PMFLAG_A:
  760.     if (v->a != v->b) {
  761.         char **ss = (char **)zalloc(2 * sizeof(char *));
  762.  
  763.         ss[0] = val;
  764.         ss[1] = NULL;
  765.     } else {
  766.         char **ss = (v->pm->gets.afn) (v->pm);
  767.         int ac, ad, t0;
  768.  
  769.         if (v->inv)
  770.         v->a--, v->b--;
  771.         ac = arrlen(ss);
  772.         if (v->a < 0) {
  773.         v->a += ac;
  774.         if (v->a < 0)
  775.             v->a = 0;
  776.         }
  777.         if (v->a >= ac) {
  778.         char **st = ss;
  779.  
  780.         ad = v->a + 1;
  781.         ss = (char **)zalloc((ad + 1) * sizeof *ss);
  782.         for (t0 = 0; t0 != ac; t0++)
  783.             ss[t0] = ztrdup(st[t0]);
  784.         while (ac < ad)
  785.             ss[ac++] = ztrdup("");
  786.         ss[ac] = NULL;
  787.         }
  788.         zsfree(ss[v->a]);
  789.         ss[v->a] = val;
  790.         (v->pm->sets.afn) (v->pm, ss);
  791.     }
  792.     break;
  793.     }
  794.     if ((!v->pm->env && !(v->pm->flags & PMFLAG_x) &&
  795.     !(isset(ALLEXPORT) && !v->pm->old)) ||
  796.     (v->pm->flags & PMFLAG_A) || v->pm->ename)
  797.     return;
  798.     if (pmtype(v->pm) == PMFLAG_i)
  799.     convbase(val = buf, v->pm->gets.ifn(v->pm), v->pm->ct);
  800.     else
  801.     val = v->pm->gets.cfn(v->pm);
  802.     if (v->pm->env)
  803.     v->pm->env = replenv(v->pm->env, val);
  804.     else {
  805.     v->pm->flags |= PMFLAG_x;
  806.     v->pm->env = addenv(v->pm->nam, val);
  807.     }
  808. }
  809.  
  810. void setintvalue(v, val)    /**/
  811. Value v;
  812. long val;
  813. {
  814.     char buf[20];
  815.  
  816.     if (v->pm->flags & PMFLAG_r)
  817.     return;
  818.     sprintf(buf, "%ld", val);
  819.     if (v->pm->env) {
  820.     v->pm->env = replenv(v->pm->env, buf);
  821.     } else if ((v->pm->flags & PMFLAG_x) ||
  822.            (isset(ALLEXPORT) && !v->pm->old)) {
  823.     v->pm->flags |= PMFLAG_x;
  824.     v->pm->env = addenv(v->pm->nam, buf);
  825.     }
  826.     switch (pmtype(v->pm)) {
  827.     case PMFLAG_s:
  828.     (v->pm->sets.cfn) (v->pm, ztrdup(buf));
  829.     break;
  830.     case PMFLAG_i:
  831.     (v->pm->sets.ifn) (v->pm, val);
  832.     if (!v->pm->ct && lastbase != -1)
  833.         v->pm->ct = lastbase;
  834.     break;
  835.     case PMFLAG_A:
  836.     zerr("attempt to assign integer to array", NULL, 0);
  837.     break;
  838.     }
  839. }
  840.  
  841. void setintenv(s, val)        /**/
  842. char *s;
  843. long val;
  844. {
  845.     Param pm;
  846.     char buf[20];
  847.  
  848.     if ((pm = (Param) gethnode(s, paramtab)) && pm->env) {
  849.     sprintf(buf, "%ld", val);
  850.     pm->env = replenv(pm->env, buf);
  851.     }
  852. }
  853.  
  854. void setarrvalue(v, val)    /**/
  855. Value v;
  856. char **val;
  857. {
  858.     if (v->pm->flags & PMFLAG_r) {
  859.     freearray(val);
  860.     return;
  861.     }
  862.     if (pmtype(v->pm) != PMFLAG_A) {
  863.     freearray(val);
  864.     zerr("attempt to assign array value to non-array", NULL, 0);
  865.     return;
  866.     }
  867.     if (v->a == 0 && v->b == -1)
  868.     (v->pm->sets.afn) (v->pm, val);
  869.     else {
  870.     char **old, **new, **p, **q, **r;
  871.     int n, nn, l, ll, i;
  872.  
  873.     if (v->inv)
  874.         v->a--, v->b--;
  875.     q = old = v->pm->gets.afn(v->pm);
  876.     n = arrlen(old);
  877.     if (v->a < 0)
  878.         v->a += n;
  879.     if (v->b < 0)
  880.         v->b += n;
  881.     if (v->a < 0)
  882.         v->a = 0;
  883.     if (v->b < 0)
  884.         v->b = 0;
  885.     if (v->a >= n)
  886.         v->a = n;
  887.     if (v->b >= n)
  888.         v->b = n;
  889.  
  890.     if (v->a > v->b)
  891.         (v->pm->sets.afn) (v->pm, arrdup(nular));
  892.     else {
  893.         l = v->b - v->a + 1;
  894.  
  895.         nn = arrlen(val);
  896.  
  897.         ll = n - l + nn;
  898.  
  899.         p = new = (char **)zcalloc(sizeof(char *) * (ll + 1));
  900.  
  901.         for (i = 0; i < v->a; i++)
  902.         *p++ = ztrdup(*q++);
  903.         for (r = val; *r;)
  904.         *p++ = ztrdup(*r++);
  905.         if (*q)
  906.         for (q += l; *q;)
  907.             *p++ = ztrdup(*q++);
  908.  
  909.         (v->pm->sets.afn) (v->pm, new);
  910.     }
  911.     freearray(val);
  912.     freearray(old);
  913.     }
  914. }
  915.  
  916. long getiparam(s)        /**/
  917. char *s;
  918. {
  919.     Value v;
  920.  
  921.     if (!(v = getvalue(&s, 0)))
  922.     return 0;
  923.     return getintvalue(v);
  924. }
  925.  
  926. char *getsparam(s)        /**/
  927. char *s;
  928. {
  929.     Value v;
  930.  
  931.     if (!(v = getvalue(&s, 0)))
  932.     return NULL;
  933.     return getstrvalue(v);
  934. }
  935.  
  936. char **getaparam(s)        /**/
  937. char *s;
  938. {
  939.     Value v;
  940.  
  941.     if (!((v = getvalue(&s, 0)) && v->isarr))
  942.     return NULL;
  943.     return getarrvalue(v);
  944. }
  945.  
  946. Param setsparam(s, val)        /**/
  947. char *s;
  948. char *val;
  949. {
  950.     Value v;
  951.     char *t = s;
  952.     char *ss;
  953.  
  954.     if (!isident(s)) {
  955.     zerr("not an identifier: %s", s, 0);
  956.     zsfree(val);
  957.     errflag = 1;
  958.     return NULL;
  959.     }
  960.     if ((ss = strchr(s, '['))) {
  961.     *ss = '\0';
  962.     if (!(v = getvalue(&s, 1)))
  963.         createparam(t, PMFLAG_A);
  964.     *ss = '[';
  965.     v = NULL;
  966.     } else{
  967.     if (!(v = getvalue(&s, 1)))
  968.         createparam(t, PMFLAG_s);
  969.     else if ((v->pm->flags & PMTYPE) == PMFLAG_A &&
  970.         !(v->pm->flags & PMFLAG_SPECIAL)) {
  971.         unsetparam(t);
  972.         createparam(t, PMFLAG_s);
  973.         v = NULL;
  974.     }
  975.     }
  976.     if (!v)
  977.     v = getvalue(&t, 1);
  978.     setstrvalue(v, val);
  979.     return v->pm;
  980. }
  981.  
  982. Param setaparam(s, val)        /**/
  983. char *s;
  984. char **val;
  985. {
  986.     Value v;
  987.     char *t = s;
  988.     char *ss;
  989.  
  990.     if (!isident(s)) {
  991.     zerr("not an identifier: %s", s, 0);
  992.     freearray(val);
  993.     errflag = 1;
  994.     return NULL;
  995.     }
  996.     if ((ss = strchr(s, '['))) {
  997.     *ss = '\0';
  998.     if (!(v = getvalue(&s, 1)))
  999.         createparam(t, PMFLAG_A);
  1000.     *ss = '[';
  1001.     v = NULL;
  1002.     } else {
  1003.     if (!(v = getvalue(&s, 1)))
  1004.         createparam(t, PMFLAG_A);
  1005.     else if ((v->pm->flags & PMTYPE) != PMFLAG_A &&
  1006.         !(v->pm->flags & PMFLAG_SPECIAL)) {
  1007.         unsetparam(t);
  1008.         createparam(t, PMFLAG_A);
  1009.         v = NULL;
  1010.     }
  1011.     }
  1012.     if (!v)
  1013.     v = getvalue(&t, 1);
  1014.     setarrvalue(v, val);
  1015.     return v->pm;
  1016. }
  1017.  
  1018. Param setiparam(s, val)        /**/
  1019. char *s;
  1020. long val;
  1021. {
  1022.     Value v;
  1023.     char *t = s;
  1024.     Param pm;
  1025.  
  1026.     if (!isident(s)) {
  1027.     zerr("not an identifier: %s", s, 0);
  1028.     errflag = 1;
  1029.     return NULL;
  1030.     }
  1031.     if (!(v = getvalue(&s, 0))) {
  1032.     pm = createparam(t, PMFLAG_i);
  1033.     pm->u.val = val;
  1034.     return pm;
  1035.     }
  1036.     setintvalue(v, val);
  1037.     return v->pm;
  1038. }
  1039.  
  1040. void unsetparam(s)        /**/
  1041. char *s;
  1042. {
  1043.     Param pm, oldpm;
  1044.     int spec;
  1045.     static int altflag = 0;
  1046.  
  1047.     if (!(pm = (Param) gethnode(s, paramtab)))
  1048.     return;
  1049.     if ((pm->flags & PMFLAG_r) && pm->level <= locallevel)
  1050.     return;
  1051.     spec = (pm->flags & PMFLAG_SPECIAL) && !pm->level;
  1052.     switch (pmtype(pm)) {
  1053.     case 0:
  1054.     (pm->sets.cfn) (pm, NULL);
  1055.     break;
  1056.     case PMFLAG_i:
  1057.     (pm->sets.ifn) (pm, 0);
  1058.     break;
  1059.     case PMFLAG_A:
  1060.     (pm->sets.afn) (pm, NULL);
  1061.     break;
  1062.     }
  1063.     if ((pm->flags & PMFLAG_x) && pm->env) {
  1064.     delenv(pm->env);
  1065.     zsfree(pm->env);
  1066.     pm->env = NULL;
  1067.     }
  1068.     if (pm->ename && !altflag) {
  1069.     altflag = 1;
  1070.     unsetparam(pm->ename);
  1071.     altflag = 0;
  1072.     }
  1073.     if ((locallevel && locallevel == pm->level) || spec) {
  1074.     pm->flags |= PMFLAG_UNSET;
  1075.     } else {
  1076.     oldpm = pm->old;
  1077.     freepm(remhnode(s, paramtab));
  1078.     if (oldpm) {
  1079.         addhnode(ztrdup(s), oldpm, paramtab, freepm);
  1080.         if (!(oldpm->flags & PMTYPE) && oldpm->sets.cfn == strsetfn)
  1081.         adduserdir(oldpm->nam, oldpm->u.str, 0, 1);
  1082.     }
  1083.     }
  1084. }
  1085.  
  1086. void intsetfn(pm, x)        /**/
  1087. Param pm;
  1088. long x;
  1089. {
  1090.     pm->u.val = x;
  1091. }
  1092.  
  1093. long intgetfn(pm)        /**/
  1094. Param pm;
  1095. {
  1096.     return pm->u.val;
  1097. }
  1098.  
  1099. void strsetfn(pm, x)        /**/
  1100. Param pm;
  1101. char *x;
  1102. {
  1103.     zsfree(pm->u.str);
  1104.     pm->u.str = x;
  1105.     adduserdir(pm->nam, x, 0, 2);
  1106. }
  1107.  
  1108. char *strgetfn(pm)        /**/
  1109. Param pm;
  1110. {
  1111.     return pm->u.str ? pm->u.str : "";
  1112. }
  1113.  
  1114. void nullsetfn(pm, x)        /**/
  1115. Param pm;
  1116. char *x;
  1117. {
  1118.     zsfree(x);
  1119. }
  1120.  
  1121. void arrsetfn(pm, x)        /**/
  1122. Param pm;
  1123. char **x;
  1124. {
  1125.     if (pm->u.arr && pm->u.arr != x)
  1126.     freearray(pm->u.arr);
  1127.     pm->u.arr = x;
  1128. }
  1129.  
  1130.  
  1131. char **arrgetfn(pm)        /**/
  1132. Param pm;
  1133. {
  1134.     char *nullarray = NULL;
  1135.  
  1136.     return pm->u.arr ? pm->u.arr : &nullarray;
  1137. }
  1138.  
  1139. void intvarsetfn(pm, x)        /**/
  1140. Param pm;
  1141. long x;
  1142. {
  1143.     *((long *)pm->data) = x;
  1144. }
  1145.  
  1146. long intvargetfn(pm)        /**/
  1147. Param pm;
  1148. {
  1149.     return *((long *)pm->data);
  1150. }
  1151.  
  1152. void strvarsetfn(pm, x)        /**/
  1153. Param pm;
  1154. char *x;
  1155. {
  1156.     char **q = ((char **)pm->data);
  1157.  
  1158.     zsfree(*q);
  1159.     *q = x;
  1160. }
  1161.  
  1162. char *strvargetfn(pm)        /**/
  1163. Param pm;
  1164. {
  1165.     char *s = *((char **)pm->data);
  1166.     if (!s)
  1167.     return "";
  1168.     return s;
  1169. }
  1170.  
  1171. char *strconstgetfn(pm)        /**/
  1172. Param pm;
  1173. {
  1174.     return (char *)pm->data;
  1175. }
  1176.  
  1177. char **colonfix(x, ename)    /**/
  1178. char *x;
  1179. char *ename;
  1180. {
  1181.     char **s, **t;
  1182.  
  1183.     s = colonsplit(x);
  1184.     if (ename)
  1185.     arrfixenv(ename, s);
  1186.     zsfree(x);
  1187.     for (t = s; *t; t++)
  1188.     if (!**t) {
  1189.         free(*t);
  1190.         *t = ztrdup(".");
  1191.     }
  1192.     return s;
  1193. }
  1194.  
  1195. void colonarrsetfn(pm, x)    /**/
  1196. Param pm;
  1197. char *x;
  1198. {
  1199.     char ***dptr = (char ***)pm->data;
  1200.  
  1201.     freearray(*dptr);
  1202.     if (pm->data == (vptr) &mailpath &&    x && !*x) {
  1203.     zsfree(x);
  1204.     *dptr = mkarray(NULL);
  1205.     }
  1206.     else
  1207.     *dptr = x ? colonfix(x, pm->ename ? pm->nam : NULL) : mkarray(NULL);
  1208. }
  1209.  
  1210. void colonpathsetfn(pm, x)    /**/
  1211. Param pm;
  1212. char *x;
  1213. {
  1214.     freearray(path);
  1215.     path = x ? colonfix(x, pm->nam) : mkarray(NULL);
  1216.     newcmdnamtab();
  1217. }
  1218.  
  1219. char *colonarrgetfn(pm)        /**/
  1220. Param pm;
  1221. {
  1222.     return join(*(char ***)pm->data, ':');
  1223. }
  1224.  
  1225. char *colonpathgetfn(pm)        /**/
  1226. Param pm;
  1227. {
  1228.     return join(path, ':');
  1229. }
  1230.  
  1231. char **arrvargetfn(pm)        /**/
  1232. Param pm;
  1233. {
  1234.     return *((char ***)pm->data);
  1235. }
  1236.  
  1237. void arrvarsetfn(pm, x)        /**/
  1238. Param pm;
  1239. char **x;
  1240. {
  1241.     char ***dptr = (char ***)pm->data;
  1242.     if (*dptr != x)
  1243.     freearray(*dptr);
  1244.     *dptr = x ? x : mkarray(NULL);
  1245.     if (pm->ename && x)
  1246.     arrfixenv(pm->ename, x);
  1247. }
  1248.  
  1249. char **pathgetfn(pm)        /**/
  1250. Param pm;
  1251. {
  1252.     return path;
  1253. }
  1254.  
  1255. void pathsetfn(pm, x)        /**/
  1256. Param pm;
  1257. char **x;
  1258. {
  1259.     if (path != x)
  1260.     freearray(path);
  1261.     path = x ? x : mkarray(NULL);
  1262.     newcmdnamtab();
  1263.     if (x) arrfixenv("PATH", x);
  1264. }
  1265.  
  1266. long poundgetfn(pm)        /**/
  1267. Param pm;
  1268. {
  1269.     return arrlen(pparams);
  1270. }
  1271.  
  1272. long randomgetfn(pm)        /**/
  1273. Param pm;
  1274. {
  1275.     return rand() & 0x7fff;
  1276. }
  1277.  
  1278. void randomsetfn(pm, v)        /**/
  1279. Param pm;
  1280. long v;
  1281. {
  1282.     srand((unsigned int)v);
  1283. }
  1284.  
  1285. long secondsgetfn(pm)        /**/
  1286. Param pm;
  1287. {
  1288.     return time(NULL) - shtimer.tv_sec;
  1289. }
  1290.  
  1291. void secondssetfn(pm, x)    /**/
  1292. Param pm;
  1293. long x;
  1294. {
  1295.     shtimer.tv_sec = time(NULL) - x;
  1296.     shtimer.tv_usec = 0;
  1297. }
  1298.  
  1299. long uidgetfn(pm)        /**/
  1300. Param pm;
  1301. {
  1302.     return getuid();
  1303. }
  1304.  
  1305. long euidgetfn(pm)        /**/
  1306. Param pm;
  1307. {
  1308.     return geteuid();
  1309. }
  1310.  
  1311. long gidgetfn(pm)        /**/
  1312. Param pm;
  1313. {
  1314.     return getegid();
  1315. }
  1316.  
  1317. long egidgetfn(pm)        /**/
  1318. Param pm;
  1319. {
  1320.     return getegid();
  1321. }
  1322.  
  1323. char *ifsgetfn(pm)        /**/
  1324. Param pm;
  1325. {
  1326.     return ifs;
  1327. }
  1328.  
  1329. void ifssetfn(pm, x)        /**/
  1330. Param pm;
  1331. char *x;
  1332. {
  1333.     if (x) {
  1334.     zsfree(ifs);
  1335.     ifs = x;
  1336.     }
  1337.     inittyptab();
  1338. }
  1339.  
  1340. void histsizesetfn(pm, v)    /**/
  1341. Param pm;
  1342. long v;
  1343. {
  1344.     if ((histsiz = v) <= 2)
  1345.     histsiz = 2;
  1346.     resizehistents();
  1347. }
  1348.  
  1349. long histsizegetfn(pm)        /**/
  1350. Param pm;
  1351. {
  1352.     return histsiz;
  1353. }
  1354.  
  1355. void lithistsizesetfn(pm, v)    /**/
  1356. Param pm;
  1357. long v;
  1358. {
  1359.     if ((lithistsiz = v) <= 2)
  1360.     lithistsiz = 2;
  1361.     resizehistents();
  1362. }
  1363.  
  1364. long lithistsizegetfn(pm)    /**/
  1365. Param pm;
  1366. {
  1367.     return lithistsiz;
  1368. }
  1369.  
  1370. long errnogetfn(pm)        /**/
  1371. Param pm;
  1372. {
  1373.     return errno;
  1374. }
  1375.  
  1376. char *dashgetfn(pm)        /**/
  1377. Param pm;
  1378. {
  1379.     static char buf[100];
  1380.     char *val;
  1381.     int t0;
  1382.  
  1383.     for (val = buf, t0 = ' '; t0 <= 'z'; t0++)
  1384.     if (isset(t0))
  1385.         *val++ = t0;
  1386.     *val = '\0';
  1387.     return buf;
  1388. }
  1389.  
  1390. void histcharssetfn(pm, x)    /**/
  1391. Param pm;
  1392. char *x;
  1393. {
  1394.     if (x) {
  1395.     bangchar = x[0];
  1396.     hatchar = (bangchar) ? x[1] : '\0';
  1397.     hashchar = (hatchar) ? x[2] : '\0';
  1398.     zsfree(x);
  1399.     }
  1400. }
  1401.  
  1402. char *histcharsgetfn(pm)    /**/
  1403. Param pm;
  1404. {
  1405.     static char buf[4];
  1406.  
  1407.     buf[0] = bangchar;
  1408.     buf[1] = hatchar;
  1409.     buf[2] = hashchar;
  1410.     buf[3] = '\0';
  1411.     return buf;
  1412. }
  1413.  
  1414. char *homegetfn(pm)        /**/
  1415. Param pm;
  1416. {
  1417.     return home;
  1418. }
  1419.  
  1420. void homesetfn(pm, x)        /**/
  1421. Param pm;
  1422. char *x;
  1423. {
  1424.     zsfree(home);
  1425.     if (x && isset(CHASELINKS) && (home = xsymlink(x)))
  1426.     zsfree(x);
  1427.     else
  1428.     home = x ? x : ztrdup("");
  1429.     adduserdir("", home, 0, 1);
  1430. }
  1431.  
  1432. char *wordcharsgetfn(pm)    /**/
  1433. Param pm;
  1434. {
  1435.     return wordchars;
  1436. }
  1437.  
  1438. void wordcharssetfn(pm, x)    /**/
  1439. Param pm;
  1440. char *x;
  1441. {
  1442.     zsfree(wordchars);
  1443.     if (x)
  1444.     wordchars = x;
  1445.     else
  1446.     wordchars = ztrdup(DEFWORDCHARS);
  1447.     inittyptab();
  1448. }
  1449.  
  1450. char *underscoregetfn(pm)    /**/
  1451. Param pm;
  1452. {
  1453.     char *s, *t;
  1454.  
  1455.     if (!(s = qgetevent(curhist - 1)))
  1456.     return "";
  1457.     for (t = s + strlen(s); t > s; t--)
  1458.     if (*t == HISTSPACE)
  1459.         break;
  1460.     if (t != s)
  1461.     t++;
  1462.     return t;
  1463. }
  1464.  
  1465. char *termgetfn(pm)        /**/
  1466. Param pm;
  1467. {
  1468.     return term;
  1469. }
  1470.  
  1471. extern hasam;
  1472.  
  1473. void termsetfn(pm, x)        /**/
  1474. Param pm;
  1475. char *x;
  1476. {
  1477.     zsfree(term);
  1478.     term = x ? x : ztrdup("");
  1479.     if (!interact || unset(USEZLE))
  1480.     return;
  1481.     if (!*term) {
  1482.     termok = 0;
  1483.     } else if (tgetent(termbuf, term) != 1) {
  1484.     zerr("can't find termcap info for %s", term, 0);
  1485.     errflag = 0;
  1486.     termok = 0;
  1487.     } else {
  1488.     char tbuf[1024], *pp;
  1489.     int t0;
  1490.  
  1491.     termok = 1;
  1492.     for (t0 = 0; t0 != TC_COUNT; t0++) {
  1493.         pp = tbuf;
  1494.         zsfree(tcstr[t0]);
  1495.     /* AIX tgetstr() ignores second argument */
  1496.         if (!(pp = tgetstr(tccapnams[t0], &pp)))
  1497.         tcstr[t0] = NULL, tclen[t0] = 0;
  1498.         else {
  1499.         tcstr[t0] = (char *)zalloc(tclen[t0] = strlen(pp) + 1);
  1500.         memcpy(tcstr[t0], pp, tclen[t0]);
  1501.         }
  1502.     }
  1503.  
  1504.     /* if there's no termcap entry for cursor up, forget it.
  1505.     Use single line mode. */
  1506.  
  1507.     if (!tccan(TCUP)) {
  1508.         termok = 0;
  1509.         return;
  1510.     }
  1511.     hasam = tgetflag("am");
  1512.     /* if there's no termcap entry for cursor left, use \b. */
  1513.  
  1514.     if (!tccan(TCLEFT)) {
  1515.         tcstr[TCLEFT] = ztrdup("\b");
  1516.         tclen[TCLEFT] = 1;
  1517.     }
  1518.     /* if there's no termcap entry for clear, use ^L. */
  1519.  
  1520.     if (!tccan(TCCLEARSCREEN)) {
  1521.         tcstr[TCCLEARSCREEN] = ztrdup("\14");
  1522.         tclen[TCCLEARSCREEN] = 1;
  1523.     }
  1524.     /* if the termcap entry for down is \n, don't use it. */
  1525.  
  1526.     if (tccan(TCDOWN) && tcstr[TCDOWN][0] == '\n') {
  1527.         tclen[TCDOWN] = 0;
  1528.         zsfree(tcstr[TCDOWN]);
  1529.         tcstr[TCDOWN] = NULL;
  1530.     }
  1531.     }
  1532. }
  1533.  
  1534. void setparams()
  1535. {                /**/
  1536.     char **envp, **envp2, **envp3, *str;
  1537.     char buf[50];
  1538.     struct param *pm;
  1539.     int ct;
  1540.  
  1541.     noerrs = 1;
  1542.     for (envp = environ, ct = 2; *envp; envp++, ct++);
  1543.     envp = environ;
  1544.     envp2 = envp3 = (char **)zalloc(sizeof(char *) * ct);
  1545.  
  1546.     for (; *envp; envp++)
  1547.     *envp2++ = ztrdup(*envp);
  1548.     *envp2 = NULL;
  1549.     envp = environ;
  1550.     environ = envp2 = envp3;
  1551.     for (; *envp; envp++, envp2++) {
  1552.     for (str = *envp; *str && *str != '='; str++);
  1553.     if (*str == '=') {
  1554.         char *iname = NULL;
  1555.  
  1556.         *str = '\0';
  1557.         pm = (!idigit(**envp) && isident(*envp) && !strchr(*envp, '[')) ?
  1558.         setsparam(iname = *envp, ztrdup(str + 1)) : NULL;
  1559.         if (pm) {
  1560.         pm->flags |= PMFLAG_x;
  1561.         pm->env = *envp2;
  1562.         if (pm->flags & PMFLAG_SPECIAL)
  1563.             pm->env = replenv(pm->env, getsparam(iname));
  1564.         }
  1565.         *str = '=';
  1566.     }
  1567.     }
  1568.     pm = (struct param *)gethnode("HOME", paramtab);
  1569.     if (!(pm->flags & PMFLAG_x)) {
  1570.     pm->flags |= PMFLAG_x;
  1571.     pm->env = addenv("HOME", home);
  1572.     }
  1573.     pm = (struct param *)gethnode("PWD", paramtab);
  1574.     if (!(pm->flags & PMFLAG_x)) {
  1575.     pm->flags |= PMFLAG_x;
  1576.     pm->env = addenv("PWD", pwd);
  1577.     }
  1578.     pm = (struct param *)gethnode("LOGNAME", paramtab);
  1579.     if (!(pm->flags & PMFLAG_x)) {
  1580.     pm->flags |= PMFLAG_x;
  1581.     pm->env = addenv("LOGNAME", zlogname);
  1582.     }
  1583.     pm = (struct param *)gethnode("SHLVL", paramtab);
  1584.     if (!(pm->flags & PMFLAG_x))
  1585.     pm->flags |= PMFLAG_x;
  1586.     sprintf(buf, "%d", (int) ++shlvl);
  1587.     pm->env = addenv("SHLVL", buf);
  1588.     noerrs = 0;
  1589. }
  1590.  
  1591. char *mkenvstr(x, y)        /**/
  1592. char *x;
  1593. char *y;
  1594. {
  1595.     char *z;
  1596.     int xl = strlen(x), yl = strlen(y);
  1597.  
  1598.     z = (char *)zalloc(xl + yl + 2);
  1599.     strcpy(z, x);
  1600.     z[xl] = '=';
  1601.     strcpy(z + xl + 1, y);
  1602.     z[xl + yl + 1] = '\0';
  1603.     return z;
  1604. }
  1605.  
  1606. void arrfixenv(s, t)    /**/
  1607. char *s;
  1608. char **t;
  1609. {
  1610.     char **ep, *u = join(t, ':');
  1611.     int sl = strlen(s);
  1612.     Param pm = (Param) gethnode(s, paramtab);
  1613.  
  1614.     for (ep = environ; *ep; ep++)
  1615.     if (!strncmp(*ep, s, sl) && (*ep)[sl] == '=') {
  1616.         pm->env = replenv(*ep, u);
  1617.         return;
  1618.     }
  1619.     if (isset(ALLEXPORT))
  1620.     pm->flags |= PMFLAG_x;
  1621.     if (pm->flags & PMFLAG_x) pm->env = addenv(s, u);
  1622. }
  1623.  
  1624. char *replenv(e, value)        /**/
  1625. char *e;
  1626. char *value;
  1627. {
  1628.     char **ep;
  1629.  
  1630.     for (ep = environ; *ep; ep++)
  1631.     if (*ep == e) {
  1632.         char *s = e;
  1633.  
  1634.         while (*s++ != '=');
  1635.         *s = '\0';
  1636.         *ep = (char *)zalloc(strlen(e) + strlen(value) + 2);
  1637.         strcpy(*ep, e);
  1638.         strcat(*ep, value);
  1639.         zsfree(e);
  1640.         return *ep;
  1641.     }
  1642.     return NULL;
  1643. }
  1644.  
  1645. char *addenv(name, value)    /**/
  1646. char *name;
  1647. char *value;
  1648. {
  1649.     char **ep, **ep2, **ep3;
  1650.     int envct;
  1651.  
  1652.     for (ep = environ; *ep; ep++) {
  1653.     char *s = *ep, *t = name;
  1654.  
  1655.     while (*s && *s == *t)
  1656.         s++, t++;
  1657.     if (*s == '=' && !*t) {
  1658.         zsfree(*ep);
  1659.         return *ep = mkenvstr(name, value);
  1660.     }
  1661.     }
  1662.     envct = arrlen(environ);
  1663.     ep = ep2 = (char **)zalloc((sizeof(char *)) * (envct + 3));
  1664.  
  1665.     for (ep3 = environ; (*ep2 = *ep3); ep3++, ep2++);
  1666.     *ep2 = mkenvstr(name, value);
  1667.     ep2[1] = NULL;
  1668.     free(environ);
  1669.     environ = ep;
  1670.     return *ep2;
  1671. }
  1672.  
  1673. void delenv(x)            /**/
  1674. char *x;
  1675. {
  1676.     char **ep;
  1677.  
  1678.     ep = environ;
  1679.     for (; *ep; ep++)
  1680.     if (*ep == x)
  1681.         break;
  1682.     if (*ep)
  1683.     for (; (ep[0] = ep[1]); ep++);
  1684. }
  1685.  
  1686. void convbase(s, v, base)    /**/
  1687. char *s;
  1688. long v;
  1689. int base;
  1690. {
  1691.     int digs = 0;
  1692.     long x;
  1693.  
  1694.     if (base <= 1)
  1695.     base = 10;
  1696.     x = v;
  1697.     if (x < 0) {
  1698.     x = -x;
  1699.     digs++;
  1700.     }
  1701.     for (; x; digs++)
  1702.     x /= base;
  1703.     if (!digs)
  1704.     digs = 1;
  1705.     s[digs--] = '\0';
  1706.     x = (v < 0) ? -v : v;
  1707.     while (digs >= 0) {
  1708.     int dig = x % base;
  1709.  
  1710.     s[digs--] = (dig < 10) ? '0' + dig : dig - 10 + 'A';
  1711.     x /= base;
  1712.     }
  1713.     if (v < 0)
  1714.     s[0] = '-';
  1715. }
  1716.