Blame src/cmd/ksh93/sh/deparse.c

Packit 992a25
/***********************************************************************
Packit 992a25
*                                                                      *
Packit 992a25
*               This software is part of the ast package               *
Packit 992a25
*          Copyright (c) 1982-2011 AT&T Intellectual Property          *
Packit 992a25
*                      and is licensed under the                       *
Packit 992a25
*                 Eclipse Public License, Version 1.0                  *
Packit 992a25
*                    by AT&T Intellectual Property                     *
Packit 992a25
*                                                                      *
Packit 992a25
*                A copy of the License is available at                 *
Packit 992a25
*          http://www.eclipse.org/org/documents/epl-v10.html           *
Packit 992a25
*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
Packit 992a25
*                                                                      *
Packit 992a25
*              Information and Software Systems Research               *
Packit 992a25
*                            AT&T Research                             *
Packit 992a25
*                           Florham Park NJ                            *
Packit 992a25
*                                                                      *
Packit 992a25
*                  David Korn <dgk@research.att.com>                   *
Packit 992a25
*                                                                      *
Packit 992a25
***********************************************************************/
Packit 992a25
#pragma prototyped
Packit 992a25
/*
Packit 992a25
 * David Korn
Packit 992a25
 * AT&T Labs
Packit 992a25
 *
Packit 992a25
 * shell deparser
Packit 992a25
 *
Packit 992a25
 */
Packit 992a25
Packit 992a25
#include	"defs.h"
Packit 992a25
#include	"shnodes.h"
Packit 992a25
#include	"test.h"
Packit 992a25
Packit 992a25
Packit 992a25
#define HUGE_INT	(((unsigned)-1)>>1)
Packit 992a25
#define	BEGIN	0
Packit 992a25
#define MIDDLE	1
Packit 992a25
#define	END	2
Packit 992a25
#define PRE	1
Packit 992a25
#define POST	2
Packit 992a25
Packit 992a25
Packit 992a25
/* flags that can be specified with p_tree() */
Packit 992a25
#define NO_NEWLINE	1
Packit 992a25
#define NEED_BRACE	2
Packit 992a25
#define NO_BRACKET	4
Packit 992a25
Packit 992a25
static void p_comlist(const struct dolnod*,int);
Packit 992a25
static void p_arg(const struct argnod*, int endchar, int opts);
Packit 992a25
static void p_comarg(const struct comnod*);
Packit 992a25
static void p_keyword(const char*,int);
Packit 992a25
static void p_redirect(const struct ionod*);
Packit 992a25
static void p_switch(const struct regnod*);
Packit 992a25
static void here_body(const struct ionod*);
Packit 992a25
static void p_tree(const Shnode_t*,int);
Packit 992a25
Packit 992a25
static int level;
Packit 992a25
static int begin_line;
Packit 992a25
static int end_line;
Packit 992a25
static char io_op[7];
Packit 992a25
static char un_op[3] = "-?";
Packit 992a25
static const struct ionod *here_doc;
Packit 992a25
static Sfio_t *outfile;
Packit 992a25
static const char *forinit = "";
Packit 992a25
Packit 992a25
extern void sh_deparse(Sfio_t*, const Shnode_t*,int);
Packit 992a25
Packit 992a25
void sh_deparse(Sfio_t *out, const Shnode_t *t,int tflags)
Packit 992a25
{
Packit 992a25
	outfile = out;
Packit 992a25
	p_tree(t,tflags);
Packit 992a25
}
Packit 992a25
/*
Packit 992a25
 * print script corresponding to shell tree <t>
Packit 992a25
 */
