home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / k / ksh48.zip / sh / tree.c < prev    next >
C/C++ Source or Header  |  1992-05-03  |  10KB  |  568 lines

  1. /*
  2.  * command tree climbing
  3.  */
  4.  
  5. #ifndef lint
  6. static char *RCSid = "$Id: tree.c,v 1.2 1992/04/25 08:33:28 sjg Exp $";
  7. #endif
  8.  
  9. #include "stdh.h"
  10. #include <errno.h>
  11. #include <setjmp.h>
  12. #include <memory.h>
  13.  
  14. #ifdef __STDC__
  15. # include <stdarg.h>
  16. #else
  17. # include <varargs.h>
  18. #endif
  19. #include "sh.h"
  20.  
  21. #define    FSTRING    (FILE*)NULL
  22.  
  23. static int      tputc       ARGS((int c, FILE *f));
  24. static void     tputC       ARGS((int c, FILE *f));
  25. static void     tputS       ARGS((char *wp, FILE *f));
  26. static struct ioword **iocopy ARGS((struct ioword **iow, Area *ap));
  27. static void     iofree      ARGS((struct ioword **iow, Area *ap));
  28.  
  29. /*
  30.  * print a command tree
  31.  */
  32.  
  33. void
  34. ptree(t, f)
  35.     register struct op *t;
  36.     register FILE *f;
  37. {
  38.     register char **w;
  39.     struct ioword **ioact;
  40.     struct op *t1;
  41.  
  42.  Chain:
  43.     if (t == NULL)
  44.         return;
  45.     switch (t->type) {
  46.       case TCOM:
  47.         for (w = t->vars; *w != NULL; )
  48.             fptreef(f, "%S ", *w++);
  49.         for (w = t->args; *w != NULL; )
  50.             fptreef(f, "%S ", *w++);
  51.         break;
  52.       case TEXEC:
  53.         t = t->left;
  54.         goto Chain;
  55.       case TPAREN:
  56.         fptreef(f, "(%T)", t->left);
  57.         break;
  58.       case TPIPE:
  59.         fptreef(f, "%T| ", t->left);
  60.         t = t->right;
  61.         goto Chain;
  62.       case TLIST:
  63.         fptreef(f, "%T", t->left);
  64.         fptreef(f, "%;");
  65.         t = t->right;
  66.         goto Chain;
  67.       case TOR:
  68.       case TAND:
  69.         fptreef(f, "%T", t->left);
  70.         fptreef(f, "%s %T", (t->type==TOR) ? "||" : "&&", t->right);
  71.         break;
  72.       case TFOR:
  73.         fptreef(f, "for %s ", t->str);
  74.         if (t->vars != NULL) {
  75.             fptreef(f, "in ");
  76.             for (w = t->vars; *w; )
  77.                 fptreef(f, "%S ", *w++);
  78.             fptreef(f, "%;");
  79.         }
  80.         fptreef(f, "do %T", t->left);
  81.         fptreef(f, "%;done ");
  82.         break;
  83.       case TCASE:
  84.         fptreef(f, "case %S in%;", t->str);
  85.         for (t1 = t->left; t1 != NULL; t1 = t1->right) {
  86.             fptreef(f, "(");
  87.             for (w = t1->vars; *w != NULL; w++) {
  88.                 fptreef(f, "%S", *w);
  89.                 fptreef(f, "%c", (w[1] != NULL) ? '|' : ')');
  90.             }
  91.             fptreef(f, " %T;;%;", t1->left);
  92.         }
  93.         fptreef(f, "esac ");
  94.         break;
  95.       case TIF:
  96.         fptreef(f, "if %T", t->left);
  97.         fptreef(f, "%;");
  98.         t = t->right;
  99.         if (t->left != NULL) {
  100.             fptreef(f, "then %T", t->left);
  101.             fptreef(f, "%;");
  102.         }
  103.         if (t->right != NULL) {
  104.             fptreef(f, "else %T", t->right);
  105.             fptreef(f, "%;");
  106.         }
  107.         fptreef(f, "fi ");
  108.         break;
  109.       case TWHILE:
  110.       case TUNTIL:
  111.         fptreef(f, "%s %T",
  112.             (t->type==TWHILE) ? "while" : "until",
  113.             t->left);
  114.         fptreef(f, "%;do %T", t->right);
  115.         fptreef(f, "%;done ");
  116.         break;
  117.       case TBRACE:
  118.         fptreef(f, "{%;%T", t->left);
  119.         fptreef(f, "%;} ");
  120.         break;
  121.       case TASYNC:
  122.         fptreef(f, "%T&", t->left);
  123.         break;
  124.       case TFUNCT:
  125.         fptreef(f, "function %s %T", t->str, t->left);
  126.         break;
  127.       case TTIME:
  128.         fptreef(f, "time %T", t->left);
  129.         break;
  130.       default:
  131.         fptreef(f, "<botch>");
  132.         break;
  133.     }
  134.     if ((ioact = t->ioact) != NULL)
  135.         while (*ioact != NULL)
  136.             pioact(f, *ioact++);
  137. }
  138.  
  139. pioact(f, iop)
  140.     register FILE *f;
  141.     register struct ioword *iop;
  142. {
  143.     register int flag = iop->flag;
  144.     if (iop->unit > 1)
  145.         fptreef(f, "%c", '0' + iop->unit );
  146.  
  147.     switch(flag&IOTYPE) {
  148.     case IOREAD:
  149.         fptreef(f, "< ");
  150.         break;
  151.     case IOHERE:
  152.         if (flag&IOSKIP)
  153.             fptreef(f, "<<- ");
  154.         else
  155.             fptreef(f, "<< ");
  156.         if (!(flag&IOEVAL))
  157.             fptreef(f, "'");
  158.         break;
  159.     case IOCAT:
  160.         fptreef(f, ">> ");
  161.         break;
  162.     case IOWRITE:
  163.         if (flag&IOCLOB)
  164.             fptreef(f, ">! ");
  165.         else
  166.             fptreef(f, "> ");
  167.         break;
  168.     case IODUP:            /* Needs help */
  169.         if (iop->unit == 0)
  170.             fptreef(f, "<&");
  171.         else
  172.             fptreef(f, ">&");
  173.         break;
  174.     }
  175.  
  176.     if ((flag&IOTYPE) == IOHERE) {
  177.         if (flag&IOEVAL)
  178.             fptreef(f, "%s ", iop->name);
  179.         else
  180.             fptreef(f, "%s' ", iop->name);
  181.     } else {
  182.         fptreef(f, "%S ", iop->name);
  183.     }
  184. }
  185.  
  186.  
  187. /*
  188.  * variants of fputc, fputs for ptreef and snptreef
  189.  */
  190.  
  191. static    char   *snpf_s;        /* snptreef string */
  192. static    int    snpf_n;        /* snptreef length */
  193.  
  194. static int
  195. tputc(c, f)
  196.     int c;
  197.     register FILE *f;
  198. {
  199.     if (f != NULL)
  200.         putc(c, f);
  201.     else
  202.         if (--snpf_n >= 0)
  203.             *snpf_s++ = c;
  204.     return c;
  205. }
  206.  
  207. static void
  208. tputC(c, f)
  209.     register int c;
  210.     register FILE *f;
  211. {
  212.     if ((c&0x60) == 0) {        /* C0|C1 */
  213.         tputc((c&0x80) ? '$' : '^', f);
  214.         tputc(((c&0x7F)|0x40), f);
  215.     } else if ((c&0x7F) == 0x7F) {    /* DEL */
  216.         tputc((c&0x80) ? '$' : '^', f);
  217.         tputc('?', f);
  218.     } else
  219.         tputc(c, f);
  220. }
  221.  
  222. static void
  223. tputS(wp, f)
  224.     register char *wp;
  225.     register FILE *f;
  226. {
  227.     register int c, quoted=0;
  228.  
  229.     while (1)
  230.         switch ((c = *wp++)) {
  231.           case EOS:
  232.             return;
  233.           case CHAR:
  234.             tputC(*wp++, f);
  235.             break;
  236.           case QCHAR:
  237.             if (!quoted)
  238.                 tputc('\\', f);
  239.             tputC(*wp++, f);
  240.             break;
  241.           case OQUOTE:
  242.               quoted = 1;
  243.             tputc('"', f);
  244.             break;
  245.           case CQUOTE:
  246.             quoted = 0;
  247.             tputc('"', f);
  248.             break;
  249.           case OSUBST:
  250.             tputc('$', f);
  251.             tputc('{', f);
  252.             while ((c = *wp++) != 0)
  253.                 tputc(c, f);
  254.             if (*wp != CSUBST)
  255.                 tputC(*wp++, f);
  256.             break;
  257.           case CSUBST:
  258.             tputc('}', f);
  259.             break;
  260.           case COMSUB:
  261.             tputc('$', f);
  262.             tputc('(', f);
  263.             while (*wp != 0)
  264.                 tputC(*wp++, f);
  265.             tputc(')', f);
  266.             break;
  267.         }
  268. }
  269.  
  270. /*
  271.  * this is the _only_ way to reliably handle
  272.  * variable args with an ANSI compiler
  273.  */
  274. #ifdef __STDC__
  275. /* VARARGS */ int
  276. fptreef(FILE *f, char *fmt, ...)
  277. {
  278. #else
  279. fptreef(va_alist) 
  280.   va_dcl
  281. {
  282.   FILE *f;
  283.   char *fmt;
  284. #endif
  285.   va_list    va;
  286.  
  287. #ifdef __STDC__
  288.   va_start(va, fmt);
  289. #else
  290.   va_start(va);
  291.   f = va_arg(va, FILE *);
  292.   fmt = va_arg(va, char *);
  293. #endif
  294.   
  295.   vfptreef(f, fmt, va);
  296.   va_end(va);
  297.   return 0;
  298. }
  299.  
  300. /* VARARGS */ int
  301. #ifdef __STDC__
  302. snptreef(char *s, int n, char *fmt, ...)
  303. {
  304. #else
  305. snptreef(va_alist)
  306.   va_dcl
  307. {
  308.   char *s;
  309.   int n;
  310.   char *fmt;
  311. #endif
  312.   va_list va;
  313.  
  314. #ifdef __STDC__
  315.   va_start(va, fmt);
  316. #else
  317.   va_start(va);
  318.   s = va_arg(va, char *);
  319.   n = va_arg(va, int);
  320.   fmt = va_arg(va, char *);
  321. #endif
  322.  
  323.   snpf_s = s;
  324.   snpf_n = n;
  325.   vfptreef(FSTRING, fmt, va);
  326.   tputc('\0', FSTRING);
  327.   va_end(va);
  328.   return 0;
  329. }
  330.  
  331.  
  332. vfptreef(f, fmt, va)
  333.     register FILE *f;
  334.     register char *fmt;
  335.     register va_list va;
  336. {
  337.     register int c;
  338.  
  339.     while ((c = *fmt++))
  340.         if (c == '%') {
  341.         register long n;
  342.         register char *p;
  343.         int neg;
  344.  
  345.         switch ((c = *fmt++)) {
  346.           case 'c':
  347.             tputc(va_arg(va, int), f);
  348.             break;
  349.           case 's':
  350.             p = va_arg(va, char *);
  351.             while (*p)
  352.                 tputc(*p++, f);
  353.             break;
  354.           case 'S':    /* word */
  355.             p = va_arg(va, char *);
  356.             tputS(p, f);
  357.             break;
  358.           case 'd': case 'u': /* decimal */
  359.             n = (c == 'd') ? va_arg(va, int) : va_arg(va, unsigned int);
  360.             neg = c=='d' && n<0;
  361.             p = ulton((neg) ? -n : n, 10);
  362.             if (neg)
  363.                 *--p = '-';
  364.             while (*p)
  365.                 tputc(*p++, f);
  366.             break;
  367.           case 'T':    /* format tree */
  368.             ptree(va_arg(va, struct op *), f);
  369.             break;
  370.           case ';':    /* newline or ; */
  371.             p = (f == FSTRING) ? "; " : "\n";
  372.             while (*p)
  373.                 tputc(*p++, f);
  374.             break;
  375.           default:
  376.             tputc(c, f);
  377.             break;
  378.         }
  379.         } else
  380.         tputc(c, f);
  381. }
  382.  
  383. /*
  384.  * copy tree (for function definition)
  385.  */
  386.  
  387. static    struct ioword **iocopy();
  388.  
  389. struct op *
  390. tcopy(t, ap)
  391.     register struct op *t;
  392.     Area *ap;
  393. {
  394.     register struct op *r;
  395.     register char **tw, **rw;
  396.  
  397.     if (t == NULL)
  398.         return NULL;
  399.  
  400.     r = (struct op *) alloc(sizeof(struct op), ap);
  401.  
  402.     r->type = t->type;
  403.  
  404.     /* this will copy function and for identifiers quite accidently */
  405.     r->str = (t->str == NULL) ? NULL : wdcopy(t->str, ap);
  406.  
  407.     if (t->vars == NULL)
  408.         r->vars = NULL;
  409.     else {
  410.         for (tw = t->vars; *tw++ != NULL; )
  411.             ;
  412.         rw = r->vars = (char **)
  413.             alloc((int)(tw - t->vars) * sizeof(*tw), ap);
  414.         for (tw = t->vars; *tw != NULL; )
  415.             *rw++ = wdcopy(*tw++, ap);
  416.         *rw = NULL;
  417.     }
  418.  
  419.     if (t->args == NULL)
  420.         r->args = NULL;
  421.     else {
  422.         for (tw = t->args; *tw++ != NULL; )
  423.             ;
  424.         rw = r->args = (char **)
  425.             alloc((int)(tw - t->args) * sizeof(*tw), ap);
  426.         for (tw = t->args; *tw != NULL; )
  427.             *rw++ = wdcopy(*tw++, ap);
  428.         *rw = NULL;
  429.     }
  430.  
  431.     r->ioact = (t->ioact == NULL) ? NULL : iocopy(t->ioact, ap);
  432.  
  433.     r->left = tcopy(t->left, ap);
  434.     r->right = tcopy(t->right, ap);
  435.  
  436.     return r;
  437. }
  438.  
  439. char *
  440. wdcopy(wp, ap)
  441.     char *wp;
  442.     Area *ap;
  443. {
  444.     size_t len = wdscan(wp, EOS) - wp;
  445.     return memcpy(alloc(len, ap), wp, len);
  446. }
  447.  
  448. /* return the position of prefix c in wp plus 1 */
  449. char *
  450. wdscan(wp, c)
  451.     register char *wp;
  452.     register int c;
  453. {
  454.     register int nest = 0;
  455.  
  456.     while (1)
  457.         switch (*wp++) {
  458.           case EOS:
  459.             return wp;
  460.           case CHAR:
  461.           case QCHAR:
  462.             wp++;
  463.             break;
  464.           case OQUOTE:
  465.           case CQUOTE:
  466.             break;
  467.           case OSUBST:
  468.             nest++;
  469.             while (*wp++ != 0)
  470.                 ;
  471.             if (*wp != CSUBST)
  472.                 wp++;
  473.             break;
  474.           case CSUBST:
  475.             if (c == CSUBST && nest == 0)
  476.                 return wp;
  477.             nest--;
  478.             break;
  479.           case COMSUB:
  480.             while (*wp++ != 0)
  481.                 ;
  482.             break;
  483.         }
  484. }
  485.  
  486. static    struct ioword **
  487. iocopy(iow, ap)
  488.     register struct ioword **iow;
  489.     Area *ap;
  490. {
  491.     register struct ioword **ior;
  492.     register int i;
  493.  
  494.     for (ior = iow; *ior++ != NULL; )
  495.         ;
  496.     ior = (struct ioword **) alloc((int)(ior - iow) * sizeof(*ior), ap);
  497.  
  498.     for (i = 0; iow[i] != NULL; i++) {
  499.         register struct ioword *p, *q;
  500.  
  501.         p = iow[i];
  502.         q = (struct ioword *) alloc(sizeof(*p), ap);
  503.         ior[i] = q;
  504.         *q = *p;
  505.         if (p->name != NULL)
  506.             q->name = wdcopy(p->name, ap);
  507.     }
  508.     ior[i] = NULL;
  509.  
  510.     return ior;
  511. }
  512.  
  513. /*
  514.  * free tree (for function definition)
  515.  */
  516.  
  517. static    void iofree();
  518.  
  519. void
  520. tfree(t, ap)
  521.     register struct op *t;
  522.     Area *ap;
  523. {
  524.     register char **w;
  525.  
  526.     if (t == NULL)
  527.         return;
  528.  
  529.     if (t->str != NULL)
  530.         afree((void*)t->str, ap);
  531.  
  532.     if (t->vars != NULL) {
  533.         for (w = t->vars; *w != NULL; w++)
  534.             afree((void*)*w, ap);
  535.         afree((void*)t->vars, ap);
  536.     }
  537.  
  538.     if (t->args != NULL) {
  539.         for (w = t->args; *w != NULL; w++)
  540.             afree((void*)*w, ap);
  541.         afree((void*)t->args, ap);
  542.     }
  543.  
  544.     if (t->ioact != NULL)
  545.         iofree(t->ioact, ap);
  546.  
  547.     tfree(t->left, ap);
  548.     tfree(t->right, ap);
  549.  
  550.     afree((void*)t, ap);
  551. }
  552.  
  553. static    void
  554. iofree(iow, ap)
  555.     struct ioword **iow;
  556.     Area *ap;
  557. {
  558.     register struct ioword **iop;
  559.     register struct ioword *p;
  560.  
  561.     for (iop = iow; (p = *iop++) != NULL; ) {
  562.         if (p->name != NULL)
  563.             afree((void*)p->name, ap);
  564.         afree((void*)p, ap);
  565.     }
  566. }
  567.  
  568.