home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume30 / rc / part05 / var.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-30  |  5.8 KB  |  227 lines

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