Packit 992a25
static void p_tree(register const Shnode_t *t,register int tflags)
Packit 992a25
{
Packit 992a25
	register char *cp;
Packit 992a25
	int save = end_line;
Packit 992a25
	int needbrace = (tflags&NEED_BRACE);
Packit 992a25
	tflags &= ~NEED_BRACE;
Packit 992a25
	if(tflags&NO_NEWLINE)
Packit 992a25
		end_line = ' ';
Packit 992a25
	else
Packit 992a25
		end_line = '\n';
Packit 992a25
	switch(t->tre.tretyp&COMMSK)
Packit 992a25
	{
Packit 992a25
		case TTIME:
Packit 992a25
			if(t->tre.tretyp&COMSCAN)
Packit 992a25
				p_keyword("!",BEGIN);
Packit 992a25
			else
Packit 992a25
				p_keyword("time",BEGIN);
Packit 992a25
			if(t->par.partre)
Packit 992a25
				p_tree(t->par.partre,tflags); 
Packit 992a25
			level--;
Packit 992a25
			break;
Packit 992a25
Packit 992a25
		case TCOM:
Packit 992a25
			if(begin_line && level>0)
Packit 992a25
				sfnputc(outfile,'\t',level);
Packit 992a25
			begin_line = 0;
Packit 992a25
			p_comarg((struct comnod*)t);
Packit 992a25
			break;
Packit 992a25
Packit 992a25
		case TSETIO:
Packit 992a25
			if(t->tre.tretyp&FPCL)
Packit 992a25
				tflags |= NEED_BRACE;
Packit 992a25
			else
Packit 992a25
				tflags = NO_NEWLINE|NEED_BRACE;
Packit 992a25
			p_tree(t->fork.forktre,tflags);
Packit 992a25
			p_redirect(t->fork.forkio);
Packit 992a25
			break;
Packit 992a25
Packit 992a25
		case TFORK:
Packit 992a25
			if(needbrace)
Packit 992a25
				tflags |= NEED_BRACE;
Packit 992a25
			if(t->tre.tretyp&(FAMP|FCOOP))
Packit 992a25
			{
Packit 992a25
				tflags = NEED_BRACE|NO_NEWLINE;
Packit 992a25
				end_line = ' ';
Packit 992a25
			}
Packit 992a25
			else if(t->fork.forkio)
Packit 992a25
				tflags = NO_NEWLINE;
Packit 992a25
			p_tree(t->fork.forktre,tflags);
Packit 992a25
			if(t->fork.forkio)
Packit 992a25
				p_redirect(t->fork.forkio);
Packit 992a25
			if(t->tre.tretyp&FCOOP)
Packit 992a25
			{
Packit 992a25
				sfputr(outfile,"|&",'\n');
Packit 992a25
				begin_line = 1;
Packit 992a25
			}
Packit 992a25
			else if(t->tre.tretyp&FAMP)
Packit 992a25
			{
Packit 992a25
				sfputr(outfile,"&",'\n');
Packit 992a25
				begin_line = 1;
Packit 992a25
			}
Packit 992a25
			break;
Packit 992a25
	
Packit 992a25
		case TIF:
Packit 992a25
			p_keyword("if",BEGIN);
Packit 992a25
			p_tree(t->if_.iftre,0);
Packit 992a25
			p_keyword("then",MIDDLE);
Packit 992a25
			p_tree(t->if_.thtre,0);
Packit 992a25
			if(t->if_.eltre)
Packit 992a25
			{
Packit 992a25
				p_keyword("else",MIDDLE);
Packit 992a25
				p_tree(t->if_.eltre,0);
Packit 992a25
			}
Packit 992a25
			p_keyword("fi",END);
Packit 992a25
			break;
Packit 992a25
Packit 992a25
		case TWH:
Packit 992a25
			if(t->wh.whinc)
Packit 992a25
				cp = "for";
Packit 992a25
			else if(t->tre.tretyp&COMSCAN)
Packit 992a25
				cp = "until";
Packit 992a25
			else
Packit 992a25
				cp = "while";
Packit 992a25
			p_keyword(cp,BEGIN);
Packit 992a25
			if(t->wh.whinc)
Packit 992a25
			{
Packit 992a25
				struct argnod *arg = (t->wh.whtre)->ar.arexpr;
Packit 992a25
				sfprintf(outfile,"(( %s; ",forinit);
Packit 992a25
				forinit = "";
Packit 992a25
				sfputr(outfile,arg->argval,';');
Packit 992a25
				arg = (t->wh.whinc)->arexpr;
Packit 992a25
				sfprintf(outfile," %s))\n",arg->argval);
Packit 992a25
			}
Packit 992a25
			else
Packit 992a25
				p_tree(t->wh.whtre,0);
Packit 992a25
			t = t->wh.dotre;
Packit 992a25
			goto dolist;
Packit 992a25
Packit 992a25
		case TLST:
Packit 992a25
		{
Packit 992a25
			Shnode_t *tr = t->lst.lstrit;
Packit 992a25
			if(tr->tre.tretyp==TWH && tr->wh.whinc && t->lst.lstlef->tre.tretyp==TARITH)
Packit 992a25
			{
Packit 992a25
				/* arithmetic for statement */
Packit 992a25
				struct argnod *init = (t->lst.lstlef)->ar.arexpr;
Packit 992a25
				forinit= init->argval;
Packit 992a25
				p_tree(t->lst.lstrit,tflags);
Packit 992a25
				break;
Packit 992a25
			}
Packit 992a25
			if(needbrace)
Packit 992a25
				p_keyword("{",BEGIN);
Packit 992a25
			p_tree(t->lst.lstlef,0);
Packit 992a25
			if(needbrace)
Packit 992a25
				tflags = 0;
Packit 992a25
			p_tree(t->lst.lstrit,tflags);
Packit 992a25
			if(needbrace)
Packit 992a25
				p_keyword("}",END);
Packit 992a25
			break;
Packit 992a25
		}
Packit 992a25
Packit 992a25
		case TAND:
Packit 992a25
			cp = "&&";
Packit 992a25
			goto andor;
Packit 992a25
		case TORF:
Packit 992a25
			cp = "||";
Packit 992a25
			goto andor;
Packit 992a25
		case TFIL:
Packit 992a25
			cp = "|";
Packit 992a25
		andor:
Packit 992a25
		{
Packit 992a25
			int bracket = 0;
Packit 992a25
			if(t->tre.tretyp&TTEST)
Packit 992a25
			{
Packit 992a25
				tflags |= NO_NEWLINE;
Packit 992a25
				if(!(tflags&NO_BRACKET))
Packit 992a25
				{
Packit 992a25
					p_keyword("[[",BEGIN);
Packit 992a25
					tflags |= NO_BRACKET;
Packit 992a25
					bracket=1;
Packit 992a25
				}
Packit 992a25
			}
Packit 992a25
			p_tree(t->lst.lstlef,NEED_BRACE|NO_NEWLINE|(tflags&NO_BRACKET));
Packit 992a25
			if(tflags&FALTPIPE)
Packit 992a25
			{
Packit 992a25
				Shnode_t *tt = t->lst.lstrit;
Packit 992a25
				if(tt->tre.tretyp!=TFIL || !(tt->lst.lstlef->tre.tretyp&FALTPIPE))
Packit 992a25
				{
Packit 992a25
					sfputc(outfile,'\n');
Packit 992a25
					return;
Packit 992a25
				}
Packit 992a25
			}
Packit 992a25
			sfputr(outfile,cp,here_doc?'\n':' ');
Packit 992a25
			if(here_doc)
Packit 992a25
			{
Packit 992a25
				here_body(here_doc);
Packit 992a25
				here_doc = 0;
Packit 992a25
			}
Packit 992a25
			level++;
Packit 992a25
			p_tree(t->lst.lstrit,tflags|NEED_BRACE);
Packit 992a25
			if(bracket)
Packit 992a25
				p_keyword("]]",END);
Packit 992a25
			level--;
Packit 992a25
			break;
Packit 992a25
		}
Packit 992a25
	
Packit 992a25
		case TPAR:
Packit 992a25
			p_keyword("(",BEGIN);
Packit 992a25
			p_tree(t->par.partre,0); 
Packit 992a25
			p_keyword(")",END);
Packit 992a25
			break;
Packit 992a25
Packit 992a25
		case TARITH:
Packit 992a25
		{
Packit 992a25
			register struct argnod *ap = t->ar.arexpr;
Packit 992a25
			if(begin_line && level)
Packit 992a25
				sfnputc(outfile,'\t',level);
Packit 992a25
			sfprintf(outfile,"(( %s ))%c",ap->argval,end_line);
Packit 992a25
			if(!(tflags&NO_NEWLINE))
Packit 992a25
				begin_line=1;
Packit 992a25
			break;
Packit 992a25
		}
Packit 992a25
Packit 992a25
		case TFOR:
Packit 992a25
			cp = ((t->tre.tretyp&COMSCAN)?"select":"for");
Packit 992a25
			p_keyword(cp,BEGIN);
Packit 992a25
			sfputr(outfile,t->for_.fornam,' ');
Packit 992a25
			if(t->for_.forlst)
Packit 992a25
			{
Packit 992a25
				sfputr(outfile,"in",' ');
Packit 992a25
				tflags = end_line;
Packit 992a25
				end_line = '\n';
Packit 992a25
				p_comarg(t->for_.forlst);
Packit 992a25
				end_line = tflags;
Packit 992a25
			}
Packit 992a25
			else
Packit 992a25
				sfputc(outfile,'\n');
Packit 992a25
			begin_line = 1;
Packit 992a25
			t = t->for_.fortre;
Packit 992a25
		dolist:
Packit 992a25
			p_keyword("do",MIDDLE);
Packit 992a25
			p_tree(t,0);
Packit 992a25
			p_keyword("done",END);
Packit 992a25
			break;
Packit 992a25
	
Packit 992a25
		case TSW:
Packit 992a25
			p_keyword("case",BEGIN);
Packit 992a25
			p_arg(t->sw.swarg,' ',0);
Packit 992a25
			if(t->sw.swlst)
Packit 992a25
			{
Packit 992a25
				begin_line = 1;
Packit 992a25
				sfputr(outfile,"in",'\n');
Packit 992a25
				tflags = end_line;
Packit 992a25
				end_line = '\n';
Packit 992a25
				p_switch(t->sw.swlst);
Packit 992a25
				end_line = tflags;
Packit 992a25
			}
Packit 992a25
			p_keyword("esac",END);
Packit 992a25
			break;
Packit 992a25
Packit 992a25
		case TFUN:
Packit 992a25
			if(t->tre.tretyp&FPOSIX)
Packit 992a25
			{
Packit 992a25
				sfprintf(outfile,"%s",t->funct.functnam);
Packit 992a25
				p_keyword("()\n",BEGIN);
Packit 992a25
			}
Packit 992a25
			else
Packit 992a25
			{
Packit 992a25
				p_keyword("function",BEGIN);
Packit 992a25
				tflags = (t->funct.functargs?' ':'\n');
Packit 992a25
				sfputr(outfile,t->funct.functnam,tflags);
Packit 992a25
				if(t->funct.functargs)
Packit 992a25
				{
Packit 992a25
					tflags = end_line;
Packit 992a25
					end_line = '\n';
Packit 992a25
					p_comarg(t->funct.functargs);
Packit 992a25
					end_line = tflags;
Packit 992a25
				}
Packit 992a25
			}
Packit 992a25
			begin_line = 1;
Packit 992a25
			p_keyword("{\n",MIDDLE);
Packit 992a25
			begin_line = 1;
Packit 992a25
			p_tree(t->funct.functtre,0); 
Packit 992a25
			p_keyword("}",END);
Packit 992a25
			break;
Packit 992a25
		/* new test compound command */
Packit 992a25
		case TTST:
Packit 992a25
			if(!(tflags&NO_BRACKET))
Packit 992a25
				p_keyword("[[",BEGIN);
Packit 992a25
			if((t->tre.tretyp&TPAREN)==TPAREN)
Packit 992a25
			{
Packit 992a25
				p_keyword("(",BEGIN);
Packit 992a25
				p_tree(t->lst.lstlef,NO_BRACKET|NO_NEWLINE); 
Packit 992a25
				p_keyword(")",END);
Packit 992a25
			}
Packit 992a25
			else
Packit 992a25
			{
Packit 992a25
				int flags = (t->tre.tretyp)>>TSHIFT;
Packit 992a25
				if(t->tre.tretyp&TNEGATE)
Packit 992a25
					sfputr(outfile,"!",' ');
Packit 992a25
				if(t->tre.tretyp&TUNARY)
Packit 992a25
				{
Packit 992a25
					un_op[1] = flags;
Packit 992a25
					sfputr(outfile,un_op,' ');
Packit 992a25
				}
Packit 992a25
				else
Packit 992a25
					cp = ((char*)(shtab_testops+(flags&037)-1)->sh_name);
Packit 992a25
				p_arg(&(t->lst.lstlef->arg),' ',0);
Packit 992a25
				if(t->tre.tretyp&TBINARY)
Packit 992a25
				{
Packit 992a25
					sfputr(outfile,cp,' ');
Packit 992a25
					p_arg(&(t->lst.lstrit->arg),' ',0);
Packit 992a25
				}
Packit 992a25
			}
Packit 992a25
			if(!(tflags&NO_BRACKET))
Packit 992a25
				p_keyword("]]",END);
Packit 992a25
	}
Packit 992a25
	while(begin_line && here_doc)
Packit 992a25
	{
Packit 992a25
		here_body(here_doc);
Packit 992a25
		here_doc = 0;
Packit 992a25
	}
Packit 992a25
	end_line = save;
Packit 992a25
	return;
Packit 992a25
}
Packit 992a25
Packit 992a25
/*
Packit 992a25
 * print a keyword
Packit 992a25
 * increment indent level for flag==BEGIN
Packit 992a25
 * decrement indent level for flag==END
Packit 992a25
 */
