home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Shells / zsh-3.0.5-MIHS / src / Src / text.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-03  |  9.6 KB  |  515 lines

  1. /*
  2.  * $Id: text.c,v 2.6 1996/10/15 20:16:35 hzoli Exp $
  3.  *
  4.  * text.c - textual representations of syntax trees
  5.  *
  6.  * This file is part of zsh, the Z shell.
  7.  *
  8.  * Copyright (c) 1992-1996 Paul Falstad
  9.  * All rights reserved.
  10.  *
  11.  * Permission is hereby granted, without written agreement and without
  12.  * license or royalty fees, to use, copy, modify, and distribute this
  13.  * software and to distribute modified versions of this software for any
  14.  * purpose, provided that the above copyright notice and the following
  15.  * two paragraphs appear in all copies of this software.
  16.  *
  17.  * In no event shall Paul Falstad or the Zsh Development Group be liable
  18.  * to any party for direct, indirect, special, incidental, or consequential
  19.  * damages arising out of the use of this software and its documentation,
  20.  * even if Paul Falstad and the Zsh Development Group have been advised of
  21.  * the possibility of such damage.
  22.  *
  23.  * Paul Falstad and the Zsh Development Group specifically disclaim any
  24.  * warranties, including, but not limited to, the implied warranties of
  25.  * merchantability and fitness for a particular purpose.  The software
  26.  * provided hereunder is on an "as is" basis, and Paul Falstad and the
  27.  * Zsh Development Group have no obligation to provide maintenance,
  28.  * support, updates, enhancements, or modifications.
  29.  *
  30.  */
  31.  
  32. #include "zsh.h"
  33.  
  34. static char *tptr, *tbuf, *tlim;
  35. static int tsiz, tindent, tnewlins;
  36.  
  37. /* add a character to the text buffer */
  38.  
  39. /**/
  40. void
  41. taddchr(int c)
  42. {
  43.     *tptr++ = c;
  44.     if (tptr == tlim) {
  45.     if (!tbuf) {
  46.         tptr--;
  47.         return;
  48.     }
  49.     tbuf = realloc(tbuf, tsiz *= 2);
  50.     tlim = tbuf + tsiz;
  51.     tptr = tbuf + tsiz / 2;
  52.     }
  53. }
  54.  
  55. /* add a string to the text buffer */
  56.  
  57. /**/
  58. void
  59. taddstr(char *s)
  60. {
  61.     int sl = strlen(s);
  62.  
  63.     while (tptr + sl >= tlim) {
  64.     int x = tptr - tbuf;
  65.  
  66.     if (!tbuf)
  67.         return;
  68.     tbuf = realloc(tbuf, tsiz *= 2);
  69.     tlim = tbuf + tsiz;
  70.     tptr = tbuf + x;
  71.     }
  72.     strcpy(tptr, s);
  73.     tptr += sl;
  74. }
  75.  
  76. /* add an integer to the text buffer */
  77.  
  78. /**/
  79. void
  80. taddint(int x)
  81. {
  82.     char buf[DIGBUFSIZE];
  83.  
  84.     sprintf(buf, "%d", x);
  85.     taddstr(buf);
  86. }
  87.  
  88. /* add a newline, or something equivalent, to the text buffer */
  89.  
  90. /**/
  91. void
  92. taddnl(void)
  93. {
  94.     int t0;
  95.  
  96.     if (tnewlins) {
  97.     taddchr('\n');
  98.     for (t0 = 0; t0 != tindent; t0++)
  99.         taddchr('\t');
  100.     } else
  101.     taddstr("; ");
  102. }
  103.  
  104. /* get a permanent textual representation of n */
  105.  
  106. /**/
  107. char *
  108. getpermtext(struct node *n)
  109. {
  110.     tnewlins = 1;
  111.     tbuf = (char *)zalloc(tsiz = 32);
  112.     tptr = tbuf;
  113.     tlim = tbuf + tsiz;
  114.     tindent = 1;
  115.     gettext2(n);
  116.     *tptr = '\0';
  117.     untokenize(tbuf);
  118.     return tbuf;
  119. }
  120.  
  121. /* get a representation of n in a job text buffer */
  122.  
  123. /**/
  124. char *
  125. getjobtext(struct node *n)
  126. {
  127.     static char jbuf[JOBTEXTSIZE];
  128.  
  129.     tnewlins = 0;
  130.     tbuf = NULL;
  131.     tptr = jbuf;
  132.     tlim = tptr + JOBTEXTSIZE - 1;
  133.     tindent = 1;
  134.     gettext2(n);
  135.     *tptr = '\0';
  136.     untokenize(jbuf);
  137.     return jbuf;
  138. }
  139.  
  140. #define gt2(X) gettext2((struct node *) (X))
  141.  
  142. /*
  143.     "gettext2" or "type checking and how to avoid it"
  144.     an epic function by Paul Falstad
  145. */
  146.  
  147. #define _Cond(X) ((Cond) (X))
  148. #define _Cmd(X) ((Cmd) (X))
  149. #define _Pline(X) ((Pline) (X))
  150. #define _Sublist(X) ((Sublist) (X))
  151. #define _List(X) ((List) (X))
  152. #define _casecmd(X) ((struct casecmd *) (X))
  153. #define _ifcmd(X) ((struct ifcmd *) (X))
  154. #define _whilecmd(X) ((struct whilecmd *) (X))
  155.  
  156. /**/
  157. void
  158. gettext2(struct node *n)
  159. {
  160.     Cmd nn;
  161.  
  162.     if (!n || ((List) n) == &dummy_list)
  163.     return;
  164.     switch (NT_TYPE(n->ntype)) {
  165.     case N_LIST:
  166.     gt2(_List(n)->left);
  167.     if (_List(n)->type & Z_ASYNC) {
  168.         taddstr(" &");
  169.         if (_List(n)->type & Z_DISOWN)
  170.         taddstr("|");
  171.     }
  172.     simplifyright(_List(n));
  173.     if (_List(n)->right) {
  174.         if (tnewlins)
  175.         taddnl();
  176.         else
  177.         taddstr((_List(n)->type & Z_ASYNC) ? " " : "; ");
  178.         gt2(_List(n)->right);
  179.     }
  180.     break;
  181.     case N_SUBLIST:
  182.     if (_Sublist(n)->flags & PFLAG_NOT)
  183.         taddstr("! ");
  184.     if (_Sublist(n)->flags & PFLAG_COPROC)
  185.         taddstr("coproc ");
  186.     gt2(_Sublist(n)->left);
  187.     if (_Sublist(n)->right) {
  188.         taddstr((_Sublist(n)->type == ORNEXT) ? " || " : " && ");
  189.         gt2(_Sublist(n)->right);
  190.     }
  191.     break;
  192.     case N_PLINE:
  193.     gt2(_Pline(n)->left);
  194.     if (_Pline(n)->type == PIPE) {
  195.         taddstr(" | ");
  196.         gt2(_Pline(n)->right);
  197.     }
  198.     break;
  199.     case N_CMD:
  200.     nn = _Cmd(n);
  201.     switch (nn->type) {
  202.     case SIMPLE:
  203.         getsimptext(nn);
  204.         break;
  205.     case SUBSH:
  206.         taddstr("( ");
  207.         tindent++;
  208.         gt2(nn->u.list);
  209.         tindent--;
  210.         taddstr(" )");
  211.         break;
  212.     case ZCTIME:
  213.         taddstr("time ");
  214.         tindent++;
  215.         gt2(nn->u.pline);
  216.         tindent--;
  217.         break;
  218.     case FUNCDEF:
  219.         taddlist(nn->args);
  220.         taddstr(" () {");
  221.         tindent++;
  222.         taddnl();
  223.         gt2(nn->u.list);
  224.         tindent--;
  225.         taddnl();
  226.         taddstr("}");
  227.         break;
  228.     case CURSH:
  229.         taddstr("{ ");
  230.         tindent++;
  231.         gt2(nn->u.list);
  232.         tindent--;
  233.         taddstr(" }");
  234.         break;
  235.     case CFOR:
  236.     case CSELECT:
  237.         taddstr((nn->type == CFOR) ? "for " : "select ");
  238.         taddstr(nn->u.forcmd->name);
  239.         if (nn->u.forcmd->inflag) {
  240.         taddstr(" in ");
  241.         taddlist(nn->args);
  242.         }
  243.         taddnl();
  244.         taddstr("do");
  245.         tindent++;
  246.         taddnl();
  247.         gt2(nn->u.forcmd->list);
  248.         tindent--;
  249.         taddnl();
  250.         taddstr("done");
  251.         break;
  252.     case CIF:
  253.         gt2(nn->u.ifcmd);
  254.         taddstr("fi");
  255.         break;
  256.     case CCASE:
  257.         gt2(nn->u.casecmd);
  258.         break;
  259.     case COND:
  260.         taddstr("[[ ");
  261.         gt2(nn->u.cond);
  262.         taddstr(" ]]");
  263.         break;
  264.     case CARITH:
  265.         taddstr("((");
  266.         taddlist(nn->args);
  267.         taddstr("))");
  268.         break;
  269.     case CREPEAT:
  270.         taddstr("repeat ");
  271.         taddlist(nn->args);
  272.         taddnl();
  273.         taddstr("do");
  274.         tindent++;
  275.         taddnl();
  276.         gt2(nn->u.list);
  277.         tindent--;
  278.         taddnl();
  279.         taddstr("done");
  280.         break;
  281.     case CWHILE:
  282.         gt2(nn->u.whilecmd);
  283.         break;
  284.     }
  285.     getredirs(nn);
  286.     break;
  287.     case N_COND:
  288.     getcond(_Cond(n), 0);
  289.     break;
  290.     case N_CASE:
  291.     {
  292.         List *l;
  293.         char **p;
  294.  
  295.         l = _casecmd(n)->lists;
  296.         p = _casecmd(n)->pats;
  297.  
  298.         taddstr("case ");
  299.         taddstr(*p++);
  300.         taddstr(" in");
  301.         tindent++;
  302.         for (; *l; p++, l++) {
  303.         if (tnewlins)
  304.             taddnl();
  305.         else
  306.             taddchr(' ');
  307.         taddstr(*p);
  308.         taddstr(") ");
  309.         tindent++;
  310.         gt2(*l);
  311.         tindent--;
  312.         taddstr(" ;;");
  313.         }
  314.         tindent--;
  315.         if (tnewlins)
  316.         taddnl();
  317.         else
  318.         taddchr(' ');
  319.         taddstr("esac");
  320.         break;
  321.     }
  322.     case N_IF:
  323.     {
  324.         List *i, *t;
  325.  
  326.         taddstr("if ");
  327.         for (i = _ifcmd(n)->ifls, t = _ifcmd(n)->thenls; *i; i++, t++) {
  328.         tindent++;
  329.         gt2(*i);
  330.         tindent--;
  331.         taddnl();
  332.         taddstr("then");
  333.         tindent++;
  334.         taddnl();
  335.         gt2(*t);
  336.         tindent--;
  337.         taddnl();
  338.         if (i[1]) {
  339.             taddstr("elif ");
  340.         }
  341.         }
  342.         if (*t) {
  343.         taddstr("else");
  344.         tindent++;
  345.         taddnl();
  346.         gt2(*t);
  347.         tindent--;
  348.         taddnl();
  349.         }
  350.         break;
  351.     }
  352.     case N_WHILE:
  353.     taddstr((_whilecmd(n)->cond) ? "until " : "while ");
  354.     tindent++;
  355.     gt2(_whilecmd(n)->cont);
  356.     tindent--;
  357.     taddnl();
  358.     taddstr("do");
  359.     tindent++;
  360.     taddnl();
  361.     gt2(_whilecmd(n)->loop);
  362.     tindent--;
  363.     taddnl();
  364.     taddstr("done");
  365.     break;
  366.     }
  367. }
  368.  
  369. /* Print a condition bracketed by [[ ... ]].             *
  370.  * With addpar non-zero, parenthesise the subexpression. */
  371.  
  372. /**/
  373. void
  374. getcond(Cond nm, int addpar)
  375. {
  376.     static char *c1[] =
  377.     {
  378.     "=", "!=", "<", ">", "-nt", "-ot", "-ef", "-eq",
  379.     "-ne", "-lt", "-gt", "-le", "-ge"
  380.     };
  381.  
  382.     if (addpar)
  383.     taddstr("( ");
  384.     switch (nm->type) {
  385.     case COND_NOT:
  386.     taddstr("! ");
  387.     getcond(nm->left, _Cond(nm->left)->type <= COND_OR);
  388.     break;
  389.     case COND_AND:
  390.     getcond(nm->left, _Cond(nm->left)->type == COND_OR);
  391.     taddstr(" && ");
  392.     getcond(nm->right, _Cond(nm->right)->type == COND_OR);
  393.     break;
  394.     case COND_OR:
  395.     /* This is deliberately over-generous with parentheses: *
  396.      * in fact omitting them gives correct precedence.      */
  397.     getcond(nm->left, _Cond(nm->left)->type == COND_AND);
  398.     taddstr(" || ");
  399.     getcond(nm->right, _Cond(nm->right)->type == COND_AND);
  400.     break;
  401.     default:
  402.     if (nm->type <= COND_GE) {
  403.         /* Binary test: `a = b' etc. */
  404.         taddstr(nm->left);
  405.         taddstr(" ");
  406.         taddstr(c1[nm->type - COND_STREQ]);
  407.         taddstr(" ");
  408.         taddstr(nm->right);
  409.     } else {
  410.         /* Unary test: `-f foo' etc. */ 
  411.         char c2[4];
  412.  
  413.         c2[0] = '-';
  414.         c2[1] = nm->type;
  415.         c2[2] = ' ';
  416.         c2[3] = '\0';
  417.         taddstr(c2);
  418.         taddstr(nm->left);
  419.     }
  420.     break;
  421.     }
  422.     if (addpar)
  423.     taddstr(" )");
  424. }
  425.  
  426. /**/
  427. void
  428. getsimptext(Cmd cmd)
  429. {
  430.     LinkNode n;
  431.  
  432.     for (n = firstnode(cmd->vars); n; incnode(n)) {
  433.     struct varasg *v = (struct varasg *)getdata(n);
  434.  
  435.     taddstr(v->name);
  436.     taddchr('=');
  437.     if (PM_TYPE(v->type) == PM_ARRAY) {
  438.         taddchr('(');
  439.         taddlist(v->arr);
  440.         taddstr(") ");
  441.     } else {
  442.         taddstr(v->str);
  443.         taddchr(' ');
  444.     }
  445.     }
  446.     taddlist(cmd->args);
  447. }
  448.  
  449. /**/
  450. void
  451. getredirs(Cmd cmd)
  452. {
  453.     LinkNode n;
  454.     static char *fstr[] =
  455.     {
  456.     ">", ">|", ">>", ">>|", "&>", "&>|", "&>>", "&>>|", "<", "<>",
  457.     "<<", "<<-", "<<<", "<&", ">&", NULL /* >&- */, "<", ">"
  458.     };
  459.  
  460.     taddchr(' ');
  461.     for (n = firstnode(cmd->redir); n; incnode(n)) {
  462.     struct redir *f = (struct redir *)getdata(n);
  463.  
  464.     switch (f->type) {
  465.     case WRITE:
  466.     case WRITENOW:
  467.     case APP:
  468.     case APPNOW:
  469.     case ERRWRITE:
  470.     case ERRWRITENOW:
  471.     case ERRAPP:
  472.     case ERRAPPNOW:
  473.     case READ:
  474.     case READWRITE:
  475.     case HERESTR:
  476.     case MERGEIN:
  477.     case MERGEOUT:
  478.     case INPIPE:
  479.     case OUTPIPE:
  480.         if (f->fd1 != (IS_READFD(f->type) ? 0 : 1))
  481.         taddchr('0' + f->fd1);
  482.         taddstr(fstr[f->type]);
  483.         taddchr(' ');
  484.         taddstr(f->name);
  485.         taddchr(' ');
  486.         break;
  487. #ifdef DEBUG
  488.     case CLOSE:
  489.         DPUTS(1, "What?  CLOSE in getredirs?");
  490.         taddchr(f->fd1 + '0');
  491.         taddstr(">&- ");
  492.         break;
  493.     default:
  494.         DPUTS(1, "unknown redirection in getredirs()");
  495. #endif
  496.     }
  497.     }
  498.     tptr--;
  499. }
  500.  
  501. /**/
  502. void
  503. taddlist(LinkList l)
  504. {
  505.     LinkNode n;
  506.  
  507.     if (!(n = firstnode(l)))
  508.     return;
  509.     for (; n; incnode(n)) {
  510.     taddstr(getdata(n));
  511.     taddchr(' ');
  512.     }
  513.     tptr--;
  514. }
  515.