home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / Shells / zsh / Source / src / text.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-07  |  8.7 KB  |  486 lines

  1.  
  2. /*
  3.  *
  4.  * text.c - textual representations of syntax trees
  5.  *
  6.  * This file is part of zsh, the Z shell.
  7.  *
  8.  * This software is Copyright 1992 by Paul Falstad
  9.  *
  10.  * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  11.  * use this software as long as: there is no monetary profit gained
  12.  * specifically from the use or reproduction of this software, it is not
  13.  * sold, rented, traded or otherwise marketed, and this copyright notice is
  14.  * included prominently in any copy made.
  15.  *
  16.  * The author make no claims as to the fitness or correctness of this software
  17.  * for any use whatsoever, and it is provided as is. Any use of this software
  18.  * is at the user's own risk.
  19.  *
  20.  */
  21.  
  22. #include "zsh.h"
  23.  
  24. static char *tptr, *tbuf, *tlim;
  25. static int tsiz, tindent, tnewlins;
  26.  
  27. /* add a character to the text buffer */
  28.  
  29. void taddchr(c)            /**/
  30. int c;
  31. {
  32.     *tptr++ = c;
  33.     if (tptr == tlim) {
  34.     if (!tbuf) {
  35.         tptr--;
  36.         return;
  37.     }
  38.     tbuf = realloc(tbuf, tsiz *= 2);
  39.     tlim = tbuf + tsiz;
  40.     tptr = tbuf + tsiz / 2;
  41.     }
  42. }
  43.  
  44. /* add a string to the text buffer */
  45.  
  46. void taddstr(s)            /**/
  47. char *s;
  48. {
  49.     int sl = strlen(s);
  50.  
  51.     while (tptr + sl >= tlim) {
  52.     int x = tptr - tbuf;
  53.  
  54.     if (!tbuf)
  55.         return;
  56.     tbuf = realloc(tbuf, tsiz *= 2);
  57.     tlim = tbuf + tsiz;
  58.     tptr = tbuf + x;
  59.     }
  60.     strcpy(tptr, s);
  61.     tptr += sl;
  62. }
  63.  
  64. /* add an integer to the text buffer */
  65.  
  66. void taddint(x)            /**/
  67. int x;
  68. {
  69.     char buf[10];
  70.  
  71.     sprintf(buf, "%d", x);
  72.     taddstr(buf);
  73. }
  74.  
  75. /* add a newline, or something equivalent, to the text buffer */
  76.  
  77. void taddnl()
  78. {                /**/
  79.     int t0;
  80.  
  81.     if (tnewlins) {
  82.     taddchr('\n');
  83.     for (t0 = 0; t0 != tindent; t0++)
  84.         taddchr('\t');
  85.     } else
  86.     taddstr("; ");
  87. }
  88.  
  89. /* get a permanent textual representation of n */
  90.  
  91. char *getpermtext(n)        /**/
  92. struct node *n;
  93. {
  94.     tnewlins = 1;
  95.     tbuf = (char *)zalloc(tsiz = 32);
  96.     tptr = tbuf;
  97.     tlim = tbuf + tsiz;
  98.     tindent = 1;
  99.     gettext2(n);
  100.     *tptr = '\0';
  101.     untokenize(tbuf);
  102.     return tbuf;
  103. }
  104.  
  105. /* get a representation of n in a job text buffer */
  106.  
  107. char *getjobtext(n)        /**/
  108. struct node *n;
  109. {
  110.     static char jbuf[JOBTEXTSIZE];
  111.  
  112.     tnewlins = 0;
  113.     tbuf = NULL;
  114.     tptr = jbuf;
  115.     tlim = tptr + JOBTEXTSIZE - 1;
  116.     tindent = 1;
  117.     gettext2(n);
  118.     *tptr = '\0';
  119.     untokenize(jbuf);
  120.     return jbuf;
  121. }
  122.  
  123. #define gt2(X) gettext2((struct node *) (X))
  124.  
  125. /*
  126.     "gettext2" or "type checking and how to avoid it"
  127.     an epic function by Paul Falstad
  128. */
  129.  
  130. #define _Cond(X) ((Cond) (X))
  131. #define _Cmd(X) ((Cmd) (X))
  132. #define _Pline(X) ((Pline) (X))
  133. #define _Sublist(X) ((Sublist) (X))
  134. #define _List(X) ((List) (X))
  135. #define _casecmd(X) ((struct casecmd *) (X))
  136. #define _ifcmd(X) ((struct ifcmd *) (X))
  137. #define _whilecmd(X) ((struct whilecmd *) (X))
  138.  
  139. void gettext2(n)        /**/
  140. struct node *n;
  141. {
  142.     Cmd nn;
  143.     Cond nm;
  144.  
  145.     if (!n || ((List) n) == &dummy_list)
  146.     return;
  147.     switch (NT_TYPE(n->type)) {
  148.     case N_LIST:
  149.     gt2(_List(n)->left);
  150.     if (_List(n)->type == ASYNC)
  151.         taddstr(" &");
  152.     simplifyright(_List(n));
  153.     if (_List(n)->right) {
  154.         if (tnewlins)
  155.         taddnl();
  156.         else
  157.         taddstr((_List(n)->type == ASYNC) ? " " : "; ");
  158.         gt2(_List(n)->right);
  159.     }
  160.     break;
  161.     case N_SUBLIST:
  162.     if (_Sublist(n)->flags & PFLAG_NOT)
  163.         taddstr("! ");
  164.     if (_Sublist(n)->flags & PFLAG_COPROC)
  165.         taddstr("coproc ");
  166.     gt2(_Sublist(n)->left);
  167.     if (_Sublist(n)->right) {
  168.         taddstr((_Sublist(n)->type == ORNEXT) ? " || " : " && ");
  169.         gt2(_Sublist(n)->right);
  170.     }
  171.     break;
  172.     case N_PLINE:
  173.     gt2(_Pline(n)->left);
  174.     if (_Pline(n)->type == PIPE) {
  175.         taddstr(" | ");
  176.         gt2(_Pline(n)->right);
  177.     }
  178.     break;
  179.     case N_CMD:
  180.     nn = _Cmd(n);
  181.     if (nn->flags & CFLAG_EXEC)
  182.         taddstr("exec ");
  183.     if (nn->flags & CFLAG_COMMAND)
  184.         taddstr("command ");
  185.     switch (nn->type) {
  186.     case SIMPLE:
  187.         getsimptext(nn);
  188.         break;
  189.     case SUBSH:
  190.         taddstr("( ");
  191.         tindent++;
  192.         gt2(nn->u.list);
  193.         tindent--;
  194.         taddstr(" )");
  195.         break;
  196.     case ZCTIME:
  197.         taddstr("time ");
  198.         tindent++;
  199.         gt2(nn->u.pline);
  200.         tindent--;
  201.         break;
  202.     case FUNCDEF:
  203.         taddlist(nn->args);
  204.         taddstr(" () {");
  205.         tindent++;
  206.         taddnl();
  207.         gt2(nn->u.list);
  208.         tindent--;
  209.         taddnl();
  210.         taddstr("}");
  211.         break;
  212.     case CURSH:
  213.         taddstr("{ ");
  214.         tindent++;
  215.         gt2(nn->u.list);
  216.         tindent--;
  217.         taddstr(" }");
  218.         break;
  219.     case CFOR:
  220.     case CSELECT:
  221.         taddstr((nn->type == CFOR) ? "for " : "select ");
  222.         taddstr(nn->u.forcmd->name);
  223.         if (nn->u.forcmd->inflag) {
  224.         taddstr(" in ");
  225.         taddlist(nn->args);
  226.         }
  227.         taddnl();
  228.         taddstr("do");
  229.         tindent++;
  230.         taddnl();
  231.         gt2(nn->u.forcmd->list);
  232.         tindent--;
  233.         taddnl();
  234.         taddstr("done");
  235.         break;
  236.     case CIF:
  237.         gt2(nn->u.ifcmd);
  238.         taddstr("fi");
  239.         break;
  240.     case CCASE:
  241.         taddstr("case ");
  242.         taddlist(nn->args);
  243.         taddstr(" in");
  244.         tindent++;
  245.         taddnl();
  246.         gt2(nn->u.casecmd);
  247.         tindent--;
  248.         if (tnewlins)
  249.         taddnl();
  250.         else
  251.         taddchr(' ');
  252.         taddstr("esac");
  253.         break;
  254.     case COND:
  255.         taddstr("[[ ");
  256.         gt2(nn->u.cond);
  257.         taddstr(" ]]");
  258.         break;
  259.     case CREPEAT:
  260.         taddstr("repeat ");
  261.         taddlist(nn->args);
  262.         taddnl();
  263.         taddstr("do");
  264.         tindent++;
  265.         taddnl();
  266.         gt2(nn->u.list);
  267.         tindent--;
  268.         taddnl();
  269.         taddstr("done");
  270.         break;
  271.     case CWHILE:
  272.         gt2(nn->u.whilecmd);
  273.         break;
  274.     }
  275.     getredirs(nn);
  276.     break;
  277.     case N_COND:
  278.     nm = _Cond(n);
  279.     switch (nm->type) {
  280.     case COND_NOT:
  281.         taddstr("! ");
  282.         gt2(nm->left);
  283.         break;
  284.     case COND_AND:
  285.         taddstr("( ");
  286.         gt2(nm->left);
  287.         taddstr(" && ");
  288.         gt2(nm->right);
  289.         taddstr(" )");
  290.         break;
  291.     case COND_OR:
  292.         taddstr("( ");
  293.         gt2(nm->left);
  294.         taddstr(" || ");
  295.         gt2(nm->right);
  296.         taddstr(" )");
  297.         break;
  298.     default:
  299.         {
  300.         static char *c1[] =
  301.         {
  302.             " = ", " != ", " < ", " > ", " -nt ", " -ot ", " -ef ", " -eq ",
  303.             " -ne ", " -lt ", " -gt ", " -le ", " -ge "
  304.         };
  305.  
  306.         if (nm->right)
  307.             taddstr(nm->left);
  308.         if (nm->type <= COND_GE)
  309.             taddstr(c1[nm->type - COND_STREQ]);
  310.         else {
  311.             char c2[5];
  312.  
  313.             c2[0] = ' ';
  314.             c2[1] = '-';
  315.             c2[2] = nm->type;
  316.             c2[3] = ' ';
  317.             c2[4] = '\0';
  318.             taddstr(c2);
  319.         }
  320.         taddstr((nm->right) ? nm->right : nm->left);
  321.         }
  322.         break;
  323.     }
  324.     break;
  325.     case N_CASE:
  326.     {
  327.         List *l;
  328.         char **p;
  329.  
  330.         l = _casecmd(n)->lists;
  331.         p = _casecmd(n)->pats;
  332.  
  333.         for (; *l; p++, l++) {
  334.         taddstr(*p);
  335.         taddstr(") ");
  336.         tindent++;
  337.         gt2(*l);
  338.         tindent--;
  339.         taddstr(";;");
  340.         if (tnewlins)
  341.             taddnl();
  342.         else
  343.             taddchr(' ');
  344.         }
  345.         break;
  346.     }
  347.     case N_IF:
  348.     {
  349.         List *i, *t;
  350.  
  351.         taddstr("if ");
  352.         for (i = _ifcmd(n)->ifls, t = _ifcmd(n)->thenls; *i; i++, t++) {
  353.         tindent++;
  354.         gt2(*i);
  355.         tindent--;
  356.         taddnl();
  357.         taddstr("then");
  358.         tindent++;
  359.         taddnl();
  360.         gt2(*t);
  361.         tindent--;
  362.         taddnl();
  363.         if (i[1]) {
  364.             taddstr("elif");
  365.             taddnl();
  366.         }
  367.         }
  368.         if (*t) {
  369.         taddstr("else");
  370.         tindent++;
  371.         taddnl();
  372.         gt2(*t);
  373.         tindent--;
  374.         taddnl();
  375.         }
  376.         break;
  377.     }
  378.     case N_WHILE:
  379.     taddstr((_whilecmd(n)->cond) ? "until " : "while ");
  380.     tindent++;
  381.     gt2(_whilecmd(n)->cont);
  382.     tindent--;
  383.     taddnl();
  384.     taddstr("do");
  385.     tindent++;
  386.     taddnl();
  387.     gt2(_whilecmd(n)->loop);
  388.     tindent--;
  389.     taddnl();
  390.     taddstr("done");
  391.     break;
  392.     }
  393. }
  394.  
  395. void getsimptext(cmd)        /**/
  396. Cmd cmd;
  397. {
  398.     Lknode n;
  399.  
  400.     for (n = firstnode(cmd->vars); n; incnode(n)) {
  401.     struct varasg *v = (struct varasg *)getdata(n);
  402.  
  403.     taddstr(v->name);
  404.     taddchr('=');
  405.     if ((v->type & PMTYPE) == PMFLAG_A) {
  406.         taddchr('(');
  407.         taddlist(v->arr);
  408.         taddstr(") ");
  409.     } else {
  410.         taddstr(v->str);
  411.         taddchr(' ');
  412.     }
  413.     }
  414.     taddlist(cmd->args);
  415. }
  416.  
  417. void getredirs(cmd)        /**/
  418. Cmd cmd;
  419. {
  420.     Lknode n;
  421.     static char *fstr[] =
  422.     {
  423.     ">", ">!", ">>", ">>!", ">&", ">&!", ">>&", ">>&!", "<", "<<",
  424.     "<<-", "<<<", "<&", ">&-", "..", ".."
  425.     };
  426.  
  427.     taddchr(' ');
  428.     for (n = firstnode(cmd->redir); n; incnode(n)) {
  429.     struct redir *f = (struct redir *)getdata(n);
  430.  
  431.     switch (f->type) {
  432.     case WRITE:
  433.     case WRITENOW:
  434.     case APP:
  435.     case APPNOW:
  436.     case READ:
  437.     case HERESTR:
  438.         if (f->fd1 != ((f->type == READ) ? 0 : 1))
  439.         taddchr('0' + f->fd1);
  440.         taddstr(fstr[f->type]);
  441.         taddchr(' ');
  442.         taddstr(f->name);
  443.         taddchr(' ');
  444.         break;
  445.     case MERGE:
  446.     case MERGEOUT:
  447.         if (f->fd1 != ((f->type == MERGEOUT) ? 1 : 0))
  448.         taddchr('0' + f->fd1);
  449.         taddstr(fstr[f->type]);
  450.         if (f->fd2 == FD_COPROC)
  451.         taddchr('p');
  452.         else
  453.         taddint(f->fd2);
  454.         taddchr(' ');
  455.         break;
  456.     case CLOSE:
  457.         taddchr(f->fd1 + '0');
  458.         taddstr(">&- ");
  459.         break;
  460.     case INPIPE:
  461.     case OUTPIPE:
  462.         if (f->fd1 != ((f->type == INPIPE) ? 0 : 1))
  463.         taddchr('0' + f->fd1);
  464.         taddstr((f->type == INPIPE) ? "< " : "> ");
  465.         taddstr(f->name);
  466.         taddchr(' ');
  467.         break;
  468.     }
  469.     }
  470.     tptr--;
  471. }
  472.  
  473. void taddlist(l)        /**/
  474. Lklist l;
  475. {
  476.     Lknode n;
  477.  
  478.     if (!(n = firstnode(l)))
  479.     return;
  480.     for (; n; incnode(n)) {
  481.     taddstr(getdata(n));
  482.     taddchr(' ');
  483.     }
  484.     tptr--;
  485. }
  486.