home *** CD-ROM | disk | FTP | other *** search
- /*
- * $Id: text.c,v 2.6 1996/10/15 20:16:35 hzoli Exp $
- *
- * text.c - textual representations of syntax trees
- *
- * This file is part of zsh, the Z shell.
- *
- * Copyright (c) 1992-1996 Paul Falstad
- * All rights reserved.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and to distribute modified versions of this software for any
- * purpose, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * In no event shall Paul Falstad or the Zsh Development Group be liable
- * to any party for direct, indirect, special, incidental, or consequential
- * damages arising out of the use of this software and its documentation,
- * even if Paul Falstad and the Zsh Development Group have been advised of
- * the possibility of such damage.
- *
- * Paul Falstad and the Zsh Development Group specifically disclaim any
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose. The software
- * provided hereunder is on an "as is" basis, and Paul Falstad and the
- * Zsh Development Group have no obligation to provide maintenance,
- * support, updates, enhancements, or modifications.
- *
- */
-
- #include "zsh.h"
-
- static char *tptr, *tbuf, *tlim;
- static int tsiz, tindent, tnewlins;
-
- /* add a character to the text buffer */
-
- /**/
- void
- taddchr(int c)
- {
- *tptr++ = c;
- if (tptr == tlim) {
- if (!tbuf) {
- tptr--;
- return;
- }
- tbuf = realloc(tbuf, tsiz *= 2);
- tlim = tbuf + tsiz;
- tptr = tbuf + tsiz / 2;
- }
- }
-
- /* add a string to the text buffer */
-
- /**/
- void
- taddstr(char *s)
- {
- int sl = strlen(s);
-
- while (tptr + sl >= tlim) {
- int x = tptr - tbuf;
-
- if (!tbuf)
- return;
- tbuf = realloc(tbuf, tsiz *= 2);
- tlim = tbuf + tsiz;
- tptr = tbuf + x;
- }
- strcpy(tptr, s);
- tptr += sl;
- }
-
- /* add an integer to the text buffer */
-
- /**/
- void
- taddint(int x)
- {
- char buf[DIGBUFSIZE];
-
- sprintf(buf, "%d", x);
- taddstr(buf);
- }
-
- /* add a newline, or something equivalent, to the text buffer */
-
- /**/
- void
- taddnl(void)
- {
- int t0;
-
- if (tnewlins) {
- taddchr('\n');
- for (t0 = 0; t0 != tindent; t0++)
- taddchr('\t');
- } else
- taddstr("; ");
- }
-
- /* get a permanent textual representation of n */
-
- /**/
- char *
- getpermtext(struct node *n)
- {
- tnewlins = 1;
- tbuf = (char *)zalloc(tsiz = 32);
- tptr = tbuf;
- tlim = tbuf + tsiz;
- tindent = 1;
- gettext2(n);
- *tptr = '\0';
- untokenize(tbuf);
- return tbuf;
- }
-
- /* get a representation of n in a job text buffer */
-
- /**/
- char *
- getjobtext(struct node *n)
- {
- static char jbuf[JOBTEXTSIZE];
-
- tnewlins = 0;
- tbuf = NULL;
- tptr = jbuf;
- tlim = tptr + JOBTEXTSIZE - 1;
- tindent = 1;
- gettext2(n);
- *tptr = '\0';
- untokenize(jbuf);
- return jbuf;
- }
-
- #define gt2(X) gettext2((struct node *) (X))
-
- /*
- "gettext2" or "type checking and how to avoid it"
- an epic function by Paul Falstad
- */
-
- #define _Cond(X) ((Cond) (X))
- #define _Cmd(X) ((Cmd) (X))
- #define _Pline(X) ((Pline) (X))
- #define _Sublist(X) ((Sublist) (X))
- #define _List(X) ((List) (X))
- #define _casecmd(X) ((struct casecmd *) (X))
- #define _ifcmd(X) ((struct ifcmd *) (X))
- #define _whilecmd(X) ((struct whilecmd *) (X))
-
- /**/
- void
- gettext2(struct node *n)
- {
- Cmd nn;
-
- if (!n || ((List) n) == &dummy_list)
- return;
- switch (NT_TYPE(n->ntype)) {
- case N_LIST:
- gt2(_List(n)->left);
- if (_List(n)->type & Z_ASYNC) {
- taddstr(" &");
- if (_List(n)->type & Z_DISOWN)
- taddstr("|");
- }
- simplifyright(_List(n));
- if (_List(n)->right) {
- if (tnewlins)
- taddnl();
- else
- taddstr((_List(n)->type & Z_ASYNC) ? " " : "; ");
- gt2(_List(n)->right);
- }
- break;
- case N_SUBLIST:
- if (_Sublist(n)->flags & PFLAG_NOT)
- taddstr("! ");
- if (_Sublist(n)->flags & PFLAG_COPROC)
- taddstr("coproc ");
- gt2(_Sublist(n)->left);
- if (_Sublist(n)->right) {
- taddstr((_Sublist(n)->type == ORNEXT) ? " || " : " && ");
- gt2(_Sublist(n)->right);
- }
- break;
- case N_PLINE:
- gt2(_Pline(n)->left);
- if (_Pline(n)->type == PIPE) {
- taddstr(" | ");
- gt2(_Pline(n)->right);
- }
- break;
- case N_CMD:
- nn = _Cmd(n);
- switch (nn->type) {
- case SIMPLE:
- getsimptext(nn);
- break;
- case SUBSH:
- taddstr("( ");
- tindent++;
- gt2(nn->u.list);
- tindent--;
- taddstr(" )");
- break;
- case ZCTIME:
- taddstr("time ");
- tindent++;
- gt2(nn->u.pline);
- tindent--;
- break;
- case FUNCDEF:
- taddlist(nn->args);
- taddstr(" () {");
- tindent++;
- taddnl();
- gt2(nn->u.list);
- tindent--;
- taddnl();
- taddstr("}");
- break;
- case CURSH:
- taddstr("{ ");
- tindent++;
- gt2(nn->u.list);
- tindent--;
- taddstr(" }");
- break;
- case CFOR:
- case CSELECT:
- taddstr((nn->type == CFOR) ? "for " : "select ");
- taddstr(nn->u.forcmd->name);
- if (nn->u.forcmd->inflag) {
- taddstr(" in ");
- taddlist(nn->args);
- }
- taddnl();
- taddstr("do");
- tindent++;
- taddnl();
- gt2(nn->u.forcmd->list);
- tindent--;
- taddnl();
- taddstr("done");
- break;
- case CIF:
- gt2(nn->u.ifcmd);
- taddstr("fi");
- break;
- case CCASE:
- gt2(nn->u.casecmd);
- break;
- case COND:
- taddstr("[[ ");
- gt2(nn->u.cond);
- taddstr(" ]]");
- break;
- case CARITH:
- taddstr("((");
- taddlist(nn->args);
- taddstr("))");
- break;
- case CREPEAT:
- taddstr("repeat ");
- taddlist(nn->args);
- taddnl();
- taddstr("do");
- tindent++;
- taddnl();
- gt2(nn->u.list);
- tindent--;
- taddnl();
- taddstr("done");
- break;
- case CWHILE:
- gt2(nn->u.whilecmd);
- break;
- }
- getredirs(nn);
- break;
- case N_COND:
- getcond(_Cond(n), 0);
- break;
- case N_CASE:
- {
- List *l;
- char **p;
-
- l = _casecmd(n)->lists;
- p = _casecmd(n)->pats;
-
- taddstr("case ");
- taddstr(*p++);
- taddstr(" in");
- tindent++;
- for (; *l; p++, l++) {
- if (tnewlins)
- taddnl();
- else
- taddchr(' ');
- taddstr(*p);
- taddstr(") ");
- tindent++;
- gt2(*l);
- tindent--;
- taddstr(" ;;");
- }
- tindent--;
- if (tnewlins)
- taddnl();
- else
- taddchr(' ');
- taddstr("esac");
- break;
- }
- case N_IF:
- {
- List *i, *t;
-
- taddstr("if ");
- for (i = _ifcmd(n)->ifls, t = _ifcmd(n)->thenls; *i; i++, t++) {
- tindent++;
- gt2(*i);
- tindent--;
- taddnl();
- taddstr("then");
- tindent++;
- taddnl();
- gt2(*t);
- tindent--;
- taddnl();
- if (i[1]) {
- taddstr("elif ");
- }
- }
- if (*t) {
- taddstr("else");
- tindent++;
- taddnl();
- gt2(*t);
- tindent--;
- taddnl();
- }
- break;
- }
- case N_WHILE:
- taddstr((_whilecmd(n)->cond) ? "until " : "while ");
- tindent++;
- gt2(_whilecmd(n)->cont);
- tindent--;
- taddnl();
- taddstr("do");
- tindent++;
- taddnl();
- gt2(_whilecmd(n)->loop);
- tindent--;
- taddnl();
- taddstr("done");
- break;
- }
- }
-
- /* Print a condition bracketed by [[ ... ]]. *
- * With addpar non-zero, parenthesise the subexpression. */
-
- /**/
- void
- getcond(Cond nm, int addpar)
- {
- static char *c1[] =
- {
- "=", "!=", "<", ">", "-nt", "-ot", "-ef", "-eq",
- "-ne", "-lt", "-gt", "-le", "-ge"
- };
-
- if (addpar)
- taddstr("( ");
- switch (nm->type) {
- case COND_NOT:
- taddstr("! ");
- getcond(nm->left, _Cond(nm->left)->type <= COND_OR);
- break;
- case COND_AND:
- getcond(nm->left, _Cond(nm->left)->type == COND_OR);
- taddstr(" && ");
- getcond(nm->right, _Cond(nm->right)->type == COND_OR);
- break;
- case COND_OR:
- /* This is deliberately over-generous with parentheses: *
- * in fact omitting them gives correct precedence. */
- getcond(nm->left, _Cond(nm->left)->type == COND_AND);
- taddstr(" || ");
- getcond(nm->right, _Cond(nm->right)->type == COND_AND);
- break;
- default:
- if (nm->type <= COND_GE) {
- /* Binary test: `a = b' etc. */
- taddstr(nm->left);
- taddstr(" ");
- taddstr(c1[nm->type - COND_STREQ]);
- taddstr(" ");
- taddstr(nm->right);
- } else {
- /* Unary test: `-f foo' etc. */
- char c2[4];
-
- c2[0] = '-';
- c2[1] = nm->type;
- c2[2] = ' ';
- c2[3] = '\0';
- taddstr(c2);
- taddstr(nm->left);
- }
- break;
- }
- if (addpar)
- taddstr(" )");
- }
-
- /**/
- void
- getsimptext(Cmd cmd)
- {
- LinkNode n;
-
- for (n = firstnode(cmd->vars); n; incnode(n)) {
- struct varasg *v = (struct varasg *)getdata(n);
-
- taddstr(v->name);
- taddchr('=');
- if (PM_TYPE(v->type) == PM_ARRAY) {
- taddchr('(');
- taddlist(v->arr);
- taddstr(") ");
- } else {
- taddstr(v->str);
- taddchr(' ');
- }
- }
- taddlist(cmd->args);
- }
-
- /**/
- void
- getredirs(Cmd cmd)
- {
- LinkNode n;
- static char *fstr[] =
- {
- ">", ">|", ">>", ">>|", "&>", "&>|", "&>>", "&>>|", "<", "<>",
- "<<", "<<-", "<<<", "<&", ">&", NULL /* >&- */, "<", ">"
- };
-
- taddchr(' ');
- for (n = firstnode(cmd->redir); n; incnode(n)) {
- struct redir *f = (struct redir *)getdata(n);
-
- switch (f->type) {
- case WRITE:
- case WRITENOW:
- case APP:
- case APPNOW:
- case ERRWRITE:
- case ERRWRITENOW:
- case ERRAPP:
- case ERRAPPNOW:
- case READ:
- case READWRITE:
- case HERESTR:
- case MERGEIN:
- case MERGEOUT:
- case INPIPE:
- case OUTPIPE:
- if (f->fd1 != (IS_READFD(f->type) ? 0 : 1))
- taddchr('0' + f->fd1);
- taddstr(fstr[f->type]);
- taddchr(' ');
- taddstr(f->name);
- taddchr(' ');
- break;
- #ifdef DEBUG
- case CLOSE:
- DPUTS(1, "What? CLOSE in getredirs?");
- taddchr(f->fd1 + '0');
- taddstr(">&- ");
- break;
- default:
- DPUTS(1, "unknown redirection in getredirs()");
- #endif
- }
- }
- tptr--;
- }
-
- /**/
- void
- taddlist(LinkList l)
- {
- LinkNode n;
-
- if (!(n = firstnode(l)))
- return;
- for (; n; incnode(n)) {
- taddstr(getdata(n));
- taddchr(' ');
- }
- tptr--;
- }
-