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

  1. /*
  2.    footobar.c: a collection of functions to convert internal representations of
  3.    variables and functions to external representations, and vice versa
  4. */
  5.  
  6. #include "rc.h"
  7. #include "utils.h"
  8. #include "lex.h"
  9. #include "footobar.h"
  10. #include "nalloc.h"
  11. #include "input.h"
  12. #include "list.h"
  13.  
  14. #define FSCHAR '\1'
  15. #define FSSTRING "\1"
  16.  
  17. static char *getenvw(char *, boolean);
  18. static void funcat(char *);
  19. static void strtree(Node *);
  20.  
  21. static char *fun;
  22. static SIZE_T funsize, funpos;
  23.  
  24. /* a specialized strcat, used in strtree */
  25.  
  26. static void funcat(char *s) {
  27.     SIZE_T l = strlen(s);
  28.     char *new;
  29.  
  30.     if (l + funpos > funsize) {
  31.         new = nalloc(funsize *= 2);
  32.         memcpy(new, fun, funpos);
  33.         new[funpos] = 0;
  34.         fun = new;
  35.     }
  36.     strcpy(fun + funpos, s);
  37.     funpos += l;
  38. }
  39.  
  40. /* used to turn a function in Node * form into something we can export to the environment */
  41.  
  42. char *fun2str(char *name, Node *s) {
  43.     fun = nalloc(funsize = 512);
  44.     funpos = 0;
  45.     funcat("fn_");
  46.     funcat(name);
  47.     funcat("={");
  48.     strtree(s);
  49.     funcat("}");
  50.     return ecpy(fun); /* put into malloc space */
  51. }
  52.  
  53. /* ptree is used by whatis in order to print the definition of a function to the terminal */
  54.  
  55. char *ptree(Node *s) {
  56.     fun = nalloc(funsize = 512);
  57.     funpos = 0;
  58.     fun[0] = 0;
  59.     strtree(s);
  60.     return fun;
  61. }
  62.  
  63. /* save some code space by gathering this operation in a function */
  64.  
  65. static void catredir(int i) {
  66.     switch (i) {
  67.     case CREATE: funcat(">"); break;
  68.     case APPEND: funcat(">>"); break;
  69.     case HEREDOC: funcat("<<"); break;
  70.     case HERESTRING: funcat("<<<"); break;
  71.     case FROM: funcat("<"); break;
  72.     }
  73. }
  74.  
  75. /* convert a function in Node * form into something rc can parse (and humans can read?) */
  76.  
  77. static void strtree(Node *n) {
  78.     int defaultfd;
  79.     char b[16];
  80.  
  81.     if (n == NULL) {
  82.         funcat("()");
  83.         return;
  84.     }
  85.  
  86.     switch (n->type) {
  87.     case rDUP:
  88.         catredir(n->u[0].i);
  89.         if (n->u[2].i != -1)
  90.             sprint(b, "[%d=%d]", n->u[1].i, n->u[2].i);
  91.         else
  92.             sprint(b, "[%d=]", n->u[1].i);
  93.         funcat(b);
  94.         break;
  95.     case rWORD:
  96.         if (*n->u[0].s == '\'')
  97.             funcat(strprint(n->u[0].s + 1, TRUE, FALSE));
  98.         else
  99.             funcat(strprint(n->u[0].s, FALSE, FALSE));
  100.         break;
  101.     case BACKQ:
  102.         if (n->u[0].p != NULL && n->u[0].p->type == VAR
  103.             && n->u[0].p->u[0].p != NULL && n->u[0].p->u[0].p->type == rWORD
  104.             && streq(n->u[0].p->u[0].p->u[0].s,"ifs")) {
  105.             funcat("`{");
  106.         } else {
  107.             funcat("``");
  108.             strtree(n->u[0].p);
  109.             funcat("{");
  110.         }
  111.         strtree(n->u[1].p);
  112.         funcat("}");
  113.         break;
  114.     case rBANG:
  115.         funcat("! ");
  116.         strtree(n->u[0].p);
  117.         break;
  118.     case NOWAIT:
  119.         strtree(n->u[0].p);
  120.         funcat("&");
  121.         break;
  122.     case rCOUNT:
  123.         funcat("$#");
  124.         strtree(n->u[0].p);
  125.         break;
  126.     case rFLAT:
  127.         funcat("$^");
  128.         strtree(n->u[0].p);
  129.         break;
  130.     case RMFN:
  131.         funcat("fn ");
  132.         strtree(n->u[0].p);
  133.         break;
  134.     case rSUBSHELL:
  135.         funcat("@ ");
  136.         strtree(n->u[0].p);
  137.         break;
  138.     case VAR:
  139.         funcat("$");
  140.         strtree(n->u[0].p);
  141.         break;
  142.     case rANDAND:
  143.         strtree(n->u[0].p);
  144.         funcat("&&");
  145.         strtree(n->u[1].p);
  146.         break;
  147.     case ASSIGN:
  148.         strtree(n->u[0].p);
  149.         funcat("=");
  150.         strtree(n->u[1].p);
  151.         break;
  152.     case BODY:
  153.         if (n->u[1].p != NULL)
  154.             funcat("{");
  155.         strtree(n->u[0].p);
  156.         if (n->u[1].p != NULL) {
  157.             funcat(";");
  158.             strtree(n->u[1].p);
  159.             funcat("}");
  160.         }
  161.         break;
  162.     case BRACE:
  163.         funcat("{");
  164.         strtree(n->u[0].p);
  165.         funcat("}");
  166.         strtree(n->u[1].p);
  167.         break;
  168.     case CONCAT:
  169.         strtree(n->u[0].p);
  170.         funcat("^");
  171.         strtree(n->u[1].p);
  172.         break;
  173.     case rELSE:
  174.         funcat("{");
  175.         strtree(n->u[0].p);
  176.         funcat("}else ");
  177.         strtree(n->u[1].p);
  178.         break;
  179.     case EPILOG:
  180.     case PRE:
  181.         strtree(n->u[0].p);
  182.         funcat(" ");
  183.         strtree(n->u[1].p);
  184.         break;
  185.     case NEWFN:
  186.         funcat("fn ");
  187.         strtree(n->u[0].p);
  188.         funcat(" {");
  189.         strtree(n->u[1].p);
  190.         funcat("}");
  191.         break;
  192.     case rIF:
  193.         funcat("if(");
  194.         strtree(n->u[0].p);
  195.         funcat(")");
  196.         strtree(n->u[1].p);
  197.         break;
  198.     case rOROR:
  199.         strtree(n->u[0].p);
  200.         funcat("||");
  201.         strtree(n->u[1].p);
  202.         break;
  203.     case ARGS:
  204.         strtree(n->u[0].p);
  205.         funcat(" ");
  206.         strtree(n->u[1].p);
  207.         break;
  208.     case rSWITCH:
  209.         funcat("switch(");
  210.         strtree(n->u[0].p);
  211.         funcat(")");
  212.         strtree(n->u[1].p);
  213.         break;
  214.     case MATCH:
  215.         funcat("~ ");
  216.         strtree(n->u[0].p);
  217.         funcat(" ");
  218.         strtree(n->u[1].p);
  219.         break;
  220.     case VARSUB:
  221.         funcat("$");
  222.         strtree(n->u[0].p);
  223.         funcat("(");
  224.         strtree(n->u[1].p);
  225.         funcat(")");
  226.         break;
  227.     case rWHILE:
  228.         funcat("while(");
  229.         strtree(n->u[0].p);
  230.         funcat(")");
  231.         strtree(n->u[1].p);
  232.         break;
  233.     case LAPPEND:
  234.         funcat("(");
  235.         strtree(n->u[0].p);
  236.         funcat(" ");
  237.         strtree(n->u[1].p);
  238.         funcat(")");
  239.         break;
  240.     case FORIN:
  241.         funcat("for(");
  242.         strtree(n->u[0].p);
  243.         funcat(" in ");
  244.         strtree(n->u[1].p);
  245.         funcat(")");
  246.         strtree(n->u[2].p);
  247.         break;
  248.     case rPIPE:
  249.         funcat("{");
  250.         strtree(n->u[2].p);
  251.         if (n->u[0].i == 1) {
  252.             if (n->u[1].i == 0)
  253.                 sprint(b, "}|{");
  254.             else
  255.                 sprint(b, "}|[1=%d]{", n->u[1].p);
  256.         } else {
  257.             if (n->u[1].i == 0)
  258.                 sprint(b, "}|[%d]{", n->u[0].p);
  259.             else
  260.                 sprint(b, "}|[%d=%d]{", n->u[0].i, n->u[1].i);
  261.         }
  262.         funcat(b);
  263.         strtree(n->u[3].p);
  264.         funcat("}");
  265.         break;
  266.     case NMPIPE:
  267.         catredir(n->u[0].i);
  268.         if (n->u[1].i != 1) {
  269.             sprint(b, "[%d]{", n->u[1].i);
  270.             funcat(b);
  271.         } else
  272.             funcat("{");
  273.         strtree(n->u[2].p);
  274.         funcat("}");
  275.         break;
  276.     case rREDIR:
  277.         defaultfd = (n->u[0].i == CREATE || n->u[0].i == APPEND);
  278.         catredir(n->u[0].i);
  279.         if (n->u[1].i != defaultfd) {
  280.             sprint(b, "[%d]", n->u[1].i);
  281.             funcat(b);
  282.         }
  283.         strtree(n->u[2].p);
  284.         break;
  285.      }
  286. }
  287.  
  288. /* convert a List to a string, separating it with ^A characters. Used for exporting variables to the environment */
  289.  
  290. char *list2str(char *name, List *s) {
  291.     SIZE_T size;
  292.     List *t;
  293.     char *w;
  294.  
  295.     size = listlen(s);
  296.     size += strlen(name);
  297.  
  298.     w = ealloc(size + 2);
  299.     t = s;
  300.     strcpy(w, name);
  301.     strcat(w, "=");
  302.     strcat(w, t->w);
  303.     for (s = s->n; s != NULL; s = s->n) {
  304.         strcat(w, FSSTRING);
  305.         strcat(w, s->w);
  306.     }
  307.     return w;
  308. }
  309.  
  310. /* convert a List to an array, for execve() */
  311.  
  312. char **list2array(List *s, boolean print) {
  313.     char **av;
  314.     int i;
  315.  
  316.     av = nalloc((listnel(s) + 1) * sizeof (char *));
  317.  
  318.     for (i = 0; s != NULL; i++) {
  319.         av[i] = s->w;
  320.         if (print)
  321.             fprint(2,"%s",s->w);
  322.         s = s->n;
  323.         if (print) {
  324.             if (s == NULL)
  325.                 fprint(2,"\n");
  326.             else
  327.                 fprint(2," ");
  328.         }
  329.     }
  330.     av[i] = NULL;
  331.     return av;
  332. }
  333.  
  334. /* figure out the name of a variable given an environment string. copy this into malloc space */
  335.  
  336. char *get_name(char *s) {
  337.     char *r;
  338.     SIZE_T i;
  339.  
  340.     for (i = 0; s[i] != '\0' && s[i] != '='; i++)
  341.         ;
  342.  
  343.     if (s[i] == '\0')
  344.         return NULL;
  345.  
  346.     r = ealloc(i + 1);
  347.  
  348.     r[i] = '\0';
  349.  
  350.     while (i > 0) {
  351.         --i;
  352.         r[i] = s[i];
  353.     }
  354.     return r;
  355. }
  356.  
  357. /* get the next word from a variable's value as represented in the environment. */
  358.  
  359. static char *getenvw(char *s, boolean saw_alpha) {
  360.     char *r;
  361.     SIZE_T i,j;
  362.  
  363.     for (i = j = 0; s[i] != '\0' && s[i] != FSCHAR; i++)
  364.         ;
  365.  
  366.     if (i == 0)
  367.         if(s[i] == '\0' && !saw_alpha)
  368.             return NULL;
  369.         else {
  370.             r = enew(char);
  371.             *r = '\0';
  372.             return r;
  373.         }
  374.  
  375.     r = ealloc(i + j + 1);
  376.  
  377.     r[i + j] = '\0';
  378.  
  379.     while (i > 0) {
  380.         --i;
  381.         r[i + j] = s[i];
  382.     }
  383.     return r;
  384. }
  385.  
  386. /* take an environment entry for a variable (elements ^A separated) and turn it into a List */
  387.  
  388. List *parse_var(char *name, char *extdef) {
  389.     List *r, *top = r;
  390.     char *f;
  391.     boolean saw_alpha;
  392.  
  393.     top = r = enew(List);
  394.     extdef += strlen(name) + 1;
  395.  
  396.     
  397.     if ((f = getenvw(extdef, FALSE)) == NULL)
  398.         return NULL;
  399.  
  400.     while (1) {
  401.         r->w = f;
  402.         r->m = NULL;
  403.         extdef += strlen(f);
  404.         if (*extdef == FSCHAR) {
  405.             extdef++;
  406.             saw_alpha = TRUE;
  407.         } else {
  408.             saw_alpha = FALSE;
  409.         }        
  410.         if ((f = getenvw(extdef, saw_alpha)) == NULL) {
  411.             r->n = NULL;
  412.             break;
  413.         }
  414.         r = r->n = enew(List);
  415.     }
  416.     return top;
  417. }
  418.  
  419. /* get an environment entry for a function and have rc parse it. */
  420.  
  421. Node *parse_fn(char *name, char *extdef) {
  422.     Node *def;
  423.     int len;
  424.  
  425.     len = strlen(name);
  426.     extdef[2] = ' ';
  427.     extdef[3 + len] = ' ';
  428.     def = parseline(extdef);
  429.     extdef[2] = '_';
  430.     extdef[3 + len] = '=';
  431.  
  432.     if (def == NULL || def->type != NEWFN)
  433.         return NULL;
  434.     else
  435.         return def->u[1].p;
  436. }
  437.