home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / z / zsh220.zip / zsh2.2 / src / params.c < prev    next >
C/C++ Source or Header  |  1992-05-07  |  25KB  |  1,316 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 <pwd.h>
  23.  
  24. #define new(X) (X=(vptr)alloc(sizeof(*(X))))
  25.  
  26. static Param argvparam;
  27.  
  28. struct iparam {
  29.     struct hashnode *next; int canfree; char *nam; /* hash data */
  30.     void *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.     };
  39.  
  40. #define IFN(X) ((int (*)())(X))
  41.  
  42. /* put predefined params in hash table */
  43.  
  44. void setupparams() /**/
  45. {
  46. static struct iparam pinit[] = {
  47. #define IPDEF1(A,B,C,D) {NULL,0,A,NULL,IFN(C),IFN(B),10,\
  48.         PMFLAG_i|PMFLAG_SPECIAL|D,NULL,NULL,NULL}
  49.     IPDEF1("#",poundgetfn,IFN(nullsetfn),PMFLAG_r),
  50.     IPDEF1("ARGC",poundgetfn,IFN(nullsetfn),PMFLAG_r),
  51.     IPDEF1("ERRNO",errnogetfn,IFN(nullsetfn),PMFLAG_r),
  52.     IPDEF1("GID",gidgetfn,IFN(nullsetfn),PMFLAG_r),
  53.     IPDEF1("HISTSIZE",histsizegetfn,histsizesetfn,0),
  54.     IPDEF1("LITHISTSIZE",lithistsizegetfn,lithistsizesetfn,0),
  55.     IPDEF1("RANDOM",randomgetfn,randomsetfn,0),
  56.     IPDEF1("SECONDS",secondsgetfn,secondssetfn,0),
  57.     IPDEF1("UID",uidgetfn,IFN(nullsetfn),PMFLAG_r),
  58.  
  59. #define IPDEF2(A,B,C,D) {NULL,0,A,NULL,IFN(C),IFN(B),0,\
  60.         PMFLAG_SPECIAL|D,NULL,NULL,NULL}
  61.     IPDEF2("-",dashgetfn,IFN(nullsetfn),PMFLAG_r),
  62.     IPDEF2("HISTCHARS",histcharsgetfn,histcharssetfn,0),
  63.     IPDEF2("HOME",homegetfn,homesetfn,0),
  64.     IPDEF2("TERM",termgetfn,termsetfn,0),
  65.     IPDEF2("WORDCHARS",wordcharsgetfn,wordcharssetfn,0),
  66.     IPDEF2("IFS",ifsgetfn,ifssetfn,0),
  67.     IPDEF2("_",underscoregetfn,IFN(nullsetfn),PMFLAG_r),
  68.  
  69. #define IPDEF3(A,B) {NULL,0,A,NULL,IFN(nullsetfn),IFN(strconstgetfn),0,PMFLAG_r|\
  70.         PMFLAG_SPECIAL,(vptr)B,NULL,NULL}
  71.     IPDEF3("HOSTTYPE",HOSTTYPE),
  72.     IPDEF3("VERSION",VERSIONSTR),
  73.  
  74. #define IPDEF4(A,B) {NULL,0,A,NULL,IFN(nullsetfn),IFN(intvargetfn),10,\
  75.         PMFLAG_r|PMFLAG_i|PMFLAG_SPECIAL,(vptr)B,NULL,NULL}
  76.     IPDEF4("!",&lastpid),
  77.     IPDEF4("$",&mypid),
  78.     IPDEF4("?",&lastval),
  79.     IPDEF4("status",&lastval),
  80.     IPDEF4("LINENO",&lineno),
  81.     IPDEF4("PPID",&ppid),
  82.  
  83. #define IPDEF5(A,B) {NULL,0,A,NULL,IFN(intvarsetfn),IFN(intvargetfn),10,\
  84.         PMFLAG_i|PMFLAG_SPECIAL,(vptr)B,NULL,NULL}
  85.     IPDEF5("BAUD",&baud),
  86.     IPDEF5("COLUMNS",&columns),
  87.     IPDEF5("DIRSTACKSIZE",&dirstacksize),
  88.     IPDEF5("LINES",&lines),
  89.     IPDEF5("LISTMAX",&listmax),
  90.     IPDEF5("LOGCHECK",&logcheck),
  91.     IPDEF5("MAILCHECK",&mailcheck),
  92.     IPDEF5("OPTIND",&zoptind),
  93.     IPDEF5("PERIOD",&period),
  94.     IPDEF5("REPORTTIME",&reporttime),
  95.     IPDEF5("SAVEHIST",&savehist),
  96.     IPDEF5("SHLVL",&shlvl),
  97.     IPDEF5("TMOUT",&tmout),
  98.  
  99. #define IPDEF6(A,B) {NULL,0,A,NULL,IFN(nullsetfn),IFN(strvargetfn),0,\
  100.         PMFLAG_r|PMFLAG_SPECIAL,(vptr)B,NULL,NULL}
  101.     IPDEF6("LOGNAME",&logname),
  102.     IPDEF6("PWD",&pwd),
  103.     IPDEF6("TTY",&ttystrname),
  104.     IPDEF6("USERNAME",&username),
  105.  
  106. #define IPDEF7(A,B) {NULL,0,A,NULL,IFN(strvarsetfn),IFN(strvargetfn),0,\
  107.         PMFLAG_SPECIAL,(vptr)B,NULL,NULL}
  108.     IPDEF7("FCEDIT",&fceditparam),
  109.     IPDEF7("HOST",&hostnam),
  110.     IPDEF7("OLDPWD",&oldpwd),
  111.     IPDEF7("OPTARG",&optarg),
  112.     IPDEF7("MAIL",&mailfile),
  113.     IPDEF7("NULLCMD",&nullcmd),
  114.     IPDEF7("POSTEDIT",&postedit),
  115.     IPDEF7("prompt",&prompt),
  116.     IPDEF7("PROMPT",&prompt),
  117.     IPDEF7("PROMPT2",&prompt2),
  118.     IPDEF7("PROMPT3",&prompt3),
  119.     IPDEF7("PROMPT4",&prompt4),
  120.     IPDEF7("READNULLCMD",&readnullcmd),
  121.     IPDEF7("RPROMPT",&rprompt),
  122.     IPDEF7("PS1",&prompt),
  123.     IPDEF7("PS2",&prompt2),
  124.     IPDEF7("PS3",&prompt3),
  125.     IPDEF7("PS4",&prompt4),
  126.     IPDEF7("RPS1",&rprompt),
  127.     IPDEF7("SPROMPT",&sprompt),
  128.     IPDEF7("TIMEFMT",&timefmt),
  129.     IPDEF7("TMPPREFIX",&tmpprefix),
  130.     IPDEF7("WATCHFMT",&watchfmt),
  131.     IPDEF7("0",&argzero),
  132.  
  133. #define IPDEF8(A,B,C) {NULL,0,A,NULL,IFN(colonarrsetfn),IFN(colonarrgetfn),0,\
  134.         PMFLAG_SPECIAL,(vptr)C,NULL,B}
  135.     IPDEF8("CDPATH","cdpath",&cdpath),
  136.     IPDEF8("FIGNORE","fignore",&fignore),
  137.     IPDEF8("FPATH","fpath",&fpath),
  138.     IPDEF8("MAILPATH","mailpath",&mailpath),
  139.     IPDEF8("MANPATH","manpath",&manpath),
  140.     IPDEF8("WATCH","watch",&watch),
  141.     IPDEF8("HOSTS","hosts",&hosts),
  142.     IPDEF8("PATH",NULL,NULL),
  143.  
  144. #define IPDEF9(A,B,C) {NULL,0,A,NULL,IFN(arrvarsetfn),IFN(arrvargetfn),0,\
  145.         PMFLAG_A|PMFLAG_SPECIAL|C,(vptr)B,NULL,NULL}
  146.     IPDEF9("cdpath",&cdpath,0),
  147.     IPDEF9("fignore",&fignore,0),
  148.     IPDEF9("fpath",&fpath,0),
  149.     IPDEF9("mailpath",&mailpath,0),
  150.     IPDEF9("manpath",&manpath,0),
  151.     IPDEF9("watch",&watch,0),
  152.     IPDEF9("hosts",&hosts,0),
  153.     IPDEF9("signals",&sigptr,PMFLAG_r),
  154.     IPDEF9("argv",&pparams,0),
  155.     IPDEF9("*",&pparams,0),
  156.     IPDEF9("@",&pparams,0),
  157.  
  158. #define IPDEF10(A,C,D) {NULL,0,A,NULL,IFN(D),IFN(C),0,\
  159.         PMFLAG_A|PMFLAG_SPECIAL,NULL,NULL,NULL}
  160.     IPDEF10("path",pathgetfn,pathsetfn),
  161.     IPDEF10("hostcmds",nullgetfn,hostcmdssetfn),
  162.     IPDEF10("optcmds",nullgetfn,optcmdssetfn),
  163.     IPDEF10("bindcmds",nullgetfn,bindcmdssetfn),
  164.     IPDEF10("varcmds",nullgetfn,varcmdssetfn),
  165.     {NULL,}
  166.     };
  167. struct iparam *ip;
  168.  
  169.     for (ip = pinit; ip->nam; ip++) addhperm(ip->nam,ip,paramtab,NULL);
  170.     argvparam = gethnode("argv",paramtab);
  171. }
  172.  
  173. static int unsetflag;
  174.  
  175. struct param *createparam(name,value,flags) /**/
  176. char *name;vptr value;int flags;
  177. {
  178. struct param *pm;
  179. char buf[20];
  180.  
  181.     pm = zcalloc(sizeof *pm);
  182.     if (isset(ALLEXPORT))
  183.         flags |= PMFLAG_x;
  184.     pm->flags = flags;
  185.     if ((flags & PMTYPE) == PMFLAG_s) {
  186.         pm->u.str = value;
  187.         pm->sets.cfn = strsetfn;
  188.         pm->gets.cfn = strgetfn;
  189.     } else if ((flags & PMTYPE) == PMFLAG_A) {
  190.         pm->u.arr = value;
  191.         pm->sets.afn = arrsetfn;
  192.         pm->gets.afn = arrgetfn;
  193.     } else {
  194.         pm->u.val = (value) ? matheval(value) : 0;
  195.         pm->sets.ifn = intsetfn;
  196.         pm->gets.ifn = intgetfn;
  197.         sprintf(buf,"%ld",pm->u.val);
  198.         value = buf;
  199.     }
  200.     if (flags & PMFLAG_x)
  201.         pm->env = addenv(name,value);
  202.     addhnode(ztrdup(name),pm,paramtab,freepm);
  203.     return pm;
  204. }
  205.  
  206. int isident(s) /**/
  207. char *s;
  208. {
  209. char *ss;
  210.  
  211.     for (ss = s; *ss; ss++) if (!iident(*ss)) break;
  212.     if (!*ss || *ss == '[') return 1;
  213.     if (*s == Quest)
  214.         *s = '?';
  215.     else if (*s == Pound)
  216.         *s = '#';
  217.     else if (*s == String || *s == Qstring)
  218.         *s = '$';
  219.     else if (*s == Star)
  220.         *s = '*';
  221.     if (*s == '#' || *s == '-' || *s == '?' || *s == '$' || *s == '_' ||
  222.          *s == '!' || *s == '@' || *s == '*')
  223.         return 1;
  224.     return 0;
  225. }
  226.  
  227. Value getvalue(pptr,bracks) /**/
  228. char **pptr;int bracks;
  229. {
  230. char *s = *pptr,*t = *pptr;
  231. char sav;
  232. Value v;
  233.  
  234.     if (idigit(*s)) while (idigit(*s)) s++;
  235.     else if (iident(*s)) while (iident(*s)) s++;
  236.     else if (*s == Quest) *s++ = '?';
  237.     else if (*s == Pound) *s++ = '#';
  238.     else if (*s == String) *s++ = '$';
  239.     else if (*s == Qstring) *s++ = '$';
  240.     else if (*s == Star) *s++ = '*';
  241.     else if (*s == '#' || *s == '-' || *s == '?' || *s == '$' ||
  242.                 *s == '_' || *s == '!' || *s == '@' || *s == '*') s++;
  243.     else return NULL;
  244.     if (sav = *s) *s = '\0';
  245.     if (idigit(*t) && *t != '0') {
  246.         v = (Value) hcalloc(sizeof *v);
  247.         v->pm = argvparam;
  248.         v->a = v->b = atoi(t)-1;
  249.         if (sav)
  250.             *s = sav;
  251.     } else {
  252.         struct param *pm;
  253.         int isvarat = !strcmp(t, "@");
  254.  
  255.         pm = gethnode(t,paramtab);
  256.         if (sav)
  257.             *s = sav;
  258.         *pptr = s;
  259.         if (!pm)
  260.             return NULL;
  261.         v = hcalloc(sizeof *v);
  262.         if (pmtype(pm) == PMFLAG_A)
  263.             v->isarr = isvarat ? -1 : 1;
  264.         v->pm = pm;
  265.         v->a = 0; v->b = -1;
  266.         if (bracks && (*s == '[' || *s == Inbrack)) {
  267.             int a,b;
  268.             char *olds = s,*t;
  269.  
  270.             *s++ = '[';
  271.             for (t = s; *t && *t != ']' && *t != Outbrack; t++)
  272.                 if (itok(*t))
  273.                     *t = ztokens[*t-Pound];
  274.             if (*t == Outbrack)
  275.                 *t = ']';
  276.             if ((s[0] == '*' || s[0] == '@')  && s[1] == ']') {
  277.                 if (v->isarr) v->isarr = (s[0] == '*') ? 1 : -1;
  278.                 v->a = 0;
  279.                 v->b = -1;
  280.                 s += 2;
  281.             } else {
  282.                 a = mathevalarg(s,&s);
  283.                 if (a > 0) a--;
  284.                 if (*s == ',' || *s == Comma) {
  285.                     s++;
  286.                     b = mathevalarg(s,&s);
  287.                     if (b > 0) b--;
  288.                 } else
  289.                     b = a;
  290.                 if (*s == ']') {
  291.                     s++;
  292.                     if (v->isarr && a == b)
  293.                         v->isarr = 0;
  294.                     v->a = a;
  295.                     v->b = b;
  296.                 } else
  297.                     s = olds;
  298.             }
  299.         }
  300.     }
  301.     if (!bracks && *s)
  302.         return NULL;
  303.     *pptr = s;
  304.     return v;
  305. }
  306.  
  307. char *getstrvalue(v) /**/
  308. Value v;
  309. {
  310. char *s,**ss;
  311. static char buf[20];
  312.  
  313.     if (!v)
  314.         return "";
  315.     if (pmtype(v->pm) != PMFLAG_A) {
  316.         if ((pmtype(v->pm) == PMFLAG_i))
  317.             convbase(s = buf,v->pm->gets.ifn(v->pm),v->pm->ct);
  318.         else
  319.             s = v->pm->gets.cfn(v->pm);
  320.         if (v->a == 0 && v->b == -1) return s;
  321.         if (v->a < 0) v->a += strlen(s);
  322.         if (v->b < 0) v->b += strlen(s);
  323.         s = (v->a > strlen(s)) ? strdup("") : strdup(s+v->a);
  324.         if (v->b < v->a) s[0] = '\0';
  325.         else if (v->b-v->a < strlen(s)) s[v->b-v->a+1] = '\0';
  326.         return s;
  327.     }
  328.     if (v->isarr) return spacejoin(v->pm->gets.afn(v->pm));
  329.  
  330.     ss = v->pm->gets.afn(v->pm);
  331.     if (v->a < 0) v->a += arrlen(ss);
  332.     s = (v->a >= arrlen(ss) || v->a < 0) ? "" : ss[v->a];
  333.     return s;
  334. }
  335.  
  336. char **getarrvalue(v) /**/
  337. Value v;
  338. {
  339. char **s;
  340. static char *nular[] = { "", NULL };
  341.  
  342.     if (!v)
  343.         return arrdup(nular);
  344.     s = v->pm->gets.afn(v->pm);
  345.     if (v->a == 0 && v->b == -1) return s;
  346.     if (v->a < 0) v->a += arrlen(s);
  347.     if (v->b < 0) v->b += arrlen(s);
  348.     if (v->a > arrlen(s) || v->a < 0)
  349.         s = arrdup(nular);
  350.     else
  351.         s = arrdup(s)+v->a;
  352.     if (v->b < v->a) s[0] = NULL;
  353.     else if (v->b-v->a < arrlen(s)) s[v->b-v->a+1] = NULL;
  354.     return s;
  355. }
  356.  
  357. long getintvalue(v) /**/
  358. Value v;
  359. {
  360. char **ss;
  361.  
  362.     if (!v || v->isarr)
  363.         return 0;
  364.     if (pmtype(v->pm) != PMFLAG_A) {
  365.         if (pmtype(v->pm) == PMFLAG_i)
  366.             return v->pm->gets.ifn(v->pm);
  367.         return atol(v->pm->gets.cfn(v->pm));
  368.     }
  369.     ss = v->pm->gets.afn(v->pm);
  370.     if (v->a < 0) v->a += arrlen(ss);
  371.     if (v->a < 0 || v->a > arrlen(ss)) return 0;
  372.     return atol(ss[v->a]);
  373. }
  374.  
  375. void setstrvalue(v,val) /**/
  376. Value v;char *val;
  377. {
  378. char *s;
  379.  
  380.     if (v->pm->flags & PMFLAG_r) {
  381.         free(val);
  382.         return;
  383.     }
  384.     if ((s = v->pm->env) && val)
  385.         v->pm->env = replenv(v->pm->env,val);
  386.     switch (pmtype(v->pm)) {
  387.         case PMFLAG_s:
  388.             if (v->a == 0 && v->b == -1)
  389.                 (v->pm->sets.cfn)(v->pm,val);
  390.             else {
  391.                 char *z,*y,*x;
  392.  
  393.                 z = strdup((v->pm->gets.cfn)(v->pm));
  394.                 if (v->a < 0) {
  395.                     v->a += strlen(z);
  396.                     if (v->a < 0) v->a = 0;
  397.                 }
  398.                 if (v->a > strlen(z)) v->a = strlen(z);
  399.                 if (v->b < 0) v->b += strlen(z);
  400.                 if (v->b < v->a) v->b = v->a;
  401.                 z[v->a] = '\0';
  402.                 y = z+v->b+1;
  403.                 x = zalloc(strlen(z)+strlen(y)+strlen(val)+1);
  404.                 strcpy(x,z);
  405.                 strcat(x,val);
  406.                 strcat(x,y);
  407.                 (v->pm->sets.cfn)(v->pm,x);
  408.             }
  409.             if (v->pm->flags & (PMFLAG_L|PMFLAG_R|PMFLAG_Z) && !v->pm->ct)
  410.                 v->pm->ct = strlen(val);
  411.             break;
  412.         case PMFLAG_i:
  413.             (v->pm->sets.ifn)(v->pm,matheval(val));
  414.             if (!v->pm->ct && lastbase != 1)
  415.                 v->pm->ct = lastbase;
  416.             free(val);
  417.             break;
  418.         case PMFLAG_A:
  419.             if (v->a != v->b)
  420.                 zerr("illegal array assignment",NULL,0);
  421.             else {
  422.                 char **ss = (v->pm->gets.afn)(v->pm);
  423.                 int ac,ad,t0;
  424.  
  425.                 ac = arrlen(ss);
  426.                 if (v->a < 0) {
  427.                     v->a += ac;
  428.                     if (v->a < 0) v->a = 0;
  429.                 }
  430.                 if (v->a >= ac) {
  431.                     char **st = ss;
  432.  
  433.                     ad = v->a+1;
  434.                     ss = zalloc((ad+1)*sizeof *ss);
  435.                     memcpy(ss,st,(ad+1)*sizeof *ss);
  436.                     for (t0 = 0; t0 != ac; t0++)
  437.                         ss[t0] = ztrdup(ss[t0]);
  438.                     while (ac < ad)
  439.                         ss[ac++] = ztrdup("");
  440.                     ss[ac] = NULL;
  441.                 }
  442.                 if (ss[v->a]) free(ss[v->a]);
  443.                 ss[v->a] = val;
  444.                 (v->pm->sets.afn)(v->pm,ss);
  445.             }
  446.             break;
  447.     }
  448. }
  449.  
  450. void setintvalue(v,val) /**/
  451. Value v;long val;
  452. {
  453. char buf[20];
  454.  
  455.     if (v->pm->flags & PMFLAG_r)
  456.         return;
  457.     if (v->pm->env) {
  458.         sprintf(buf,"%ld",val);
  459.         v->pm->env = replenv(v->pm->env,buf);
  460.     }
  461.     switch (pmtype(v->pm))
  462.         {
  463.         case PMFLAG_s:
  464.             sprintf(buf,"%ld",val);
  465.             (v->pm->sets.cfn)(v->pm,ztrdup(buf));
  466.             break;
  467.         case PMFLAG_i:
  468.             (v->pm->sets.ifn)(v->pm,val);
  469.             if (!v->pm->ct && lastbase != -1)
  470.                 v->pm->ct = lastbase;
  471.             break;
  472.         case PMFLAG_A:
  473.             zerr("attempt to assign integer to array",NULL,0);
  474.             break;
  475.         }
  476. }
  477.  
  478. void setintenv(s,val) /**/
  479. char *s; long val;
  480. {
  481. Param pm;
  482. char buf[20];
  483.  
  484.     if ((pm = gethnode(s,paramtab)) && pm->env) {
  485.         sprintf(buf,"%ld",val);
  486.         pm->env = replenv(pm->env,buf);
  487.     }
  488. }
  489.  
  490. void setarrvalue(v,val) /**/
  491. Value v;char **val;
  492. {
  493.     if (v->pm->flags & PMFLAG_r)
  494.         return;
  495.     if (pmtype(v->pm) != PMFLAG_A)
  496.         {
  497.         zerr("attempt to assign array value to non-array",NULL,0);
  498.         return;
  499.         }
  500.     (v->pm->sets.afn)(v->pm,val);
  501. }
  502.  
  503. char *getsparamval(s,l) /**/
  504. char *s;int l;
  505. {
  506. char sav,*t = s;
  507. Value v;
  508.  
  509.     if (sav = t[l])
  510.         t[l] = '\0';
  511.     if (!(v = getvalue(&s,0)))
  512.         return NULL;
  513.     t[l] = sav;
  514.     t = getstrvalue(v);
  515.     return t;
  516. }
  517.  
  518. long getiparam(s) /**/
  519. char *s;
  520. {
  521. Value v;
  522.  
  523.     if (!(v = getvalue(&s,0)))
  524.         return 0;
  525.     return getintvalue(v);
  526. }
  527.  
  528. char *getsparam(s) /**/
  529. char *s;
  530. {
  531. Value v;
  532.  
  533.     if (!(v = getvalue(&s,0)))
  534.         return NULL;
  535.     return getstrvalue(v);
  536. }
  537.  
  538. char **getaparam(s) /**/
  539. char *s;
  540. {
  541. Value v;
  542.  
  543.     if (!(v = getvalue(&s,0))) return NULL;
  544.     return getarrvalue(v);
  545. }
  546.  
  547. Param setsparam(s,val) /**/
  548. char *s;char *val;
  549. {
  550. Value v;
  551. char *t = s;
  552.  
  553.     if (!isident(s)) {
  554.         zerr("not an identifier: %s",s,0);
  555.         free(val);
  556.         return NULL;
  557.     }
  558.     if (!(v = getvalue(&s,1)) || *s)
  559.         return createparam(t,val,PMFLAG_s);
  560.     if ((v->pm->flags & PMTYPE) != PMFLAG_s &&
  561.             !(v->pm->flags & PMFLAG_SPECIAL)) {
  562.         unsetparam(s);
  563.         return createparam(t,val,PMFLAG_s);
  564.     }
  565.     setstrvalue(v,val);
  566.     return v->pm;
  567. }
  568.  
  569. Param setaparam(s,val) /**/
  570. char *s;char **val;
  571. {
  572. Value v;
  573. char *t = s;
  574.  
  575.     if (!isident(s))
  576.         {
  577.         zerr("not an identifier: %s",s,0);
  578.         return NULL;
  579.         }
  580.     if (!(v = getvalue(&s,1)) || *s)
  581.         return createparam(t,val,PMFLAG_A);
  582.     if ((v->pm->flags & PMTYPE) != PMFLAG_A &&
  583.             !(v->pm->flags & PMFLAG_SPECIAL)) {
  584.         unsetparam(s);
  585.         return createparam(t,val,PMFLAG_A);
  586.     }
  587.     setarrvalue(v,val);
  588.     return v->pm;
  589. }
  590.  
  591. Param setiparam(s,val) /**/
  592. char *s;long val;
  593. {
  594. Value v;
  595. char *t = s;
  596. Param pm;
  597.  
  598.     if (!isident(s))
  599.         {
  600.         zerr("not an identifier: %s",s,0);
  601.         return NULL;
  602.         }
  603.     if (!(v = getvalue(&s,0)))
  604.         {
  605.         pm = createparam(t,NULL,PMFLAG_i);
  606.         pm->u.val = val;
  607.         return pm;
  608.         }
  609.     setintvalue(v,val);
  610.     return v->pm;
  611. }
  612.  
  613. void unsetparam(s) /**/
  614. char *s;
  615. {
  616. Param pm;
  617.  
  618.     if (!(pm = gethnode(s,paramtab)))
  619.         return;
  620.     if (pm->flags & PMFLAG_r)
  621.         return;
  622.     unsetflag = 1;
  623.     switch (pmtype(pm))
  624.         {
  625.         case 0:
  626.             (pm->sets.cfn)(pm,ztrdup(""));
  627.             break;
  628.         case PMFLAG_i:
  629.             (pm->sets.ifn)(pm,0);
  630.             break;
  631.         case PMFLAG_A:
  632.             (pm->sets.afn)(pm,mkarray(NULL));
  633.             break;
  634.         }
  635.     if (pmtype(pm) == PMFLAG_s && (pm->flags & PMFLAG_x)) {
  636.         delenv(pm->env);
  637.         free(pm->env);
  638.     }
  639.     if (!(pm->flags & PMFLAG_SPECIAL))
  640.         freepm(remhnode(s,paramtab));
  641.     unsetflag = 0;
  642. }
  643.  
  644. void intsetfn(pm,x) /**/
  645. Param pm;long x;
  646. {
  647.     pm->u.val = x;
  648. }
  649.  
  650. long intgetfn(pm) /**/
  651. Param pm;
  652. {
  653.     return pm->u.val;
  654. }
  655.  
  656. void strsetfn(pm,x) /**/
  657. Param pm;char *x;
  658. {
  659.     if (x) 
  660.         {
  661.         if (pm->u.str)
  662.             free(pm->u.str);
  663.         pm->u.str = x;
  664.         }
  665. }
  666.  
  667. char *strgetfn(pm) /**/
  668. Param pm;
  669. {
  670.     return pm->u.str;
  671. }
  672.  
  673. void nullsetfn(pm,x) /**/
  674. Param pm; char *x;
  675. {
  676.     free(x);
  677. }
  678.  
  679. void arrsetfn(pm,x) /**/
  680. Param pm;char **x;
  681. {
  682. int ct;
  683.  
  684.     if (x)
  685.         {
  686.         if (pm->u.arr && pm->u.arr != x)
  687.             freearray(pm->u.arr);
  688.         pm->u.arr = x;
  689.         for (ct = 0; *x; x++,ct++);
  690.         pm->ct = ct;
  691.         }
  692. }
  693.  
  694. char **arrgetfn(pm) /**/
  695. Param pm;
  696. {
  697.     return pm->u.arr;
  698. }
  699.  
  700. void intvarsetfn(pm,x) /**/
  701. Param pm;long x;
  702. {
  703.     *((long *) pm->data) = x;
  704. }
  705.  
  706. long intvargetfn(pm) /**/
  707. Param pm;
  708. {
  709.     return *((long *) pm->data);
  710. }
  711.  
  712. void strvarsetfn(pm,x) /**/
  713. Param pm;char *x;
  714. {
  715. char **q = ((char **) pm->data);
  716.  
  717.     if (*q) free(*q);
  718.     *q = x;
  719. }
  720.  
  721. void strvarnonullsetfn(pm,x) /**/
  722. Param pm;char *x;
  723. {
  724. char **q = ((char **) pm->data);
  725.  
  726.     if (*q) free(*q);
  727.     *q = (x) ? x : ztrdup("");
  728. }
  729.  
  730. char *strvargetfn(pm) /**/
  731. Param pm;
  732. {
  733. char *s;
  734.  
  735.     s = *((char **) pm->data);
  736.     if (!s) return "";
  737.     return s;
  738. }
  739.  
  740. char *strconstgetfn(pm) /**/
  741. Param pm;
  742. {
  743.     return (char *) pm->data;
  744. }
  745.  
  746. void colonarrsetfn(pm,x) /**/
  747. Param pm;char *x;
  748. {
  749. char **s,**t,*u,*up;
  750.  
  751.     s = colonsplit(x);
  752.     free(x);
  753.     if (pm->data != &fignore)
  754.         for (t = s; *t; t++) {
  755.             u = *t;
  756.             if (*u == '~') *u = Tilde;
  757.             if (*u == '=') *u = Equals;
  758.             up = hcalloc(strlen(u)+1);
  759.             strcpy(up,u);
  760.             u = up;
  761.             filesub(&u);
  762.             if (!*u) u = ".";
  763.             *t = ztrdup(u);
  764.         }
  765.     if (pm->data) {
  766.         freearray(*((char ***) pm->data));
  767.         *((char ***) pm->data) = s;
  768.         if (pm->ename)
  769.             arrfixenv(pm->ename,s);
  770.     } else {
  771.         freearray(path);
  772.         path = s;
  773.         newcmdnamtab();
  774.         arrfixenv("PATH",s);
  775.     }
  776. }
  777.  
  778. char *colonarrgetfn(pm) /**/
  779. Param pm;
  780. {
  781.     if ((char **) pm->data)
  782.         return colonjoin(*(char ***) pm->data);
  783.     else
  784.         return colonjoin(path);
  785. }
  786.  
  787. char **arrvargetfn(pm) /**/
  788. Param pm;
  789. {
  790.     return *((char ***) pm->data);
  791. }
  792.  
  793. void arrvarsetfn(pm,x) /**/
  794. Param pm;char **x;
  795. {
  796.     if ((*(char ***) pm->data) != x)
  797.         freearray(*(char ***) pm->data);
  798.     *((char ***) pm->data) = x;
  799.     if (pm->ename)
  800.         arrfixenv(pm->ename,x);
  801. }
  802.  
  803. char **pathgetfn(pm) /**/
  804. Param pm;
  805. {
  806.     return path;
  807. }
  808.  
  809. void pathsetfn(pm,x) /**/
  810. Param pm;char **x;
  811. {
  812.     if (path != x) freearray(path);
  813.     path = x;
  814.     newcmdnamtab();
  815.     arrfixenv("PATH",x);
  816. }
  817.  
  818. void hostcmdssetfn(pm,x) /**/
  819. Param pm;char **x;
  820. {
  821.     compctl_process(x,CC_HOSTS|CC_FILES,NULL);
  822.     freearray(x);
  823. }
  824.  
  825. void optcmdssetfn(pm,x) /**/
  826. Param pm;char **x;
  827. {
  828.     compctl_process(x,CC_OPTIONS,NULL);
  829.     freearray(x);
  830. }
  831.  
  832. void bindcmdssetfn(pm,x) /**/
  833. Param pm;char **x;
  834. {
  835.     compctl_process(x,CC_BINDINGS,NULL);
  836.     freearray(x);
  837. }
  838.  
  839. void varcmdssetfn(pm,x) /**/
  840. Param pm;char **x;
  841. {
  842.     compctl_process(x,CC_VARS,NULL);
  843.     freearray(x);
  844. }
  845.  
  846. char **nullgetfn(pm) /**/
  847. Param pm;
  848. {
  849. static char *nl = NULL; return &nl;
  850. }
  851.  
  852. void unsettablesetfn(pm,x) /**/
  853. Param pm;char *x;
  854. { ; }
  855.  
  856. long poundgetfn(pm) /**/
  857. Param pm;
  858. {
  859.     return arrlen(pparams);
  860. }
  861.  
  862. long randomgetfn(pm) /**/
  863. Param pm;
  864. {
  865.     return rand() & 0x7fff;
  866. }
  867.  
  868. void randomsetfn(pm,v) /**/
  869. Param pm;long v;
  870. {
  871.     srand((unsigned int) v);
  872. }
  873.  
  874. long secondsgetfn(pm) /**/
  875. Param pm;
  876. {
  877.     return time(NULL)-shtimer;
  878. }
  879.  
  880. void secondssetfn(pm,x) /**/
  881. Param pm;long x;
  882. {
  883.     shtimer = time(NULL)-x;
  884. }
  885.  
  886. long uidgetfn(pm) /**/
  887. Param pm;
  888. {
  889.     return getuid();
  890. }
  891.  
  892. long gidgetfn(pm) /**/
  893. Param pm;
  894. {
  895.     return getegid();
  896. }
  897.  
  898. char *usernamegetfn(pm) /**/
  899. Param pm;
  900. {
  901. struct passwd *pwd;
  902.  
  903.     pwd = getpwuid(getuid());
  904.     return pwd->pw_name;
  905. }
  906.  
  907. char *hostgetfn(pm) /**/
  908. Param pm;
  909. {
  910. static char hostnam[65];
  911. static int got = 0;
  912.  
  913.     if (!got)
  914.         {
  915.         gethostname(hostnam,64);
  916.         hostnam[64] = '\0';
  917.         got = 1;
  918.         }
  919.     return hostnam;
  920. }
  921.  
  922. char *ifsgetfn(pm) /**/
  923. Param pm;
  924. {
  925.     return ifs;
  926. }
  927.  
  928. void ifssetfn(pm,x) /**/
  929. Param pm;char *x;
  930. {
  931.     if (x) { free(ifs); ifs = x; }
  932.     inittyptab();
  933. }
  934.  
  935. void histsizesetfn(pm,v) /**/
  936. Param pm;long v;
  937. {
  938.     if ((histsiz = v) <= 2) histsiz = 2;
  939.     resizehistents();
  940. }
  941.  
  942. long histsizegetfn(pm) /**/
  943. Param pm;
  944. {
  945.     return histsiz;
  946. }
  947.  
  948. void lithistsizesetfn(pm,v) /**/
  949. Param pm;long v;
  950. {
  951.     if ((lithistsiz = v) <= 2) lithistsiz = 2;
  952.     resizehistents();
  953. }
  954.  
  955. long lithistsizegetfn(pm) /**/
  956. Param pm;
  957. {
  958.     return lithistsiz;
  959. }
  960.  
  961. void mailchecksetfn(pm,x) /**/
  962. Param pm;long x;
  963. {
  964.     mailcheck = (unsetflag) ? 600 : x;
  965. }
  966.  
  967. void pathasetfn(pm,x) /**/
  968. Param pm;char **x;
  969. {
  970.     freearray(path);
  971.     path = x;
  972.     newcmdnamtab();
  973. }
  974.  
  975. char **pathagetfn(pm) /**/
  976. Param pm;
  977. {
  978.     return path;
  979. }
  980.  
  981. long errnogetfn(pm) /**/
  982. Param pm;
  983. {
  984.     return errno;
  985. }
  986.  
  987. char *dashgetfn(pm) /**/
  988. Param pm;
  989. {
  990. static char buf[100];
  991. char *val = buf;
  992. int t0;
  993.  
  994.     for (val = buf, t0 = ' ';t0 <= 'z'; t0++)
  995.         if (opts[t0] == OPT_SET)
  996.             *val++ = t0;
  997.     *val = '\0';
  998.     return buf;
  999. }
  1000.  
  1001. void histcharssetfn(pm,x) /**/
  1002. Param pm;char *x;
  1003. {
  1004.     if (x) {
  1005.         bangchar = x[0];
  1006.         hatchar = (bangchar) ? x[1] : '\0';
  1007.         hashchar = (hatchar) ? x[2] : '\0';
  1008.         free(x);
  1009.     }
  1010. }
  1011.  
  1012. char *histcharsgetfn(pm) /**/
  1013. Param pm;
  1014. {
  1015. static char buf[4];
  1016.  
  1017.     buf[0] = bangchar;
  1018.     buf[1] = hatchar;
  1019.     buf[2] = hashchar;
  1020.     buf[3] = '\0';
  1021.     return buf;
  1022. }
  1023.  
  1024. char *homegetfn(pm) /**/
  1025. Param pm;
  1026. {
  1027.     return home;
  1028. }
  1029.  
  1030. void homesetfn(pm,x) /**/
  1031. Param pm;char *x;
  1032. {
  1033.     free(home);
  1034.     if (isset(CHASELINKS) && (home = xsymlink(x))) free(x);
  1035.     else home = x;
  1036. }
  1037.  
  1038. char *wordcharsgetfn(pm) /**/
  1039. Param pm;
  1040. {
  1041.     return wordchars;
  1042. }
  1043.  
  1044. void wordcharssetfn(pm,x) /**/
  1045. Param pm;char *x;
  1046. {
  1047.     free(wordchars);
  1048.     if (x) wordchars = x;
  1049.     else wordchars = ztrdup(DEFWORDCHARS);
  1050.     inittyptab();
  1051. }
  1052.  
  1053. char *underscoregetfn(pm) /**/
  1054. Param pm;
  1055. {
  1056. char *s,*t;
  1057.  
  1058.     if (!(s = qgetevent(curhist-1)))
  1059.         return "";
  1060.     for (t = s+strlen(s); t > s; t--)
  1061.         if (*t == HISTSPACE)
  1062.             break;
  1063.     if (t != s)
  1064.         t++;
  1065.     return t;
  1066. }
  1067.  
  1068. char *termgetfn(pm) /**/
  1069. Param pm;
  1070. {
  1071.     return term;
  1072. }
  1073.  
  1074. void termsetfn(pm,x) /**/
  1075. Param pm;char *x;
  1076. {
  1077.     if (term) free(term);
  1078.     term = x;
  1079.     if (!interact || unset(USEZLE))
  1080.         return;
  1081.     if (tgetent(termbuf,term) != 1)
  1082.         {
  1083.         zerr("can't find termcap info for %s",term,0);
  1084.         errflag = 0;
  1085.         termok = 0;
  1086.         }
  1087.     else
  1088.         {
  1089.         char tbuf[1024],*pp;
  1090.         int t0;
  1091.  
  1092.         termok = 1;
  1093.         for (t0 = 0; t0 != TC_COUNT; t0++)
  1094.             {
  1095.             pp = tbuf;
  1096.             if (tcstr[t0])
  1097.                 free(tcstr[t0]);
  1098.             if (!tgetstr(tccapnams[t0],&pp))
  1099.                 tcstr[t0] = NULL, tclen[t0] = 0;
  1100.             else
  1101.                 {
  1102.                 tcstr[t0] = zalloc(tclen[t0] = pp-tbuf);
  1103.                 memcpy(tcstr[t0],tbuf,tclen[t0]);
  1104.                 }
  1105.             }
  1106.  
  1107. /* if there's no termcap entry for cursor left, use \b. */
  1108.  
  1109.         if (!tccan(TCLEFT))
  1110.             {
  1111.             tcstr[TCLEFT] = ztrdup("\b");
  1112.             tclen[TCLEFT] = 1;
  1113.             }
  1114.  
  1115. /* if there's no termcap entry for clear, use ^L. */
  1116.  
  1117.         if (!tccan(TCCLEARSCREEN))
  1118.             {
  1119.             tcstr[TCCLEARSCREEN] = ztrdup("\14");
  1120.             tclen[TCCLEARSCREEN] = 1;
  1121.             }
  1122.  
  1123. /* if the termcap entry for down is \n, don't use it. */
  1124.  
  1125.         if (tccan(TCDOWN) && tcstr[TCDOWN][0] == '\n')
  1126.             {
  1127.             tclen[TCDOWN] = 0;
  1128.             free(tcstr[TCDOWN]);
  1129.             tcstr[TCDOWN] = NULL;
  1130.             }
  1131.  
  1132. /* if there's no termcap entry for cursor up, forget it.
  1133.     Use single line mode. */
  1134.  
  1135.         if (!tccan(TCUP))
  1136.             termok = 0;
  1137.         }
  1138. }
  1139.  
  1140. void setparams() /**/
  1141. {
  1142. char **envp,**envp2,**envp3,*str;
  1143. char buf[50];
  1144. struct param *pm;
  1145. int ct;
  1146.  
  1147.     noerrs = 1;
  1148.     for (envp = environ, ct = 2; *envp; envp++,ct++);
  1149.     envp = environ;
  1150.     envp2 = envp3 = (char **) zalloc(sizeof(char *)*ct);
  1151.     for (; *envp; envp++)
  1152.         *envp2++ = ztrdup(*envp);
  1153.     *envp2 = NULL;
  1154.     envp = environ;
  1155.     environ = envp2 = envp3;
  1156.     for (; *envp; envp++,envp2++) {
  1157.         for (str = *envp; *str && *str != '='; str++);
  1158.         if (*str == '=') {
  1159.             char *iname;
  1160.  
  1161.             *str = '\0';
  1162.             if (isident(*envp))
  1163.                 pm = setsparam(iname = *envp,ztrdup(str+1));
  1164.             if (pm) {
  1165.                 pm->flags |= PMFLAG_x;
  1166.                 pm->env = *envp2;
  1167.                 if (pm->flags & PMFLAG_SPECIAL)
  1168.                     pm->env = replenv(pm->env,getsparam(iname));
  1169.             }
  1170.             *str = '=';
  1171.         }
  1172.     }
  1173.     pm = gethnode("HOME",paramtab);
  1174.     if (!(pm->flags & PMFLAG_x)) {
  1175.         pm->flags |= PMFLAG_x;
  1176.         pm->env = addenv("HOME",home);
  1177.     }
  1178.     pm = gethnode("PWD",paramtab);
  1179.     if (!(pm->flags & PMFLAG_x)) {
  1180.         pm->flags |= PMFLAG_x;
  1181.         pm->env = addenv("PWD",pwd);
  1182.     }
  1183.     pm = gethnode("LOGNAME",paramtab);
  1184.     if (!(pm->flags & PMFLAG_x)) {
  1185.         pm->flags |= PMFLAG_x;
  1186.         pm->env = addenv("LOGNAME",logname);
  1187.     }
  1188.     pm = gethnode("SHLVL",paramtab);
  1189.     if (!(pm->flags & PMFLAG_x))
  1190.         pm->flags |= PMFLAG_x;
  1191.     sprintf(buf,"%d",++shlvl);
  1192.     pm->env = addenv("SHLVL",buf);
  1193.     noerrs = 0;
  1194. }
  1195.  
  1196. char *mkenvstr(x,y) /**/
  1197. char *x;char *y;
  1198. {
  1199. char *z;
  1200. int xl = strlen(x),yl = strlen(y);
  1201.  
  1202.     z = zalloc(xl+yl+2);
  1203.     strcpy(z,x);
  1204.     z[xl] = '=';
  1205.     strcpy(z+xl+1,y);
  1206.     z[xl+yl+1] = '\0';
  1207.     return z;
  1208. }
  1209.  
  1210. void arrfixenv(s,t) /**/
  1211. char *s;char **t;
  1212. {
  1213. char **ep;
  1214. int sl = strlen(s);
  1215.  
  1216.     for (ep = environ; *ep; ep++)
  1217.         if (!strncmp(*ep,s,sl) && (*ep)[sl] == '=') {
  1218.             char *u = colonjoin(t);
  1219.             replenv(*ep,u);
  1220.             break;
  1221.         }
  1222. }
  1223.  
  1224. char *replenv(e,value) /**/
  1225. char *e;char *value;
  1226. {
  1227. char **ep;
  1228.  
  1229.     for (ep = environ; *ep; ep++)
  1230.         if (*ep == e)
  1231.             {
  1232.             char *s = e;
  1233.  
  1234.             while (*s++ != '=');
  1235.             *s = '\0';
  1236.             *ep = zalloc(strlen(e)+strlen(value)+2);
  1237.             strcpy(*ep,e);
  1238.             strcat(*ep,value);
  1239.             free(e);
  1240.             return *ep;
  1241.             }
  1242.     return NULL;
  1243. }
  1244.  
  1245. char *addenv(name,value) /**/
  1246. char *name;char *value;
  1247. {
  1248. char **ep,**ep2,**ep3;
  1249. int envct;
  1250.  
  1251.     for (ep = environ; *ep; ep++)
  1252.         {
  1253.         char *s = *ep,*t = name;
  1254.  
  1255.         while (*s && *s == *t) s++,t++;
  1256.         if (*s == '=' && !*t)
  1257.             {
  1258.             free(*ep);
  1259.             return *ep = mkenvstr(name,value);
  1260.             }
  1261.         }
  1262.     envct = arrlen(environ);
  1263.     ep = ep2 = (char **) zalloc((sizeof (char *))*(envct+3));
  1264.     for (ep3 = environ; *ep2 = *ep3; ep3++,ep2++);
  1265.     *ep2 = mkenvstr(name,value);
  1266.     ep2[1] = NULL;
  1267.     free(environ);
  1268.     environ = ep;
  1269.     return *ep2;
  1270. }
  1271.  
  1272. void delenv(x) /**/
  1273. char *x;
  1274. {
  1275. char **ep;
  1276.  
  1277.     ep = environ;
  1278.     for (; *ep; ep++)
  1279.         if (*ep == x)
  1280.             break;
  1281.     if (*ep)
  1282.         for (; ep[0] = ep[1]; ep++);
  1283. }
  1284.  
  1285. void convbase(s,v,base) /**/
  1286. char *s;long v;int base;
  1287. {
  1288. int digs = 0;
  1289. long x;
  1290.  
  1291.     if (base <= 1)
  1292.         base = 10;
  1293.     x = v;
  1294.     if (x < 0)
  1295.         {
  1296.         x = -x;
  1297.         digs++;
  1298.         }
  1299.     for (; x; digs++)
  1300.         x /= base;
  1301.     if (!digs)
  1302.         digs = 1;
  1303.     s[digs--] = '\0';
  1304.     x = (v < 0) ? -v : v;
  1305.     while (digs >= 0)
  1306.         {
  1307.         int dig = x%base;
  1308.         s[digs--] = (dig < 10) ? '0'+dig : dig-10+'A';
  1309.         x /= base;
  1310.         }
  1311.     if (v < 0)
  1312.         s[0] = '-';
  1313. }
  1314.  
  1315.  
  1316.