xref: /onnv-gate/usr/src/lib/libshell/common/sh/deparse.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1982-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                  David Korn <dgk@research.att.com>                   *
184887Schin *                                                                      *
194887Schin ***********************************************************************/
204887Schin #pragma prototyped
214887Schin /*
224887Schin  * David Korn
234887Schin  * AT&T Labs
244887Schin  *
254887Schin  * shell deparser
264887Schin  *
274887Schin  */
284887Schin 
294887Schin #include	"defs.h"
304887Schin #include	"shnodes.h"
314887Schin #include	"test.h"
324887Schin 
334887Schin 
344887Schin #define HUGE_INT	(((unsigned)-1)>>1)
354887Schin #define	BEGIN	0
364887Schin #define MIDDLE	1
374887Schin #define	END	2
384887Schin #define PRE	1
394887Schin #define POST	2
404887Schin 
414887Schin 
424887Schin /* flags that can be specified with p_tree() */
434887Schin #define NO_NEWLINE	1
444887Schin #define NEED_BRACE	2
454887Schin #define NO_BRACKET	4
464887Schin 
474887Schin static void p_comlist(const struct dolnod*,int);
484887Schin static void p_arg(const struct argnod*, int endchar, int opts);
494887Schin static void p_comarg(const struct comnod*);
504887Schin static void p_keyword(const char*,int);
514887Schin static void p_redirect(const struct ionod*);
524887Schin static void p_switch(const struct regnod*);
534887Schin static void here_body(const struct ionod*);
544887Schin static void p_tree(const Shnode_t*,int);
554887Schin 
564887Schin static int level;
574887Schin static int begin_line;
584887Schin static int end_line;
594887Schin static char io_op[7];
604887Schin static char un_op[3] = "-?";
614887Schin static const struct ionod *here_doc;
624887Schin static Sfio_t *outfile;
634887Schin static const char *forinit = "";
644887Schin 
654887Schin extern void sh_deparse(Sfio_t*, const Shnode_t*,int);
664887Schin 
sh_deparse(Sfio_t * out,const Shnode_t * t,int tflags)674887Schin void sh_deparse(Sfio_t *out, const Shnode_t *t,int tflags)
684887Schin {
694887Schin 	outfile = out;
704887Schin 	p_tree(t,tflags);
714887Schin }
724887Schin /*
734887Schin  * print script corresponding to shell tree <t>
744887Schin  */
p_tree(register const Shnode_t * t,register int tflags)754887Schin static void p_tree(register const Shnode_t *t,register int tflags)
764887Schin {
774887Schin 	register char *cp;
784887Schin 	int save = end_line;
794887Schin 	int needbrace = (tflags&NEED_BRACE);
804887Schin 	tflags &= ~NEED_BRACE;
814887Schin 	if(tflags&NO_NEWLINE)
824887Schin 		end_line = ' ';
834887Schin 	else
844887Schin 		end_line = '\n';
854887Schin 	switch(t->tre.tretyp&COMMSK)
864887Schin 	{
874887Schin 		case TTIME:
884887Schin 			if(t->tre.tretyp&COMSCAN)
894887Schin 				p_keyword("!",BEGIN);
904887Schin 			else
914887Schin 				p_keyword("time",BEGIN);
924887Schin 			if(t->par.partre)
934887Schin 				p_tree(t->par.partre,tflags);
944887Schin 			level--;
954887Schin 			break;
964887Schin 
974887Schin 		case TCOM:
984887Schin 			if(begin_line && level>0)
994887Schin 				sfnputc(outfile,'\t',level);
1004887Schin 			begin_line = 0;
1014887Schin 			p_comarg((struct comnod*)t);
1024887Schin 			break;
1034887Schin 
1044887Schin 		case TSETIO:
1054887Schin 			if(t->tre.tretyp&FPCL)
1064887Schin 				tflags |= NEED_BRACE;
1074887Schin 			else
1084887Schin 				tflags = NO_NEWLINE|NEED_BRACE;
1094887Schin 			p_tree(t->fork.forktre,tflags);
1104887Schin 			p_redirect(t->fork.forkio);
1114887Schin 			break;
1124887Schin 
1134887Schin 		case TFORK:
1144887Schin 			if(needbrace)
1154887Schin 				tflags |= NEED_BRACE;
1164887Schin 			if(t->tre.tretyp&(FAMP|FCOOP))
1174887Schin 			{
1184887Schin 				tflags = NEED_BRACE|NO_NEWLINE;
1194887Schin 				end_line = ' ';
1204887Schin 			}
1214887Schin 			else if(t->fork.forkio)
1224887Schin 				tflags = NO_NEWLINE;
1234887Schin 			p_tree(t->fork.forktre,tflags);
1244887Schin 			if(t->fork.forkio)
1254887Schin 				p_redirect(t->fork.forkio);
1264887Schin 			if(t->tre.tretyp&FCOOP)
1274887Schin 			{
1284887Schin 				sfputr(outfile,"|&",'\n');
1294887Schin 				begin_line = 1;
1304887Schin 			}
1314887Schin 			else if(t->tre.tretyp&FAMP)
1324887Schin 			{
1334887Schin 				sfputr(outfile,"&",'\n');
1344887Schin 				begin_line = 1;
1354887Schin 			}
1364887Schin 			break;
1374887Schin 
1384887Schin 		case TIF:
1394887Schin 			p_keyword("if",BEGIN);
1404887Schin 			p_tree(t->if_.iftre,0);
1414887Schin 			p_keyword("then",MIDDLE);
1424887Schin 			p_tree(t->if_.thtre,0);
1434887Schin 			if(t->if_.eltre)
1444887Schin 			{
1454887Schin 				p_keyword("else",MIDDLE);
1464887Schin 				p_tree(t->if_.eltre,0);
1474887Schin 			}
1484887Schin 			p_keyword("fi",END);
1494887Schin 			break;
1504887Schin 
1514887Schin 		case TWH:
1524887Schin 			if(t->wh.whinc)
1534887Schin 				cp = "for";
1544887Schin 			else if(t->tre.tretyp&COMSCAN)
1554887Schin 				cp = "until";
1564887Schin 			else
1574887Schin 				cp = "while";
1584887Schin 			p_keyword(cp,BEGIN);
1594887Schin 			if(t->wh.whinc)
1604887Schin 			{
1614887Schin 				struct argnod *arg = (t->wh.whtre)->ar.arexpr;
1624887Schin 				sfprintf(outfile,"(( %s; ",forinit);
1634887Schin 				forinit = "";
1644887Schin 				sfputr(outfile,arg->argval,';');
1654887Schin 				arg = (t->wh.whinc)->arexpr;
1664887Schin 				sfprintf(outfile," %s))\n",arg->argval);
1674887Schin 			}
1684887Schin 			else
1694887Schin 				p_tree(t->wh.whtre,0);
1704887Schin 			t = t->wh.dotre;
1714887Schin 			goto dolist;
1724887Schin 
1734887Schin 		case TLST:
1744887Schin 		{
1754887Schin 			Shnode_t *tr = t->lst.lstrit;
1764887Schin 			if(tr->tre.tretyp==TWH && tr->wh.whinc && t->lst.lstlef->tre.tretyp==TARITH)
1774887Schin 			{
1784887Schin 				/* arithmetic for statement */
1794887Schin 				struct argnod *init = (t->lst.lstlef)->ar.arexpr;
1804887Schin 				forinit= init->argval;
1814887Schin 				p_tree(t->lst.lstrit,tflags);
1824887Schin 				break;
1834887Schin 			}
1844887Schin 			if(needbrace)
1854887Schin 				p_keyword("{",BEGIN);
1864887Schin 			p_tree(t->lst.lstlef,0);
1874887Schin 			if(needbrace)
1884887Schin 				tflags = 0;
1894887Schin 			p_tree(t->lst.lstrit,tflags);
1904887Schin 			if(needbrace)
1914887Schin 				p_keyword("}",END);
1924887Schin 			break;
1934887Schin 		}
1944887Schin 
1954887Schin 		case TAND:
1964887Schin 			cp = "&&";
1974887Schin 			goto andor;
1984887Schin 		case TORF:
1994887Schin 			cp = "||";
2004887Schin 			goto andor;
2014887Schin 		case TFIL:
2024887Schin 			cp = "|";
2034887Schin 		andor:
2044887Schin 		{
2054887Schin 			int bracket = 0;
2064887Schin 			if(t->tre.tretyp&TTEST)
2074887Schin 			{
2084887Schin 				tflags |= NO_NEWLINE;
2094887Schin 				if(!(tflags&NO_BRACKET))
2104887Schin 				{
2114887Schin 					p_keyword("[[",BEGIN);
2124887Schin 					tflags |= NO_BRACKET;
2134887Schin 					bracket=1;
2144887Schin 				}
2154887Schin 			}
2164887Schin 			p_tree(t->lst.lstlef,NEED_BRACE|NO_NEWLINE|(tflags&NO_BRACKET));
2174887Schin 			sfputr(outfile,cp,here_doc?'\n':' ');
2184887Schin 			if(here_doc)
2194887Schin 			{
2204887Schin 				here_body(here_doc);
2214887Schin 				here_doc = 0;
2224887Schin 			}
2234887Schin 			level++;
2244887Schin 			p_tree(t->lst.lstrit,tflags|NEED_BRACE);
2254887Schin 			if(bracket)
2264887Schin 				p_keyword("]]",END);
2274887Schin 			level--;
2284887Schin 			break;
2294887Schin 		}
2304887Schin 
2314887Schin 		case TPAR:
2324887Schin 			p_keyword("(",BEGIN);
2334887Schin 			p_tree(t->par.partre,0);
2344887Schin 			p_keyword(")",END);
2354887Schin 			break;
2364887Schin 
2374887Schin 		case TARITH:
2384887Schin 		{
2394887Schin 			register struct argnod *ap = t->ar.arexpr;
2404887Schin 			if(begin_line && level)
2414887Schin 				sfnputc(outfile,'\t',level);
2424887Schin 			sfprintf(outfile,"(( %s ))%c",ap->argval,end_line);
2434887Schin 			if(!(tflags&NO_NEWLINE))
2444887Schin 				begin_line=1;
2454887Schin 			break;
2464887Schin 		}
2474887Schin 
2484887Schin 		case TFOR:
2494887Schin 			cp = ((t->tre.tretyp&COMSCAN)?"select":"for");
2504887Schin 			p_keyword(cp,BEGIN);
2514887Schin 			sfputr(outfile,t->for_.fornam,' ');
2524887Schin 			if(t->for_.forlst)
2534887Schin 			{
2544887Schin 				sfputr(outfile,"in",' ');
2554887Schin 				tflags = end_line;
2564887Schin 				end_line = '\n';
2574887Schin 				p_comarg(t->for_.forlst);
2584887Schin 				end_line = tflags;
2594887Schin 			}
2604887Schin 			else
2614887Schin 				sfputc(outfile,'\n');
2624887Schin 			begin_line = 1;
2634887Schin 			t = t->for_.fortre;
2644887Schin 		dolist:
2654887Schin 			p_keyword("do",MIDDLE);
2664887Schin 			p_tree(t,0);
2674887Schin 			p_keyword("done",END);
2684887Schin 			break;
2694887Schin 
2704887Schin 		case TSW:
2714887Schin 			p_keyword("case",BEGIN);
2724887Schin 			p_arg(t->sw.swarg,' ',0);
2734887Schin 			if(t->sw.swlst)
2744887Schin 			{
2754887Schin 				begin_line = 1;
2764887Schin 				sfputr(outfile,"in",'\n');
2774887Schin 				tflags = end_line;
2784887Schin 				end_line = '\n';
2794887Schin 				p_switch(t->sw.swlst);
2804887Schin 				end_line = tflags;
2814887Schin 			}
2824887Schin 			p_keyword("esac",END);
2834887Schin 			break;
2844887Schin 
2854887Schin 		case TFUN:
2864887Schin 			if(t->tre.tretyp&FPOSIX)
2874887Schin 			{
2884887Schin 				sfprintf(outfile,"%s",t->funct.functnam);
2894887Schin 				p_keyword("()\n",BEGIN);
2904887Schin 			}
2914887Schin 			else
2924887Schin 			{
2934887Schin 				p_keyword("function",BEGIN);
2944887Schin 				tflags = (t->funct.functargs?' ':'\n');
2954887Schin 				sfputr(outfile,t->funct.functnam,tflags);
2964887Schin 				if(t->funct.functargs)
2974887Schin 				{
2984887Schin 					tflags = end_line;
2994887Schin 					end_line = '\n';
3004887Schin 					p_comarg(t->funct.functargs);
3014887Schin 					end_line = tflags;
3024887Schin 				}
3034887Schin 			}
3044887Schin 			begin_line = 1;
3054887Schin 			p_keyword("{\n",MIDDLE);
3064887Schin 			begin_line = 1;
3074887Schin 			p_tree(t->funct.functtre,0);
3084887Schin 			p_keyword("}",END);
3094887Schin 			break;
3104887Schin 		/* new test compound command */
3114887Schin 		case TTST:
3124887Schin 			if(!(tflags&NO_BRACKET))
3134887Schin 				p_keyword("[[",BEGIN);
3144887Schin 			if((t->tre.tretyp&TPAREN)==TPAREN)
3154887Schin 			{
3164887Schin 				p_keyword("(",BEGIN);
3174887Schin 				p_tree(t->lst.lstlef,NO_BRACKET|NO_NEWLINE);
3184887Schin 				p_keyword(")",END);
3194887Schin 			}
3204887Schin 			else
3214887Schin 			{
3224887Schin 				int flags = (t->tre.tretyp)>>TSHIFT;
3234887Schin 				if(t->tre.tretyp&TNEGATE)
3244887Schin 					sfputr(outfile,"!",' ');
3254887Schin 				if(t->tre.tretyp&TUNARY)
3264887Schin 				{
3274887Schin 					un_op[1] = flags;
3284887Schin 					sfputr(outfile,un_op,' ');
3294887Schin 				}
3304887Schin 				else
3314887Schin 					cp = ((char*)(shtab_testops+(flags&037)-1)->sh_name);
3324887Schin 				p_arg(&(t->lst.lstlef->arg),' ',0);
3334887Schin 				if(t->tre.tretyp&TBINARY)
3344887Schin 				{
3354887Schin 					sfputr(outfile,cp,' ');
3364887Schin 					p_arg(&(t->lst.lstrit->arg),' ',0);
3374887Schin 				}
3384887Schin 			}
3394887Schin 			if(!(tflags&NO_BRACKET))
3404887Schin 				p_keyword("]]",END);
3414887Schin 	}
3424887Schin 	while(begin_line && here_doc)
3434887Schin 	{
3444887Schin 		here_body(here_doc);
3454887Schin 		here_doc = 0;
3464887Schin 	}
3474887Schin 	end_line = save;
3484887Schin 	return;
3494887Schin }
3504887Schin 
3514887Schin /*
3524887Schin  * print a keyword
3534887Schin  * increment indent level for flag==BEGIN
3544887Schin  * decrement indent level for flag==END
3554887Schin  */
p_keyword(const char * word,int flag)3564887Schin static void p_keyword(const char *word,int flag)
3574887Schin {
3584887Schin 	register int sep;
3594887Schin 	if(flag==END)
3604887Schin 		sep = end_line;
3614887Schin 	else if(*word=='[' || *word=='(')
3624887Schin 		sep = ' ';
3634887Schin 	else
3644887Schin 		sep = '\t';
3654887Schin 	if(flag!=BEGIN)
3664887Schin 		level--;
3674887Schin 	if(begin_line && level)
3684887Schin 		sfnputc(outfile,'\t',level);
3694887Schin 	sfputr(outfile,word,sep);
3704887Schin 	if(sep=='\n')
3714887Schin 		begin_line=1;
3724887Schin 	else
3734887Schin 		begin_line=0;
3744887Schin 	if(flag!=END)
3754887Schin 		level++;
3764887Schin }
3774887Schin 
p_arg(register const struct argnod * arg,register int endchar,int opts)3784887Schin static void p_arg(register const struct argnod *arg,register int endchar,int opts)
3794887Schin {
3804887Schin 	register const char *cp;
3814887Schin 	register int flag;
3824887Schin 	do
3834887Schin 	{
3844887Schin 		if(!arg->argnxt.ap)
3854887Schin 			flag = endchar;
3864887Schin 		else if(opts&PRE)
3874887Schin 		{
3884887Schin 			/* case alternation lists in reverse order */
3894887Schin 			p_arg(arg->argnxt.ap,'|',opts);
3904887Schin 			flag = endchar;
3914887Schin 		}
3924887Schin 		else if(opts)
3934887Schin 			flag = ' ';
3944887Schin 		cp = arg->argval;
3954887Schin 		if(*cp==0 && opts==POST && arg->argchn.ap)
3964887Schin 		{
3974887Schin 			/* compound assignment */
3984887Schin 			struct fornod *fp=(struct fornod*)arg->argchn.ap;
3994887Schin 			sfprintf(outfile,"%s=(\n",fp->fornam);
4004887Schin 			sfnputc(outfile,'\t',++level);
4014887Schin 			p_tree(fp->fortre,0);
4024887Schin 			if(--level)
4034887Schin 				sfnputc(outfile,'\t',level);
4044887Schin 			sfputc(outfile,')');
4054887Schin 		}
4064887Schin 		else if((arg->argflag&ARG_RAW) && (cp[1] || (*cp!='[' && *cp!=']')))
4074887Schin 			cp = sh_fmtq(cp);
4084887Schin 		sfputr(outfile,cp,flag);
4094887Schin 		if(flag=='\n')
4104887Schin 			begin_line = 1;
4114887Schin 		arg = arg->argnxt.ap;
4124887Schin 	}
4134887Schin 	while((opts&POST) && arg);
4144887Schin 	return;
4154887Schin }
4164887Schin 
p_redirect(register const struct ionod * iop)4174887Schin static void p_redirect(register const struct ionod *iop)
4184887Schin {
4194887Schin 	register char *cp;
4204887Schin 	register int iof,iof2;
4214887Schin 	for(;iop;iop=iop->ionxt)
4224887Schin 	{
4234887Schin 		iof=iop->iofile;
4244887Schin 		cp = io_op;
4254887Schin 		if(iop->iovname)
4264887Schin 		{
4274887Schin 			sfwrite(outfile,"(;",2);
4284887Schin 			sfputr(outfile,iop->iovname,')');
4294887Schin 			cp++;
4304887Schin 		}
4314887Schin 		else
4324887Schin 			*cp = '0'+(iof&IOUFD);
4334887Schin 		if(iof&IOPUT)
4344887Schin 		{
4354887Schin 			if(*cp == '1' && !iop->iovname)
4364887Schin 				cp++;
4374887Schin 			io_op[1] = '>';
4384887Schin 		}
4394887Schin 		else
4404887Schin 		{
4414887Schin 			if(*cp == '0' && !iop->iovname)
4424887Schin 				cp++;
4434887Schin 			io_op[1] = '<';
4444887Schin 		}
4454887Schin 		io_op[2] = 0;
4464887Schin 		io_op[3] = 0;
4474887Schin 		if(iof&IOLSEEK)
4484887Schin 		{
4494887Schin 			io_op[1] = '#';
4504887Schin 			if(iof&IOARITH)
4514887Schin 				strcpy(&io_op[3]," ((");
4524887Schin 		}
4534887Schin 		else if(iof&IOMOV)
4544887Schin 			io_op[2] = '&';
4554887Schin 		else if(iof&(IORDW|IOAPP))
4564887Schin 			io_op[2] = '>';
4574887Schin 		else if(iof&IOCLOB)
4584887Schin 			io_op[2] = '|';
4594887Schin 		if(iop->iodelim)
4604887Schin 		{
4614887Schin 			/* here document */
4624887Schin #ifdef xxx
4634887Schin 			iop->iolink = (char*)here_doc;
4644887Schin #endif
4654887Schin 			here_doc  = iop;
4664887Schin 			io_op[2] = '<';
4674887Schin #ifdef future
4684887Schin 			if(iof&IOSTRIP)
4694887Schin 				io_op[3] = '-';
4704887Schin #endif
4714887Schin 		}
4724887Schin 		sfputr(outfile,cp,' ');
4734887Schin 		if(iop->ionxt)
4744887Schin 			iof = ' ';
4754887Schin 		else
4764887Schin 		{
4774887Schin 			if((iof=end_line)=='\n')
4784887Schin 				begin_line = 1;
4794887Schin 		}
4804887Schin 		if((iof&IOLSEEK) && (iof&IOARITH))
4814887Schin 			iof2 = iof, iof = ' ';
4824887Schin 		if(iop->iodelim)
4834887Schin 		{
4844887Schin 			if(!(iop->iofile&IODOC))
4854887Schin 				sfwrite(outfile,"''",2);
4864887Schin 			sfputr(outfile,sh_fmtq(iop->iodelim),iof);
4874887Schin 		}
4884887Schin 		else if(iop->iofile&IORAW)
4894887Schin 			sfputr(outfile,sh_fmtq(iop->ioname),iof);
4904887Schin 		else
4914887Schin 			sfputr(outfile,iop->ioname,iof);
4924887Schin 		if((iof&IOLSEEK) && (iof&IOARITH))
4934887Schin 			sfputr(outfile, "))", iof2);
4944887Schin 	}
4954887Schin 	return;
4964887Schin }
4974887Schin 
p_comarg(register const struct comnod * com)4984887Schin static void p_comarg(register const struct comnod *com)
4994887Schin {
5004887Schin 	register int flag = end_line;
5014887Schin 	if(com->comarg || com->comio)
5024887Schin 		flag = ' ';
5034887Schin 	if(com->comset)
5044887Schin 		p_arg(com->comset,flag,POST);
5054887Schin 	if(com->comarg)
5064887Schin 	{
5074887Schin 		if(!com->comio)
5084887Schin 			flag = end_line;
5094887Schin 		if(com->comtyp&COMSCAN)
5104887Schin 			p_arg(com->comarg,flag,POST);
5114887Schin 		else
5124887Schin 			p_comlist((struct dolnod*)com->comarg,flag);
5134887Schin 	}
5144887Schin 	if(com->comio)
5154887Schin 		p_redirect(com->comio);
5164887Schin 	return;
5174887Schin }
5184887Schin 
p_comlist(const struct dolnod * dol,int endchar)5194887Schin static void p_comlist(const struct dolnod *dol,int endchar)
5204887Schin {
5214887Schin 	register char *cp, *const*argv;
5224887Schin 	register int flag = ' ', special;
5234887Schin 	argv = dol->dolval+ARG_SPARE;
5244887Schin 	cp = *argv;
5254887Schin 	special = (*cp=='[' && cp[1]==0);
5264887Schin 	do
5274887Schin 	{
5284887Schin 		if(cp)
5294887Schin 			argv++;
5304887Schin 		else
5314887Schin 			cp = "";
5324887Schin 		if(*argv==0)
5334887Schin 		{
5344887Schin 			if((flag=endchar)=='\n')
5354887Schin 				begin_line = 1;
5364887Schin 			special = (*cp==']' && cp[1]==0);
5374887Schin 		}
5384887Schin 		sfputr(outfile,special?cp:sh_fmtq(cp),flag);
5394887Schin 		special = 0;
5404887Schin 	}
5414887Schin 	while(cp  = *argv);
5424887Schin 	return;
5434887Schin }
5444887Schin 
p_switch(register const struct regnod * reg)5454887Schin static void p_switch(register const struct regnod *reg)
5464887Schin {
5474887Schin 	if(level>1)
5484887Schin 		sfnputc(outfile,'\t',level-1);
5494887Schin 	p_arg(reg->regptr,')',PRE);
5504887Schin 	begin_line = 0;
5514887Schin 	sfputc(outfile,'\t');
5524887Schin 	if(reg->regcom)
5534887Schin 		p_tree(reg->regcom,0);
5544887Schin 	level++;
5554887Schin 	if(reg->regflag)
5564887Schin 		p_keyword(";&",END);
5574887Schin 	else
5584887Schin 		p_keyword(";;",END);
5594887Schin 	if(reg->regnxt)
5604887Schin 		p_switch(reg->regnxt);
5614887Schin 	return;
5624887Schin }
5634887Schin 
5644887Schin /*
5654887Schin  * output here documents
5664887Schin  */
here_body(register const struct ionod * iop)5674887Schin static void here_body(register const struct ionod *iop)
5684887Schin {
5694887Schin 	Sfio_t *infile;
5704887Schin #ifdef xxx
5714887Schin 	if(iop->iolink)
5724887Schin 		here_body((struct inode*)iop->iolink);
5734887Schin 	iop->iolink = 0;
5744887Schin #endif
5754887Schin 	if(iop->iofile&IOSTRG)
5764887Schin 		infile = sfnew((Sfio_t*)0,iop->ioname,iop->iosize,-1,SF_STRING|SF_READ);
5774887Schin 	else
5784887Schin 		sfseek(infile=sh.heredocs,iop->iooffset,SEEK_SET);
5794887Schin 	sfmove(infile,outfile,iop->iosize,-1);
5804887Schin 	if(iop->iofile&IOSTRG)
5814887Schin 		sfclose(infile);
5824887Schin 	sfputr(outfile,iop->iodelim,'\n');
5834887Schin }
5844887Schin 
585