home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume20 / rc / part03 / var.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-22  |  5.7 KB  |  252 lines

  1. /* var.c: provide "public" functions for adding and removing variables from the symbol table */
  2.  
  3. #include "rc.h"
  4. #include "utils.h"
  5. #include "hash.h"
  6. #include "list.h"
  7. #include "footobar.h"
  8. #include "nalloc.h"
  9. #include "status.h"
  10. #include "glom.h"
  11.  
  12. #ifdef READLINE /* need to reset readline() every time TERM or TERMCAP changes */
  13. extern void rl_reset_terminal(char *);
  14. #endif
  15.  
  16. static void colonassign(char *, List *, boolean);
  17. static void listassign(char *, List *, boolean);
  18. static int hasalias(char *);
  19.  
  20. static char *const aliases[] = {
  21.     "home", "HOME", "path", "PATH", "cdpath", "CDPATH"
  22. };
  23.  
  24. /* assign a variable in List form to a name, stacking if appropriate */
  25.  
  26. void varassign(char *name, List *def, boolean stack) {
  27.     Variable *new;
  28.     List *newdef = listcpy(def); /* important to do the listcpy first; get_var_place() frees old values */
  29.  
  30.     new = get_var_place(name, stack);
  31.     new->def = newdef;
  32.     new->extdef = NULL;
  33.  
  34. #ifdef READLINE /* need to reset readline() every time TERM or TERMCAP changes */
  35.     if (interactive && streq(name, "TERM") || streq(name, "TERMCAP"))
  36.         rl_reset_terminal(NULL);
  37. #endif
  38. }
  39.  
  40. /* assign a variable in string form. Check to see if it is aliased (e.g., PATH and path) */
  41.  
  42. boolean varassign_string(char *extdef) {
  43.     char *name = get_name(extdef);
  44.     Variable *new;
  45.     int i;
  46.     static boolean aliasset[arraysize(aliases)] = {
  47.         FALSE, FALSE, FALSE, FALSE, FALSE, FALSE
  48.     };
  49.  
  50.     if (name == NULL)
  51.         return FALSE; /* add it to bozo env */
  52.  
  53.     i = hasalias(name);
  54.     if (i >= 0) {
  55.         aliasset[i] = TRUE;
  56.         if ((i & 1 == 0) && aliasset[i^1])
  57.             return TRUE; /* don't alias variables that are already set in upper case */
  58.     }
  59.     new = get_var_place(name, FALSE);
  60.     new->def = NULL;
  61.     new->extdef = ealloc(strlen(extdef) + 1);
  62.     strcpy(new->extdef, extdef);
  63.     if (hasalias(name) != -1)
  64.         alias(name, varlookup(name), FALSE);
  65.     return TRUE;
  66. }
  67.  
  68. /*
  69.    Return a List based on a name lookup. If the list is in external (string) form,
  70.    convert it to internal (List) form. Treat $n (n is an integer) specially as $*(n).
  71.    Also check to see if $status is being dereferenced. (we lazily evaluate the List
  72.    associated with $status)
  73. */
  74.  
  75. List *varlookup(char *name) {
  76.     Variable *look;
  77.     List *ret, *l;
  78.     int sub;
  79.  
  80.     if (streq(name, "status"))
  81.         return sgetstatus();
  82.  
  83.     if (*name != '\0' && (sub = a2u(name)) != -1) { /* handle $1, $2, etc. */
  84.         for (l = varlookup("*"); l != NULL && sub != 0; --sub)
  85.             l = l->n;
  86.         if (l == NULL)
  87.             return NULL;
  88.         ret = nnew(List);
  89.         ret->w = l->w;
  90.         ret->m = NULL;
  91.         ret->n = NULL;
  92.         return ret;
  93.     }
  94.  
  95.     look = lookup_var(name);
  96.  
  97.     if (look == NULL)
  98.         return NULL; /* not found */
  99.     if (look->def != NULL)
  100.         return look->def;
  101.     if (look->extdef == NULL)
  102.         return NULL; /* variable was set to null, e.g., a=() echo foo */
  103.  
  104.     ret = parse_var(name, look->extdef);
  105.  
  106.     if (ret == NULL) {
  107.         look->extdef = NULL;
  108.         return NULL;
  109.     }
  110.     return look->def = ret;
  111. }
  112.  
  113. /* lookup a variable in external (string) form, converting if necessary. Used by makeenv() */
  114.  
  115. char *varlookup_string(char *name) {
  116.     Variable *look;
  117.  
  118.     look = lookup_var(name);
  119.  
  120.     if (look == NULL)
  121.         return NULL;
  122.     if (look->extdef != NULL)
  123.         return look->extdef;
  124.     if (look->def == NULL)
  125.         return NULL;
  126.     return look->extdef = list2str(name, look->def);
  127. }
  128.  
  129. /* remove a variable from the symtab. "stack" determines whether a level of scoping is popped or not */
  130.  
  131. void varrm(char *name, boolean stack) {
  132.     int i = hasalias(name);
  133.  
  134.     if (streq(name, "*") && !stack) { /* when assigning () to $*, we want to preserve $0 */
  135.         varassign("*", varlookup("0"), FALSE);
  136.         return;
  137.     }
  138.         
  139.     delete_var(name, stack);
  140.     if (i != -1)
  141.         delete_var(aliases[i^1], stack);
  142. }
  143.  
  144. /* assign a value (List) to a variable, using array "a" as input. Used to assign $* */
  145.  
  146. void starassign(char *dollarzero, char **a, boolean stack) {
  147.     List *s, *var;
  148.  
  149.     var = nnew(List);
  150.     var->w = dollarzero;
  151.  
  152.     if (*a == NULL) {
  153.         var->n = NULL;
  154.         varassign("*", var, stack);
  155.         return;
  156.     }
  157.  
  158.     var->n = s = nnew(List);
  159.  
  160.     while (1) {
  161.         s->w = *a++;
  162.         if (*a == NULL) {
  163.             s->n = NULL;
  164.             break;
  165.         } else {
  166.             s->n = nnew(List);
  167.             s = s->n;
  168.         }
  169.     }
  170.     varassign("*", var, stack);
  171. }
  172.  
  173. /* (ugly name, huh?) assign a colon-separated value to a variable (e.g., PATH) from a List (e.g., path) */
  174.  
  175. static void colonassign(char *name, List *def, boolean stack) {
  176.     char *colondef;
  177.     List dud;
  178.     SIZE_T deflen;
  179.     List *r;
  180.  
  181.     if (def == NULL) {
  182.         varassign(name, NULL, stack);
  183.         return;
  184.     }
  185.  
  186.     deflen = listlen(def) + 1; /* one for the null terminator */
  187.  
  188.     colondef = nalloc(deflen);
  189.     strcpy(colondef, def->w);
  190.  
  191.     for (r = def->n; r != NULL; r = r->n) {
  192.         strcat(colondef, ":");
  193.         strcat(colondef, r->w);
  194.     }
  195.  
  196.     dud.w = colondef;
  197.     dud.n = NULL;
  198.     varassign(name, &dud, stack);
  199. }
  200.  
  201. /* assign a List variable (e.g., path) from a colon-separated string (e.g., PATH) */
  202.  
  203. static void listassign(char *name, List *def, boolean stack) {
  204.     List *val, *r;
  205.     char *v, *w;
  206.  
  207.     if (def == NULL) {
  208.         varassign(name, NULL, stack);
  209.         return;
  210.     }
  211.  
  212.     v = def->w;
  213.  
  214.     r = val = enew(List);
  215.  
  216.     while((w = strchr(v,':')) != NULL) {
  217.         *w = '\0';
  218.         r->w = ecpy(v);
  219.         *w = ':';
  220.         v = w + 1;
  221.         r->n = enew(List);
  222.         r = r->n;
  223.     }
  224.     r->w = ecpy(v);
  225.     r->n = NULL;
  226.  
  227.     varassign(name, val, stack);
  228. }
  229.  
  230. /* check to see if a particular variable is aliased; return -1 on failure, or the index */
  231.  
  232. static int hasalias(char *name) {
  233.     int i;
  234.  
  235.     for (i = 0; i < arraysize(aliases); i++)
  236.         if (streq(name, aliases[i]))
  237.             return i;
  238.     return -1;
  239. }
  240.  
  241. /* alias a variable to its lowercase equivalent. function pointers are used to specify the conversion function */
  242.  
  243. void alias(char *name, List *s, boolean stack) {
  244.     int i = hasalias(name);
  245.     static void (*vectors[])(char *, List *, boolean) = {
  246.         varassign, varassign, colonassign, listassign, colonassign, listassign
  247.     };
  248.  
  249.     if (i != -1)
  250.         vectors[i](aliases[i^1], s, stack); /* xor hack to reverse case of alias entry */
  251. }
  252.