home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / pdksh-4.9-src.tgz / tar.out / contrib / pdksh / sh / tree.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  10KB  |  567 lines

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