Packit 992a25
static void p_keyword(const char *word,int flag)
Packit 992a25
{
Packit 992a25
	register int sep;
Packit 992a25
	if(flag==END)
Packit 992a25
		sep = end_line;
Packit 992a25
	else if(*word=='[' || *word=='(')
Packit 992a25
		sep = ' ';
Packit 992a25
	else
Packit 992a25
		sep = '\t';
Packit 992a25
	if(flag!=BEGIN)
Packit 992a25
		level--;
Packit 992a25
	if(begin_line && level)
Packit 992a25
		sfnputc(outfile,'\t',level);
Packit 992a25
	sfputr(outfile,word,sep);
Packit 992a25
	if(sep=='\n')
Packit 992a25
		begin_line=1;
Packit 992a25
	else
Packit 992a25
		begin_line=0;
Packit 992a25
	if(flag!=END)
Packit 992a25
		level++;
Packit 992a25
}
Packit 992a25
Packit 992a25
static void p_arg(register const struct argnod *arg,register int endchar,int opts)
Packit 992a25
{
Packit 992a25
	register const char *cp;
Packit 992a25
	register int flag;
Packit 992a25
	do
Packit 992a25
	{
Packit 992a25
		if(!arg->argnxt.ap)
Packit 992a25
			flag = endchar;
Packit 992a25
		else if(opts&PRE)
Packit 992a25
		{
Packit 992a25
			/* case alternation lists in reverse order */
Packit 992a25
			p_arg(arg->argnxt.ap,'|',opts);
Packit 992a25
			flag = endchar;
Packit 992a25
		}
Packit 992a25
		else if(opts)
Packit 992a25
			flag = ' ';
Packit 992a25
		cp = arg->argval;
Packit 992a25
		if(*cp==0 && (arg->argflag&ARG_EXP)  && arg->argchn.ap)
Packit 992a25
		{
Packit 992a25
			int c = (arg->argflag&ARG_RAW)?'>':'<';
Packit 992a25
			sfputc(outfile,c);
Packit 992a25
			sfputc(outfile,'(');
Packit 992a25
			p_tree((Shnode_t*)arg->argchn.ap,0);
Packit 992a25
			sfputc(outfile,')');
Packit 992a25
		}
Packit 992a25
		else if(*cp==0 && opts==POST && arg->argchn.ap)
Packit 992a25
		{
Packit 992a25
			/* compound assignment */
Packit 992a25
			struct fornod *fp=(struct fornod*)arg->argchn.ap;
Packit 992a25
			sfprintf(outfile,"%s=(\n",fp->fornam);
Packit 992a25
			sfnputc(outfile,'\t',++level);
Packit 992a25
			p_tree(fp->fortre,0);
Packit 992a25
			if(--level)
Packit 992a25
				sfnputc(outfile,'\t',level);
Packit 992a25
			sfputc(outfile,')');
Packit 992a25
		}
Packit 992a25
		else if((arg->argflag&ARG_RAW) && (cp[1] || (*cp!='[' && *cp!=']')))
Packit 992a25
			cp = sh_fmtq(cp);
Packit 992a25
		sfputr(outfile,cp,flag);
Packit 992a25
		if(flag=='\n')
Packit 992a25
			begin_line = 1;
Packit 992a25
		arg = arg->argnxt.ap;
Packit 992a25
	}
Packit 992a25
	while((opts&POST) && arg);
Packit 992a25
	return;
Packit 992a25
}
Packit 992a25
Packit 992a25
static void p_redirect(register const struct ionod *iop)
Packit 992a25
{
Packit 992a25
	register char *cp;
Packit 992a25
	register int iof,iof2;
Packit 992a25
	for(;iop;iop=iop->ionxt)
Packit 992a25
	{
Packit 992a25
		iof=iop->iofile;
Packit 992a25
		cp = io_op;
Packit 992a25
		if(iop->iovname)
Packit 992a25
		{
Packit 992a25
			sfwrite(outfile,"(;",2);
Packit 992a25
			sfputr(outfile,iop->iovname,')');
Packit 992a25
			cp++;
Packit 992a25
		}
Packit 992a25
		else
Packit 992a25
			*cp = '0'+(iof&IOUFD);
Packit 992a25
		if(iof&IOPUT)
Packit 992a25
		{
Packit 992a25
			if(*cp == '1' && !iop->iovname)
Packit 992a25
				cp++;
Packit 992a25
			io_op[1] = '>';
Packit 992a25
		}
Packit 992a25
		else
Packit 992a25
		{
Packit 992a25
			if(*cp == '0' && !iop->iovname)
Packit 992a25
				cp++;
Packit 992a25
			io_op[1] = '<';
Packit 992a25
		}
Packit 992a25
		io_op[2] = 0;
Packit 992a25
		io_op[3] = 0;
Packit 992a25
		if(iof&IOLSEEK)
Packit 992a25
		{
Packit 992a25
			io_op[1] = '#';
Packit 992a25
			if(iof&IOARITH)
Packit 992a25
				strcpy(&io_op[3]," ((");
Packit 992a25
		}
Packit 992a25
		else if(iof&IOMOV)
Packit 992a25
			io_op[2] = '&';
Packit 992a25
		else if(iof&(IORDW|IOAPP))
Packit 992a25
			io_op[2] = '>';
Packit 992a25
		else if(iof&IOCLOB)
Packit 992a25
			io_op[2] = '|';
Packit 992a25
		if(iop->iodelim)
Packit 992a25
		{
Packit 992a25
			/* here document */
Packit 992a25
#ifdef xxx
Packit 992a25
			iop->iolink = (char*)here_doc;
Packit 992a25
#endif
Packit 992a25
			here_doc  = iop;
Packit 992a25
			io_op[2] = '<';
Packit 992a25
#ifdef future
Packit 992a25
			if(iof&IOSTRIP)
Packit 992a25
				io_op[3] = '-';
Packit 992a25
#endif
Packit 992a25
		}
Packit 992a25
		sfputr(outfile,cp,' ');
Packit 992a25
		if(iop->ionxt)
Packit 992a25
			iof = ' ';
Packit 992a25
		else
Packit 992a25
		{
Packit 992a25
			if((iof=end_line)=='\n')
Packit 992a25
				begin_line = 1;
Packit 992a25
		}
Packit 992a25
		if((iof&IOLSEEK) && (iof&IOARITH))
Packit 992a25
			iof2 = iof, iof = ' ';
Packit 992a25
		if(iop->iodelim)
Packit 992a25
		{
Packit 992a25
			if(!(iop->iofile&IODOC))
Packit 992a25
				sfwrite(outfile,"''",2);
Packit 992a25
			sfputr(outfile,sh_fmtq(iop->iodelim),iof);
Packit 992a25
		}
Packit 992a25
		else if(iop->iofile&IORAW)
Packit 992a25
			sfputr(outfile,sh_fmtq(iop->ioname),iof);
Packit 992a25
		else
Packit 992a25
			sfputr(outfile,iop->ioname,iof);
Packit 992a25
		if((iof&IOLSEEK) && (iof&IOARITH))
Packit 992a25
			sfputr(outfile, "))", iof2);
Packit 992a25
	}
Packit 992a25
	return;
Packit 992a25
}
Packit 992a25
Packit 992a25
static void p_comarg(register const struct comnod *com)
Packit 992a25
{
Packit 992a25
	register int flag = end_line;
Packit 992a25
	if(com->comtyp&FAMP)
Packit 992a25
		sfwrite(outfile,"& ",2);
Packit 992a25
	if(com->comarg || com->comio)
Packit 992a25
		flag = ' ';
Packit 992a25
	if(com->comset)
Packit 992a25
		p_arg(com->comset,flag,POST);
Packit 992a25
	if(com->comarg)
Packit 992a25
	{
Packit 992a25
		if(!com->comio)
Packit 992a25
			flag = end_line;
Packit 992a25
		if(com->comtyp&COMSCAN)
Packit 992a25
			p_arg(com->comarg,flag,POST);
Packit 992a25
		else
Packit 992a25
			p_comlist((struct dolnod*)com->comarg,flag);
Packit 992a25
	}
Packit 992a25
	if(com->comio)
Packit 992a25
		p_redirect(com->comio);
Packit 992a25
	return;
Packit 992a25
}
Packit 992a25
Packit 992a25
static void p_comlist(const struct dolnod *dol,int endchar)
Packit 992a25
{
Packit 992a25
	register char *cp, *const*argv;
Packit 992a25
	register int flag = ' ', special;
Packit 992a25
	argv = dol->dolval+ARG_SPARE;
Packit 992a25
	cp = *argv;
Packit 992a25
	special = (*cp=='[' && cp[1]==0);
Packit 992a25
	do
Packit 992a25
	{
Packit 992a25
		if(cp)
Packit 992a25
			argv++;
Packit 992a25
		else
Packit 992a25
			cp = "";
Packit 992a25
		if(*argv==0)
Packit 992a25
		{
Packit 992a25
			if((flag=endchar)=='\n')
Packit 992a25
				begin_line = 1;
Packit 992a25
			special = (*cp==']' && cp[1]==0);
Packit 992a25
		}
Packit 992a25
		sfputr(outfile,special?cp:sh_fmtq(cp),flag);
Packit 992a25
		special = 0;
Packit 992a25
	}
Packit 992a25
	while(cp  = *argv);
Packit 992a25
	return;
Packit 992a25
}
Packit 992a25
Packit 992a25
static void p_switch(register const struct regnod *reg)
Packit 992a25
{
Packit 992a25
	if(level>1)
Packit 992a25
		sfnputc(outfile,'\t',level-1);
Packit 992a25
	p_arg(reg->regptr,')',PRE);
Packit 992a25
	begin_line = 0;
Packit 992a25
	sfputc(outfile,'\t');
Packit 992a25
	if(reg->regcom)
Packit 992a25
		p_tree(reg->regcom,0);
Packit 992a25
	level++;
Packit 992a25
	if(reg->regflag)
Packit 992a25
		p_keyword(";&",END);
Packit 992a25
	else
Packit 992a25
		p_keyword(";;",END);
Packit 992a25
	if(reg->regnxt)
Packit 992a25
		p_switch(reg->regnxt);
Packit 992a25
	return;
Packit 992a25
}
Packit 992a25
Packit 992a25
/*
Packit 992a25
 * output here documents
Packit 992a25
 */
Packit 992a25
static void here_body(register const struct ionod *iop)
Packit 992a25
{
Packit 992a25
	Sfio_t *infile;
Packit 992a25
#ifdef xxx
Packit 992a25
	if(iop->iolink)
Packit 992a25
		here_body((struct inode*)iop->iolink);
Packit 992a25
	iop->iolink = 0;
Packit 992a25
#endif
Packit 992a25
	if(iop->iofile&IOSTRG)
Packit 992a25
		infile = sfnew((Sfio_t*)0,iop->ioname,iop->iosize,-1,SF_STRING|SF_READ);
Packit 992a25
	else
Packit 992a25
		sfseek(infile=sh.heredocs,iop->iooffset,SEEK_SET);
Packit 992a25
	sfmove(infile,outfile,iop->iosize,-1);
Packit 992a25
	if(iop->iofile&IOSTRG)
Packit 992a25
		sfclose(infile);
Packit 992a25
	sfputr(outfile,iop->iodelim,'\n');
Packit 992a25
}
Packit 992a25